diff options
-rw-r--r-- | clang/lib/AST/ASTImporter.cpp | 11 | ||||
-rw-r--r-- | clang/unittests/AST/ASTImporterTest.cpp | 32 |
2 files changed, 41 insertions, 2 deletions
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 77a1a7f4990..67feef16f26 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -2311,9 +2311,16 @@ ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { 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); diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 3a0ee5d129c..0450cb41a40 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -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()), ); |