11 #include "clang/AST/ASTContext.h"
12 #include "clang/AST/DeclCXX.h"
13 #include "clang/AST/RecursiveASTVisitor.h"
14 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 #include "clang/Basic/SourceLocation.h"
16 #include "clang/Lex/Lexer.h"
22 namespace readability {
24 AST_MATCHER(CXXMethodDecl, isStatic) {
return Node.isStatic(); }
26 AST_MATCHER(CXXMethodDecl, hasTrivialBody) {
return Node.hasTrivialBody(); }
29 return Node.isOverloadedOperator();
33 return Node.hasAnyDependentBases();
37 return Node.getTemplatedKind() != FunctionDecl::TK_NonTemplate;
41 return Node.isDependentContext();
45 const ASTContext &Ctxt = Finder->getASTContext();
46 return clang::Lexer::makeFileCharRange(
47 clang::CharSourceRange::getCharRange(
48 Node.getTypeSourceInfo()->getTypeLoc().getSourceRange()),
49 Ctxt.getSourceManager(), Ctxt.getLangOpts())
54 ast_matchers::internal::Matcher<CXXMethodDecl>, InnerMatcher) {
55 return InnerMatcher.matches(*Node.getCanonicalDecl(), Finder,
Builder);
63 bool VisitCXXThisExpr(
const CXXThisExpr *
E) {
70 UsageOfThis.TraverseStmt(const_cast<Stmt *>(Node.getBody()));
72 return UsageOfThis.Used;
75 void ConvertMemberFunctionsToStatic::registerMatchers(MatchFinder *Finder) {
78 isDefinition(), isUserProvided(),
80 isExpansionInSystemHeader(), isVirtual(), isStatic(),
81 hasTrivialBody(), isOverloadedOperator(), cxxConstructorDecl(),
82 cxxDestructorDecl(), cxxConversionDecl(), isTemplate(),
86 hasAnyDependentBases())
89 isInsideMacroDefinition(),
90 hasCanonicalDecl(isInsideMacroDefinition()), usesThis())))
97 const LangOptions &LangOpts,
103 return Lexer::getSourceText(CharSourceRange(
Range,
true),
SourceMgr,
109 const LangOptions &LangOpts) {
111 const auto FTL = TSI->getTypeLoc().IgnoreParens().getAs<FunctionTypeLoc>();
114 SourceRange
Range{FTL.getRParenLoc().getLocWithOffset(1),
115 FTL.getLocalRangeEnd()};
120 if (
Offset == StringRef::npos)
123 SourceLocation Start =
Range.getBegin().getLocWithOffset(
Offset);
124 return {Start, Start.getLocWithOffset(strlen(
"const") - 1)};
127 void ConvertMemberFunctionsToStatic::check(
128 const MatchFinder::MatchResult &Result) {
129 const auto *Definition = Result.Nodes.getNodeAs<CXXMethodDecl>(
"x");
133 DiagnosticBuilder Diag =
134 diag(Definition->getLocation(),
"method %0 can be made static")
138 if (Definition->getMethodQualifiers().hasVolatile() ||
139 Definition->getMethodQualifiers().hasRestrict() ||
140 Definition->getRefQualifier() != RQ_None)
143 const CXXMethodDecl *Declaration = Definition->getCanonicalDecl();
145 if (Definition->isConst()) {
149 *Result.SourceManager,
150 Result.Context->getLangOpts());
152 if (DefConst.isInvalid())
155 if (Declaration != Definition) {
157 Declaration->getTypeSourceInfo(), *Result.SourceManager,
158 Result.Context->getLangOpts());
160 if (DeclConst.isInvalid())
162 Diag << FixItHint::CreateRemoval(DeclConst);
166 Diag << FixItHint::CreateRemoval(DefConst);
168 Diag << FixItHint::CreateInsertion(Declaration->getBeginLoc(),
"static ");