10#include "../utils/LexerUtils.h"
11#include "clang/AST/ASTContext.h"
12#include "clang/ASTMatchers/ASTMatchFinder.h"
13#include "clang/Basic/SourceLocation.h"
14#include "clang/Lex/Lexer.h"
25static std::optional<Token>
27 const MatchFinder::MatchResult &Result) {
28 if (!Def->getReturnType().isLocalConstQualified())
35 SourceLocation NameBeginLoc = Def->getQualifier()
36 ? Def->getQualifierLoc().getBeginLoc()
41 CharSourceRange FileRange = Lexer::makeFileCharRange(
42 CharSourceRange::getCharRange(Def->getBeginLoc(), NameBeginLoc),
43 *Result.SourceManager, Result.Context->getLangOpts());
45 if (FileRange.isInvalid())
49 tok::kw_const, FileRange, *Result.Context, *Result.SourceManager);
55 return Node.isLocalConstQualified();
59 return isa<TypeOfType>(
Node.getTypePtr());
63 return isa<TypeOfExprType>(
Node.getTypePtr());
71 llvm::SmallVector<clang::FixItHint, 4>
Hints;
74 llvm::SmallVector<clang::SourceLocation, 4>
DeclLocs;
80static CheckResult
checkDef(
const clang::FunctionDecl *Def,
81 const MatchFinder::MatchResult &MatchResult) {
88 CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc());
89 Result.Hints.push_back(FixItHint::CreateRemoval(Result.ConstRange));
94 for (
const FunctionDecl *
Decl = Def->getPreviousDecl();
Decl !=
nullptr;
97 Result.Hints.push_back(FixItHint::CreateRemoval(
98 CharSourceRange::getCharRange(T->getLocation(), T->getEndLoc())));
101 Result.DeclLocs.push_back(
Decl->getInnerLocStart());
113 auto NonLocalConstType =
114 qualType(unless(isLocalConstQualified()),
115 anyOf(decltypeType(), autoType(), isTypeOfType(),
116 isTypeOfExprType(), substTemplateTypeParmType()));
119 returns(allOf(isConstQualified(), unless(NonLocalConstType))),
120 anyOf(isDefinition(), cxxMethodDecl(isPure())),
122 unless(cxxMethodDecl(isOverride())))
128 const auto *Def = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
131 (Def->getBeginLoc().isMacroID() || Def->getEndLoc().isMacroID()))
134 CheckResult CR =
checkDef(Def, Result);
140 diag(Def->getInnerLocStart(),
141 "return type %0 is 'const'-qualified at the top level, which may "
142 "reduce code readability without improving const correctness")
143 << Def->getReturnType();
144 if (CR.ConstRange.isValid())
148 const auto *Method = dyn_cast<CXXMethodDecl>(Def);
149 if (Method && Method->isVirtual())
152 for (
auto &Hint : CR.Hints)
155 for (
auto Loc : CR.DeclLocs)
156 diag(
Loc,
"could not transform this declaration", DiagnosticIDs::Note);
const FunctionDecl * Decl
DiagnosticCallback Diagnostic
llvm::SmallVector< clang::SourceLocation, 4 > DeclLocs
CharSourceRange ConstRange
std::vector< FixItHint > Hints
::clang::DynTypedNode Node
void store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const
Stores an option with the check-local name LocalName with string value Value to Options.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
void storeOptions(ClangTidyOptions::OptionMap &Opts) override
Should store all options supported by this check with their current values or default values for opti...
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register AST matchers with Finder.
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
AST_MATCHER(CXXMethodDecl, isStatic)
static CheckResult checkDef(const clang::FunctionDecl *Def, const MatchFinder::MatchResult &MatchResult)
static std::optional< Token > findConstToRemove(const FunctionDecl *Def, const MatchFinder::MatchResult &Result)
std::optional< Token > getQualifyingToken(tok::TokenKind TK, CharSourceRange Range, const ASTContext &Context, const SourceManager &SM)
Assuming that Range spans a CVR-qualified type, returns the token in Range that is responsible for th...
llvm::StringMap< ClangTidyValue > OptionMap