diff options
author | Marek Polacek <polacek@redhat.com> | 2021-12-10 15:38:35 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2021-12-15 17:47:43 -0500 |
commit | 06d5dcef72542baf49ac245cfde2ad7ecef0916b (patch) | |
tree | e988e7ac830e95c16f9028d6a3e83d67ac84afcc /gcc/cp/decl.c | |
parent | 45b768cb80930c0beeb735727349c44ec66f7dd2 (diff) | |
download | gcc-06d5dcef72542baf49ac245cfde2ad7ecef0916b.zip gcc-06d5dcef72542baf49ac245cfde2ad7ecef0916b.tar.gz gcc-06d5dcef72542baf49ac245cfde2ad7ecef0916b.tar.bz2 |
c++: Allow constexpr decltype(auto) [PR102229]
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.
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.
Diffstat (limited to 'gcc/cp/decl.c')
-rw-r--r-- | gcc/cp/decl.c | 58 |
1 files changed, 39 insertions, 19 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 7c2048c..2e03398 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) |