[clang] [Sema] Default arguments for template parameters affect ContainsUnexpandedPacks (PR #99880)

Ilya Biryukov via cfe-commits cfe-commits at lists.llvm.org
Tue Jul 23 10:14:40 PDT 2024


https://github.com/ilya-biryukov updated https://github.com/llvm/llvm-project/pull/99880

>From ad2d2f42282d5493761fa0af13b77dc7aab73bba Mon Sep 17 00:00:00 2001
From: Ilya Biryukov <ibiryukov at google.com>
Date: Mon, 22 Jul 2024 15:19:07 +0200
Subject: [PATCH 1/5] [Sema] Default arguments for template parameters affect
 ContainsUnexpandedPacks

This addresses the FIXME in the code. There are tests for the new
behavior in a follow up fix for #99877, which also addresses other bugs
that prevent exposing the wrong results of `ContainsUnexpandedPacks` in
the outputs of the compiler without crashes.
---
 clang/lib/AST/DeclTemplate.cpp | 38 ++++++++++++++++++++++++----------
 1 file changed, 27 insertions(+), 11 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 722c7fcf0b0df..f95be88e6c087 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -61,27 +61,43 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
 
     bool IsPack = P->isTemplateParameterPack();
     if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
-      if (!IsPack && NTTP->getType()->containsUnexpandedParameterPack())
-        ContainsUnexpandedParameterPack = true;
+      if (!IsPack) {
+        if (NTTP->getType()->containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+        else if (NTTP->hasDefaultArgument() &&
+                 NTTP->getDefaultArgument()
+                     .getArgument()
+                     .containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+      }
       if (NTTP->hasPlaceholderTypeConstraint())
         HasConstrainedParameters = true;
     } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) {
-      if (!IsPack &&
-          TTP->getTemplateParameters()->containsUnexpandedParameterPack())
-        ContainsUnexpandedParameterPack = true;
-    } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
-      if (const TypeConstraint *TC = TTP->getTypeConstraint()) {
-        if (TC->getImmediatelyDeclaredConstraint()
-            ->containsUnexpandedParameterPack())
+      if (!IsPack) {
+        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
           ContainsUnexpandedParameterPack = true;
+        else if (TTP->hasDefaultArgument() &&
+                 TTP->getDefaultArgument()
+                     .getArgument()
+                     .containsUnexpandedParameterPack())
+          ContainsUnexpandedParameterPack = true;
+      }
+    } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
+      if (!IsPack && TTP->hasDefaultArgument() &&
+          TTP->getDefaultArgument()
+              .getArgument()
+              .containsUnexpandedParameterPack()) {
+        ContainsUnexpandedParameterPack = true;
+      } else if (const TypeConstraint *TC = TTP->getTypeConstraint();
+                 TC && TC->getImmediatelyDeclaredConstraint()
+                           ->containsUnexpandedParameterPack()) {
+        ContainsUnexpandedParameterPack = true;
       }
       if (TTP->hasTypeConstraint())
         HasConstrainedParameters = true;
     } else {
       llvm_unreachable("unexpected template parameter type");
     }
-    // FIXME: If a default argument contains an unexpanded parameter pack, the
-    // template parameter list does too.
   }
 
   if (HasRequiresClause) {

>From 34a18e0c78c2915df201aea368f6c2763f885fbe Mon Sep 17 00:00:00 2001
From: Ilya Biryukov <ibiryukov at google.com>
Date: Tue, 23 Jul 2024 13:01:10 +0200
Subject: [PATCH 2/5] fixup! [Sema] Default arguments for template parameters
 affect ContainsUnexpandedPacks

Add a helper function to avoid code duplication.
---
 clang/lib/AST/DeclTemplate.cpp | 23 +++++++++++------------
 1 file changed, 11 insertions(+), 12 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index f95be88e6c087..5d207cfbecb97 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -45,6 +45,14 @@ using namespace clang;
 //===----------------------------------------------------------------------===//
 
 
+namespace {
+template<class TemplateParam>
+bool DefaultArgumentContainsUnexpandedPack(const TemplateParam& P) {
+  return P.hasDefaultArgument() &&
+         P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
+}
+}
+
 TemplateParameterList::TemplateParameterList(const ASTContext& C,
                                              SourceLocation TemplateLoc,
                                              SourceLocation LAngleLoc,
@@ -64,10 +72,7 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
       if (!IsPack) {
         if (NTTP->getType()->containsUnexpandedParameterPack())
           ContainsUnexpandedParameterPack = true;
-        else if (NTTP->hasDefaultArgument() &&
-                 NTTP->getDefaultArgument()
-                     .getArgument()
-                     .containsUnexpandedParameterPack())
+        else if (DefaultArgumentContainsUnexpandedPack(*NTTP))
           ContainsUnexpandedParameterPack = true;
       }
       if (NTTP->hasPlaceholderTypeConstraint())
@@ -76,17 +81,11 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
       if (!IsPack) {
         if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
           ContainsUnexpandedParameterPack = true;
-        else if (TTP->hasDefaultArgument() &&
-                 TTP->getDefaultArgument()
-                     .getArgument()
-                     .containsUnexpandedParameterPack())
+        else if (DefaultArgumentContainsUnexpandedPack(*TTP))
           ContainsUnexpandedParameterPack = true;
       }
     } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
-      if (!IsPack && TTP->hasDefaultArgument() &&
-          TTP->getDefaultArgument()
-              .getArgument()
-              .containsUnexpandedParameterPack()) {
+      if (!IsPack && DefaultArgumentContainsUnexpandedPack(*TTP)) {
         ContainsUnexpandedParameterPack = true;
       } else if (const TypeConstraint *TC = TTP->getTypeConstraint();
                  TC && TC->getImmediatelyDeclaredConstraint()

>From d8e2db25421c459e6f2a19baf5e387ab377378ee Mon Sep 17 00:00:00 2001
From: Ilya Biryukov <ibiryukov at google.com>
Date: Tue, 23 Jul 2024 13:07:26 +0200
Subject: [PATCH 3/5] fixup! [Sema] Default arguments for template parameters
 affect ContainsUnexpandedPacks

reformat the code
---
 clang/lib/AST/DeclTemplate.cpp | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 5d207cfbecb97..c1a4181d9b6e2 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -44,14 +44,13 @@ using namespace clang;
 // TemplateParameterList Implementation
 //===----------------------------------------------------------------------===//
 
-
 namespace {
-template<class TemplateParam>
-bool DefaultArgumentContainsUnexpandedPack(const TemplateParam& P) {
+template <class TemplateParam>
+bool DefaultArgumentContainsUnexpandedPack(const TemplateParam &P) {
   return P.hasDefaultArgument() &&
          P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
 }
-}
+} // namespace
 
 TemplateParameterList::TemplateParameterList(const ASTContext& C,
                                              SourceLocation TemplateLoc,

>From ae4021d31bf71622765221ac68b7ff1a316fe670 Mon Sep 17 00:00:00 2001
From: Ilya Biryukov <ibiryukov at google.com>
Date: Tue, 23 Jul 2024 15:51:04 +0200
Subject: [PATCH 4/5] fixup! [Sema] Default arguments for template parameters
 affect ContainsUnexpandedPacks

Simplify the code and reduce nesting
---
 clang/lib/AST/DeclTemplate.cpp | 18 +++++++-----------
 1 file changed, 7 insertions(+), 11 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index c1a4181d9b6e2..5a47b4e646355 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -68,20 +68,16 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
 
     bool IsPack = P->isTemplateParameterPack();
     if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
-      if (!IsPack) {
-        if (NTTP->getType()->containsUnexpandedParameterPack())
-          ContainsUnexpandedParameterPack = true;
-        else if (DefaultArgumentContainsUnexpandedPack(*NTTP))
-          ContainsUnexpandedParameterPack = true;
-      }
+      if (!IsPack && (NTTP->getType()->containsUnexpandedParameterPack() ||
+                      DefaultArgumentContainsUnexpandedPack(*NTTP)))
+        ContainsUnexpandedParameterPack = true;
       if (NTTP->hasPlaceholderTypeConstraint())
         HasConstrainedParameters = true;
     } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) {
-      if (!IsPack) {
-        if (TTP->getTemplateParameters()->containsUnexpandedParameterPack())
-          ContainsUnexpandedParameterPack = true;
-        else if (DefaultArgumentContainsUnexpandedPack(*TTP))
-          ContainsUnexpandedParameterPack = true;
+      if (!IsPack &&
+          (TTP->getTemplateParameters()->containsUnexpandedParameterPack() ||
+           DefaultArgumentContainsUnexpandedPack(*TTP))) {
+        ContainsUnexpandedParameterPack = true;
       }
     } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
       if (!IsPack && DefaultArgumentContainsUnexpandedPack(*TTP)) {

>From d64b95c8df6d0a287fb1924d1ced090d33d76ce3 Mon Sep 17 00:00:00 2001
From: Ilya Biryukov <ibiryukov at google.com>
Date: Tue, 23 Jul 2024 19:11:46 +0200
Subject: [PATCH 5/5] fixup! [Sema] Default arguments for template parameters
 affect ContainsUnexpandedPacks

- Rename function
- Use static instead of anonymous namespace
---
 clang/lib/AST/DeclTemplate.cpp | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index 5a47b4e646355..976b3a3e1eced 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -44,13 +44,12 @@ using namespace clang;
 // TemplateParameterList Implementation
 //===----------------------------------------------------------------------===//
 
-namespace {
 template <class TemplateParam>
-bool DefaultArgumentContainsUnexpandedPack(const TemplateParam &P) {
+static bool
+DefaultTemplateArgumentContainsUnexpandedPack(const TemplateParam &P) {
   return P.hasDefaultArgument() &&
          P.getDefaultArgument().getArgument().containsUnexpandedParameterPack();
 }
-} // namespace
 
 TemplateParameterList::TemplateParameterList(const ASTContext& C,
                                              SourceLocation TemplateLoc,
@@ -69,18 +68,18 @@ TemplateParameterList::TemplateParameterList(const ASTContext& C,
     bool IsPack = P->isTemplateParameterPack();
     if (const auto *NTTP = dyn_cast<NonTypeTemplateParmDecl>(P)) {
       if (!IsPack && (NTTP->getType()->containsUnexpandedParameterPack() ||
-                      DefaultArgumentContainsUnexpandedPack(*NTTP)))
+                      DefaultTemplateArgumentContainsUnexpandedPack(*NTTP)))
         ContainsUnexpandedParameterPack = true;
       if (NTTP->hasPlaceholderTypeConstraint())
         HasConstrainedParameters = true;
     } else if (const auto *TTP = dyn_cast<TemplateTemplateParmDecl>(P)) {
       if (!IsPack &&
           (TTP->getTemplateParameters()->containsUnexpandedParameterPack() ||
-           DefaultArgumentContainsUnexpandedPack(*TTP))) {
+           DefaultTemplateArgumentContainsUnexpandedPack(*TTP))) {
         ContainsUnexpandedParameterPack = true;
       }
     } else if (const auto *TTP = dyn_cast<TemplateTypeParmDecl>(P)) {
-      if (!IsPack && DefaultArgumentContainsUnexpandedPack(*TTP)) {
+      if (!IsPack && DefaultTemplateArgumentContainsUnexpandedPack(*TTP)) {
         ContainsUnexpandedParameterPack = true;
       } else if (const TypeConstraint *TC = TTP->getTypeConstraint();
                  TC && TC->getImmediatelyDeclaredConstraint()



More information about the cfe-commits mailing list