11 #include "clang/AST/ASTContext.h"
12 #include "clang/Lex/Lexer.h"
14 using namespace clang::ast_matchers;
20 ast_matchers::internal::Matcher<Stmt>, InnerMatcher) {
21 const Stmt *E = &Node;
24 if (
const auto *EWC = dyn_cast<ExprWithCleanups>(E))
25 E = EWC->getSubExpr();
27 else if (
const auto *BTE = dyn_cast<CXXBindTemporaryExpr>(E))
28 E = BTE->getSubExpr();
30 else if (
const auto *FCE = dyn_cast<CXXFunctionalCastExpr>(E))
31 E = FCE->getSubExpr();
36 return InnerMatcher.matches(*E,
Finder, Builder);
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);
52 void UndelegatedConstructorCheck::registerMatchers(MatchFinder *
Finder) {
61 if (!getLangOpts().CPlusPlus11)
67 cxxConstructorDecl(ofClass(cxxRecordDecl().bind(
"parent")))),
68 forEach(ignoringTemporaryExpr(
69 cxxConstructExpr(hasDeclaration(cxxConstructorDecl(ofClass(
70 cxxRecordDecl(baseOfBoundNode(
"parent"))))))
72 unless(isInTemplateInstantiation())),
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");
std::unique_ptr< ast_matchers::MatchFinder > Finder
AST_MATCHER_P(CXXForRangeStmt, hasRangeBeginEndStmt, ast_matchers::internal::Matcher< DeclStmt >, InnerMatcher)