Author: martong Date: Thu Mar 7 05:01:51 2019 New Revision: 355593 URL: http://llvm.org/viewvc/llvm-project?rev=355593&view=rev Log: [ASTImporter] Handle redecl chain of FunctionTemplateDecls
Summary: Redecl chains of function templates are not handled well currently. We want to handle them similarly to functions, i.e. try to keep the structure of the original AST as much as possible. The aim is to not squash a prototype with a definition, rather we create both and put them in a redecl chain. Reviewers: a_sidorin, shafik, a.sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D58494 Modified: cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=355593&r1=355592&r2=355593&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Mar 7 05:01:51 2019 @@ -4943,15 +4943,15 @@ ASTNodeImporter::VisitTemplateTemplatePa return ToD; } -// Returns the definition for a (forward) declaration of a ClassTemplateDecl, if +// Returns the definition for a (forward) declaration of a TemplateDecl, if // it has any definition in the redecl chain. -static ClassTemplateDecl *getDefinition(ClassTemplateDecl *D) { - CXXRecordDecl *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); +template <typename T> static auto getTemplateDefinition(T *D) -> T * { + assert(D->getTemplatedDecl() && "Should be called on templates only"); + auto *ToTemplatedDef = D->getTemplatedDecl()->getDefinition(); if (!ToTemplatedDef) return nullptr; - ClassTemplateDecl *TemplateWithDef = - ToTemplatedDef->getDescribedClassTemplate(); - return TemplateWithDef; + auto *TemplateWithDef = ToTemplatedDef->getDescribedTemplate(); + return cast_or_null<T>(TemplateWithDef); } ExpectedDecl ASTNodeImporter::VisitClassTemplateDecl(ClassTemplateDecl *D) { @@ -4983,7 +4983,8 @@ ExpectedDecl ASTNodeImporter::VisitClass if (FoundTemplate) { if (IsStructuralMatch(D, FoundTemplate)) { - ClassTemplateDecl *TemplateWithDef = getDefinition(FoundTemplate); + ClassTemplateDecl *TemplateWithDef = + getTemplateDefinition(FoundTemplate); if (D->isThisDeclarationADefinition() && TemplateWithDef) { return Importer.MapImported(D, TemplateWithDef); } @@ -5046,6 +5047,8 @@ ExpectedDecl ASTNodeImporter::VisitClass // and this time the lookup finds the previous fwd friend class template. // In this case we must set up the previous decl for the templated decl. if (!ToTemplated->getPreviousDecl()) { + assert(FoundByLookup->getTemplatedDecl() && + "Found decl must have its templated decl set"); CXXRecordDecl *PrevTemplated = FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); if (ToTemplated != PrevTemplated) @@ -5508,8 +5511,11 @@ ASTNodeImporter::VisitFunctionTemplateDe if (ToD) return ToD; + const FunctionTemplateDecl *FoundByLookup = nullptr; + // Try to find a function in our own ("to") context with the same name, same // type, and in the same context as the function we're importing. + // FIXME Split this into a separate function. if (!LexicalDC->isFunctionOrMethod()) { unsigned IDNS = Decl::IDNS_Ordinary | Decl::IDNS_OrdinaryFriend; auto FoundDecls = Importer.findDeclsInToCtx(DC, Name); @@ -5517,18 +5523,21 @@ ASTNodeImporter::VisitFunctionTemplateDe if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; - if (auto *FoundFunction = - dyn_cast<FunctionTemplateDecl>(FoundDecl)) { - if (FoundFunction->hasExternalFormalLinkage() && + if (auto *FoundTemplate = dyn_cast<FunctionTemplateDecl>(FoundDecl)) { + if (FoundTemplate->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { - if (IsStructuralMatch(D, FoundFunction)) { - Importer.MapImported(D, FoundFunction); - // FIXME: Actually try to merge the body and other attributes. - return FoundFunction; + if (IsStructuralMatch(D, FoundTemplate)) { + FunctionTemplateDecl *TemplateWithDef = + getTemplateDefinition(FoundTemplate); + if (D->isThisDeclarationADefinition() && TemplateWithDef) { + return Importer.MapImported(D, TemplateWithDef); + } + FoundByLookup = FoundTemplate; + break; } + // TODO: handle conflicting names } } - // TODO: handle conflicting names } } @@ -5547,10 +5556,25 @@ ASTNodeImporter::VisitFunctionTemplateDe return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); + ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - LexicalDC->addDeclInternal(ToFunc); + + if (FoundByLookup) { + auto *Recent = + const_cast<FunctionTemplateDecl *>(FoundByLookup->getMostRecentDecl()); + if (!TemplatedFD->getPreviousDecl()) { + assert(FoundByLookup->getTemplatedDecl() && + "Found decl must have its templated decl set"); + auto *PrevTemplated = + FoundByLookup->getTemplatedDecl()->getMostRecentDecl(); + if (TemplatedFD != PrevTemplated) + TemplatedFD->setPreviousDecl(PrevTemplated); + } + ToFunc->setPreviousDecl(Recent); + } + return ToFunc; } Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=355593&r1=355592&r2=355593&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Thu Mar 7 05:01:51 2019 @@ -4197,9 +4197,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Variable, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) -// FIXME Enable this test, once we import function templates chains correctly. ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( - RedeclChain, FunctionTemplate, DISABLED_, + RedeclChain, FunctionTemplate, , PrototypeShouldBeImportedAsAPrototypeWhenThereIsNoDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, ClassTemplate, , @@ -4214,9 +4213,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Class, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, Variable, , DefinitionShouldBeImportedAsADefinition) -// FIXME Enable this test, once we import function templates chains correctly. ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( - RedeclChain, FunctionTemplate, DISABLED_, + RedeclChain, FunctionTemplate, , DefinitionShouldBeImportedAsADefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( RedeclChain, ClassTemplate, , DefinitionShouldBeImportedAsADefinition) @@ -4230,9 +4228,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedPrototype) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeAfterImportedPrototype) @@ -4245,9 +4241,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionAfterImportedPrototype) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportDefinitionAfterImportedPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitionAfterImportedPrototype) @@ -4260,9 +4254,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeAfterImportedDefinition) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeAfterImportedDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeAfterImportedDefinition) @@ -4274,9 +4266,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Class, , ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypes) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, ImportPrototypes) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , + ImportPrototypes) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypes) // FIXME This does not pass, possible error with Spec import. @@ -4289,9 +4280,8 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitions) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, ImportDefinitions) +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , + ImportDefinitions) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitions) // FIXME This does not pass, possible error with Spec import. @@ -4304,9 +4294,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportDefinitionThenPrototype) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportDefinitionThenPrototype) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportDefinitionThenPrototype) @@ -4321,9 +4309,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeThenDefinition) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeThenDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, ClassTemplate, , ImportPrototypeThenDefinition) @@ -4336,9 +4322,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( WholeRedeclChainIsImportedAtOnce) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , WholeRedeclChainIsImportedAtOnce) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , WholeRedeclChainIsImportedAtOnce) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, , WholeRedeclChainIsImportedAtOnce) @@ -4347,9 +4331,7 @@ ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE( ImportPrototypeThenProtoAndDefinition) ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, Variable, , ImportPrototypeThenProtoAndDefinition) -// FIXME Enable this test, once we import function templates chains correctly. -ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, - DISABLED_, +ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplate, , ImportPrototypeThenProtoAndDefinition) // FIXME This does not pass, possible error with Spec import. ASTIMPORTER_INSTANTIATE_TYPED_TEST_CASE(RedeclChain, FunctionTemplateSpec, @@ -5442,9 +5424,7 @@ TEST_P(ImportFriendFunctionTemplates, Lo FromTU, functionTemplateDecl(hasName("foo"))); auto *Imported = Import(FromFoo, Lang_CXX); - // FIXME Currently chains of FunctionTemplateDecls are not implemented. - //EXPECT_EQ(Imported->getPreviousDecl(), Friend); - EXPECT_EQ(Imported, Friend); + EXPECT_EQ(Imported->getPreviousDecl(), Friend); } INSTANTIATE_TEST_CASE_P(ParameterizedTests, ASTImporterLookupTableTest, _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits