clang-tools  3.8.0
UnnecessaryCopyInitialization.cpp
Go to the documentation of this file.
1 //===--- UnnecessaryCopyInitialization.cpp - clang-tidy--------------------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
11 
12 #include "../utils/LexerUtils.h"
13 #include "../utils/Matchers.h"
14 
15 namespace clang {
16 namespace tidy {
17 namespace performance {
18 
19 using namespace ::clang::ast_matchers;
20 
21 namespace {
22 AST_MATCHER(QualType, isPointerType) { return Node->isPointerType(); }
23 } // namespace
24 
26  ast_matchers::MatchFinder *Finder) {
27  auto ConstReference = referenceType(pointee(qualType(isConstQualified())));
28  auto ConstOrConstReference =
29  allOf(anyOf(ConstReference, isConstQualified()),
30  unless(allOf(isPointerType(), unless(pointerType(pointee(qualType(
31  isConstQualified())))))));
32  // Match method call expressions where the this argument is a const
33  // type or const reference. This returned const reference is highly likely to
34  // outlive the local const reference of the variable being declared.
35  // The assumption is that the const reference being returned either points
36  // to a global static variable or to a member of the called object.
37  auto ConstRefReturningMethodCallOfConstParam = cxxMemberCallExpr(
38  callee(cxxMethodDecl(returns(ConstReference))),
39  on(declRefExpr(to(varDecl(hasType(qualType(ConstOrConstReference)))))));
40  auto ConstRefReturningFunctionCall =
41  callExpr(callee(functionDecl(returns(ConstReference))),
42  unless(callee(cxxMethodDecl())));
43  Finder->addMatcher(
44  varDecl(
45  hasLocalStorage(), hasType(isConstQualified()),
46  hasType(matchers::isExpensiveToCopy()),
47  hasInitializer(cxxConstructExpr(
48  hasDeclaration(cxxConstructorDecl(isCopyConstructor())),
49  hasArgument(0, anyOf(ConstRefReturningFunctionCall,
50  ConstRefReturningMethodCallOfConstParam)))))
51  .bind("varDecl"),
52  this);
53 }
54 
56  const ast_matchers::MatchFinder::MatchResult &Result) {
57  const auto *Var = Result.Nodes.getNodeAs<VarDecl>("varDecl");
58  SourceLocation AmpLocation = Var->getLocation();
59  auto Token = lexer_utils::getPreviousNonCommentToken(*Result.Context,
60  Var->getLocation());
61  if (!Token.is(tok::unknown)) {
62  AmpLocation = Token.getLocation().getLocWithOffset(Token.getLength());
63  }
64  diag(Var->getLocation(),
65  "the const qualified variable '%0' is copy-constructed from a "
66  "const reference; consider making it a const reference")
67  << Var->getName() << FixItHint::CreateInsertion(AmpLocation, "&");
68 }
69 
70 } // namespace performance
71 } // namespace tidy
72 } // namespace clang
void registerMatchers(ast_matchers::MatchFinder *Finder) override
Override this to register ASTMatchers with Finder.
std::unique_ptr< ast_matchers::MatchFinder > Finder
Definition: ClangTidy.cpp:188
Token getPreviousNonCommentToken(const ASTContext &Context, SourceLocation Location)
Definition: LexerUtils.cpp:16
AST_MATCHER(Stmt, isInsideOfRangeBeginEndStmt)
llvm::Optional< bool > isExpensiveToCopy(QualType Type, ASTContext &Context)
Definition: TypeTraits.cpp:27
void check(const ast_matchers::MatchFinder::MatchResult &Result) override
ClangTidyChecks that register ASTMatchers should do the actual work in here.
DiagnosticBuilder diag(SourceLocation Loc, StringRef Description, DiagnosticIDs::Level Level=DiagnosticIDs::Warning)
Add a diagnostic with the check's name.
Definition: ClangTidy.cpp:323
const NamedDecl * Result
Definition: USRFinder.cpp:121