* [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
@ 2021-12-10 22:29 Marek Polacek
2021-12-13 15:02 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2021-12-10 22:29 UTC (permalink / raw)
To: GCC Patches, Jason Merrill
My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
"If the placeholder-type-specifier is of the form type-constraint[opt]
decltype(auto), T shall be the placeholder alone." But this made us
reject 'constexpr decltype(auto)', which, after clarification from CWG,
should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
constraint, not semantic, so it's OK that the constexpr marks the object
as const.
As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
and we have a FIXME there anyway. So in this patch I'm attempting to
detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
it needs to happen before we mark the object as const due to constexpr,
that is, before grokdeclarator's
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
...
Constrained decltype(auto) was a little problem, hence the TYPENAME
check. But in a typename context you can't use decltype(auto) anyway,
I think.
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
PR c++/102229
gcc/cp/ChangeLog:
* decl.c (check_decltype_auto): New.
(grokdeclarator): Call it.
* pt.c (do_auto_deduction): Don't check decltype(auto) here.
gcc/testsuite/ChangeLog:
* g++.dg/cpp1y/decltype-auto5.C: New test.
---
gcc/cp/decl.c | 58 ++++++++++++++-------
gcc/cp/pt.c | 13 -----
gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C | 35 +++++++++++++
3 files changed, 74 insertions(+), 32 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 56f80775ca0..196eac287eb 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -11354,6 +11354,33 @@ name_unnamed_type (tree type, tree decl)
gcc_assert (!TYPE_UNNAMED_P (type));
}
+/* Check that decltype(auto) was well-formed: only plain decltype(auto)
+ is allowed. TYPE might contain a decltype(auto). Returns true if
+ there was a problem, false otherwise. */
+
+static bool
+check_decltype_auto (location_t loc, tree type)
+{
+ if (tree a = type_uses_auto (type))
+ {
+ if (AUTO_IS_DECLTYPE (a))
+ {
+ if (a != type)
+ {
+ error_at (loc, "%qT as type rather than plain "
+ "%<decltype(auto)%>", type);
+ return true;
+ }
+ else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
+ {
+ error_at (loc, "%<decltype(auto)%> cannot be cv-qualified");
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
/* Given declspecs and a declarator (abstract or otherwise), determine
the name and type of the object declared and construct a DECL node
for it.
@@ -12702,25 +12729,9 @@ grokdeclarator (const cp_declarator *declarator,
"allowed");
return error_mark_node;
}
- /* Only plain decltype(auto) is allowed. */
- if (tree a = type_uses_auto (type))
- {
- if (AUTO_IS_DECLTYPE (a))
- {
- if (a != type)
- {
- error_at (typespec_loc, "%qT as type rather than "
- "plain %<decltype(auto)%>", type);
- return error_mark_node;
- }
- else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
- {
- error_at (typespec_loc, "%<decltype(auto)%> cannot be "
- "cv-qualified");
- return error_mark_node;
- }
- }
- }
+
+ if (check_decltype_auto (typespec_loc, type))
+ return error_mark_node;
if (ctype == NULL_TREE
&& decl_context == FIELD
@@ -13080,6 +13091,15 @@ grokdeclarator (const cp_declarator *declarator,
id_loc = declarator ? declarator->id_loc : input_location;
+ if (innermost_code != cdk_function
+ /* Don't check this if it can be the artifical decltype(auto)
+ we created when building a constraint in a compound-requirement:
+ that the type-constraint is plain is going to be checked in
+ cp_parser_compound_requirement. */
+ && decl_context != TYPENAME
+ && check_decltype_auto (id_loc, type))
+ return error_mark_node;
+
/* A `constexpr' specifier used in an object declaration declares
the object as `const'. */
if (constexpr_p && innermost_code != cdk_function)
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 9834baf34db..6d5da17b9d0 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -29912,19 +29912,6 @@ do_auto_deduction (tree type, tree init, tree auto_node,
return error_mark_node;
targs = make_tree_vec (1);
TREE_VEC_ELT (targs, 0) = deduced;
- /* FIXME: These errors ought to be diagnosed at parse time. */
- if (type != auto_node)
- {
- if (complain & tf_error)
- error ("%qT as type rather than plain %<decltype(auto)%>", type);
- return error_mark_node;
- }
- else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
- {
- if (complain & tf_error)
- error ("%<decltype(auto)%> cannot be cv-qualified");
- return error_mark_node;
- }
}
else
{
diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
new file mode 100644
index 00000000000..01cc54fb71d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
@@ -0,0 +1,35 @@
+// PR c++/102229
+// { dg-do compile { target c++14 } }
+
+struct S {
+ constexpr static decltype(auto) x = 42;
+ const constexpr static decltype(auto) y = 42; // { dg-error "cannot be cv-qualified" }
+
+ constexpr decltype(auto) mfn1 () { return 0; }
+ const constexpr decltype(auto) mfn2 () { return 0; } // { dg-error "cannot be cv-qualified" }
+};
+
+constexpr decltype(auto) i = 42;
+const constexpr decltype(auto) j = 42; // { dg-error "cannot be cv-qualified" }
+
+constexpr decltype(auto) fn() { return 42; }
+const decltype(auto) fn2() { return 42; } // { dg-error "cannot be cv-qualified" }
+
+auto constexpr foo() -> const decltype(auto) // { dg-error "cannot be cv-qualified" }
+{
+ return 0;
+}
+
+#if __cpp_concepts
+template<typename>
+concept C = true;
+
+constexpr C decltype(auto) x1 = 0;
+const constexpr C decltype(auto) x2 = 0; // { dg-error "cannot be cv-qualified" "" { target c++20 } }
+
+constexpr C decltype(auto) fn3() { return 0; }
+const constexpr C decltype(auto) fn4() { return 0; } // { dg-error "cannot be cv-qualified" "" { target c++20 } }
+#endif
+
+template<const decltype(auto) = 42> // { dg-error "cannot be cv-qualified" }
+void g ();
base-commit: 1e2eee7b29ed2afbc7edea6f3da7e6c8f70b1a4e
--
2.33.1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
2021-12-10 22:29 [PATCH] c++: Allow constexpr decltype(auto) [PR102229] Marek Polacek
@ 2021-12-13 15:02 ` Jason Merrill
2021-12-15 20:20 ` Marek Polacek
0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2021-12-13 15:02 UTC (permalink / raw)
To: Marek Polacek, GCC Patches
On 12/10/21 17:29, Marek Polacek wrote:
> My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
> "If the placeholder-type-specifier is of the form type-constraint[opt]
> decltype(auto), T shall be the placeholder alone." But this made us
> reject 'constexpr decltype(auto)', which, after clarification from CWG,
> should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
> constraint, not semantic, so it's OK that the constexpr marks the object
> as const.
>
> As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
> and we have a FIXME there anyway. So in this patch I'm attempting to
> detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
> it needs to happen before we mark the object as const due to constexpr,
> that is, before grokdeclarator's
>
> /* A `constexpr' specifier used in an object declaration declares
> the object as `const'. */
> if (constexpr_p && innermost_code != cdk_function)
> ...
>
> Constrained decltype(auto) was a little problem, hence the TYPENAME
> check. But in a typename context you can't use decltype(auto) anyway,
> I think.
I wonder about checking even earlier, like in cp_parser_decl_specifier_seq?
> Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/11?
>
> PR c++/102229
>
> gcc/cp/ChangeLog:
>
> * decl.c (check_decltype_auto): New.
> (grokdeclarator): Call it.
> * pt.c (do_auto_deduction): Don't check decltype(auto) here.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp1y/decltype-auto5.C: New test.
> ---
> gcc/cp/decl.c | 58 ++++++++++++++-------
> gcc/cp/pt.c | 13 -----
> gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C | 35 +++++++++++++
> 3 files changed, 74 insertions(+), 32 deletions(-)
> create mode 100644 gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
>
> diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
> index 56f80775ca0..196eac287eb 100644
> --- a/gcc/cp/decl.c
> +++ b/gcc/cp/decl.c
> @@ -11354,6 +11354,33 @@ name_unnamed_type (tree type, tree decl)
> gcc_assert (!TYPE_UNNAMED_P (type));
> }
>
> +/* Check that decltype(auto) was well-formed: only plain decltype(auto)
> + is allowed. TYPE might contain a decltype(auto). Returns true if
> + there was a problem, false otherwise. */
> +
> +static bool
> +check_decltype_auto (location_t loc, tree type)
> +{
> + if (tree a = type_uses_auto (type))
> + {
> + if (AUTO_IS_DECLTYPE (a))
> + {
> + if (a != type)
> + {
> + error_at (loc, "%qT as type rather than plain "
> + "%<decltype(auto)%>", type);
> + return true;
> + }
> + else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
> + {
> + error_at (loc, "%<decltype(auto)%> cannot be cv-qualified");
> + return true;
> + }
> + }
> + }
> + return false;
> +}
> +
> /* Given declspecs and a declarator (abstract or otherwise), determine
> the name and type of the object declared and construct a DECL node
> for it.
> @@ -12702,25 +12729,9 @@ grokdeclarator (const cp_declarator *declarator,
> "allowed");
> return error_mark_node;
> }
> - /* Only plain decltype(auto) is allowed. */
> - if (tree a = type_uses_auto (type))
> - {
> - if (AUTO_IS_DECLTYPE (a))
> - {
> - if (a != type)
> - {
> - error_at (typespec_loc, "%qT as type rather than "
> - "plain %<decltype(auto)%>", type);
> - return error_mark_node;
> - }
> - else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
> - {
> - error_at (typespec_loc, "%<decltype(auto)%> cannot be "
> - "cv-qualified");
> - return error_mark_node;
> - }
> - }
> - }
> +
> + if (check_decltype_auto (typespec_loc, type))
> + return error_mark_node;
>
> if (ctype == NULL_TREE
> && decl_context == FIELD
> @@ -13080,6 +13091,15 @@ grokdeclarator (const cp_declarator *declarator,
>
> id_loc = declarator ? declarator->id_loc : input_location;
>
> + if (innermost_code != cdk_function
> + /* Don't check this if it can be the artifical decltype(auto)
> + we created when building a constraint in a compound-requirement:
> + that the type-constraint is plain is going to be checked in
> + cp_parser_compound_requirement. */
> + && decl_context != TYPENAME
> + && check_decltype_auto (id_loc, type))
> + return error_mark_node;
> +
> /* A `constexpr' specifier used in an object declaration declares
> the object as `const'. */
> if (constexpr_p && innermost_code != cdk_function)
> diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
> index 9834baf34db..6d5da17b9d0 100644
> --- a/gcc/cp/pt.c
> +++ b/gcc/cp/pt.c
> @@ -29912,19 +29912,6 @@ do_auto_deduction (tree type, tree init, tree auto_node,
> return error_mark_node;
> targs = make_tree_vec (1);
> TREE_VEC_ELT (targs, 0) = deduced;
> - /* FIXME: These errors ought to be diagnosed at parse time. */
> - if (type != auto_node)
> - {
> - if (complain & tf_error)
> - error ("%qT as type rather than plain %<decltype(auto)%>", type);
> - return error_mark_node;
> - }
> - else if (TYPE_QUALS (type) != TYPE_UNQUALIFIED)
> - {
> - if (complain & tf_error)
> - error ("%<decltype(auto)%> cannot be cv-qualified");
> - return error_mark_node;
> - }
> }
> else
> {
> diff --git a/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C b/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
> new file mode 100644
> index 00000000000..01cc54fb71d
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp1y/decltype-auto5.C
> @@ -0,0 +1,35 @@
> +// PR c++/102229
> +// { dg-do compile { target c++14 } }
> +
> +struct S {
> + constexpr static decltype(auto) x = 42;
> + const constexpr static decltype(auto) y = 42; // { dg-error "cannot be cv-qualified" }
> +
> + constexpr decltype(auto) mfn1 () { return 0; }
> + const constexpr decltype(auto) mfn2 () { return 0; } // { dg-error "cannot be cv-qualified" }
> +};
> +
> +constexpr decltype(auto) i = 42;
> +const constexpr decltype(auto) j = 42; // { dg-error "cannot be cv-qualified" }
> +
> +constexpr decltype(auto) fn() { return 42; }
> +const decltype(auto) fn2() { return 42; } // { dg-error "cannot be cv-qualified" }
> +
> +auto constexpr foo() -> const decltype(auto) // { dg-error "cannot be cv-qualified" }
> +{
> + return 0;
> +}
> +
> +#if __cpp_concepts
> +template<typename>
> +concept C = true;
> +
> +constexpr C decltype(auto) x1 = 0;
> +const constexpr C decltype(auto) x2 = 0; // { dg-error "cannot be cv-qualified" "" { target c++20 } }
> +
> +constexpr C decltype(auto) fn3() { return 0; }
> +const constexpr C decltype(auto) fn4() { return 0; } // { dg-error "cannot be cv-qualified" "" { target c++20 } }
> +#endif
> +
> +template<const decltype(auto) = 42> // { dg-error "cannot be cv-qualified" }
> +void g ();
>
> base-commit: 1e2eee7b29ed2afbc7edea6f3da7e6c8f70b1a4e
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
2021-12-13 15:02 ` Jason Merrill
@ 2021-12-15 20:20 ` Marek Polacek
2021-12-15 21:17 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2021-12-15 20:20 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Mon, Dec 13, 2021 at 10:02:24AM -0500, Jason Merrill wrote:
> On 12/10/21 17:29, Marek Polacek wrote:
> > My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
> > "If the placeholder-type-specifier is of the form type-constraint[opt]
> > decltype(auto), T shall be the placeholder alone." But this made us
> > reject 'constexpr decltype(auto)', which, after clarification from CWG,
> > should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
> > constraint, not semantic, so it's OK that the constexpr marks the object
> > as const.
> >
> > As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
> > and we have a FIXME there anyway. So in this patch I'm attempting to
> > detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
> > it needs to happen before we mark the object as const due to constexpr,
> > that is, before grokdeclarator's
> >
> > /* A `constexpr' specifier used in an object declaration declares
> > the object as `const'. */
> > if (constexpr_p && innermost_code != cdk_function)
> > ...
> >
> > Constrained decltype(auto) was a little problem, hence the TYPENAME
> > check. But in a typename context you can't use decltype(auto) anyway,
> > I think.
>
> I wonder about checking even earlier, like in cp_parser_decl_specifier_seq?
That _almost_ works except it wouldn't detect things like 'decltype(auto)*'
because the '*' isn't parsed in cp_parser_decl_specifier_seq, only in
declarator. So the
if (a != type)
{
error_at (loc, "%qT as type rather than plain "
"%<decltype(auto)%>", type);
check wouldn't work. Maybe I could just check if the next token is * or &
and give an error then.
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
2021-12-15 20:20 ` Marek Polacek
@ 2021-12-15 21:17 ` Jason Merrill
2021-12-15 21:28 ` Marek Polacek
0 siblings, 1 reply; 6+ messages in thread
From: Jason Merrill @ 2021-12-15 21:17 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 12/15/21 15:20, Marek Polacek wrote:
> On Mon, Dec 13, 2021 at 10:02:24AM -0500, Jason Merrill wrote:
>> On 12/10/21 17:29, Marek Polacek wrote:
>>> My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
>>> "If the placeholder-type-specifier is of the form type-constraint[opt]
>>> decltype(auto), T shall be the placeholder alone." But this made us
>>> reject 'constexpr decltype(auto)', which, after clarification from CWG,
>>> should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
>>> constraint, not semantic, so it's OK that the constexpr marks the object
>>> as const.
>>>
>>> As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
>>> and we have a FIXME there anyway. So in this patch I'm attempting to
>>> detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
>>> it needs to happen before we mark the object as const due to constexpr,
>>> that is, before grokdeclarator's
>>>
>>> /* A `constexpr' specifier used in an object declaration declares
>>> the object as `const'. */
>>> if (constexpr_p && innermost_code != cdk_function)
>>> ...
>>>
>>> Constrained decltype(auto) was a little problem, hence the TYPENAME
>>> check. But in a typename context you can't use decltype(auto) anyway,
>>> I think.
>>
>> I wonder about checking even earlier, like in cp_parser_decl_specifier_seq?
>
> That _almost_ works except it wouldn't detect things like 'decltype(auto)*'
> because the '*' isn't parsed in cp_parser_decl_specifier_seq, only in
> declarator. So the
Ah, right.
> if (a != type)
> {
> error_at (loc, "%qT as type rather than plain "
> "%<decltype(auto)%>", type);
>
> check wouldn't work. Maybe I could just check if the next token is * or &
> and give an error then.
No, checking in grokdeclarator makes sense.
> Constrained decltype(auto) was a little problem, hence the TYPENAME
> check. But in a typename context you can't use decltype(auto) anyway,
> I think.
Maybe check PLACEHOLDER_TYPE_CONSTRAINTS in check_decltype_auto instead?
Jason
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
2021-12-15 21:17 ` Jason Merrill
@ 2021-12-15 21:28 ` Marek Polacek
2021-12-15 21:51 ` Jason Merrill
0 siblings, 1 reply; 6+ messages in thread
From: Marek Polacek @ 2021-12-15 21:28 UTC (permalink / raw)
To: Jason Merrill; +Cc: GCC Patches
On Wed, Dec 15, 2021 at 04:17:37PM -0500, Jason Merrill wrote:
> On 12/15/21 15:20, Marek Polacek wrote:
> > On Mon, Dec 13, 2021 at 10:02:24AM -0500, Jason Merrill wrote:
> > > On 12/10/21 17:29, Marek Polacek wrote:
> > > > My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
> > > > "If the placeholder-type-specifier is of the form type-constraint[opt]
> > > > decltype(auto), T shall be the placeholder alone." But this made us
> > > > reject 'constexpr decltype(auto)', which, after clarification from CWG,
> > > > should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
> > > > constraint, not semantic, so it's OK that the constexpr marks the object
> > > > as const.
> > > >
> > > > As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
> > > > and we have a FIXME there anyway. So in this patch I'm attempting to
> > > > detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
> > > > it needs to happen before we mark the object as const due to constexpr,
> > > > that is, before grokdeclarator's
> > > >
> > > > /* A `constexpr' specifier used in an object declaration declares
> > > > the object as `const'. */
> > > > if (constexpr_p && innermost_code != cdk_function)
> > > > ...
> > > >
> > > > Constrained decltype(auto) was a little problem, hence the TYPENAME
> > > > check. But in a typename context you can't use decltype(auto) anyway,
> > > > I think.
> > >
> > > I wonder about checking even earlier, like in cp_parser_decl_specifier_seq?
> >
> > That _almost_ works except it wouldn't detect things like 'decltype(auto)*'
> > because the '*' isn't parsed in cp_parser_decl_specifier_seq, only in
> > declarator. So the
>
> Ah, right.
>
> > if (a != type)
> > {
> > error_at (loc, "%qT as type rather than plain "
> > "%<decltype(auto)%>", type);
> >
> > check wouldn't work. Maybe I could just check if the next token is * or &
> > and give an error then.
>
> No, checking in grokdeclarator makes sense.
>
> > Constrained decltype(auto) was a little problem, hence the TYPENAME
> > check. But in a typename context you can't use decltype(auto) anyway,
> > I think.
>
> Maybe check PLACEHOLDER_TYPE_CONSTRAINTS in check_decltype_auto instead?
I've tried that, but that is also true for
const constexpr C decltype(auto) x2 = 0;
const constexpr C decltype(auto) fn4() { return 0; }
where we do want to check if the auto has quals. Therefore the not very
pretty TYPENAME check :/.
Marek
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH] c++: Allow constexpr decltype(auto) [PR102229]
2021-12-15 21:28 ` Marek Polacek
@ 2021-12-15 21:51 ` Jason Merrill
0 siblings, 0 replies; 6+ messages in thread
From: Jason Merrill @ 2021-12-15 21:51 UTC (permalink / raw)
To: Marek Polacek; +Cc: GCC Patches
On 12/15/21 16:28, Marek Polacek wrote:
> On Wed, Dec 15, 2021 at 04:17:37PM -0500, Jason Merrill wrote:
>> On 12/15/21 15:20, Marek Polacek wrote:
>>> On Mon, Dec 13, 2021 at 10:02:24AM -0500, Jason Merrill wrote:
>>>> On 12/10/21 17:29, Marek Polacek wrote:
>>>>> My r11-2202 was trying to enforce [dcl.type.auto.deduct]/4, which says
>>>>> "If the placeholder-type-specifier is of the form type-constraint[opt]
>>>>> decltype(auto), T shall be the placeholder alone." But this made us
>>>>> reject 'constexpr decltype(auto)', which, after clarification from CWG,
>>>>> should be valid. [dcl.type.auto.deduct]/4 is supposed to be a syntactic
>>>>> constraint, not semantic, so it's OK that the constexpr marks the object
>>>>> as const.
>>>>>
>>>>> As a consequence, checking TYPE_QUALS in do_auto_deduction is too late,
>>>>> and we have a FIXME there anyway. So in this patch I'm attempting to
>>>>> detect 'const decltype(auto)' earlier. If I'm going to use TYPE_QUALS,
>>>>> it needs to happen before we mark the object as const due to constexpr,
>>>>> that is, before grokdeclarator's
>>>>>
>>>>> /* A `constexpr' specifier used in an object declaration declares
>>>>> the object as `const'. */
>>>>> if (constexpr_p && innermost_code != cdk_function)
>>>>> ...
>>>>>
>>>>> Constrained decltype(auto) was a little problem, hence the TYPENAME
>>>>> check. But in a typename context you can't use decltype(auto) anyway,
>>>>> I think.
>>>>
>>>> I wonder about checking even earlier, like in cp_parser_decl_specifier_seq?
>>>
>>> That _almost_ works except it wouldn't detect things like 'decltype(auto)*'
>>> because the '*' isn't parsed in cp_parser_decl_specifier_seq, only in
>>> declarator. So the
>>
>> Ah, right.
>>
>>> if (a != type)
>>> {
>>> error_at (loc, "%qT as type rather than plain "
>>> "%<decltype(auto)%>", type);
>>>
>>> check wouldn't work. Maybe I could just check if the next token is * or &
>>> and give an error then.
>>
>> No, checking in grokdeclarator makes sense.
>>
>>> Constrained decltype(auto) was a little problem, hence the TYPENAME
>>> check. But in a typename context you can't use decltype(auto) anyway,
>>> I think.
>>
>> Maybe check PLACEHOLDER_TYPE_CONSTRAINTS in check_decltype_auto instead?
>
> I've tried that, but that is also true for
>
> const constexpr C decltype(auto) x2 = 0;
> const constexpr C decltype(auto) fn4() { return 0; }
>
> where we do want to check if the auto has quals. Therefore the not very
> pretty TYPENAME check :/.
Aha. The patch is OK.
Jason
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2021-12-15 21:51 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-12-10 22:29 [PATCH] c++: Allow constexpr decltype(auto) [PR102229] Marek Polacek
2021-12-13 15:02 ` Jason Merrill
2021-12-15 20:20 ` Marek Polacek
2021-12-15 21:17 ` Jason Merrill
2021-12-15 21:28 ` Marek Polacek
2021-12-15 21:51 ` 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).