Index: cfe/trunk/lib/AST/Stmt.cpp =================================================================== --- cfe/trunk/lib/AST/Stmt.cpp +++ cfe/trunk/lib/AST/Stmt.cpp @@ -113,17 +113,23 @@ Stmt *Stmt::IgnoreImplicit() { Stmt *s = this; - if (auto *ewc = dyn_cast(s)) - s = ewc->getSubExpr(); + Stmt *lasts = nullptr; - if (auto *mte = dyn_cast(s)) - s = mte->GetTemporaryExpr(); + while (s != lasts) { + lasts = s; - if (auto *bte = dyn_cast(s)) - s = bte->getSubExpr(); + if (auto *ewc = dyn_cast(s)) + s = ewc->getSubExpr(); - while (auto *ice = dyn_cast(s)) - s = ice->getSubExpr(); + if (auto *mte = dyn_cast(s)) + s = mte->GetTemporaryExpr(); + + if (auto *bte = dyn_cast(s)) + s = bte->getSubExpr(); + + if (auto *ice = dyn_cast(s)) + s = ice->getSubExpr(); + } return s; } Index: cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp =================================================================== --- cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ cfe/trunk/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1321,6 +1321,45 @@ varDecl(has(ignoringImplicit(cxxConstructExpr()))))); } +TEST(IgnoringImplicit, MatchesNestedImplicit) { + EXPECT_TRUE(matches(R"( + +struct OtherType; + +struct SomeType +{ + SomeType() {} + SomeType(const OtherType&) {} + SomeType& operator=(OtherType const&) { return *this; } +}; + +struct OtherType +{ + OtherType() {} + ~OtherType() {} +}; + +OtherType something() +{ + return {}; +} + +int main() +{ + SomeType i = something(); +} +)" + , varDecl( + hasName("i"), + hasInitializer(exprWithCleanups(has( + cxxConstructExpr(has(expr(ignoringImplicit(cxxConstructExpr( + has(expr(ignoringImplicit(callExpr()))) + ))))) + ))) + ) + )); +} + TEST(IgnoringImplicit, DoesNotMatchIncorrectly) { EXPECT_TRUE( notMatches("class C {}; C a = C();", varDecl(has(cxxConstructExpr()))));