diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 337c14a0038ce..320c302f7492c 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1365,12 +1365,16 @@ ExpectedType ASTNodeImporter::VisitTypedefType(const TypedefType *T) { Expected ToDeclOrErr = import(T->getDecl()); if (!ToDeclOrErr) return ToDeclOrErr.takeError(); + + TypedefNameDecl *ToDecl = *ToDeclOrErr; + if (ToDecl->getTypeForDecl()) + return QualType(ToDecl->getTypeForDecl(), 0); + ExpectedType ToUnderlyingTypeOrErr = import(T->desugar()); if (!ToUnderlyingTypeOrErr) return ToUnderlyingTypeOrErr.takeError(); - return Importer.getToContext().getTypedefType(*ToDeclOrErr, - *ToUnderlyingTypeOrErr); + return Importer.getToContext().getTypedefType(ToDecl, *ToUnderlyingTypeOrErr); } ExpectedType ASTNodeImporter::VisitTypeOfExprType(const TypeOfExprType *T) { diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index ebdb81b98734a..b90a18d539668 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -8576,6 +8576,69 @@ TEST_P(ASTImporterOptionSpecificTestBase, ImportTwoTypedefsToUnnamedRecord) { Typedef2->getUnderlyingType().getTypePtr()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ImportExistingTypedefToUnnamedRecordPtr) { + const char *Code = + R"( + typedef const struct { int fff; } * const T; + extern T x; + )"; + Decl *ToTU = getToTuDecl(Code, Lang_C99); + Decl *FromTU = getTuDecl(Code, Lang_C99); + + auto *FromX = + FirstDeclMatcher().match(FromTU, varDecl(hasName("x"))); + auto *ToX = Import(FromX, Lang_C99); + EXPECT_TRUE(ToX); + + auto *Typedef1 = + FirstDeclMatcher().match(ToTU, typedefDecl(hasName("T"))); + auto *Typedef2 = + LastDeclMatcher().match(ToTU, typedefDecl(hasName("T"))); + // FIXME: These should be imported separately, like in the test above. + // Or: In the test above these should be merged too. + EXPECT_EQ(Typedef1, Typedef2); + + auto *FromR = FirstDeclMatcher().match( + FromTU, recordDecl(hasDescendant(fieldDecl(hasName("fff"))))); + auto *ToRExisting = FirstDeclMatcher().match( + ToTU, recordDecl(hasDescendant(fieldDecl(hasName("fff"))))); + ASSERT_TRUE(FromR); + auto *ToRImported = Import(FromR, Lang_C99); + // FIXME: If typedefs are not imported separately, do not import ToRImported + // separately. + EXPECT_NE(ToRExisting, ToRImported); +} + +TEST_P(ASTImporterOptionSpecificTestBase, + ImportTypedefWithDifferentUnderlyingType) { + const char *Code = + R"( + using X1 = int; + using Y1 = int; + + using RPB1 = X1*; + typedef RPB1 RPX1; + using RPB1 = Y1*; // redeclared + typedef RPB1 RPY1; + + auto X = 0 ? (RPX1){} : (RPY1){}; + )"; + Decl *ToTU = getToTuDecl("", Lang_CXX11); + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + + auto *FromX = + FirstDeclMatcher().match(FromTU, varDecl(hasName("X"))); + + auto *FromXType = FromX->getType()->getAs(); + EXPECT_FALSE(FromXType->typeMatchesDecl()); + + auto *ToX = Import(FromX, Lang_CXX11); + auto *ToXType = ToX->getType()->getAs(); + // FIXME: This should be false. + EXPECT_TRUE(ToXType->typeMatchesDecl()); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions);