* [PATCH] c++: Implement DR2351 - void{} [PR102820] @ 2021-10-21 8:42 Jakub Jelinek 2021-10-27 20:58 ` Jason Merrill 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2021-10-21 8:42 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches 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? 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 ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Implement DR2351 - void{} [PR102820] 2021-10-21 8:42 [PATCH] c++: Implement DR2351 - void{} [PR102820] Jakub Jelinek @ 2021-10-27 20:58 ` Jason Merrill 2021-10-28 11:26 ` [PATCH] c++, v2: " Jakub Jelinek 0 siblings, 1 reply; 6+ messages in thread From: Jason Merrill @ 2021-10-27 20:58 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches 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 > ^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH] c++, v2: Implement DR2351 - void{} [PR102820] 2021-10-27 20:58 ` Jason Merrill @ 2021-10-28 11:26 ` Jakub Jelinek 2021-10-28 12:01 ` Jason Merrill 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2021-10-28 11:26 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On Wed, Oct 27, 2021 at 04:58:53PM -0400, Jason Merrill wrote: > 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. Ok. But counting how many packs its CONSTRUCTOR_ELTS have and then comparing that number against CONSTRUCTOR_NELTS seems to be unnecessarily expensive if there are many elements, for the purpose the DR2351 code needs we can stop as soon as we see first non-pack element. So what about this if it passes bootstrap/regtest? 2021-10-28 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.jj 2021-10-27 09:16:41.161600606 +0200 +++ gcc/cp/semantics.c 2021-10-28 13:06:59.325791588 +0200 @@ -3079,6 +3079,24 @@ finish_unary_op_expr (location_t op_loc, 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; + unsigned int i; + tree val; + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val) + if (!PACK_EXPANSION_P (val)) + 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 +3122,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 + && 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)) --- gcc/testsuite/g++.dg/cpp0x/dr2351.C.jj 2021-10-28 12:59:27.987120315 +0200 +++ gcc/testsuite/g++.dg/cpp0x/dr2351.C 2021-10-28 13:15:20.532760871 +0200 @@ -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" } +} Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++, v2: Implement DR2351 - void{} [PR102820] 2021-10-28 11:26 ` [PATCH] c++, v2: " Jakub Jelinek @ 2021-10-28 12:01 ` Jason Merrill 2021-10-28 12:19 ` Jakub Jelinek 0 siblings, 1 reply; 6+ messages in thread From: Jason Merrill @ 2021-10-28 12:01 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On 10/28/21 07:26, Jakub Jelinek wrote: > On Wed, Oct 27, 2021 at 04:58:53PM -0400, Jason Merrill wrote: >> 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. > > Ok. But counting how many packs its CONSTRUCTOR_ELTS have and then comparing > that number against CONSTRUCTOR_NELTS seems to be unnecessarily expensive if > there are many elements, for the purpose the DR2351 code needs we can stop > as soon as we see first non-pack element. > > So what about this if it passes bootstrap/regtest? > > 2021-10-28 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.jj 2021-10-27 09:16:41.161600606 +0200 > +++ gcc/cp/semantics.c 2021-10-28 13:06:59.325791588 +0200 > @@ -3079,6 +3079,24 @@ finish_unary_op_expr (location_t op_loc, > 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; > + unsigned int i; > + tree val; > + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val) Let's use for (constructor_elt &elt : CONSTRUCTOR_ELTS (t)) > + if (!PACK_EXPANSION_P (val)) > + 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 +3122,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; This test now seems redundant with the one below (if you remove the && processing_template_decl). OK with those tweaks. > + 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)) > --- gcc/testsuite/g++.dg/cpp0x/dr2351.C.jj 2021-10-28 12:59:27.987120315 +0200 > +++ gcc/testsuite/g++.dg/cpp0x/dr2351.C 2021-10-28 13:15:20.532760871 +0200 > @@ -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" } > +} > > > Jakub > ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++, v2: Implement DR2351 - void{} [PR102820] 2021-10-28 12:01 ` Jason Merrill @ 2021-10-28 12:19 ` Jakub Jelinek 2021-10-28 14:56 ` Jason Merrill 0 siblings, 1 reply; 6+ messages in thread From: Jakub Jelinek @ 2021-10-28 12:19 UTC (permalink / raw) To: Jason Merrill; +Cc: gcc-patches On Thu, Oct 28, 2021 at 08:01:27AM -0400, Jason Merrill wrote: > > --- gcc/cp/semantics.c.jj 2021-10-27 09:16:41.161600606 +0200 > > +++ gcc/cp/semantics.c 2021-10-28 13:06:59.325791588 +0200 > > @@ -3079,6 +3079,24 @@ finish_unary_op_expr (location_t op_loc, > > 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; > > + unsigned int i; > > + tree val; > > + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val) > > Let's use > > for (constructor_elt &elt : CONSTRUCTOR_ELTS (t)) Ok, will do. > > @@ -3104,9 +3122,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; > > This test now seems redundant with the one below (if you remove the && > processing_template_decl). It is not redundant, for the maybe case it doesn't return void_node, but falls through into if (processing_template_decl), which, because compound_literal is necessarily instantiation_dependent_expression_p (it contains packs) will just create CONSTRUCTOR_IS_DEPENDENT CONSTRUCTOR and we'll get here back during instantiation. For the CONSTRUCTOR_NELTS == 0 case even in templates we know compound_literal isn't dependent (it doesn't contain anything) and type isn't either, so we can return void_node right away (and when !processing_template_decl we have to do that). Jakub ^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++, v2: Implement DR2351 - void{} [PR102820] 2021-10-28 12:19 ` Jakub Jelinek @ 2021-10-28 14:56 ` Jason Merrill 0 siblings, 0 replies; 6+ messages in thread From: Jason Merrill @ 2021-10-28 14:56 UTC (permalink / raw) To: Jakub Jelinek; +Cc: gcc-patches On 10/28/21 08:19, Jakub Jelinek wrote: > On Thu, Oct 28, 2021 at 08:01:27AM -0400, Jason Merrill wrote: >>> --- gcc/cp/semantics.c.jj 2021-10-27 09:16:41.161600606 +0200 >>> +++ gcc/cp/semantics.c 2021-10-28 13:06:59.325791588 +0200 >>> @@ -3079,6 +3079,24 @@ finish_unary_op_expr (location_t op_loc, >>> 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; >>> + unsigned int i; >>> + tree val; >>> + FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), i, val) >> >> Let's use >> >> for (constructor_elt &elt : CONSTRUCTOR_ELTS (t)) > > Ok, will do. > >>> @@ -3104,9 +3122,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; >> >> This test now seems redundant with the one below (if you remove the && >> processing_template_decl). > > It is not redundant, for the maybe case it doesn't return void_node, but > falls through into if (processing_template_decl), which, because > compound_literal is necessarily instantiation_dependent_expression_p > (it contains packs) will just create CONSTRUCTOR_IS_DEPENDENT CONSTRUCTOR > and we'll get here back during instantiation. > For the CONSTRUCTOR_NELTS == 0 case even in templates we know > compound_literal isn't dependent (it doesn't contain anything) and type > isn't either, so we can return void_node right away (and when > !processing_template_decl we have to do that). Ah, right. Never mind that comment, then. Jason ^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-10-28 14:56 UTC | newest] Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2021-10-21 8:42 [PATCH] c++: Implement DR2351 - void{} [PR102820] Jakub Jelinek 2021-10-27 20:58 ` Jason Merrill 2021-10-28 11:26 ` [PATCH] c++, v2: " Jakub Jelinek 2021-10-28 12:01 ` Jason Merrill 2021-10-28 12:19 ` Jakub Jelinek 2021-10-28 14:56 ` Jason Merrill
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).