https://github.com/balazske created https://github.com/llvm/llvm-project/pull/101836
Commit e4440b8 added a change that introduced new crash in an incorrectly handled case. This is fixed here. From 2e98fc222566c5e746ade4ccaba23de3b59e0a5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bal=C3=A1zs=20K=C3=A9ri?= <balazs.k...@ericsson.com> Date: Sat, 3 Aug 2024 18:10:34 +0200 Subject: [PATCH] [clang][ASTImporter] New fix for default template parameter values. Commit e4440b8 added a change that introduced new crash in an incorrectly handled case. This is fixed here. --- clang/lib/AST/ASTImporter.cpp | 12 ++- clang/unittests/AST/ASTImporterTest.cpp | 97 +++++++++++++++++++++++++ 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index 103235547f482..7e4a92ccbe40f 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -5972,7 +5972,11 @@ ASTNodeImporter::VisitTemplateTypeParmDecl(TemplateTypeParmDecl *D) { import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(ToD->getASTContext(), *ToDefaultArgOrErr); + // The import process can trigger import of the parent template which can + // set the default argument value (to "inherited"). + // In this case do nothing here. + if (!ToD->hasDefaultArgument()) + ToD->setDefaultArgument(ToD->getASTContext(), *ToDefaultArgOrErr); } return ToD; @@ -6004,7 +6008,8 @@ ASTNodeImporter::VisitNonTypeTemplateParmDecl(NonTypeTemplateParmDecl *D) { import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); + if (!ToD->hasDefaultArgument()) + ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } return ToD; @@ -6041,7 +6046,8 @@ ASTNodeImporter::VisitTemplateTemplateParmDecl(TemplateTemplateParmDecl *D) { import(D->getDefaultArgument()); if (!ToDefaultArgOrErr) return ToDefaultArgOrErr.takeError(); - ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); + if (!ToD->hasDefaultArgument()) + ToD->setDefaultArgument(Importer.getToContext(), *ToDefaultArgOrErr); } return ToD; diff --git a/clang/unittests/AST/ASTImporterTest.cpp b/clang/unittests/AST/ASTImporterTest.cpp index 57242ff49fe3b..4c41171deec46 100644 --- a/clang/unittests/AST/ASTImporterTest.cpp +++ b/clang/unittests/AST/ASTImporterTest.cpp @@ -9919,6 +9919,103 @@ TEST_P(ImportTemplateParmDeclDefaultValue, ImportExistingVarTemplate) { testImport(FromLastD); } +TEST_P(ImportTemplateParmDeclDefaultValue, + ImportParentTemplateDuringNonTypeTemplateParmDecl) { + // This wants to provoke that during import of 'Y' in "typename T = Y" + // (before this import returns) the later definition of 'X' is imported fully. + const char *Code = + R"( + struct Z; + + struct Y { + Z *z; + static const int x = 1; + }; + + template <int P = Y::x> + struct X; + + template <int P> + struct X { + static const int A = 1; + }; + + struct Z { + template<int P> + void f(int A = X<P>::A); + }; + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX14); + auto *FromD = FirstDeclMatcher<NonTypeTemplateParmDecl>().match( + FromTU, nonTypeTemplateParmDecl(hasName("P"))); + auto *ToD = Import(FromD, Lang_CXX14); + EXPECT_TRUE(ToD); +} + +TEST_P(ImportTemplateParmDeclDefaultValue, + ImportParentTemplateDuringTemplateTypeParmDecl) { + const char *Code = + R"( + struct Z; + + struct Y { + Z *z; + }; + + template <typename T = Y> + struct X; + + template <typename T> + struct X { + static const int A = 1; + }; + + struct Z { + template<typename T> + void f(int A = X<T>::A); + }; + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX14); + auto *FromD = FirstDeclMatcher<TemplateTypeParmDecl>().match( + FromTU, templateTypeParmDecl(hasName("T"))); + auto *ToD = Import(FromD, Lang_CXX14); + EXPECT_TRUE(ToD); +} + +TEST_P(ImportTemplateParmDeclDefaultValue, + ImportParentTemplateDuringTemplateTemplateParmDecl) { + const char *Code = + R"( + struct Z; + + template <int> + struct Y { + Z *z; + }; + + template <template <int> class T = Y> + struct X; + + template <template <int> class T> + struct X { + static const int A = 1; + }; + + struct Z { + template <template <int> class T> + void f(int A = X<T>::A); + }; + )"; + + Decl *FromTU = getTuDecl(Code, Lang_CXX14); + auto *FromD = FirstDeclMatcher<TemplateTemplateParmDecl>().match( + FromTU, templateTemplateParmDecl(hasName("T"))); + auto *ToD = Import(FromD, Lang_CXX14); + EXPECT_TRUE(ToD); +} + 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