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
Stmt *Stmt::IgnoreImplicit() {
Stmt *s = this;
- if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
- s = ewc->getSubExpr();
+ Stmt *lasts = nullptr;
- if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
- s = mte->GetTemporaryExpr();
+ while (s != lasts) {
+ lasts = s;
- if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
- s = bte->getSubExpr();
+ if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
+ s = ewc->getSubExpr();
- while (auto *ice = dyn_cast<ImplicitCastExpr>(s))
- s = ice->getSubExpr();
+ if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
+ s = mte->GetTemporaryExpr();
+
+ if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
+ s = bte->getSubExpr();
+
+ if (auto *ice = dyn_cast<ImplicitCastExpr>(s))
+ s = ice->getSubExpr();
+ }
return s;
}
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()))));