balazske created this revision. Herald added subscribers: whisperity, martong, teemperor, gamesh411, Szelethus, dkrupp. Herald added a reviewer: a.sidorin. Herald added a reviewer: shafik. balazske requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Template parameters are created in ASTImporter with the translation unit as DeclContext. The DeclContext is later updated (by the create function of template classes). ASTImporterLookupTable was not updated after these changes of the DC. The patch adds update of the DeclContext in ASTImporterLookupTable. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D103792 Files: clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp
Index: clang/unittests/AST/ASTImporterTest.cpp =================================================================== --- clang/unittests/AST/ASTImporterTest.cpp +++ clang/unittests/AST/ASTImporterTest.cpp @@ -4368,6 +4368,178 @@ EXPECT_EQ(ToD->getNumTemplateParameterLists(), 1u); } +const internal::VariadicDynCastAllOfMatcher<Decl, VarTemplateDecl> + varTemplateDecl; + +const internal::VariadicDynCastAllOfMatcher< + Decl, VarTemplatePartialSpecializationDecl> + varTemplatePartialSpecializationDecl; + +TEST_P(ASTImporterOptionSpecificTestBase, + FunctionTemplateParameterDeclContext) { + constexpr auto Code = + R"( + template<class T> + void f() {}; + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + + auto *FromD = FirstDeclMatcher<FunctionTemplateDecl>().match( + FromTU, functionTemplateDecl(hasName("f"))); + + ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD->getTemplatedDecl()); + + auto *ToD = Import(FromD, Lang_CXX11); + EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD->getTemplatedDecl()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0))); +} + +TEST_P(ASTImporterOptionSpecificTestBase, ClassTemplateParameterDeclContext) { + constexpr auto Code = + R"( + template<class T1, class T2> + struct S {}; + template<class T2> + struct S<int, T2> {}; + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + + auto *FromD = FirstDeclMatcher<ClassTemplateDecl>().match( + FromTU, classTemplateDecl(hasName("S"))); + auto *FromDPart = + FirstDeclMatcher<ClassTemplatePartialSpecializationDecl>().match( + FromTU, classTemplatePartialSpecializationDecl(hasName("S"))); + + ASSERT_EQ(FromD->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD->getTemplatedDecl()); + ASSERT_EQ(FromDPart->getTemplateParameters()->getParam(0)->getDeclContext(), + FromDPart); + + auto *ToD = Import(FromD, Lang_CXX11); + auto *ToDPart = Import(FromDPart, Lang_CXX11); + + EXPECT_EQ(ToD->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD->getTemplatedDecl()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD->getTemplatedDecl(), ToD->getTemplateParameters()->getParam(0))); + + EXPECT_EQ(ToDPart->getTemplateParameters()->getParam(0)->getDeclContext(), + ToDPart); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToDPart, ToDPart->getTemplateParameters()->getParam(0))); +} + +TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) { + constexpr auto Code = + R"( + template<class T1, class T2> + int X1; + template<class T2> + int X1<int, T2>; + + namespace Ns { + template<class T1, class T2> + int X2; + template<class T2> + int X2<int, T2>; + } + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX14); + + auto *FromD1 = FirstDeclMatcher<VarTemplateDecl>().match( + FromTU, varTemplateDecl(hasName("X1"))); + auto *FromD1Part = + FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match( + FromTU, varTemplatePartialSpecializationDecl(hasName("X1"))); + auto *FromD2 = FirstDeclMatcher<VarTemplateDecl>().match( + FromTU, varTemplateDecl(hasName("X2"))); + auto *FromD2Part = + FirstDeclMatcher<VarTemplatePartialSpecializationDecl>().match( + FromTU, varTemplatePartialSpecializationDecl(hasName("X2"))); + + ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD1->getDeclContext()); + ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD2->getDeclContext()); + + ASSERT_EQ(FromD1Part->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD1Part->getDeclContext()); + // FIXME: VarTemplatePartialSpecializationDecl does not update ("adopt") + // template parameter decl context + // ASSERT_EQ(FromD2Part->getTemplateParameters()->getParam(0)->getDeclContext(), + // FromD2Part->getDeclContext()); + + auto *ToD1 = Import(FromD1, Lang_CXX14); + auto *ToD2 = Import(FromD2, Lang_CXX14); + + auto *ToD1Part = Import(FromD1Part, Lang_CXX14); + auto *ToD2Part = Import(FromD2Part, Lang_CXX14); + + EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD1->getDeclContext()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0))); + EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD2->getDeclContext()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0))); + + EXPECT_EQ(ToD1Part->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD1Part->getDeclContext()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD1Part->getDeclContext(), + ToD1Part->getTemplateParameters()->getParam(0))); + // EXPECT_EQ(ToD2Part->getTemplateParameters()->getParam(0)->getDeclContext(), + // ToD2Part->getDeclContext()); + // EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + // ToD2Part->getDeclContext(), + // ToD2Part->getTemplateParameters()->getParam(0))); + (void)ToD2Part; +} + +TEST_P(ASTImporterOptionSpecificTestBase, + TypeAliasTemplateParameterDeclContext) { + constexpr auto Code = + R"( + template<class T1, class T2> + struct S {}; + template<class T> using S1 = S<T, int>; + namespace Ns { + template<class T> using S2 = S<T, int>; + } + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX11); + + auto *FromD1 = FirstDeclMatcher<TypeAliasTemplateDecl>().match( + FromTU, typeAliasTemplateDecl(hasName("S1"))); + auto *FromD2 = FirstDeclMatcher<TypeAliasTemplateDecl>().match( + FromTU, typeAliasTemplateDecl(hasName("S2"))); + + ASSERT_EQ(FromD1->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD1->getDeclContext()); + ASSERT_EQ(FromD2->getTemplateParameters()->getParam(0)->getDeclContext(), + FromD2->getDeclContext()); + + auto *ToD1 = Import(FromD1, Lang_CXX11); + auto *ToD2 = Import(FromD2, Lang_CXX11); + + EXPECT_EQ(ToD1->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD1->getDeclContext()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD1->getDeclContext(), ToD1->getTemplateParameters()->getParam(0))); + EXPECT_EQ(ToD2->getTemplateParameters()->getParam(0)->getDeclContext(), + ToD2->getDeclContext()); + EXPECT_TRUE(SharedStatePtr->getLookupTable()->contains( + ToD2->getDeclContext(), ToD2->getTemplateParameters()->getParam(0))); +} + struct ASTImporterLookupTableTest : ASTImporterOptionSpecificTestBase {}; TEST_P(ASTImporterLookupTableTest, OneDecl) { Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -322,6 +322,21 @@ } } + void updateLookupTableForTemplateParameters(TemplateParameterList &Params, + DeclContext *OldDC) { + ASTImporterLookupTable *LT = Importer.SharedState->getLookupTable(); + if (!LT) + return; + + for (NamedDecl *TP : Params) + LT->update(TP, OldDC); + } + + void updateLookupTableForTemplateParameters(TemplateParameterList &Params) { + updateLookupTableForTemplateParameters( + Params, Importer.getToContext().getTranslationUnitDecl()); + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} @@ -2607,6 +2622,8 @@ ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToAlias); + if (DC != Importer.getToContext().getTranslationUnitDecl()) + updateLookupTableForTemplateParameters(*ToTemplateParameters); return ToAlias; } @@ -5467,6 +5484,7 @@ D2->setLexicalDeclContext(LexicalDC); addDeclToContexts(D, D2); + updateLookupTableForTemplateParameters(**TemplateParamsOrErr); if (FoundByLookup) { auto *Recent = @@ -5610,6 +5628,7 @@ // Add this partial specialization to the class template. ClassTemplate->AddPartialSpecialization(PartSpec2, InsertPos); + updateLookupTableForTemplateParameters(*ToTPList); } else { // Not a partial specialization. if (GetImportedOrCreateDecl( D2, D, Importer.getToContext(), D->getTagKind(), DC, @@ -5759,6 +5778,8 @@ ToVarTD->setAccess(D->getAccess()); ToVarTD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToVarTD); + if (DC != Importer.getToContext().getTranslationUnitDecl()) + updateLookupTableForTemplateParameters(**TemplateParamsOrErr); if (FoundByLookup) { auto *Recent = @@ -5884,6 +5905,9 @@ D2 = ToPartial; + // FIXME: Use this update if VarTemplatePartialSpecializationDecl is fixed + // to adopt template parameters. + // updateLookupTableForTemplateParameters(**ToTPListOrErr); } else { // Full specialization if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, *BeginLocOrErr, *IdLocOrErr, VarTemplate, @@ -5972,14 +5996,26 @@ auto ParamsOrErr = import(D->getTemplateParameters()); if (!ParamsOrErr) return ParamsOrErr.takeError(); + TemplateParameterList *Params = *ParamsOrErr; FunctionDecl *TemplatedFD; if (Error Err = importInto(TemplatedFD, D->getTemplatedDecl())) return std::move(Err); + // Template parameters for a CXXDeductionGuideDecl are re-used by the + // non-deduction-guide-decl template. That template is imported too, and + // DeclContext of the template parameters is changed by both imports. So we + // do not know what the old DC is here without saving it. + // FIXME: The DeclContext of the parameters is now set finally to the function + // or DeductionGuideDecl that was imported later. This may not be the same + // that is in the original AST. + DeclContext *OldParamDC = nullptr; + if (Params->size() > 0) + OldParamDC = Params->getParam(0)->getDeclContext(); + FunctionTemplateDecl *ToFunc; if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, - *ParamsOrErr, TemplatedFD)) + Params, TemplatedFD)) return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); @@ -5987,6 +6023,7 @@ ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToFunc); + updateLookupTableForTemplateParameters(*Params, OldParamDC); if (FoundByLookup) { auto *Recent =
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits