tambre updated this revision to Diff 265855.
tambre marked an inline comment as done.
tambre added a comment.

Improve comment


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/dr22xx.cpp
  clang/test/CXX/drs/dr7xx.cpp
  clang/www/cxx_dr_status.html

Index: clang/www/cxx_dr_status.html
===================================================================
--- clang/www/cxx_dr_status.html
+++ clang/www/cxx_dr_status.html
@@ -4681,7 +4681,7 @@
     <td><a href="https://wg21.link/cwg777";>777</a></td>
     <td>CD2</td>
     <td>Default arguments and parameter packs</td>
-    <td class="full" align="center">Clang 3.7</td>
+    <td class="full" align="center">Superseded by <a href="#2233">2233</a></td>
   </tr>
   <tr id="778">
     <td><a href="https://wg21.link/cwg778";>778</a></td>
@@ -13213,7 +13213,7 @@
     <td><a href="https://wg21.link/cwg2233";>2233</a></td>
     <td>DRWP</td>
     <td>Function parameter packs following default arguments</td>
-    <td class="none" align="center">Unknown</td>
+    <td class="full" align="center">Clang 11</td>
   </tr>
   <tr id="2234">
     <td><a href="https://wg21.link/cwg2234";>2234</a></td>
Index: clang/test/CXX/drs/dr7xx.cpp
===================================================================
--- clang/test/CXX/drs/dr7xx.cpp
+++ clang/test/CXX/drs/dr7xx.cpp
@@ -219,16 +219,4 @@
   Collision<int, int> c; // expected-note {{in instantiation of}}
 }
 
-namespace dr777 { // dr777: 3.7
-#if __cplusplus >= 201103L
-template <typename... T>
-void f(int i = 0, T ...args) {}
-void ff() { f(); }
-
-template <typename... T>
-void g(int i = 0, T ...args, T ...args2) {}
-
-template <typename... T>
-void h(int i = 0, T ...args, int j = 1) {}
-#endif
-}
+// dr777 superseded by dr2233
Index: clang/test/CXX/drs/dr22xx.cpp
===================================================================
--- clang/test/CXX/drs/dr22xx.cpp
+++ clang/test/CXX/drs/dr22xx.cpp
@@ -35,3 +35,44 @@
   }
 #endif
 }
+
+namespace dr2233 { // dr2233: 11
+#if __cplusplus >= 201103L
+template <typename... T>
+void f(int i = 0, T... args) {}
+
+template <typename... T>
+void g(int i = 0, T... args, T... args2) {}
+
+template <typename... T>
+void h(int i = 0, T... args, int j = 1) {}
+
+template <typename... T, typename... U>
+void i(int i = 0, T... args, int j = 1, U... args2) {}
+
+template <class... Ts>
+void j(int i = 0, Ts... ts) {}
+
+template <>
+void j<int>(int i, int j) {}
+
+// PR23029
+// Ensure instantiating the templates works.
+void use() {
+  f();
+  f(0, 1);
+  f<int>(1, 2);
+  g<int>(1, 2, 3);
+  h(0, 1);
+  i();
+  i(3);
+  i<int>(3, 2);
+  i<int>(3, 2, 1);
+  i<int, int>(1, 2, 3, 4, 5);
+  j();
+  j(1);
+  j(1, 2);
+  j<int>(1, 2);
+}
+#endif
+} // namespace dr2233
Index: clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
===================================================================
--- clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -1974,6 +1974,48 @@
                             TemplateArgumentList::CreateCopy(SemaRef.Context,
                                                              Innermost),
                                                 /*InsertPos=*/nullptr);
+
+    // DR777, DR2233.
+    // Parameter packs are allowed after and inbetween parameters with default
+    // values. We need to remove default arguments for parameters before the
+    // first expanded parameter pack to prevent the declaration being diagnosed
+    // as invalid due to the expanded parameters after parameters with default
+    // values lacking default values. This is safe to do because if a parameter
+    // pack is expanded the user must've provided arguments for all parameters
+    // before it.
+    FunctionDecl *TemplatedDecl = FunctionTemplate->getTemplatedDecl();
+    unsigned FirstPack = Function->getNumParams();
+    bool RemoveDefaults = false;
+
+    // Go backwards through the template declaration parameters and find the
+    // first parameter pack, which has non-zero number of arguments.
+    for (unsigned p = TemplatedDecl->getNumParams(); p-- > 0;) {
+      ParmVarDecl *Param = TemplatedDecl->getParamDecl(p);
+
+      if (Param->isParameterPack()) {
+        llvm::Optional<unsigned> Args =
+            SemaRef.getNumArgumentsInExpansion(Param->getType(), TemplateArgs);
+        assert(Args != None && "Unknown number of pack expansion arguments.");
+
+        if (Args.getValue() == 0)
+          continue;
+
+        FirstPack -= Args.getValue();
+        RemoveDefaults = true;
+        break;
+      } else {
+        FirstPack--;
+      }
+    }
+
+    // If we found such a parameter pack, then remove default arguments for all
+    // parameters before it.
+    if (RemoveDefaults) {
+      for (unsigned p = 0; p < FirstPack; 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
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
  • [PATCH] D79800: [... Raul Tambre via Phabricator via cfe-commits

Reply via email to