Author: Balázs Kéri Date: 2024-01-15T12:38:02+01:00 New Revision: 5e355942cd8e5826394cdeceb140fb6d0a1f9561
URL: https://github.com/llvm/llvm-project/commit/5e355942cd8e5826394cdeceb140fb6d0a1f9561 DIFF: https://github.com/llvm/llvm-project/commit/5e355942cd8e5826394cdeceb140fb6d0a1f9561.diff LOG: [clang][ASTImporter] Fix import of variable template redeclarations. (#72841) In some cases variable templates (specially if static member of record) were not correctly imported and an assertion "Missing call to MapImported?" could happen. Added: Modified: clang/lib/AST/ASTImporter.cpp clang/unittests/AST/ASTImporterTest.cpp Removed: ################################################################################ diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index b762d6a4cd3800..aa23c99b599010 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -6280,17 +6280,21 @@ ExpectedDecl ASTNodeImporter::VisitVarTemplateDecl(VarTemplateDecl *D) { D->getTemplatedDecl())) continue; if (IsStructuralMatch(D, FoundTemplate)) { - // The Decl in the "From" context has a definition, but in the - // "To" context we already have a definition. + // FIXME Check for ODR error if the two definitions have + // diff erent initializers? VarTemplateDecl *FoundDef = getTemplateDefinition(FoundTemplate); - if (D->isThisDeclarationADefinition() && FoundDef) - // FIXME Check for ODR error if the two definitions have - // diff erent initializers? - return Importer.MapImported(D, FoundDef); - if (FoundTemplate->getDeclContext()->isRecord() && - D->getDeclContext()->isRecord()) - return Importer.MapImported(D, FoundTemplate); - + if (D->getDeclContext()->isRecord()) { + assert(FoundTemplate->getDeclContext()->isRecord() && + "Member variable template imported as non-member, " + "inconsistent imported AST?"); + if (FoundDef) + return Importer.MapImported(D, FoundDef); + if (!D->isThisDeclarationADefinition()) + return Importer.MapImported(D, FoundTemplate); + } else { + if (FoundDef && D->isThisDeclarationADefinition()) + return Importer.MapImported(D, FoundDef); + } FoundByLookup = FoundTemplate; break; } diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 37cf14bdff6b33..3d1f4c85c90ad5 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -5219,6 +5219,59 @@ TEST_P(ImportFriendClasses, RecordVarTemplateDecl) { EXPECT_EQ(ToTUX, ToX); } +TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateDeclConflict) { + getToTuDecl( + R"( + template <class U> + constexpr int X = 1; + )", + Lang_CXX14); + + Decl *FromTU = getTuDecl( + R"( + template <class U> + constexpr int X = 2; + )", + Lang_CXX14, "input1.cc"); + auto *FromX = FirstDeclMatcher<VarTemplateDecl>().match( + FromTU, varTemplateDecl(hasName("X"))); + auto *ToX = Import(FromX, Lang_CXX11); + // FIXME: This import should fail. + EXPECT_TRUE(ToX); +} + +TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateStaticDefinition) { + Decl *ToTU = getToTuDecl( + R"( + struct A { + template <class U> + static int X; + }; + )", + Lang_CXX14); + auto *ToX = FirstDeclMatcher<VarTemplateDecl>().match( + ToTU, varTemplateDecl(hasName("X"))); + ASSERT_FALSE(ToX->isThisDeclarationADefinition()); + + Decl *FromTU = getTuDecl( + R"( + struct A { + template <class U> + static int X; + }; + template <class U> + int A::X = 2; + )", + Lang_CXX14, "input1.cc"); + auto *FromXDef = LastDeclMatcher<VarTemplateDecl>().match( + FromTU, varTemplateDecl(hasName("X"))); + ASSERT_TRUE(FromXDef->isThisDeclarationADefinition()); + auto *ToXDef = Import(FromXDef, Lang_CXX14); + EXPECT_TRUE(ToXDef); + EXPECT_TRUE(ToXDef->isThisDeclarationADefinition()); + EXPECT_EQ(ToXDef->getPreviousDecl(), ToX); +} + TEST_P(ASTImporterOptionSpecificTestBase, VarTemplateParameterDeclContext) { constexpr auto Code = R"( _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits