10 #include "clang/AST/ASTContext.h" 11 #include "clang/ASTMatchers/ASTMatchFinder.h" 17 namespace readability {
19 void NonConstParameterCheck::registerMatchers(MatchFinder *Finder) {
21 Finder->addMatcher(parmVarDecl(unless(isInstantiated())).bind(
"Parm"),
this);
24 Finder->addMatcher(cxxConstructorDecl().bind(
"Ctor"),
this);
28 Finder->addMatcher(declRefExpr().bind(
"Ref"),
this);
31 Finder->addMatcher(stmt(anyOf(unaryOperator(anyOf(hasOperatorName(
"++"),
32 hasOperatorName(
"--"))),
33 binaryOperator(), callExpr(), returnStmt(),
37 Finder->addMatcher(varDecl(hasInitializer(anything())).bind(
"Mark"),
this);
40 void NonConstParameterCheck::check(
const MatchFinder::MatchResult &Result) {
41 if (
const auto *Parm = Result.Nodes.getNodeAs<ParmVarDecl>(
"Parm")) {
42 if (
const DeclContext *D = Parm->getParentFunctionOrMethod()) {
43 if (
const auto *M = dyn_cast<CXXMethodDecl>(D)) {
44 if (M->isVirtual() || M->size_overridden_methods() != 0)
49 }
else if (
const auto *Ctor =
50 Result.Nodes.getNodeAs<CXXConstructorDecl>(
"Ctor")) {
51 for (
const auto *Parm : Ctor->parameters())
53 for (
const auto *Init : Ctor->inits())
54 markCanNotBeConst(Init->getInit(),
true);
55 }
else if (
const auto *Ref = Result.Nodes.getNodeAs<DeclRefExpr>(
"Ref")) {
57 }
else if (
const auto *S = Result.Nodes.getNodeAs<Stmt>(
"Mark")) {
58 if (
const auto *B = dyn_cast<BinaryOperator>(S)) {
59 if (B->isAssignmentOp())
60 markCanNotBeConst(B,
false);
61 }
else if (
const auto *CE = dyn_cast<CallExpr>(S)) {
65 for (
const auto *Arg : CE->arguments()) {
66 markCanNotBeConst(Arg->IgnoreParenCasts(),
true);
70 if (
const FunctionDecl *FD = CE->getDirectCallee()) {
72 for (
const auto *Par : FD->parameters()) {
73 if (ArgNr >= CE->getNumArgs())
75 const Expr *Arg = CE->getArg(ArgNr++);
77 const Type *ParType = Par->getType().getTypePtr();
78 if (!ParType->isReferenceType() || Par->getType().isConstQualified())
80 markCanNotBeConst(Arg->IgnoreParenCasts(),
false);
83 }
else if (
const auto *CE = dyn_cast<CXXConstructExpr>(S)) {
84 for (
const auto *Arg : CE->arguments()) {
85 markCanNotBeConst(Arg->IgnoreParenCasts(),
true);
87 }
else if (
const auto *R = dyn_cast<ReturnStmt>(S)) {
88 markCanNotBeConst(R->getRetValue(),
true);
89 }
else if (
const auto *U = dyn_cast<UnaryOperator>(S)) {
90 markCanNotBeConst(U,
true);
92 }
else if (
const auto *VD = Result.Nodes.getNodeAs<VarDecl>(
"Mark")) {
93 const QualType T = VD->getType();
94 if ((T->isPointerType() && !T->getPointeeType().isConstQualified()) ||
96 markCanNotBeConst(VD->getInit(),
true);
100 void NonConstParameterCheck::addParm(
const ParmVarDecl *Parm) {
102 const QualType T = Parm->getType();
103 if (!T->isPointerType() || T->getPointeeType().isConstQualified() ||
104 !(T->getPointeeType()->isIntegerType() ||
105 T->getPointeeType()->isFloatingType()))
112 PI.IsReferenced =
false;
113 PI.CanBeConst =
true;
117 void NonConstParameterCheck::setReferenced(
const DeclRefExpr *Ref) {
118 auto It =
Parameters.find(dyn_cast<ParmVarDecl>(Ref->getDecl()));
120 It->second.IsReferenced =
true;
123 void NonConstParameterCheck::onEndOfTranslationUnit() {
124 diagnoseNonConstParameters();
127 void NonConstParameterCheck::diagnoseNonConstParameters() {
129 const ParmVarDecl *Par = It.first;
130 const ParmInfo &ParamInfo = It.second;
133 if (!ParamInfo.IsReferenced)
137 if (!ParamInfo.CanBeConst)
140 SmallVector<FixItHint, 8> Fixes;
142 dyn_cast_or_null<const FunctionDecl>(Par->getParentFunctionOrMethod());
145 unsigned Index = Par->getFunctionScopeIndex();
146 for (FunctionDecl *FnDecl : Function->redecls())
147 Fixes.push_back(FixItHint::CreateInsertion(
148 FnDecl->getParamDecl(Index)->getBeginLoc(),
"const "));
150 diag(Par->getLocation(),
"pointer parameter '%0' can be pointer to const")
151 << Par->getName() << Fixes;
155 void NonConstParameterCheck::markCanNotBeConst(
const Expr *
E,
156 bool CanNotBeConst) {
160 if (
const auto *Cast = dyn_cast<ImplicitCastExpr>(E)) {
162 const QualType T = Cast->getType();
163 if (T->isPointerType() && T->getPointeeType().isConstQualified())
167 E = E->IgnoreParenCasts();
169 if (
const auto *B = dyn_cast<BinaryOperator>(E)) {
170 if (B->isAdditiveOp()) {
172 markCanNotBeConst(B->getLHS(), CanNotBeConst);
173 markCanNotBeConst(B->getRHS(), CanNotBeConst);
174 }
else if (B->isAssignmentOp()) {
175 markCanNotBeConst(B->getLHS(),
false);
178 const QualType T = B->getLHS()->getType();
179 if (T->isPointerType() && !T->getPointeeType().isConstQualified())
180 markCanNotBeConst(B->getRHS(),
true);
182 }
else if (
const auto *C = dyn_cast<ConditionalOperator>(E)) {
183 markCanNotBeConst(C->getTrueExpr(), CanNotBeConst);
184 markCanNotBeConst(C->getFalseExpr(), CanNotBeConst);
185 }
else if (
const auto *U = dyn_cast<UnaryOperator>(E)) {
186 if (U->getOpcode() == UO_PreInc || U->getOpcode() == UO_PreDec ||
187 U->getOpcode() == UO_PostInc || U->getOpcode() == UO_PostDec) {
188 if (
const auto *SubU =
189 dyn_cast<UnaryOperator>(U->getSubExpr()->IgnoreParenCasts()))
190 markCanNotBeConst(SubU->getSubExpr(),
true);
191 markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
192 }
else if (U->getOpcode() == UO_Deref) {
194 markCanNotBeConst(U->getSubExpr(),
true);
196 markCanNotBeConst(U->getSubExpr(), CanNotBeConst);
198 }
else if (
const auto *A = dyn_cast<ArraySubscriptExpr>(E)) {
199 markCanNotBeConst(A->getBase(),
true);
200 }
else if (
const auto *CLE = dyn_cast<CompoundLiteralExpr>(E)) {
201 markCanNotBeConst(CLE->getInitializer(),
true);
202 }
else if (
const auto *Constr = dyn_cast<CXXConstructExpr>(E)) {
203 for (
const auto *Arg : Constr->arguments()) {
204 if (
const auto *M = dyn_cast<MaterializeTemporaryExpr>(Arg))
205 markCanNotBeConst(cast<Expr>(M->getSubExpr()), CanNotBeConst);
207 }
else if (
const auto *ILE = dyn_cast<InitListExpr>(E)) {
208 for (
unsigned I = 0U; I < ILE->getNumInits(); ++I)
209 markCanNotBeConst(ILE->getInit(I),
true);
210 }
else if (CanNotBeConst) {
212 if (
const auto *D = dyn_cast<DeclRefExpr>(E)) {
213 auto It =
Parameters.find(dyn_cast<ParmVarDecl>(D->getDecl()));
215 It->second.CanBeConst =
false;
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
const SymbolIndex * Index