10 #include "clang/AST/ASTContext.h" 11 #include "clang/AST/RecursiveASTVisitor.h" 12 #include "clang/ASTMatchers/ASTMatchFinder.h" 18 namespace readability {
20 AST_MATCHER(CXXMethodDecl, isStatic) {
return Node.isStatic(); }
22 AST_MATCHER(CXXMethodDecl, hasTrivialBody) {
return Node.hasTrivialBody(); }
25 return Node.hasAnyDependentBases();
29 return Node.getTemplatedKind() != FunctionDecl::TK_NonTemplate;
33 return Node.isDependentContext();
36 AST_MATCHER(CXXMethodDecl, isInsideMacroDefinition) {
37 const ASTContext &Ctxt = Finder->getASTContext();
38 return clang::Lexer::makeFileCharRange(
39 clang::CharSourceRange::getCharRange(
40 Node.getTypeSourceInfo()->getTypeLoc().getSourceRange()),
41 Ctxt.getSourceManager(), Ctxt.getLangOpts())
46 ast_matchers::internal::Matcher<CXXMethodDecl>, InnerMatcher) {
47 return InnerMatcher.matches(*Node.getCanonicalDecl(), Finder,
Builder);
60 ASTContext::DynTypedNodeList Parents = Ctxt.getParents(*E);
61 if (Parents.size() != 1)
64 return Parents.begin()->get<T>();
93 if (Cast->getCastKind() != CK_NoOp)
97 QualType QT = Cast->getType();
98 if (QT->isPointerType())
99 QT = QT->getPointeeType();
101 if (!QT.isConstQualified())
104 const auto *
Parent = getParent<Stmt>(Cast);
108 if (isa<ReturnStmt>(
Parent))
111 if (isa<CallExpr>(
Parent))
115 if (
const auto *Member = dyn_cast<MemberExpr>(
Parent))
116 return VisitUser(Member,
true);
123 bool VisitUser(
const MemberExpr *Member,
bool OnConstObject) {
124 if (Member->isBoundMemberFunction(Ctxt)) {
125 if (!OnConstObject || Member->getFoundDecl().getAccess() != AS_public) {
141 const auto *
Parent = getParent<Expr>(Member);
143 if (
const auto *Cast = dyn_cast_or_null<ImplicitCastExpr>(
Parent)) {
148 if (Member->getFoundDecl().getAccess() != AS_public &&
149 !Cast->getType()->isBuiltinType())
152 if (Cast->getCastKind() == CK_LValueToRValue)
155 if (Cast->getCastKind() == CK_NoOp && Cast->getType().isConstQualified())
159 if (
const auto *M = dyn_cast_or_null<MemberExpr>(
Parent))
160 return VisitUser(M,
false);
168 const auto *
Parent = getParent<Expr>(
E);
171 if (
const auto *UnOp = dyn_cast_or_null<UnaryOperator>(
Parent)) {
172 if (UnOp->getOpcode() == UO_Deref) {
173 Parent = getParent<Expr>(UnOp);
182 if (
const auto *Cast = dyn_cast_or_null<ImplicitCastExpr>(
Parent)) {
190 }
else if (
const auto *Member = dyn_cast_or_null<MemberExpr>(
Parent)) {
191 if (VisitUser(Member,
false))
205 UsageOfThis.TraverseStmt(const_cast<Stmt *>(Node.getBody()));
210 void MakeMemberFunctionConstCheck::registerMatchers(MatchFinder *Finder) {
211 if (!getLangOpts().CPlusPlus)
216 isDefinition(), isUserProvided(),
218 isExpansionInSystemHeader(), isVirtual(), isConst(), isStatic(),
219 hasTrivialBody(), cxxConstructorDecl(), cxxDestructorDecl(),
220 isTemplate(), isDependentContext(),
223 hasAnyDependentBases())
226 isInsideMacroDefinition(),
227 hasCanonicalDecl(isInsideMacroDefinition()))),
234 TypeSourceInfo *TSI = M->getTypeSourceInfo();
238 FunctionTypeLoc FTL =
239 TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
243 return FTL.getRParenLoc().getLocWithOffset(1);
246 void MakeMemberFunctionConstCheck::check(
247 const MatchFinder::MatchResult &Result) {
248 const auto *Definition = Result.Nodes.getNodeAs<CXXMethodDecl>(
"x");
250 auto Declaration = Definition->getCanonicalDecl();
252 auto Diag = diag(Definition->getLocation(),
"method %0 can be made const")
256 if (Declaration != Definition) {
const T * getParent(const Expr *E)
AST_MATCHER(Expr, isMacroID)
bool VisitCXXConstCastExpr(const CXXConstCastExpr *)
bool VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *)
bool VisitUser(const ImplicitCastExpr *Cast)
FindUsageOfThis(ASTContext &Ctxt)
bool VisitUser(const MemberExpr *Member, bool OnConstObject)
static SourceLocation getConstInsertionPoint(const CXXMethodDecl *M)
CodeCompletionBuilder Builder
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
bool VisitCXXThisExpr(const CXXThisExpr *E)
AST_MATCHER_P(CXXMethodDecl, hasCanonicalDecl, ast_matchers::internal::Matcher< CXXMethodDecl >, InnerMatcher)