11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
22 ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
23 const Stmt *E = &Node;
26 if (
const auto *EWC = dyn_cast<ExprWithCleanups>(E))
27 E = EWC->getSubExpr();
29 else if (
const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
30 E = BTE->getSubExpr();
32 else if (
const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
33 E = FCE->getSubExpr();
38 return InnerMatcher.matches(*E,
Finder, Builder);
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);
51 void UndelegatedConstructorCheck::registerMatchers(MatchFinder *
Finder) {
60 if (!getLangOpts().CPlusPlus11)
66 cxxConstructorDecl(ofClass(cxxRecordDecl().bind(
"parent")))),
67 forEach(ignoringTemporaryExpr(
68 cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass(
69 cxxRecordDecl(baseOfBoundNode(
"parent"))))))
71 unless(isInTemplateInstantiation())),
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");
std::unique_ptr< ast_matchers::MatchFinder > Finder
AST_MATCHER_P(CXXForRangeStmt, hasRangeBeginEndStmt, ast_matchers::internal::Matcher< DeclStmt >, InnerMatcher)