clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

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