Author: martong
Date: Tue Nov 27 01:51:36 2018
New Revision: 347648

URL: http://llvm.org/viewvc/llvm-project?rev=347648&view=rev
Log:
[ASTImporter] Typedef import brings in the complete type

Summary:
When we already have an incomplete underlying type of a typedef in the
"To" context, and the "From" context has the same typedef, but the
underlying type is complete, then the imported type should be complete.

Fixes an assertion in CTU analysis of Xerces:
Assertion `DD && "queried property of class with no definition"' failed.
This assert is happening in the analyzer engine, because that attempts
to query an underlying type of a typedef, which happens to be
incomplete.

Reviewers: a_sidorin, a.sidorin

Subscribers: rnkovacs, dkrupp, Szelethus, cfe-commits

Differential Revision: https://reviews.llvm.org/D53693

Modified:
    cfe/trunk/lib/AST/ASTImporter.cpp
    cfe/trunk/unittests/AST/ASTImporterTest.cpp

Modified: cfe/trunk/lib/AST/ASTImporter.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=347648&r1=347647&r2=347648&view=diff
==============================================================================
--- cfe/trunk/lib/AST/ASTImporter.cpp (original)
+++ cfe/trunk/lib/AST/ASTImporter.cpp Tue Nov 27 01:51:36 2018
@@ -2311,9 +2311,16 @@ ASTNodeImporter::VisitTypedefNameDecl(Ty
       if (!FoundDecl->isInIdentifierNamespace(IDNS))
         continue;
       if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) {
-        if (Importer.IsStructurallyEquivalent(
-                D->getUnderlyingType(), FoundTypedef->getUnderlyingType()))
+        QualType FromUT = D->getUnderlyingType();
+        QualType FoundUT = FoundTypedef->getUnderlyingType();
+        if (Importer.IsStructurallyEquivalent(FromUT, FoundUT)) {
+          // If the "From" context has a complete underlying type but we
+          // already have a complete underlying type then return with that.
+          if (!FromUT->isIncompleteType() && !FoundUT->isIncompleteType())
             return Importer.MapImported(D, FoundTypedef);
+        }
+        // FIXME Handle redecl chain.
+        break;
       }
 
       ConflictingDecls.push_back(FoundDecl);

Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=347648&r1=347647&r2=347648&view=diff
==============================================================================
--- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original)
+++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Tue Nov 27 01:51:36 2018
@@ -3764,6 +3764,38 @@ TEST_P(ASTImporterTestBase,
   }
 }
 
+TEST_P(ASTImporterTestBase, ImportingTypedefShouldImportTheCompleteType) {
+  // We already have an incomplete underlying type in the "To" context.
+  auto Code =
+      R"(
+      template <typename T>
+      struct S {
+        void foo();
+      };
+      using U = S<int>;
+      )";
+  Decl *ToTU = getToTuDecl(Code, Lang_CXX11);
+  auto *ToD = FirstDeclMatcher<TypedefNameDecl>().match(ToTU,
+      typedefNameDecl(hasName("U")));
+  ASSERT_TRUE(ToD->getUnderlyingType()->isIncompleteType());
+
+  // The "From" context has the same typedef, but the underlying type is
+  // complete this time.
+  Decl *FromTU = getTuDecl(std::string(Code) +
+      R"(
+      void foo(U* u) {
+        u->foo();
+      }
+      )", Lang_CXX11);
+  auto *FromD = FirstDeclMatcher<TypedefNameDecl>().match(FromTU,
+      typedefNameDecl(hasName("U")));
+  ASSERT_FALSE(FromD->getUnderlyingType()->isIncompleteType());
+
+  // The imported type should be complete.
+  auto *ImportedD = cast<TypedefNameDecl>(Import(FromD, Lang_CXX11));
+  EXPECT_FALSE(ImportedD->getUnderlyingType()->isIncompleteType());
+}
+
 INSTANTIATE_TEST_CASE_P(ParameterizedTests, DeclContextTest,
                         ::testing::Values(ArgVector()), );
 


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to