clang-tools 6.0.0

UndelegatedConstructor.cpp
Go to the documentation of this file.
1 //===--- UndelegatedConstructor.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
10 #include "UndelegatedConstructor.h"
11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
13
14 using namespace clang::ast_matchers;
15
16 namespace clang {
17 namespace tidy {
18 namespace misc {
19
20 namespace {
21 AST_MATCHER_P(Stmt, ignoringTemporaryExpr,
22 ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
23 const Stmt *E = &Node;
24 for (;;) {
25 // Temporaries with non-trivial dtors.
26 if (const auto *EWC = dyn_cast<ExprWithCleanups>(E))
27 E = EWC->getSubExpr();
28 // Temporaries with zero or more than two ctor arguments.
29 else if (const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
30 E = BTE->getSubExpr();
31 // Temporaries with exactly one ctor argument.
32 else if (const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
33 E = FCE->getSubExpr();
34 else
35 break;
36 }
37
38 return InnerMatcher.matches(*E, Finder, Builder);
39 }
40
41 // Finds a node if it's a base of an already bound node.
42 AST_MATCHER_P(CXXRecordDecl, baseOfBoundNode, std::string, ID) {
43 return Builder->removeBindings(
44 [&](const ast_matchers::internal::BoundNodesMap &Nodes) {
45 const auto *Derived = Nodes.getNodeAs<CXXRecordDecl>(ID);
46 return Derived != &Node && !Derived->isDerivedFrom(&Node);
47 });
48 }
49 } // namespace
50
51 void UndelegatedConstructorCheck::registerMatchers(MatchFinder *Finder) {
52 // We look for calls to constructors of the same type in constructors. To do
53 // this we have to look through a variety of nodes that occur in the path,
54 // depending on the type's destructor and the number of arguments on the
55 // constructor call, this is handled by ignoringTemporaryExpr. Ignore template
56 // instantiations to reduce the number of duplicated warnings.
57 //
58 // Only register the matchers for C++11; the functionality currently does not
59 // provide any benefit to other languages, despite being benign.
60 if (!getLangOpts().CPlusPlus11)
61 return;
62
63 Finder->addMatcher(
64 compoundStmt(
65 hasParent(
66 cxxConstructorDecl(ofClass(cxxRecordDecl().bind("parent")))),
67 forEach(ignoringTemporaryExpr(
68 cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass(
69 cxxRecordDecl(baseOfBoundNode("parent"))))))
70 .bind("construct"))),
71 unless(isInTemplateInstantiation())),
72 this);
73 }
74
75 void UndelegatedConstructorCheck::check(
76 const MatchFinder::MatchResult &Result) {
77 const auto *E = Result.Nodes.getNodeAs<CXXConstructExpr>("construct");
78 diag(E->getLocStart(), "did you intend to call a delegated constructor? "
79 "A temporary object is created here instead");
80 }
81
82 } // namespace misc
83 } // namespace tidy
84 } // namespace clang
clang::ast_matchers
Definition: ClangTidyDiagnosticConsumer.h:27
UndelegatedConstructor.h
clang
Definition: AndroidTidyModule.cpp:28
clang::tidy::bugprone::AST_MATCHER_P
AST_MATCHER_P(IntegerLiteral, isBiggerThan, unsigned, N)
Definition: StringConstructorCheck.cpp:21