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"
15 #include "llvm/ADT/Optional.h"
21 namespace readability {
27 static llvm::Optional<Token>
29 const MatchFinder::MatchResult &Result) {
30 if (!Def->getReturnType().isLocalConstQualified())
37 SourceLocation NameBeginLoc = Def->getQualifier()
38 ? Def->getQualifierLoc().getBeginLoc()
43 CharSourceRange FileRange = Lexer::makeFileCharRange(
44 CharSourceRange::getCharRange(Def->getBeginLoc(), NameBeginLoc),
45 *Result.SourceManager, Result.Context->getLangOpts());
47 if (FileRange.isInvalid())
51 tok::kw_const, FileRange, *Result.Context, *Result.SourceManager);
61 llvm::SmallVector<clang::FixItHint, 4>
Hints;
64 llvm::SmallVector<clang::SourceLocation, 4>
DeclLocs;
70 static CheckResult
checkDef(
const clang::FunctionDecl *Def,
71 const MatchFinder::MatchResult &MatchResult) {
78 CharSourceRange::getCharRange(Tok->getLocation(), Tok->getEndLoc());
79 Result.Hints.push_back(FixItHint::CreateRemoval(Result.ConstRange));
84 for (
const FunctionDecl *
Decl = Def->getPreviousDecl();
Decl !=
nullptr;
87 Result.Hints.push_back(FixItHint::CreateRemoval(
88 CharSourceRange::getCharRange(T->getLocation(), T->getEndLoc())));
91 Result.DeclLocs.push_back(
Decl->getInnerLocStart());
96 void ConstReturnTypeCheck::registerMatchers(MatchFinder *Finder) {
100 functionDecl(returns(isConstQualified()), isDefinition()).bind(
"func"),
104 void ConstReturnTypeCheck::check(
const MatchFinder::MatchResult &Result) {
105 const auto *Def = Result.Nodes.getNodeAs<FunctionDecl>(
"func");
106 CheckResult CR =
checkDef(Def, Result);
112 diag(Def->getInnerLocStart(),
113 "return type %0 is 'const'-qualified at the top level, which may "
114 "reduce code readability without improving const correctness")
115 << Def->getReturnType();
116 if (CR.ConstRange.isValid())
118 for (
auto &Hint : CR.Hints)
121 for (
auto Loc : CR.DeclLocs)
122 diag(
Loc,
"could not transform this declaration", DiagnosticIDs::Note);