]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Implement DR2351 - void{} [PR102820]
authorJakub Jelinek <jakub@redhat.com>
Fri, 29 Oct 2021 07:28:32 +0000 (09:28 +0200)
committerJakub Jelinek <jakub@redhat.com>
Fri, 29 Oct 2021 07:28:32 +0000 (09:28 +0200)
Here is an implementation of DR2351 - void{} - where void{} after
pack expansion is considered valid and the same thing as void().
For templates, if CONSTRUCTOR_NELTS is 0, the CONSTRUCTOR is not dependent
and we can return void_node right away, if it is dependent and contains
only packs, then it is potentially zero element and so we need to build
CONSTRUCTOR_IS_DEPENDENT CONSTRUCTOR, while if it contains any non-pack
elts, we can diagnose it right away.

2021-10-29  Jakub Jelinek  <jakub@redhat.com>

PR c++/102820
* semantics.c (maybe_zero_constructor_nelts): New function.
(finish_compound_literal): Implement DR2351 - void{}.
If type is cv void and compound_literal has no elements, return
void_node.  If type is cv void and compound_literal might have no
elements after expansion, handle it like other dependent compound
literals.

* g++.dg/cpp0x/dr2351.C: New test.

gcc/cp/semantics.c
gcc/testsuite/g++.dg/cpp0x/dr2351.C [new file with mode: 0644]

index 3072ecdd29a5a195de0507b75724747079502f59..2443d0327498bf2fba11d80b51a4762a945dfe4e 100644 (file)
@@ -3079,6 +3079,22 @@ finish_unary_op_expr (location_t op_loc, enum tree_code code, cp_expr expr,
   return result;
 }
 
+/* Return true if CONSTRUCTOR EXPR after pack expansion could have no
+   elements.  */
+
+static bool
+maybe_zero_constructor_nelts (tree expr)
+{
+  if (CONSTRUCTOR_NELTS (expr) == 0)
+    return true;
+  if (!processing_template_decl)
+    return false;
+  for (constructor_elt &elt : CONSTRUCTOR_ELTS (expr))
+    if (!PACK_EXPANSION_P (elt.value))
+      return false;
+  return true;
+}
+
 /* Finish a compound-literal expression or C++11 functional cast with aggregate
    initializer.  TYPE is the type to which the CONSTRUCTOR in COMPOUND_LITERAL
    is being cast.  */
@@ -3104,9 +3120,20 @@ finish_compound_literal (tree type, tree compound_literal,
 
   if (!TYPE_OBJ_P (type))
     {
-      if (complain & tf_error)
-       error ("compound literal of non-object type %qT", type);
-      return error_mark_node;
+      /* DR2351 */
+      if (VOID_TYPE_P (type) && CONSTRUCTOR_NELTS (compound_literal) == 0)
+       return void_node;
+      else if (VOID_TYPE_P (type)
+              && processing_template_decl
+              && maybe_zero_constructor_nelts (compound_literal))
+       /* If there are only packs in compound_literal, it could
+          be void{} after pack expansion.  */;
+      else
+       {
+         if (complain & tf_error)
+           error ("compound literal of non-object type %qT", type);
+         return error_mark_node;
+       }
     }
 
   if (template_placeholder_p (type))
diff --git a/gcc/testsuite/g++.dg/cpp0x/dr2351.C b/gcc/testsuite/g++.dg/cpp0x/dr2351.C
new file mode 100644 (file)
index 0000000..5116dfe
--- /dev/null
@@ -0,0 +1,51 @@
+// DR2351
+// { dg-do compile { target c++11 } }
+
+void
+foo ()
+{
+  void{};
+  void();
+}
+
+template <class ...T>
+void
+bar (T... t)
+{
+  void{t...};
+  void(t...);
+}
+
+void
+baz ()
+{
+  bar ();
+}
+
+template <class ...T>
+void
+qux (T... t)
+{
+  void{t...};  // { dg-error "compound literal of non-object type" }
+}
+
+void
+corge ()
+{
+  qux (1, 2);
+}
+
+template <class ...T>
+void
+garply (T... t)
+{
+  void{t..., t..., t...};
+  void(t..., t..., t...);
+}
+
+template <class ...T>
+void
+grault (T... t)
+{
+  void{t..., 1};       // { dg-error "compound literal of non-object type" }
+}