]> granicus.if.org Git - clang/commitdiff
[ASTImporter] Merge ExprBits
authorGabor Marton <martongabesz@gmail.com>
Mon, 3 Sep 2018 13:10:53 +0000 (13:10 +0000)
committerGabor Marton <martongabesz@gmail.com>
Mon, 3 Sep 2018 13:10:53 +0000 (13:10 +0000)
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
unittests/AST/ASTImporterTest.cpp

index d39b985f28bb4a6865390633d8300b82e4e4ea2f..fa8b3c739a2d02ea9a83d7a64de2c3681c81524d 100644 (file)
@@ -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<Expr>(ToS)) {
+    auto *FromE = cast<Expr>(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;
index c36af16df558ba807f0be4388cf2265d83d0f7bf..96a8d43cdf1ce64c3dafb1be9d4fdbddd669cfd6 100644 (file)
@@ -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<VarDecl>().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<VarDecl>(ToD)->getAnyInitializer();
+  EXPECT_TRUE(ToInitExpr);
+  EXPECT_TRUE(ToInitExpr->isGLValue());
+}
+
 struct DeclContextTest : ASTImporterTestBase {};
 
 TEST_P(DeclContextTest, removeDeclOfClassTemplateSpecialization) {