From: Stephen Kelly Date: Tue, 14 Aug 2018 21:33:28 +0000 (+0000) Subject: Fix Stmt::ignoreImplicit X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=55d0b7e057772228495a26a43ca06a7efb3708cf;p=clang Fix Stmt::ignoreImplicit Summary: A CXXBindTemporaryExpr can appear inside an ImplicitCastExpr, and was not ignored previously. Fixes the case reported in PR37327. Reviewers: rsmith, dblaikie, klimek Subscribers: cfe-commits Differential Revision: https://reviews.llvm.org/D50666 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@339730 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index 5fce6332af..6ed71fd673 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -113,17 +113,23 @@ void Stmt::EnableStatistics() { 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; } diff --git a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp index 443b0588ca..52ab54467e 100644 --- a/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp +++ b/unittests/ASTMatchers/ASTMatchersTraversalTest.cpp @@ -1321,6 +1321,45 @@ TEST(IgnoringImplicit, MatchesImplicit) { 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()))));