aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2021-10-29 09:28:32 +0200
committerJakub Jelinek <jakub@redhat.com>2021-10-29 09:28:32 +0200
commiteca767aa51d1f69614222ceb130ca6bb07713232 (patch)
tree6fd22f2e45dab8a8542eeeff6ace686b4dd9e035 /gcc
parent146b83e14a0a76a9ce8a4cb79997a078f437f779 (diff)
downloadgcc-eca767aa51d1f69614222ceb130ca6bb07713232.zip
gcc-eca767aa51d1f69614222ceb130ca6bb07713232.tar.gz
gcc-eca767aa51d1f69614222ceb130ca6bb07713232.tar.bz2
c++: Implement DR2351 - void{} [PR102820]
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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/semantics.c33
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/dr2351.C51
2 files changed, 81 insertions, 3 deletions
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 3072ecd..2443d03 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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
index 0000000..5116dfe
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/dr2351.C
@@ -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" }
+}