[PATCH] D79800: [Sema] Remove default values for arguments prior to a parameter pack if the pack is used

Raul Tambre via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Wed May 13 10:17:19 PDT 2020


tambre updated this revision to Diff 263759.
tambre added a comment.

Simplify code, improve comments.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D79800/new/

https://reviews.llvm.org/D79800

Files:
  clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
  clang/test/CXX/drs/dr7xx.cpp


Index: clang/test/CXX/drs/dr7xx.cpp
===================================================================
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -230,5 +230,12 @@
 
 template <typename... T>
 void h(int i = 0, T ...args, int j = 1) {}
+
+// PR23029
+// Ensure passing parameters using the parameter packs actually works.
+void use() {
+  f(0, 1);
+  h(0, 1);
+}
 #endif
 }
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1974,6 +1974,47 @@
                             TemplateArgumentList::CreateCopy(SemaRef.Context,
                                                              Innermost),
                                                 /*InsertPos=*/nullptr);
+
+    // Parameter packs are allowed after parameters with default values.
+    // If the specialized Function has more parameters than the TemplatedDecl
+    // then the default values aren't used and the parameter pack is used and we
+    // need to remove default values from non-pack parameters to prevent it
+    // being diagnosed as invalid code due to the expanded parameters lacking
+    // default values.
+    FunctionDecl *TemplatedDecl = FunctionTemplate->getTemplatedDecl();
+    unsigned NumTemplatedParams = TemplatedDecl->getNumParams();
+
+    if (Function->getNumParams() >= NumTemplatedParams) {
+      unsigned FirstDefault = 0;
+      bool FoundDefault = false;
+
+      for (unsigned p = 0; p < NumTemplatedParams; ++p) {
+        ParmVarDecl *Param = TemplatedDecl->getParamDecl(p);
+
+        if (FoundDefault) {
+          if (Param->isParameterPack()) {
+            // Found a parameter pack. Remove default arguments for all
+            // parameters prior to this since we now know this is valid code
+            // without them.
+            for (unsigned d = FirstDefault; d < p; ++d) {
+              ParmVarDecl *Param = Function->getParamDecl(d);
+              Param->setDefaultArg(nullptr);
+            }
+
+            break;
+          }
+
+          // If we encounter a regular parameter with no default value after
+          // we've encountered any with a default, then this is invalid code and
+          // we bail out. This is diagnosed later in CheckCXXDefaultArguments().
+          if (!Param->hasDefaultArg())
+            break;
+        } else if (Param->hasDefaultArg()) {
+          FirstDefault = p;
+          FoundDefault = true;
+        }
+      }
+    }
   } else if (isFriend && D->isThisDeclarationADefinition()) {
     // Do not connect the friend to the template unless it's actually a
     // definition. We don't want non-template functions to be marked as being


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D79800.263759.patch
Type: text/x-patch
Size: 2808 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200513/7608b498/attachment.bin>


More information about the cfe-commits mailing list