summaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c178
1 files changed, 145 insertions, 33 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 38e0d5c5789..78f359a31ef 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -237,7 +237,7 @@ static tree cp_literal_operator_id
(const char *);
static tree cp_parser_array_notation
- (cp_parser *, tree, tree);
+ (location_t, cp_parser *, tree, tree);
static vec<tree, va_gc> *cp_parser_elem_fn_expression_list
(cp_parser *);
@@ -649,7 +649,11 @@ cp_lexer_new_main (void)
gcc_assert (!lexer->next_token->purged_p);
- array_notation_label_no = 0;
+ if (flag_enable_cilk)
+ {
+ array_notation_label_no = 0;
+ p_simd_nodes_clear ();
+ }
return lexer;
}
@@ -1248,7 +1252,7 @@ clear_decl_specs (cp_decl_specifier_seq *decl_specs)
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, tree, tree);
+ (cp_declarator *, tree, cp_cv_quals, cp_virt_specifiers, cp_ref_qualifier, tree, tree);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
@@ -1427,6 +1431,7 @@ make_call_declarator (cp_declarator *target,
tree parms,
cp_cv_quals cv_qualifiers,
cp_virt_specifiers virt_specifiers,
+ cp_ref_qualifier ref_qualifier,
tree exception_specification,
tree late_return_type)
{
@@ -1437,6 +1442,7 @@ make_call_declarator (cp_declarator *target,
declarator->u.function.parameters = parms;
declarator->u.function.qualifiers = cv_qualifiers;
declarator->u.function.virt_specifiers = virt_specifiers;
+ declarator->u.function.ref_qualifier = ref_qualifier;
declarator->u.function.exception_specification = exception_specification;
declarator->u.function.late_return_type = late_return_type;
if (target)
@@ -1864,7 +1870,7 @@ static tree cp_parser_qualifying_entity
static tree cp_parser_postfix_expression
(cp_parser *, bool, bool, bool, bool, cp_id_kind *);
static tree cp_parser_postfix_open_square_expression
- (cp_parser *, tree, bool);
+ (cp_parser *, tree, bool, bool);
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
static vec<tree, va_gc> *cp_parser_parenthesized_expression_list
@@ -2032,6 +2038,8 @@ static cp_cv_quals cp_parser_cv_qualifier_seq_opt
(cp_parser *);
static cp_virt_specifiers cp_parser_virt_specifier_seq_opt
(cp_parser *);
+static cp_ref_qualifier cp_parser_ref_qualifier_opt
+ (cp_parser *);
static tree cp_parser_late_return_type_opt
(cp_parser *, cp_cv_quals);
static tree cp_parser_declarator_id
@@ -3927,6 +3935,18 @@ cp_parser_translation_unit (cp_parser* parser)
return success;
}
+/* Return the appropriate tsubst flags for parsing, possibly in N3276
+ decltype context. */
+
+static inline tsubst_flags_t
+complain_flags (bool decltype_p)
+{
+ tsubst_flags_t complain = tf_warning_or_error;
+ if (decltype_p)
+ complain |= tf_decltype;
+ return complain;
+}
+
/* Expressions [gram.expr] */
/* Parse a primary-expression.
@@ -5820,7 +5840,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
postfix_expression
= cp_parser_postfix_open_square_expression (parser,
postfix_expression,
- false);
+ false,
+ decltype_p);
idk = CP_ID_KIND_NONE;
is_member_access = false;
break;
@@ -5832,12 +5853,9 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
bool is_builtin_constant_p;
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
- int complain = tf_warning_or_error;
+ tsubst_flags_t complain = complain_flags (decltype_p);
vec<tree, va_gc> *args;
- if (decltype_p)
- complain |= tf_decltype;
-
is_member_access = false;
is_builtin_constant_p
@@ -6097,7 +6115,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
static tree
cp_parser_postfix_open_square_expression (cp_parser *parser,
tree postfix_expression,
- bool for_offsetof)
+ bool for_offsetof,
+ bool decltype_p)
{
tree index;
location_t loc = cp_lexer_peek_token (parser->lexer)->location;
@@ -6110,7 +6129,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
/* If we reach here, then we have something like this:
ARRAY [:]
*/
- postfix_expression = cp_parser_array_notation (parser, NULL_TREE,
+ postfix_expression = cp_parser_array_notation (loc, parser, NULL_TREE,
postfix_expression);
else
{
@@ -6149,7 +6168,7 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
}
if (flag_enable_cilk
&& cp_lexer_peek_token (parser->lexer)->type == CPP_COLON)
- postfix_expression = cp_parser_array_notation (parser, index,
+ postfix_expression = cp_parser_array_notation (loc, parser, index,
postfix_expression);
else
{
@@ -6157,7 +6176,8 @@ cp_parser_postfix_open_square_expression (cp_parser *parser,
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
/* Build the ARRAY_REF. */
- postfix_expression = grok_array_decl (loc, postfix_expression, index);
+ postfix_expression = grok_array_decl (loc, postfix_expression,
+ index, decltype_p);
/* When not doing offsetof, array references are not permitted in
constant-expressions. */
@@ -6861,6 +6881,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
tree expression = error_mark_node;
non_integral_constant non_constant_p = NIC_NONE;
location_t loc = token->location;
+ tsubst_flags_t complain = complain_flags (decltype_p);
/* Consume the operator token. */
token = cp_lexer_consume_token (parser->lexer);
@@ -6878,7 +6899,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
non_constant_p = NIC_STAR;
expression = build_x_indirect_ref (loc, cast_expression,
RO_UNARY_STAR,
- tf_warning_or_error);
+ complain);
break;
case ADDR_EXPR:
@@ -6887,7 +6908,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
case BIT_NOT_EXPR:
expression = build_x_unary_op (loc, unary_operator,
cast_expression,
- tf_warning_or_error);
+ complain);
break;
case PREINCREMENT_EXPR:
@@ -6899,7 +6920,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
case NEGATE_EXPR:
case TRUTH_NOT_EXPR:
expression = finish_unary_op_expr (loc, unary_operator,
- cast_expression);
+ cast_expression, complain);
break;
default:
@@ -7727,7 +7748,7 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p,
current.lhs = build_x_binary_op (current.loc, current.tree_type,
current.lhs, current.lhs_type,
rhs, rhs_type, &overload,
- tf_warning_or_error);
+ complain_flags (decltype_p));
current.lhs_type = current.tree_type;
if (EXPR_P (current.lhs))
SET_EXPR_LOCATION (current.lhs, current.loc);
@@ -7882,7 +7903,7 @@ cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
expr = build_x_modify_expr (loc, expr,
assignment_operator,
rhs,
- tf_warning_or_error);
+ complain_flags (decltype_p));
input_location = saved_input_location;
}
}
@@ -8028,7 +8049,7 @@ cp_parser_expression (cp_parser* parser, bool cast_p, bool decltype_p,
else
expression = build_x_compound_expr (loc, expression,
assignment_expression,
- tf_warning_or_error);
+ complain_flags (decltype_p));
/* If the next token is not a comma, then we are done with the
expression. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
@@ -8179,12 +8200,14 @@ cp_parser_builtin_offsetof (cp_parser *parser)
{
case CPP_OPEN_SQUARE:
/* offsetof-member-designator "[" expression "]" */
- expr = cp_parser_postfix_open_square_expression (parser, expr, true);
+ expr = cp_parser_postfix_open_square_expression (parser, expr,
+ true, false);
break;
case CPP_DEREF:
/* offsetof-member-designator "->" identifier */
- expr = grok_array_decl (token->location, expr, integer_zero_node);
+ expr = grok_array_decl (token->location, expr,
+ integer_zero_node, false);
/* FALLTHRU */
case CPP_DOT:
@@ -8804,6 +8827,7 @@ cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
declarator = make_call_declarator (declarator, param_list, quals,
VIRT_SPEC_UNSPECIFIED,
+ REF_QUAL_NONE,
exception_spec,
/*late_return_type=*/NULL_TREE);
declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
@@ -9826,7 +9850,10 @@ cp_parser_range_for (cp_parser *parser, tree scope, tree init, tree range_decl)
range_expr = error_mark_node;
stmt = begin_range_for_stmt (scope, init);
finish_range_for_decl (stmt, range_decl, range_expr);
- if (!type_dependent_expression_p (range_expr)
+ if (range_expr != error_mark_node
+ && !type_dependent_expression_p (range_expr)
+ /* The length of an array might be dependent. */
+ && COMPLETE_TYPE_P (TREE_TYPE (range_expr))
/* do_auto_deduction doesn't mess with template init-lists. */
&& !BRACE_ENCLOSED_INITIALIZER_P (range_expr))
do_range_for_auto_deduction (range_decl, range_expr);
@@ -9974,7 +10001,8 @@ cp_convert_range_for (tree statement, tree range_decl, tree range_expr)
/* The new increment expression. */
expression = finish_unary_op_expr (input_location,
- PREINCREMENT_EXPR, begin);
+ PREINCREMENT_EXPR, begin,
+ tf_warning_or_error);
finish_for_expr (expression, statement);
/* The declaration is initialized with *__begin inside the loop body. */
@@ -14998,6 +15026,9 @@ cp_parser_enum_specifier (cp_parser* parser)
{
identifier = make_anon_name ();
is_anonymous = true;
+ if (scoped_enum_p)
+ error_at (type_start_token->location,
+ "anonymous scoped enum is not allowed");
}
}
pop_deferring_access_checks ();
@@ -15145,7 +15176,13 @@ cp_parser_enum_specifier (cp_parser* parser)
if (type == error_mark_node)
cp_parser_skip_to_end_of_block_or_statement (parser);
/* If the next token is not '}', then there are some enumerators. */
- else if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ {
+ if (is_anonymous && !scoped_enum_p)
+ pedwarn (type_start_token->location, OPT_Wpedantic,
+ "ISO C++ forbids empty anonymous enum");
+ }
+ else
cp_parser_enumerator_list (parser, type);
/* Consume the final '}'. */
@@ -16938,6 +16975,7 @@ cp_parser_declarator (cp_parser* parser,
declarator-id
direct-declarator ( parameter-declaration-clause )
cv-qualifier-seq [opt]
+ ref-qualifier [opt]
exception-specification [opt]
direct-declarator [ constant-expression [opt] ]
( declarator )
@@ -16946,6 +16984,7 @@ cp_parser_declarator (cp_parser* parser,
direct-abstract-declarator [opt]
( parameter-declaration-clause )
cv-qualifier-seq [opt]
+ ref-qualifier [opt]
exception-specification [opt]
direct-abstract-declarator [opt] [ constant-expression [opt] ]
( abstract-declarator )
@@ -17060,12 +17099,13 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, RT_CLOSE_PAREN);
- /* If all went well, parse the cv-qualifier-seq and the
- exception-specification. */
+ /* If all went well, parse the cv-qualifier-seq,
+ ref-qualifier and the exception-specification. */
if (member_p || cp_parser_parse_definitely (parser))
{
cp_cv_quals cv_quals;
cp_virt_specifiers virt_specifiers;
+ cp_ref_qualifier ref_qual;
tree exception_specification;
tree late_return;
tree attrs;
@@ -17080,6 +17120,8 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse the cv-qualifier-seq. */
cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
+ /* Parse the ref-qualifier. */
+ ref_qual = cp_parser_ref_qualifier_opt (parser);
/* And the exception-specification. */
exception_specification
= cp_parser_exception_specification_opt (parser);
@@ -17097,6 +17139,7 @@ cp_parser_direct_declarator (cp_parser* parser,
params,
cv_quals,
virt_specifiers,
+ ref_qual,
exception_specification,
late_return);
declarator->std_attributes = attrs;
@@ -17660,6 +17703,59 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
return cv_quals;
}
+/* Parse an (optional) ref-qualifier
+
+ ref-qualifier:
+ &
+ &&
+
+ Returns cp_ref_qualifier representing ref-qualifier. */
+
+static cp_ref_qualifier
+cp_parser_ref_qualifier_opt (cp_parser* parser)
+{
+ cp_ref_qualifier ref_qual = REF_QUAL_NONE;
+
+ while (true)
+ {
+ cp_ref_qualifier curr_ref_qual = REF_QUAL_NONE;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
+ switch (token->type)
+ {
+ case CPP_AND:
+ curr_ref_qual = REF_QUAL_LVALUE;
+ break;
+
+ case CPP_AND_AND:
+ curr_ref_qual = REF_QUAL_RVALUE;
+ break;
+
+ default:
+ curr_ref_qual = REF_QUAL_NONE;
+ break;
+ }
+
+ if (!curr_ref_qual)
+ break;
+ else if (ref_qual)
+ {
+ error_at (token->location, "multiple ref-qualifiers");
+ cp_lexer_purge_token (parser->lexer);
+ }
+ else
+ {
+ ref_qual = curr_ref_qual;
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
+
+ if (ref_qual)
+ maybe_warn_cpp0x (CPP0X_REF_QUALIFIER);
+
+ return ref_qual;
+}
+
/* Parse an (optional) virt-specifier-seq.
virt-specifier-seq:
@@ -21506,8 +21602,13 @@ cp_parser_std_attribute (cp_parser *parser)
token = cp_lexer_peek_token (parser->lexer);
}
else
- attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
- NULL_TREE);
+ {
+ attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
+ NULL_TREE);
+ /* C++11 noreturn attribute is equivalent to GNU's. */
+ if (is_attribute_p ("noreturn", attr_id))
+ TREE_PURPOSE (TREE_PURPOSE (attribute)) = get_identifier ("gnu");
+ }
/* Now parse the optional argument clause of the attribute. */
@@ -29672,7 +29773,7 @@ cp_parser_simd_private (cp_parser *parser, cp_token *pragma_token,
{
if (!same_var_in_multiple_lists_p (p_simd_values))
{
- cp_lexer_peek_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
cp_parser_for (parser, p_simd_values);
}
}
@@ -29736,7 +29837,7 @@ cp_parser_simd_vectorlength (cp_parser *parser, cp_token *pragma_token,
{
if (!same_var_in_multiple_lists_p (p_simd_values))
{
- cp_lexer_peek_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
cp_parser_for (parser, p_simd_values);
}
}
@@ -29848,7 +29949,7 @@ cp_parser_simd_reduction (cp_parser *parser, cp_token *pragma_token,
{
if (!same_var_in_multiple_lists_p (p_simd_values))
{
- cp_lexer_peek_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
cp_parser_for (parser, p_simd_values);
}
}
@@ -29979,7 +30080,8 @@ cp_parser_cilk_for_init_statement (cp_parser *parser, tree *init)
ARRAY_NOTATION_REF. If some error occurred it returns NULL_TREE. */
static tree
-cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
+cp_parser_array_notation (location_t loc, cp_parser *parser, tree init_index,
+ tree array_value)
{
cp_token *token = NULL;
tree start_index = NULL_TREE, length_index = NULL_TREE, stride = NULL_TREE;
@@ -29995,7 +30097,15 @@ cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
if (processing_template_decl)
{
array_type = TREE_TYPE (array_value);
- type = TREE_TYPE (array_type);
+ if (array_type)
+ type = TREE_TYPE (array_type);
+ else if (TREE_CODE (array_value) == ARRAY_REF)
+ {
+ array_type = TREE_TYPE (TREE_OPERAND (array_value, 0));
+ type = TREE_TYPE (array_type);
+ }
+ else
+ type = array_type;
}
else
{
@@ -30085,6 +30195,8 @@ cp_parser_array_notation (cp_parser *parser, tree init_index, tree array_value)
value_tree = build_array_notation_ref (input_location, array_value,
start_index, length_index, stride,
type);
+ if (value_tree != error_mark_node)
+ SET_EXPR_LOCATION (value_tree, loc);
return value_tree;
}