11 #include "../utils/DeclRefExprUtils.h" 12 #include "../utils/FixItHintUtils.h" 13 #include "../utils/Matchers.h" 14 #include "../utils/OptionsUtils.h" 15 #include "clang/Basic/Diagnostic.h" 19 namespace performance {
22 void recordFixes(
const VarDecl &Var, ASTContext &Context,
23 DiagnosticBuilder &Diagnostic) {
25 if (!Var.getType().isLocalConstQualified()) {
27 Var, Context, DeclSpec::TQ::TQ_const))
44 auto ConstReference = referenceType(pointee(qualType(isConstQualified())));
52 auto ConstRefReturningMethodCall =
53 cxxMemberCallExpr(callee(cxxMethodDecl(returns(ConstReference))),
54 on(declRefExpr(to(varDecl().bind(
"objectArg")))));
55 auto ConstRefReturningFunctionCall =
56 callExpr(callee(functionDecl(returns(ConstReference))),
57 unless(callee(cxxMethodDecl())));
59 auto localVarCopiedFrom = [
this](
const internal::Matcher<Expr> &CopyCtorArg) {
63 has(varDecl(hasLocalStorage(),
67 unless(hasDeclaration(namedDecl(
68 matchers::matchesAnyListedName(
73 hasDeclaration(cxxConstructorDecl(
74 isCopyConstructor())),
75 hasArgument(0, CopyCtorArg))
82 Finder->addMatcher(localVarCopiedFrom(anyOf(ConstRefReturningFunctionCall,
83 ConstRefReturningMethodCall)),
86 Finder->addMatcher(localVarCopiedFrom(declRefExpr(
87 to(varDecl(hasLocalStorage()).bind(
"oldVarDecl")))),
92 const MatchFinder::MatchResult &Result) {
93 const auto *NewVar = Result.Nodes.getNodeAs<VarDecl>(
"newVarDecl");
94 const auto *OldVar = Result.Nodes.getNodeAs<VarDecl>(
"oldVarDecl");
95 const auto *ObjectArg = Result.Nodes.getNodeAs<VarDecl>(
"objectArg");
96 const auto *BlockStmt = Result.Nodes.getNodeAs<Stmt>(
"blockStmt");
97 const auto *CtorCall = Result.Nodes.getNodeAs<CXXConstructExpr>(
"ctorCall");
102 Result.Nodes.getNodeAs<DeclStmt>(
"declStmt")->isSingleDecl() &&
103 !NewVar->getLocation().isMacroID();
108 for (
unsigned int i = 1; i < CtorCall->getNumArgs(); ++i)
109 if (!CtorCall->getArg(i)->isDefaultArgument())
112 if (OldVar ==
nullptr) {
113 handleCopyFromMethodReturn(*NewVar, *BlockStmt, IssueFix, ObjectArg,
116 handleCopyFromLocalVar(*NewVar, *OldVar, *BlockStmt, IssueFix,
121 void UnnecessaryCopyInitialization::handleCopyFromMethodReturn(
122 const VarDecl &Var,
const Stmt &BlockStmt,
bool IssueFix,
123 const VarDecl *ObjectArg, ASTContext &Context) {
124 bool IsConstQualified = Var.getType().isConstQualified();
127 if (ObjectArg !=
nullptr &&
132 diag(Var.getLocation(),
133 IsConstQualified ?
"the const qualified variable %0 is " 134 "copy-constructed from a const reference; " 135 "consider making it a const reference" 136 :
"the variable %0 is copy-constructed from a " 137 "const reference but is only used as const " 138 "reference; consider making it a const reference")
141 recordFixes(Var, Context, Diagnostic);
144 void UnnecessaryCopyInitialization::handleCopyFromLocalVar(
145 const VarDecl &NewVar,
const VarDecl &OldVar,
const Stmt &BlockStmt,
146 bool IssueFix, ASTContext &Context) {
151 auto Diagnostic =
diag(NewVar.getLocation(),
152 "local copy %0 of the variable %1 is never modified; " 153 "consider avoiding the copy")
154 << &NewVar << &OldVar;
156 recordFixes(NewVar, Context, Diagnostic);
std::string serializeStringList(ArrayRef< std::string > Strings)
Serialize a sequence of names that can be parsed by parseStringList.
bool isOnlyUsedAsConst(const VarDecl &Var, const Stmt &Stmt, ASTContext &Context)
Returns true if all DeclRefExpr to the variable within Stmt do not modify it.
Base class for all clang-tidy checks.
std::vector< std::string > parseStringList(StringRef Option)
Parse a semicolon separated list of strings.
llvm::Optional< bool > isExpensiveToCopy(QualType Type, const ASTContext &Context)
Returns true if Type is expensive to copy.
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.
static constexpr llvm::StringLiteral Name
std::map< std::string, std::string > OptionMap
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Every ClangTidyCheck reports errors through a DiagnosticsEngine provided by this context.
static cl::opt< bool > Fix("fix", cl::desc(R"(
Apply suggested fixes. Without -fix-errors
clang-tidy will bail out if any compilation
errors were found.
)"), cl::init(false), cl::cat(ClangTidyCategory))
Optional< FixItHint > addQualifierToVarDecl(const VarDecl &Var, const ASTContext &Context, DeclSpec::TQ Qualifier, QualifierTarget QualTarget, QualifierPolicy QualPolicy)
Creates fix to qualify VarDecl with the specified Qualifier.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
FixItHint changeVarDeclToReference(const VarDecl &Var, ASTContext &Context)
Creates fix to make VarDecl a reference by adding &.