[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 04:02:16 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/2] [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/2] 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()



More information about the cfe-commits mailing list