Message ID | 20211021084240.GE304296@tucnak |
---|---|
State | New |
Headers | show |
Series | c++: Implement DR2351 - void{} [PR102820] | expand |
On 10/21/21 04:42, Jakub Jelinek wrote: > Hi! > > Here is an attempt to implement DR2351 - void{} - where void{} after > pack expansion is considered valid and the same thing as void(). > For templates, dunno if we have some better way to check if a CONSTRUCTOR > might be empty after pack expansion. Would that only if the constructor > only contains EXPR_PACK_EXPANSION elements and nothing else, or something > else too? I think that's the only case. For template args there's the pack_expansion_args_count function, but I don't think there's anything similar for constructor elts; please feel free to add it. > With the patch as is we wouldn't diagnose > template <class ...T> > void > bar (T... t) > { > void{1, t...}; > } > at parsing time, only at instantiation time, even when it will always > expand to at least one CONSTRUCTOR elt. > > Bootstrapped/regtested on x86_64-linux and i686-linux. > > 2021-10-21 Jakub Jelinek <jakub@redhat.com> > > PR c++/102820 > * semantics.c (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 is instantiation > dependent, handle it like other dependent compound literals. > > * g++.dg/cpp0x/dr2351.C: New test. > > --- gcc/cp/semantics.c.jj 2021-10-15 11:58:45.079131947 +0200 > +++ gcc/cp/semantics.c 2021-10-20 17:00:38.586705600 +0200 > @@ -3104,9 +3104,20 @@ finish_compound_literal (tree type, tree > > 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 > + && instantiation_dependent_expression_p (compound_literal)) > + /* If there are 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)) > --- gcc/testsuite/g++.dg/cpp0x/dr2351.C.jj 2021-10-20 17:06:02.399162937 +0200 > +++ gcc/testsuite/g++.dg/cpp0x/dr2351.C 2021-10-20 17:05:54.294276511 +0200 > @@ -0,0 +1,36 @@ > +// 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); > +} > > Jakub >
--- gcc/cp/semantics.c.jj 2021-10-15 11:58:45.079131947 +0200 +++ gcc/cp/semantics.c 2021-10-20 17:00:38.586705600 +0200 @@ -3104,9 +3104,20 @@ finish_compound_literal (tree type, tree 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 + && instantiation_dependent_expression_p (compound_literal)) + /* If there are 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)) --- gcc/testsuite/g++.dg/cpp0x/dr2351.C.jj 2021-10-20 17:06:02.399162937 +0200 +++ gcc/testsuite/g++.dg/cpp0x/dr2351.C 2021-10-20 17:05:54.294276511 +0200 @@ -0,0 +1,36 @@ +// 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); +}