From: Balazs Keri <1.int32@gmail.com> Date: Wed, 7 Aug 2019 12:40:17 +0000 (+0000) Subject: [ASTImporter] Do not import FunctionTemplateDecl in record twice. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=4dedb042153e0f654914ff1d9bf618ed016bf7b8;p=clang [ASTImporter] Do not import FunctionTemplateDecl in record twice. Summary: For functions there is a check to not duplicate the declaration if it is in a record (class). For function templates there was no similar check, if a template (in the same class) was imported multiple times the FunctionTemplateDecl was created multiple times with the same templated FunctionDecl. This can result in problems with the declaration chain. Reviewers: martong, a.sidorin, shafik, a_sidorin Reviewed By: a_sidorin Subscribers: rnkovacs, dkrupp, Szelethus, gamesh411, cfe-commits Tags: #clang Differential Revision: https://reviews.llvm.org/D65203 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@368163 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index d7789a99a5..8ecbad3c68 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -3118,9 +3118,19 @@ ExpectedDecl ASTNodeImporter::VisitFunctionDecl(FunctionDecl *D) { if (FoundByLookup) { if (isa(FoundByLookup)) { if (D->getLexicalDeclContext() == D->getDeclContext()) { - if (!D->doesThisDeclarationHaveABody()) + if (!D->doesThisDeclarationHaveABody()) { + if (FunctionTemplateDecl *DescribedD = + D->getDescribedFunctionTemplate()) { + // Handle a "templated" function together with its described + // template. This avoids need for a similar check at import of the + // described template. + assert(FoundByLookup->getDescribedFunctionTemplate() && + "Templated function mapped to non-templated?"); + Importer.MapImported(DescribedD, + FoundByLookup->getDescribedFunctionTemplate()); + } return Importer.MapImported(D, FoundByLookup); - else { + } else { // Let's continue and build up the redecl chain in this case. // FIXME Merge the functions into one decl. } diff --git a/unittests/AST/ASTImporterTest.cpp b/unittests/AST/ASTImporterTest.cpp index 07beccefbc..151b279b9b 100644 --- a/unittests/AST/ASTImporterTest.cpp +++ b/unittests/AST/ASTImporterTest.cpp @@ -2389,6 +2389,49 @@ TEST_P(ImportFunctions, functionDecl(hasName("f"), hasDescendant(declRefExpr())))))); } +struct ImportFunctionTemplates : ASTImporterOptionSpecificTestBase {}; + +TEST_P(ImportFunctionTemplates, ImportFunctionTemplateInRecordDeclTwice) { + auto Code = + R"( + class X { + template + void f(T t); + }; + )"; + Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD1 = FirstDeclMatcher().match( + FromTU1, functionTemplateDecl(hasName("f"))); + auto *ToD1 = Import(FromD1, Lang_CXX); + Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc"); + auto *FromD2 = FirstDeclMatcher().match( + FromTU2, functionTemplateDecl(hasName("f"))); + auto *ToD2 = Import(FromD2, Lang_CXX); + EXPECT_EQ(ToD1, ToD2); +} + +TEST_P(ImportFunctionTemplates, + ImportFunctionTemplateWithDefInRecordDeclTwice) { + auto Code = + R"( + class X { + template + void f(T t); + }; + template + void X::f(T t) {}; + )"; + Decl *FromTU1 = getTuDecl(Code, Lang_CXX, "input1.cc"); + auto *FromD1 = FirstDeclMatcher().match( + FromTU1, functionTemplateDecl(hasName("f"))); + auto *ToD1 = Import(FromD1, Lang_CXX); + Decl *FromTU2 = getTuDecl(Code, Lang_CXX, "input2.cc"); + auto *FromD2 = FirstDeclMatcher().match( + FromTU2, functionTemplateDecl(hasName("f"))); + auto *ToD2 = Import(FromD2, Lang_CXX); + EXPECT_EQ(ToD1, ToD2); +} + struct ImportFriendFunctions : ImportFunctions {}; TEST_P(ImportFriendFunctions, ImportFriendFunctionRedeclChainProto) { @@ -5223,6 +5266,9 @@ INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctionTemplates, INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportClasses, DefaultTestValuesForRunOptions, ); +INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFunctionTemplates, + DefaultTestValuesForRunOptions, ); + INSTANTIATE_TEST_CASE_P(ParameterizedTests, ImportFriendFunctions, DefaultTestValuesForRunOptions, );