From 66c9a415739c7dc685fdd40f855322dea8c69a0f Mon Sep 17 00:00:00 2001 From: Gabor Marton Date: Mon, 3 Sep 2018 13:10:53 +0000 Subject: [PATCH] [ASTImporter] Merge ExprBits Summary: Some `Expr` classes set up default values for the `ExprBits` of `Stmt`. These default values are then overwritten by the parser sometimes. One example is `InitListExpr` which sets the value kind to be an rvalue in the ctor. However, this bit may change after the `InitListExpr` is created. There may be other expressions similar to `InitListExpr` in this sense, thus the safest solution is to copy the expression bits. The lack of copying `ExprBits` causes an assertion in the analyzer engine in a specific case: Since the value kind is not imported, the analyzer engine believes that the given InitListExpr is an rvalue, thus it creates a nonloc::CompoundVal instead of creating memory region (as in case of an lvalue reference). Reviewers: a_sidorin, r.stahl, xazax.hun, a.sidorin Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D51533 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@341316 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/AST/ASTImporter.cpp | 17 +++++++++++++++-- unittests/AST/ASTImporterTest.cpp | 19 +++++++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index d39b985f28..fa8b3c739a 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -6817,9 +6817,9 @@ Expr *ASTNodeImporter::VisitInitListExpr(InitListExpr *ILE) { To->setSyntacticForm(ToSyntForm); } + // Copy InitListExprBitfields, which are not handled in the ctor of + // InitListExpr. To->sawArrayRangeDesignator(ILE->hadArrayRangeDesignator()); - To->setValueDependent(ILE->isValueDependent()); - To->setInstantiationDependent(ILE->isInstantiationDependent()); return To; } @@ -7164,6 +7164,19 @@ Stmt *ASTImporter::Import(Stmt *FromS) { if (!ToS) return nullptr; + if (auto *ToE = dyn_cast(ToS)) { + auto *FromE = cast(FromS); + // Copy ExprBitfields, which may not be handled in Expr subclasses + // constructors. + ToE->setValueKind(FromE->getValueKind()); + ToE->setObjectKind(FromE->getObjectKind()); + ToE->setTypeDependent(FromE->isTypeDependent()); + ToE->setValueDependent(FromE->isValueDependent()); + ToE->setInstantiationDependent(FromE->isInstantiationDependent()); + ToE->setContainsUnexpandedParameterPack( + FromE->containsUnexpandedParameterPack()); + } + // Record the imported declaration. ImportedStmts[FromS] = ToS; return ToS; diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index c36af16df5..96a8d43cdf 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -3225,6 +3225,25 @@ TEST_P(ASTImporterTestBase, ClassTemplateFullAndPartialSpecsShouldNotBeMixed) { unless(classTemplatePartialSpecializationDecl())))); } +TEST_P(ASTImporterTestBase, InitListExprValueKindShouldBeImported) { + Decl *TU = getTuDecl( + R"( + const int &init(); + void foo() { const int &a{init()}; } + )", Lang_CXX11, "input0.cc"); + auto *FromD = FirstDeclMatcher().match(TU, varDecl(hasName("a"))); + ASSERT_TRUE(FromD->getAnyInitializer()); + auto *InitExpr = FromD->getAnyInitializer(); + ASSERT_TRUE(InitExpr); + ASSERT_TRUE(InitExpr->isGLValue()); + + auto *ToD = Import(FromD, Lang_CXX11); + EXPECT_TRUE(ToD); + auto *ToInitExpr = cast(ToD)->getAnyInitializer(); + EXPECT_TRUE(ToInitExpr); + EXPECT_TRUE(ToInitExpr->isGLValue()); +} + struct DeclContextTest : ASTImporterTestBase {}; TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) { -- 2.40.0