diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -1468,6 +1468,22 @@ // FIXME: ASTContext::getInjectedClassNameType is not suitable for AST reading // See comments in InjectedClassNameType definition for details // return Importer.getToContext().getInjectedClassNameType(D, InjType); + + // Take the actions in ASTContext::getInjectedClassNameType here as far as + // possible. Try to reuse a previous type if it exists. + // We want to avoid that multiple InjectedClassNameType objects are created + // for the same Decl object. It is not verified if this works always because + // differences in the import order and chain of PreviousDecl. + + CXXRecordDecl *ToDecl = *ToDeclOrErr; + const Type *TypeForDecl = ToDecl->getTypeForDecl(); + if (!TypeForDecl && ToDecl->getPreviousDecl()) + TypeForDecl = ToDecl->getPreviousDecl()->getTypeForDecl(); + if (TypeForDecl) { + assert(isa(TypeForDecl)); + return QualType(TypeForDecl, 0); + } + enum { TypeAlignmentInBits = 4, TypeAlignment = 1 << TypeAlignmentInBits diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -8075,6 +8075,46 @@ EXPECT_FALSE(SharedStatePtr->isNewDecl(ToBar)); } +TEST_P(ASTImporterOptionSpecificTestBase, ImportInjectedClassNameType) { + Decl *ToTU = getToTuDecl( + R"( + template + struct A { + typedef A A1; + void f(A1 *); + }; + )", + Lang_CXX11); + Decl *FromTU = getTuDecl( + R"( + template + struct A { + typedef A A1; + void f(A1 *); + }; + template + void A::f(A::A1 *) {} + )", + Lang_CXX11); + + auto *FromF = FirstDeclMatcher().match( + FromTU, functionDecl(hasName("f"), isDefinition())); + auto *ToF = Import(FromF, Lang_CXX11); + EXPECT_TRUE(ToF); + ASTContext &ToCtx = ToF->getDeclContext()->getParentASTContext(); + + auto *ToA1 = + FirstDeclMatcher().match(ToTU, typedefDecl(hasName("A1"))); + QualType ToInjTypedef = ToA1->getUnderlyingType().getCanonicalType(); + QualType ToInjParmVar = + ToF->parameters()[0]->getType().getDesugaredType(ToCtx); + ToInjParmVar = + ToInjParmVar->getAs()->getPointeeType().getCanonicalType(); + EXPECT_TRUE(isa(ToInjTypedef)); + EXPECT_TRUE(isa(ToInjParmVar)); + EXPECT_TRUE(ToCtx.hasSameType(ToInjTypedef, ToInjParmVar)); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions);