clang-tools  7.0.0
UndelegatedConstructorCheck.cpp
Go to the documentation of this file.
1 //===--- UndelegatedConstructorCheck.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 #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 bugprone {
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 bugprone
83 } // namespace tidy
84 } // namespace clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
AST_MATCHER_P(FunctionDecl, throws, internal::Matcher< Type >, InnerMatcher)