[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
Tue May 12 12:55:02 PDT 2020


tambre created this revision.
tambre added reviewers: rsmith, rjmccall.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

When a parameter pack is expanded the expanded parameters don't have default values.
Thus if a parameter pack is expanded after any arguments with a default value, the function is incorrectly rejected in CheckCXXDefaultArguments().

Fix this by removing default arguments for prior parameters if a parameter pack is expanded.

Fixes PR23029.


Repository:
  rG LLVM Github Monorepo

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,54 @@
                             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 previous parameters to prevent it
+    // being diagnosed as invalid code due to the expanded parameter lacking
+    // default values.
+    FunctionDecl *TemplatedDecl = FunctionTemplate->getTemplatedDecl();
+    unsigned NumTemplatedParams = TemplatedDecl->getNumParams();
+
+    if (Function->getNumParams() >= NumTemplatedParams) {
+      unsigned FirstDefault = 0;
+      unsigned LastDefault = 0;
+      bool FoundDefault = false;
+      bool RemoveDefaults = false;
+
+      // Find the FirstDefault up to LastDefault that need to be removed.
+      // We don't remove if the code's invalid, i.e. a default value missing on
+      // a regular parameter if there's any with a default value before.
+      for (unsigned p = 0; p < NumTemplatedParams; ++p) {
+        ParmVarDecl *Param = TemplatedDecl->getParamDecl(p);
+
+        if (FoundDefault) {
+          if (Param->isParameterPack()) {
+            RemoveDefaults = true;
+            LastDefault = p;
+            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;
+        }
+      }
+
+      // Remove default arguments if this is valid code.
+      if (RemoveDefaults) {
+        for (unsigned p = FirstDefault; p < LastDefault; ++p) {
+          ParmVarDecl *Param = Function->getParamDecl(p);
+          Param->setDefaultArg(nullptr);
+        }
+      }
+    }
   } 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.263496.patch
Type: text/x-patch
Size: 3081 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20200512/3e50c19b/attachment.bin>


More information about the cfe-commits mailing list