10#include "clang/AST/ASTContext.h"
11#include "clang/AST/ParentMapContext.h"
12#include "clang/AST/RecursiveASTVisitor.h"
13#include "clang/ASTMatchers/ASTMatchFinder.h"
14#include "clang/Lex/Lexer.h"
22AST_MATCHER(CXXMethodDecl, hasTrivialBody) {
return Node.hasTrivialBody(); }
25 return Node.hasAnyDependentBases();
29 return Node.getTemplatedKind() != FunctionDecl::TK_NonTemplate;
33 return Node.isDependentContext();
36AST_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 DynTypedNodeList Parents = Ctxt.getParents(*
E);
61 if (Parents.size() != 1)
64 return Parents.begin()->get<T>();
68 const Expr *
Parent = getParent<Expr>(
E);
69 while (isa_and_nonnull<ParenExpr>(
Parent))
100 if (Cast->getCastKind() != CK_NoOp)
104 QualType QT = Cast->getType();
105 if (QT->isPointerType())
106 QT = QT->getPointeeType();
108 if (!QT.isConstQualified())
111 const auto *
Parent = getParent<Stmt>(Cast);
115 if (isa<ReturnStmt>(
Parent))
118 if (isa<CallExpr>(
Parent))
122 if (
const auto *Member = dyn_cast<MemberExpr>(
Parent))
130 bool visitUser(
const MemberExpr *Member,
bool OnConstObject) {
131 if (Member->isBoundMemberFunction(Ctxt)) {
132 if (!OnConstObject || Member->getFoundDecl().getAccess() != AS_public) {
150 if (
const auto *Cast = dyn_cast_or_null<ImplicitCastExpr>(
Parent)) {
155 if (Member->getFoundDecl().getAccess() != AS_public &&
156 !Cast->getType()->isBuiltinType())
159 if (Cast->getCastKind() == CK_LValueToRValue)
162 if (Cast->getCastKind() == CK_NoOp && Cast->getType().isConstQualified())
166 if (
const auto *
M = dyn_cast_or_null<MemberExpr>(
Parent))
178 if (
const auto *UnOp = dyn_cast_or_null<UnaryOperator>(
Parent)) {
179 if (UnOp->getOpcode() == UO_Deref) {
189 if (
const auto *Cast = dyn_cast_or_null<ImplicitCastExpr>(
Parent)) {
197 }
else if (
const auto *Member = dyn_cast_or_null<MemberExpr>(
Parent)) {
212 UsageOfThis.TraverseStmt(
const_cast<Stmt *
>(
Node.getBody()));
222 isDefinition(), isUserProvided(),
224 isExpansionInSystemHeader(), isVirtual(), isConst(),
225 isStatic(), hasTrivialBody(), cxxConstructorDecl(),
226 cxxDestructorDecl(), isTemplate(), isDependentContext(),
227 ofClass(anyOf(isLambda(),
228 hasAnyDependentBases())
232 isInsideMacroDefinition(),
233 hasCanonicalDecl(isInsideMacroDefinition()))),
240 TypeSourceInfo *TSI =
M->getTypeSourceInfo();
244 auto FTL = TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
248 return FTL.getRParenLoc().getLocWithOffset(1);
252 const MatchFinder::MatchResult &Result) {
253 const auto *Definition = Result.Nodes.getNodeAs<CXXMethodDecl>(
"x");
255 const auto *Declaration = Definition->getCanonicalDecl();
257 auto Diag =
diag(Definition->getLocation(),
"method %0 can be made const")
261 if (Declaration != Definition) {
CodeCompletionBuilder Builder
::clang::DynTypedNode Node
const google::protobuf::Message & M
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
const T * getParent(const Expr *E)
bool VisitUnresolvedMemberExpr(const UnresolvedMemberExpr *)
FindUsageOfThis(ASTContext &Ctxt)
bool visitUser(const ImplicitCastExpr *Cast)
bool VisitCXXThisExpr(const CXXThisExpr *E)
const Expr * getParentExprIgnoreParens(const Expr *E)
bool VisitCXXConstCastExpr(const CXXConstCastExpr *)
bool visitUser(const MemberExpr *Member, bool OnConstObject)
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
AST_MATCHER(CXXMethodDecl, isStatic)
static SourceLocation getConstInsertionPoint(const CXXMethodDecl *M)
AST_MATCHER_P(CXXMethodDecl, hasCanonicalDecl, ast_matchers::internal::Matcher< CXXMethodDecl >, InnerMatcher)