Author: Balázs Kéri Date: 2023-10-16T10:31:01+02:00 New Revision: 5857fec27fe8ee5a48a2ee48a4d79a9e39b0332b
URL: https://github.com/llvm/llvm-project/commit/5857fec27fe8ee5a48a2ee48a4d79a9e39b0332b DIFF: https://github.com/llvm/llvm-project/commit/5857fec27fe8ee5a48a2ee48a4d79a9e39b0332b.diff LOG: [clang][ASTImporter] Fix of possible crash "Did not find base!". (#67680) A problem with AST import could lead to multiple instances of the same template class specialization, with different template arguments. The difference was caused by pointers to different declarations of the same function. Problem is fixed by using the canonical declaration at import. Co-authored-by: Balázs Kéri <balazs.k...@ericsson.com> 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 3adbabdb7fb878a..628a2b2bbca3986 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -811,7 +811,8 @@ ASTNodeImporter::import(const TemplateArgument &From) { ExpectedType ToTypeOrErr = import(From.getParamTypeForDecl()); if (!ToTypeOrErr) return ToTypeOrErr.takeError(); - return TemplateArgument(*ToOrErr, *ToTypeOrErr, From.getIsDefaulted()); + return TemplateArgument(dyn_cast<ValueDecl>((*ToOrErr)->getCanonicalDecl()), + *ToTypeOrErr, From.getIsDefaulted()); } case TemplateArgument::NullPtr: { diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 1dc314eafc4eff4..f1f09a0be2b8d0c 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9175,6 +9175,64 @@ TEST_P(ASTImporterOptionSpecificTestBase, EXPECT_TRUE(ToXType->typeMatchesDecl()); } +TEST_P(ASTImporterOptionSpecificTestBase, + ImportTemplateArgumentWithPointerToDifferentInstantiation) { + const char *CodeTo = + R"( + template<class A> + A f1() { + return A(); + } + template<class A, A (B)()> + class X {}; + + X<int, f1<int>> x; + )"; + const char *CodeFrom = + R"( + template<class A> + A f1(); + template<class A, A (B)()> + class X {}; + + X<int, f1<int>> x; + )"; + Decl *ToTU = getToTuDecl(CodeTo, Lang_CXX11); + Decl *FromTU = getTuDecl(CodeFrom, Lang_CXX11); + + auto *ToF1 = FirstDeclMatcher<FunctionDecl>().match( + ToTU, functionDecl(hasName("f1"), isInstantiated())); + auto *FromF1 = FirstDeclMatcher<FunctionDecl>().match( + FromTU, functionDecl(hasName("f1"), isInstantiated())); + EXPECT_TRUE(ToF1->isThisDeclarationADefinition()); + EXPECT_FALSE(FromF1->isThisDeclarationADefinition()); + + auto *ToX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( + ToTU, classTemplateSpecializationDecl(hasName("X"))); + auto *FromX = FirstDeclMatcher<ClassTemplateSpecializationDecl>().match( + FromTU, classTemplateSpecializationDecl(hasName("X"))); + + Decl *ToTArgF = ToX->getTemplateArgs().get(1).getAsDecl(); + Decl *FromTArgF = FromX->getTemplateArgs().get(1).getAsDecl(); + EXPECT_EQ(ToTArgF, ToF1); + EXPECT_EQ(FromTArgF, FromF1); + + auto *ToXImported = Import(FromX, Lang_CXX11); + // The template argument 1 of 'X' in the "From" code points to a function + // that has no definition. The import must ensure that this template argument + // is imported in a way that it will point to the existing 'f1' function, not + // to the 'f1' that is imported. In this way when specialization of 'X' is + // imported it will have the same template arguments as the existing one. + EXPECT_EQ(ToXImported, ToX); + // FIXME: This matcher causes a crash "Tried to match orphan node". + // The code is removed until the problem is fixed. + // auto *ToF1Imported = + // LastDeclMatcher<FunctionDecl>().match(ToTU, + // functionDecl(hasName("f1"),isInstantiated())); + // EXPECT_NE(ToF1Imported, ToF1); + // EXPECT_EQ(ToF1Imported->getPreviousDecl(), ToF1); +} + INSTANTIATE_TEST_SUITE_P(ParameterizedTests, ASTImporterLookupTableTest, DefaultTestValuesForRunOptions); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits