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 @@ -388,6 +388,8 @@ ExpectedType VisitObjCObjectPointerType(const ObjCObjectPointerType *T); // Importing declarations + Error ImportDeclParts(NamedDecl *D, DeclarationName &Name, NamedDecl *&ToD, + SourceLocation &Loc); Error ImportDeclParts( NamedDecl *D, DeclContext *&DC, DeclContext *&LexicalDC, DeclarationName &Name, NamedDecl *&ToD, SourceLocation &Loc); @@ -1647,6 +1649,25 @@ return Error::success(); } +Error ASTNodeImporter::ImportDeclParts(NamedDecl *D, DeclarationName &Name, + NamedDecl *&ToD, SourceLocation &Loc) { + + // Import the name of this declaration. + if (Error Err = importInto(Name, D->getDeclName())) + return Err; + + // Import the location of this declaration. + if (Error Err = importInto(Loc, D->getLocation())) + return Err; + + ToD = cast_or_null(Importer.GetAlreadyImportedOrNull(D)); + if (ToD) + if (Error Err = ASTNodeImporter(*this).ImportDefinitionIfNeeded(D, ToD)) + return Err; + + return Error::success(); +} + Error ASTNodeImporter::ImportDefinitionIfNeeded(Decl *FromD, Decl *ToD) { if (!FromD) return Error::success(); @@ -2415,22 +2436,29 @@ ExpectedDecl ASTNodeImporter::VisitTypedefNameDecl(TypedefNameDecl *D, bool IsAlias) { // Import the major distinguishing characteristics of this typedef. - DeclContext *DC, *LexicalDC; DeclarationName Name; SourceLocation Loc; NamedDecl *ToD; - if (Error Err = ImportDeclParts(D, DC, LexicalDC, Name, ToD, Loc)) + // Do not import the DeclContext, we will import it once the TypedefNameDecl + // is created. + if (Error Err = ImportDeclParts(D, Name, ToD, Loc)) return std::move(Err); if (ToD) return ToD; + DeclContext *DC = cast_or_null( + Importer.GetAlreadyImportedOrNull(cast(D->getDeclContext()))); + DeclContext *LexicalDC = + cast_or_null(Importer.GetAlreadyImportedOrNull( + cast(D->getLexicalDeclContext()))); + // If this typedef is not in block scope, determine whether we've // seen a typedef with the same name (that we can merge with) or any // other entity by that name (which name lookup could conflict with). // Note: Repeated typedefs are not valid in C99: // 'typedef int T; typedef int T;' is invalid // We do not care about this now. - if (!DC->isFunctionOrMethod()) { + if (DC && !DC->isFunctionOrMethod()) { SmallVector ConflictingDecls; unsigned IDNS = Decl::IDNS_Ordinary; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); @@ -2487,8 +2515,15 @@ Name.getAsIdentifierInfo(), ToTypeSourceInfo)) return ToTypedef; - ToTypedef->setAccess(D->getAccess()); + // Import the DeclContext and set it to the Typedef. + if ((Err = ImportDeclContext(D, DC, LexicalDC))) + return std::move(Err); + ToTypedef->setDeclContext(DC); ToTypedef->setLexicalDeclContext(LexicalDC); + // Add to the lookupTable because we could not do that in MapImported. + Importer.AddToLookupTable(ToTypedef); + + ToTypedef->setAccess(D->getAccess()); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast(D) : nullptr; @@ -9198,7 +9233,11 @@ // This mapping should be maintained only in this function. Therefore do not // check for additional consistency. ImportedFromDecls[To] = From; - AddToLookupTable(To); + // In the case of TypedefNameDecl we create the Decl first and only then we + // import and set its DeclContext. So, the DC is still not set when we reach + // here from GetImportedOrCreateDecl. + if (To->getDeclContext()) + AddToLookupTable(To); return To; } 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 @@ -5998,6 +5998,22 @@ EXPECT_TRUE(ToD->isExplicit()); } +TEST_P(ImportFunctions, CTADWithLocalTypedef) { + Decl *TU = getTuDecl( + R"( + template struct A { + typedef T U; + A(U); + }; + A a{(int)0}; + )", + Lang_CXX17, "input.cc"); + auto *FromD = FirstDeclMatcher().match( + TU, cxxDeductionGuideDecl()); + auto *ToD = Import(FromD, Lang_CXX17); + ASSERT_TRUE(ToD); +} + // FIXME Move these tests out of ASTImporterTest. For that we need to factor // out the ASTImporter specific pars from ASTImporterOptionSpecificTestBase // into a new test Fixture. Then we should lift up this Fixture to its own