aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2021-10-21 11:10:02 -0400
committerMarek Polacek <polacek@redhat.com>2021-10-26 11:34:53 -0400
commit5469d58d6620195c6275d11b474d686f5921c3ba (patch)
treec74e8137c6408bff107f4a2bfbfd89d5a9474855 /gcc
parent28006282028b548238cee4601117f21c498dc2b7 (diff)
downloadgcc-5469d58d6620195c6275d11b474d686f5921c3ba.zip
gcc-5469d58d6620195c6275d11b474d686f5921c3ba.tar.gz
gcc-5469d58d6620195c6275d11b474d686f5921c3ba.tar.bz2
c++: P2360R0: Extend init-stmt to allow alias-decl [PR102617]
The following patch implements C++23 P2360R0. This proposal merely extends init-statement to contain alias-declaration. init-statement is used in if/for/switch. It also removes the unsightly duplication of code by calling cp_parser_init_statement twice. PR c++/102617 gcc/cp/ChangeLog: * parser.c (cp_parser_for): Maybe call cp_parser_init_statement twice. Warn about range-based for loops with initializer here. (cp_parser_init_statement): Don't duplicate code. Allow alias-declaration in init-statement. gcc/testsuite/ChangeLog: * g++.dg/cpp23/init-stmt1.C: New test. * g++.dg/cpp23/init-stmt2.C: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/parser.c70
-rw-r--r--gcc/testsuite/g++.dg/cpp23/init-stmt1.C31
-rw-r--r--gcc/testsuite/g++.dg/cpp23/init-stmt2.C25
3 files changed, 95 insertions, 31 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 49d951c..93335c8 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12040,6 +12040,7 @@ cp_parser_handle_directive_omp_attributes (cp_parser *parser, tree *pattrs,
init-statement:
expression-statement
simple-declaration
+ alias-declaration
TM Extension:
@@ -13327,6 +13328,23 @@ cp_parser_for (cp_parser *parser, bool ivdep, unsigned short unroll)
/* Begin the for-statement. */
scope = begin_for_scope (&init);
+ /* Maybe parse the optional init-statement in a range-based for loop. */
+ if (cp_parser_range_based_for_with_init_p (parser)
+ /* Checked for diagnostic purposes only. */
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ {
+ tree dummy;
+ cp_parser_init_statement (parser, &dummy);
+ if (cxx_dialect < cxx20)
+ {
+ pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wc__20_extensions,
+ "range-based %<for%> loops with initializer only "
+ "available with %<-std=c++20%> or %<-std=gnu++20%>");
+ decl = error_mark_node;
+ }
+ }
+
/* Parse the initialization. */
is_range_for = cp_parser_init_statement (parser, &decl);
@@ -13987,12 +14005,13 @@ cp_parser_iteration_statement (cp_parser* parser, bool *if_p, bool ivdep,
return statement;
}
-/* Parse a init-statement or the declarator of a range-based-for.
+/* Parse an init-statement or the declarator of a range-based-for.
Returns true if a range-based-for declaration is seen.
init-statement:
expression-statement
- simple-declaration */
+ simple-declaration
+ alias-declaration */
static bool
cp_parser_init_statement (cp_parser *parser, tree *decl)
@@ -14008,40 +14027,29 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
bool is_range_for = false;
bool saved_colon_corrects_to_scope_p = parser->colon_corrects_to_scope_p;
- /* Try to parse the init-statement. */
- if (cp_parser_range_based_for_with_init_p (parser))
- {
- tree dummy;
- cp_parser_parse_tentatively (parser);
- /* Parse the declaration. */
- cp_parser_simple_declaration (parser,
- /*function_definition_allowed_p=*/false,
- &dummy);
- cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
- if (!cp_parser_parse_definitely (parser))
- /* That didn't work, try to parse it as an expression-statement. */
- cp_parser_expression_statement (parser, NULL_TREE);
-
- if (cxx_dialect < cxx20)
- {
- pedwarn (cp_lexer_peek_token (parser->lexer)->location,
- OPT_Wc__20_extensions,
- "range-based %<for%> loops with initializer only "
- "available with %<-std=c++20%> or %<-std=gnu++20%>");
- *decl = error_mark_node;
- }
- }
-
/* A colon is used in range-based for. */
parser->colon_corrects_to_scope_p = false;
/* We're going to speculatively look for a declaration, falling back
to an expression, if necessary. */
cp_parser_parse_tentatively (parser);
- /* Parse the declaration. */
- cp_parser_simple_declaration (parser,
- /*function_definition_allowed_p=*/false,
- decl);
+ bool expect_semicolon_p = true;
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+ {
+ cp_parser_alias_declaration (parser);
+ expect_semicolon_p = false;
+ if (cxx_dialect < cxx23
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+ pedwarn (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wc__23_extensions,
+ "alias-declaration in init-statement only "
+ "available with %<-std=c++23%> or %<-std=gnu++23%>");
+ }
+ else
+ /* Parse the declaration. */
+ cp_parser_simple_declaration (parser,
+ /*function_definition_allowed_p=*/false,
+ decl);
parser->colon_corrects_to_scope_p = saved_colon_corrects_to_scope_p;
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
@@ -14054,7 +14062,7 @@ cp_parser_init_statement (cp_parser *parser, tree *decl)
"range-based %<for%> loops only available with "
"%<-std=c++11%> or %<-std=gnu++11%>");
}
- else
+ else if (expect_semicolon_p)
/* The ';' is not consumed yet because we told
cp_parser_simple_declaration not to. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);
diff --git a/gcc/testsuite/g++.dg/cpp23/init-stmt1.C b/gcc/testsuite/g++.dg/cpp23/init-stmt1.C
new file mode 100644
index 0000000..29e3256a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/init-stmt1.C
@@ -0,0 +1,31 @@
+// PR c++/102617
+// P2360R0: Extend init-statement to allow alias-declaration
+// { dg-do compile { target c++20 } }
+// Test valid use.
+
+int v[10];
+
+void
+g ()
+{
+ for (using T = int; (T) false;) // { dg-error "only available with" "" { target c++20_only } }
+ ;
+ for (using T = int; T e : v) // { dg-error "only available with" "" { target c++20_only } }
+ (void) e;
+ if (using T = int; true) // { dg-error "only available with" "" { target c++20_only } }
+ {
+ T x = 0;
+ (void) x;
+ }
+ if constexpr (using T = int; true) // { dg-error "only available with" "" { target c++20_only } }
+ {
+ T x = 0;
+ (void) x;
+ }
+ switch (using T = int; 42) // { dg-error "only available with" "" { target c++20_only } }
+ case 42:
+ {
+ T x = 0;
+ (void) x;
+ }
+}
diff --git a/gcc/testsuite/g++.dg/cpp23/init-stmt2.C b/gcc/testsuite/g++.dg/cpp23/init-stmt2.C
new file mode 100644
index 0000000..ca6201b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp23/init-stmt2.C
@@ -0,0 +1,25 @@
+// PR c++/102617
+// P2360R0: Extend init-statement to allow alias-declaration
+// { dg-do compile { target c++23 } }
+// Test invalid use.
+
+int v[10];
+namespace N { using X = int; }
+
+void
+g ()
+{
+ for (using N::X; false;) // { dg-error "expected" }
+ ;
+ for (using N::X; int e : v) // { dg-error "expected" }
+ (void) e;
+ for (using T = int; using U = int; int e : v) // { dg-error "" }
+ ;
+ if (using N::X; false) // { dg-error "expected" }
+ {}
+ switch (using N::X; 0) // { dg-error "expected" }
+ ;
+ if (using T = int;) // { dg-error "expected" }
+ {
+ }
+}