[clang] [clang][ASTImporter] New fix for default template parameter values. (PR #101836)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 3 09:19:18 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Balázs Kéri (balazske)
<details>
<summary>Changes</summary>
Commit e4440b8 added a change that introduced new crash in an incorrectly handled case. This is fixed here.
---
Full diff: https://github.com/llvm/llvm-project/pull/101836.diff
2 Files Affected:
- (modified) clang/lib/AST/ASTImporter.cpp (+9-3)
- (modified) clang/unittests/AST/ASTImporterTest.cpp (+97)
``````````diff
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);
``````````
</details>
https://github.com/llvm/llvm-project/pull/101836
More information about the cfe-commits
mailing list