aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c93
1 files changed, 75 insertions, 18 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 18b09affb59..5193c36dc85 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -10266,6 +10266,11 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
first = false;
}
+ hash_set<tree> *ids = NULL;
+#if GCC_VERSION >= 8000
+ char ids_buf[sizeof (hash_set<tree>) + __alignof__ (hash_set<tree>) - 1];
+#endif
+ tree first_capture_id = NULL_TREE;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
{
cp_token* capture_token;
@@ -10301,11 +10306,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
pedwarn (loc, 0, "explicit by-copy capture of %<this%> redundant "
"with by-copy capture default");
cp_lexer_consume_token (parser->lexer);
- add_capture (lambda_expr,
- /*id=*/this_identifier,
- /*initializer=*/finish_this_expr (),
- /*by_reference_p=*/true,
- explicit_init_p);
+ if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression",
+ this_identifier);
+ else
+ add_capture (lambda_expr, /*id=*/this_identifier,
+ /*initializer=*/finish_this_expr (),
+ /*by_reference_p=*/true, explicit_init_p);
continue;
}
@@ -10319,11 +10327,14 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
"-std=c++17 or -std=gnu++17");
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- add_capture (lambda_expr,
- /*id=*/this_identifier,
- /*initializer=*/finish_this_expr (),
- /*by_reference_p=*/false,
- explicit_init_p);
+ if (LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression",
+ this_identifier);
+ else
+ add_capture (lambda_expr, /*id=*/this_identifier,
+ /*initializer=*/finish_this_expr (),
+ /*by_reference_p=*/false, explicit_init_p);
continue;
}
@@ -10445,11 +10456,35 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
"default", capture_id);
}
- add_capture (lambda_expr,
- capture_id,
- capture_init_expr,
- /*by_reference_p=*/capture_kind == BY_REFERENCE,
- explicit_init_p);
+ /* Check for duplicates.
+ Optimize for the zero or one explicit captures cases and only create
+ the hash_set after adding second capture. */
+ bool found = false;
+ if (ids && ids->elements ())
+ found = ids->add (capture_id);
+ else if (first_capture_id == NULL_TREE)
+ first_capture_id = capture_id;
+ else if (capture_id == first_capture_id)
+ found = true;
+ else
+ {
+#if GCC_VERSION >= 8000
+ ids = new (ids_buf
+ + (-(uintptr_t) ids_buf
+ & (__alignof__ (hash_set <tree>) - 1))) hash_set <tree>;
+#else
+ ids = new hash_set <tree>;
+#endif
+ ids->add (first_capture_id);
+ ids->add (capture_id);
+ }
+ if (found)
+ pedwarn (input_location, 0,
+ "already captured %qD in lambda expression", capture_id);
+ else
+ add_capture (lambda_expr, capture_id, capture_init_expr,
+ /*by_reference_p=*/capture_kind == BY_REFERENCE,
+ explicit_init_p);
/* If there is any qualification still in effect, clear it
now; we will be starting fresh with the next capture. */
@@ -10458,6 +10493,13 @@ cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
parser->object_scope = NULL_TREE;
}
+ if (ids)
+#if GCC_VERSION >= 8000
+ ids->~hash_set <tree> ();
+#else
+ delete ids;
+#endif
+
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
}
@@ -18773,7 +18815,8 @@ cp_parser_using_declaration (cp_parser* parser,
/*is_declaration=*/true);
if (!qscope)
qscope = global_namespace;
- else if (UNSCOPED_ENUM_P (qscope))
+ else if (UNSCOPED_ENUM_P (qscope)
+ && !TYPE_FUNCTION_SCOPE_P (qscope))
qscope = CP_TYPE_CONTEXT (qscope);
if (access_declaration_p && cp_parser_error_occurred (parser))
@@ -19125,8 +19168,9 @@ cp_parser_asm_definition (cp_parser* parser)
location_t volatile_loc = UNKNOWN_LOCATION;
location_t inline_loc = UNKNOWN_LOCATION;
location_t goto_loc = UNKNOWN_LOCATION;
+ location_t first_loc = UNKNOWN_LOCATION;
- if (cp_parser_allow_gnu_extensions_p (parser) && parser->in_function_body)
+ if (cp_parser_allow_gnu_extensions_p (parser))
for (;;)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
@@ -19152,6 +19196,8 @@ cp_parser_asm_definition (cp_parser* parser)
}
else
inline_loc = loc;
+ if (!first_loc)
+ first_loc = loc;
cp_lexer_consume_token (parser->lexer);
continue;
@@ -19163,6 +19209,8 @@ cp_parser_asm_definition (cp_parser* parser)
}
else
goto_loc = loc;
+ if (!first_loc)
+ first_loc = loc;
cp_lexer_consume_token (parser->lexer);
continue;
@@ -19182,6 +19230,12 @@ cp_parser_asm_definition (cp_parser* parser)
bool inline_p = (inline_loc != UNKNOWN_LOCATION);
bool goto_p = (goto_loc != UNKNOWN_LOCATION);
+ if (!parser->in_function_body && (inline_p || goto_p))
+ {
+ error_at (first_loc, "asm qualifier outside of function body");
+ inline_p = goto_p = false;
+ }
+
/* Look for the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, RT_OPEN_PAREN))
return;
@@ -38680,7 +38734,10 @@ cp_parser_initial_pragma (cp_token *first_token)
cp_lexer_get_preprocessor_token (NULL, first_token);
if (cp_parser_pragma_kind (first_token) != PRAGMA_GCC_PCH_PREPROCESS)
- return;
+ {
+ c_common_no_more_pch ();
+ return;
+ }
cp_lexer_get_preprocessor_token (NULL, first_token);
if (first_token->type == CPP_STRING)