VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
+ (cp_declarator *, tree, cp_cv_quals, tree, tree);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
cp_declarator *
make_call_declarator (cp_declarator *target,
- cp_parameter_declarator *parms,
+ tree parms,
cp_cv_quals cv_qualifiers,
- tree exception_specification)
+ tree exception_specification,
+ tree late_return_type)
{
cp_declarator *declarator;
declarator->u.function.parameters = parms;
declarator->u.function.qualifiers = cv_qualifiers;
declarator->u.function.exception_specification = exception_specification;
+ declarator->u.function.late_return_type = late_return_type;
if (target)
{
declarator->parameter_pack_p = target->parameter_pack_p;
(cp_parser *, tree *, cp_cv_quals *);
static cp_cv_quals cp_parser_cv_qualifier_seq_opt
(cp_parser *);
+static tree cp_parser_late_return_type_opt
+ (cp_parser *);
static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
static void cp_parser_type_specifier_seq
(cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
(cp_parser *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_list
+static tree cp_parser_parameter_declaration_list
(cp_parser *, bool *);
static cp_parameter_declarator *cp_parser_parameter_declaration
(cp_parser *, bool, bool *);
case RID_FUNCTION_NAME:
case RID_PRETTY_FUNCTION_NAME:
case RID_C99_FUNCTION_NAME:
- /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
- __func__ are the names of variables -- but they are
- treated specially. Therefore, they are handled here,
- rather than relying on the generic id-expression logic
- below. Grammatically, these names are id-expressions.
+ {
+ const char *name;
- Consume the token. */
- token = cp_lexer_consume_token (parser->lexer);
- /* Look up the name. */
- return finish_fname (token->u.value);
+ /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
+ __func__ are the names of variables -- but they are
+ treated specially. Therefore, they are handled here,
+ rather than relying on the generic id-expression logic
+ below. Grammatically, these names are id-expressions.
+
+ Consume the token. */
+ token = cp_lexer_consume_token (parser->lexer);
+
+ switch (token->keyword)
+ {
+ case RID_FUNCTION_NAME:
+ name = "%<__FUNCTION__%>";
+ break;
+ case RID_PRETTY_FUNCTION_NAME:
+ name = "%<__PRETTY_FUNCTION__%>";
+ break;
+ case RID_C99_FUNCTION_NAME:
+ name = "%<__func__%>";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (cp_parser_non_integral_constant_expression (parser, name))
+ return error_mark_node;
+
+ /* Look up the name. */
+ return finish_fname (token->u.value);
+ }
case RID_VA_ARG:
{
/*typename_keyword_p=*/false,
/*check_dependency_p=*/true,
/*type_p=*/false,
- /*is_declaration=*/true)
+ /*is_declaration=*/false)
!= NULL_TREE);
/* Now, if we saw a nested-name-specifier, we might be doing the
second production. */
{
tree identifier;
tree expression;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the '&&' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the identifier. */
identifier = cp_parser_identifier (parser);
/* Create an expression representing the address. */
- expression = finish_label_address_expr (identifier);
+ expression = finish_label_address_expr (identifier, loc);
if (cp_parser_non_integral_constant_expression (parser,
"the address of a label"))
expression = error_mark_node;
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
}
+/* Returns true if TOKEN may start a cast-expression and false
+ otherwise. */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+ switch (token->type)
+ {
+ case CPP_COMMA:
+ case CPP_SEMICOLON:
+ case CPP_QUERY:
+ case CPP_COLON:
+ case CPP_CLOSE_SQUARE:
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_BRACE:
+ case CPP_DOT:
+ case CPP_DOT_STAR:
+ case CPP_DEREF:
+ case CPP_DEREF_STAR:
+ case CPP_DIV:
+ case CPP_MOD:
+ case CPP_LSHIFT:
+ case CPP_RSHIFT:
+ case CPP_LESS:
+ case CPP_GREATER:
+ case CPP_LESS_EQ:
+ case CPP_GREATER_EQ:
+ case CPP_EQ_EQ:
+ case CPP_NOT_EQ:
+ case CPP_EQ:
+ case CPP_MULT_EQ:
+ case CPP_DIV_EQ:
+ case CPP_MOD_EQ:
+ case CPP_PLUS_EQ:
+ case CPP_MINUS_EQ:
+ case CPP_RSHIFT_EQ:
+ case CPP_LSHIFT_EQ:
+ case CPP_AND_EQ:
+ case CPP_XOR_EQ:
+ case CPP_OR_EQ:
+ case CPP_XOR:
+ case CPP_OR:
+ case CPP_OR_OR:
+ case CPP_EOF:
+ return false;
+
+ /* '[' may start a primary-expression in obj-c++. */
+ case CPP_OPEN_SQUARE:
+ return c_dialect_objc ();
+
+ default:
+ return true;
+ }
+}
+
/* Parse a cast-expression.
cast-expression:
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
- /* If ok so far, parse the dependent expression. We cannot be
- sure it is a cast. Consider `(T ())'. It is a parenthesized
- ctor of T, but looks like a cast to function returning T
- without a dependent expression. */
- if (!cp_parser_error_occurred (parser))
- expr = cp_parser_cast_expression (parser,
- /*address_p=*/false,
- /*cast_p=*/true);
-
- if (cp_parser_parse_definitely (parser))
+ /* At this point this can only be either a cast or a
+ parenthesized ctor such as `(T ())' that looks like a cast to
+ function returning T. */
+ if (!cp_parser_error_occurred (parser)
+ && cp_parser_token_starts_cast_expression (cp_lexer_peek_token
+ (parser->lexer)))
{
+ cp_parser_parse_definitely (parser);
+ expr = cp_parser_cast_expression (parser,
+ /*address_p=*/false,
+ /*cast_p=*/true);
+
/* Warn about old-style casts, if so requested. */
if (warn_old_style_cast
&& !in_system_header
expr = build_c_cast (type, expr);
return expr;
}
+ else
+ cp_parser_abort_tentative_parse (parser);
}
/* If we get here, then it's not a cast, so it must be a
}
overloaded_p = false;
+ /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
+ ERROR_MARK for everything that is not a binary expression.
+ This makes warn_about_parentheses miss some warnings that
+ involve unary operators. For unary expressions we should
+ pass the correct tree_code unless the unary expression was
+ surrounded by parentheses.
+ */
lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
&overloaded_p, tf_warning_or_error);
lhs_type = tree_type;
/* Parse the then-clause. */
in_statement = parser->in_statement;
parser->in_statement |= IN_IF_STMT;
- cp_parser_implicitly_scoped_statement (parser, &nested_if);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ add_stmt (build_empty_stmt ());
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+ warning_at (loc, OPT_Wempty_body, "suggest braces around "
+ "empty body in an %<if%> statement");
+ nested_if = false;
+ }
+ else
+ cp_parser_implicitly_scoped_statement (parser, &nested_if);
parser->in_statement = in_statement;
finish_then_clause (statement);
cp_lexer_consume_token (parser->lexer);
begin_else_clause (statement);
/* Parse the else-clause. */
- cp_parser_implicitly_scoped_statement (parser, NULL);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ {
+ warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wempty_body, "suggest braces around "
+ "empty body in an %<else%> statement");
+ add_stmt (build_empty_stmt ());
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ cp_parser_implicitly_scoped_statement (parser, NULL);
+
finish_else_clause (statement);
/* If we are currently parsing a then-clause, then
else
{
/* Consume the `='. */
- cp_lexer_consume_token (parser->lexer);
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
initializer = cp_parser_initializer_clause (parser, &non_constant_p);
}
if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
return cp_parser_expression (parser, /*cast_p=*/false);
}
-/* We check for a ) immediately followed by ; with no whitespacing
- between. This is used to issue a warning for:
-
- while (...);
-
- and:
-
- for (...);
-
- as the semicolon is probably extraneous.
-
- On parse errors, the next token might not be a ), so do nothing in
- that case. */
-
-static void
-check_empty_body (cp_parser* parser, const char* type)
-{
- cp_token *token;
- cp_token *close_paren;
- expanded_location close_loc;
- expanded_location semi_loc;
-
- close_paren = cp_lexer_peek_token (parser->lexer);
- if (close_paren->type != CPP_CLOSE_PAREN)
- return;
-
- close_loc = expand_location (close_paren->location);
- token = cp_lexer_peek_nth_token (parser->lexer, 2);
-
- if (token->type != CPP_SEMICOLON
- || (token->flags & PREV_WHITE))
- return;
-
- semi_loc = expand_location (token->location);
- if (close_loc.line == semi_loc.line
- && close_loc.column+1 == semi_loc.column)
- warning (OPT_Wempty_body,
- "suggest a space before %<;%> or explicit braces around empty "
- "body in %<%s%> statement",
- type);
-}
-
/* Parse an iteration-statement.
iteration-statement:
/* Parse the condition. */
condition = cp_parser_condition (parser);
finish_while_stmt_cond (condition, statement);
- check_empty_body (parser, "while");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Parse the dependent statement. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
expression = cp_parser_expression (parser, /*cast_p=*/false);
finish_for_expr (expression, statement);
- check_empty_body (parser, "for");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
(After "int (" we might be looking at a functional cast.) */
if (decl_specifiers.any_specifiers_p
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
- && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+ && !cp_parser_error_occurred (parser))
cp_parser_commit_to_tentative_parse (parser);
/* Keep going until we hit the `;' at the end of the simple
GNU Extension:
thread */
case RID_AUTO:
- /* Consume the token. */
- cp_lexer_consume_token (parser->lexer);
-
if (cxx_dialect == cxx98)
{
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+
/* Complain about `auto' as a storage specifier, if
we're complaining about C++0x compatibility. */
warning
cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
token->location);
}
- else
- /* We do not yet support the use of `auto' as a
- type-specifier. */
- error ("%HC++0x %<auto%> specifier not supported", &token->location);
+ else
+ /* C++0x auto type-specifier. */
+ found_decl_spec = false;
break;
case RID_REGISTER:
/*initialized=*/0, &attributes);
if (attributes)
cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
+
+ /* Don't give this error when parsing tentatively. This happens to
+ work because we always parse this definitively once. */
+ if (! cp_parser_uncommitted_to_tentative_parse_p (parser)
+ && type_uses_auto (type_specified))
+ {
+ error ("invalid use of %<auto%> in conversion operator");
+ return error_mark_node;
+ }
+
return type_specified;
}
break;
case RID_AUTO:
- if (cxx_dialect != cxx98)
- {
- /* Consume the token. */
- cp_lexer_consume_token (parser->lexer);
- /* We do not yet support the use of `auto' as a
- type-specifier. */
- error ("%HC++0x %<auto%> specifier not supported", &token->location);
- }
+ maybe_warn_cpp0x ("C++0x auto");
+ type = make_auto ();
break;
case RID_DECLTYPE:
tree type;
tree attributes;
bool scoped_enum_p = false;
+ bool has_underlying_type = false;
tree underlying_type = NULL_TREE;
/* Parse tentatively so that we can back up if we don't find a
scoped_enum_p = true;
}
-
+
attributes = cp_parser_attributes_opt (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
cp_decl_specifier_seq type_specifiers;
+ /* At this point this is surely not elaborated type specifier. */
+ if (!cp_parser_parse_definitely (parser))
+ return NULL_TREE;
+
if (cxx_dialect == cxx98)
maybe_warn_cpp0x ("scoped enums");
/* Consume the `:'. */
cp_lexer_consume_token (parser->lexer);
+ has_underlying_type = true;
+
/* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
&type_specifiers);
- if (type_specifiers.type == error_mark_node)
- return error_mark_node;
-
+
/* If that didn't work, stop. */
if (type_specifiers.type != error_mark_node)
{
if (underlying_type == error_mark_node)
underlying_type = NULL_TREE;
}
- else
- cp_parser_error (parser, "expected underlying type of enumeration");
}
/* Look for the `{' but don't consume it yet. */
if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- cp_parser_simulate_error (parser);
+ {
+ cp_parser_error (parser, "expected %<{%>");
+ if (has_underlying_type)
+ return NULL_TREE;
+ }
- if (!cp_parser_parse_definitely (parser))
+ if (!has_underlying_type && !cp_parser_parse_definitely (parser))
return NULL_TREE;
/* Issue an error message if type-definitions are forbidden here. */
}
else
{
+ location_t func_brace_location
+ = cp_lexer_peek_token (parser->lexer)->location;
+
/* Neither attributes nor an asm-specification are allowed
on a function-definition. */
if (asm_specification)
= (cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, prefix_attributes, declarator));
+ if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+ {
+ /* This is where the prologue starts... */
+ DECL_STRUCT_FUNCTION (decl)->function_start_locus
+ = func_brace_location;
+ }
+
return decl;
}
}
|| token->type == CPP_OPEN_PAREN
|| token->type == CPP_OPEN_BRACE)
{
- is_initialized = 1;
+ is_initialized = SD_INITIALIZED;
initialization_kind = token->type;
if (token->type == CPP_EQ
{
cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
if (t2->keyword == RID_DEFAULT)
- is_initialized = 2;
+ is_initialized = SD_DEFAULTED;
else if (t2->keyword == RID_DELETE)
- is_initialized = 3;
+ is_initialized = SD_DELETED;
}
}
else
cp_parser_error (parser, "expected initializer");
return error_mark_node;
}
- is_initialized = 0;
+ is_initialized = SD_UNINITIALIZED;
initialization_kind = CPP_EOF;
}
if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
{
- cp_parameter_declarator *params;
+ tree params;
unsigned saved_num_template_parameter_lists;
+ bool is_declarator = false;
+ tree t;
/* In a member-declarator, the only valid interpretation
of a parenthesis is the start of a
= parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0;
+ begin_scope (sk_function_parms, NULL_TREE);
+
/* Parse the parameter-declaration-clause. */
params = cp_parser_parameter_declaration_clause (parser);
{
cp_cv_quals cv_quals;
tree exception_specification;
+ tree late_return;
+
+ is_declarator = true;
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
exception_specification
= cp_parser_exception_specification_opt (parser);
+ late_return
+ = cp_parser_late_return_type_opt (parser);
+
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
cv_quals,
- exception_specification);
+ exception_specification,
+ late_return);
/* Any subsequent parameter lists are to do with
return type, so are not those of the declared
function. */
parser->default_arg_ok_p = false;
-
- /* Repeat the main loop. */
- continue;
}
+
+ /* Remove the function parms from scope. */
+ for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+ pop_binding (DECL_NAME (t), t);
+ leave_scope();
+
+ if (is_declarator)
+ /* Repeat the main loop. */
+ continue;
}
/* If this is the first, we can try a parenthesized
return cv_quals;
}
+/* Parse a late-specified return type, if any. This is not a separate
+ non-terminal, but part of a function declarator, which looks like
+
+ -> type-id
+
+ Returns the type indicated by the type-id. */
+
+static tree
+cp_parser_late_return_type_opt (cp_parser* parser)
+{
+ cp_token *token;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* A late-specified return type is indicated by an initial '->'. */
+ if (token->type != CPP_DEREF)
+ return NULL_TREE;
+
+ /* Consume the ->. */
+ cp_lexer_consume_token (parser->lexer);
+
+ return cp_parser_type_id (parser);
+}
+
/* Parse a declarator-id.
declarator-id:
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
+ if (type_specifier_seq.type
+ && type_uses_auto (type_specifier_seq.type))
+ {
+ error ("invalid use of %<auto%>");
+ return error_mark_node;
+ }
+
return groktypename (&type_specifier_seq, abstract_declarator);
}
value of NULL indicates a parameter-declaration-clause consisting
only of an ellipsis. */
-static cp_parameter_declarator *
+static tree
cp_parser_parameter_declaration_clause (cp_parser* parser)
{
- cp_parameter_declarator *parameters;
+ tree parameters;
cp_token *token;
bool ellipsis_p;
bool is_error;
{
/* Consume the `...' token. */
cp_lexer_consume_token (parser->lexer);
- return NULL;
+ return NULL_TREE;
}
else if (token->type == CPP_CLOSE_PAREN)
/* There are no parameters. */
#ifndef NO_IMPLICIT_EXTERN_C
if (in_system_header && current_class_type == NULL
&& current_lang_name == lang_name_c)
- return NULL;
+ return NULL_TREE;
else
#endif
- return no_parameters;
+ return void_list_node;
}
/* Check for `(void)', too, which is a special case. */
else if (token->keyword == RID_VOID
/* Consume the `void' token. */
cp_lexer_consume_token (parser->lexer);
/* There are no parameters. */
- return no_parameters;
+ return void_list_node;
}
/* Parse the parameter-declaration-list. */
ellipsis_p = false;
/* Finish the parameter list. */
- if (parameters && ellipsis_p)
- parameters->ellipsis_p = true;
+ if (!ellipsis_p)
+ parameters = chainon (parameters, void_list_node);
return parameters;
}
`void_list_node' is never appended to the list. Upon return,
*IS_ERROR will be true iff an error occurred. */
-static cp_parameter_declarator *
+static tree
cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
{
- cp_parameter_declarator *parameters = NULL;
- cp_parameter_declarator **tail = ¶meters;
+ tree parameters = NULL_TREE;
+ tree *tail = ¶meters;
bool saved_in_unbraced_linkage_specification_p;
/* Assume all will go well. */
while (true)
{
cp_parameter_declarator *parameter;
+ tree decl = error_mark_node;
bool parenthesized_p;
/* Parse the parameter. */
parameter
/*template_parm_p=*/false,
&parenthesized_p);
+ /* We don't know yet if the enclosing context is deprecated, so wait
+ and warn in grokparms if appropriate. */
+ deprecated_state = DEPRECATED_SUPPRESS;
+
+ if (parameter)
+ decl = grokdeclarator (parameter->declarator,
+ ¶meter->decl_specifiers,
+ PARM,
+ parameter->default_argument != NULL_TREE,
+ ¶meter->decl_specifiers.attributes);
+
+ deprecated_state = DEPRECATED_NORMAL;
+
/* If a parse error occurred parsing the parameter declaration,
then the entire parameter-declaration-list is erroneous. */
- if (!parameter)
+ if (decl == error_mark_node)
{
*is_error = true;
- parameters = NULL;
+ parameters = error_mark_node;
break;
}
+
+ if (parameter->decl_specifiers.attributes)
+ cplus_decl_attributes (&decl,
+ parameter->decl_specifiers.attributes,
+ 0);
+ if (DECL_NAME (decl))
+ decl = pushdecl (decl);
+
/* Add the new parameter to the list. */
- *tail = parameter;
- tail = ¶meter->next;
+ *tail = build_tree_list (parameter->default_argument, decl);
+ tail = &TREE_CHAIN (*tail);
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
tree scope;
bool typename_p;
cp_token *token;
+ tree identifier = NULL_TREE;
/* All class-names start with an identifier. */
token = cp_lexer_peek_token (parser->lexer);
&& !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
{
cp_token *identifier_token;
- tree identifier;
bool ambiguous_p;
/* Look for the identifier. */
if (decl == error_mark_node)
cp_parser_error (parser, "expected class-name");
+ else if (identifier && !parser->scope)
+ maybe_note_name_used_in_class (identifier, decl);
return decl;
}
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
bool saved_in_function_body;
+ bool saved_in_unbraced_linkage_specification_p;
tree old_scope = NULL_TREE;
tree scope = NULL_TREE;
tree bases;
/* We are not in a function body. */
saved_in_function_body = parser->in_function_body;
parser->in_function_body = false;
+ /* We are not immediately inside an extern "lang" block. */
+ saved_in_unbraced_linkage_specification_p
+ = parser->in_unbraced_linkage_specification_p;
+ parser->in_unbraced_linkage_specification_p = false;
/* Start the class. */
if (nested_name_specifier_p)
parser->in_function_body = saved_in_function_body;
parser->num_template_parameter_lists
= saved_num_template_parameter_lists;
+ parser->in_unbraced_linkage_specification_p
+ = saved_in_unbraced_linkage_specification_p;
return type;
}
return;
}
else
+ if (declarator->kind == cdk_function)
+ declarator->id_loc = token->location;
/* Create the declaration. */
decl = grokfield (declarator, &decl_specifiers,
initializer, /*init_const_expr_p=*/true,
/* Validate that a clause of the given type does not already exist. */
static void
-check_no_duplicate_clause (tree clauses, enum tree_code code,
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
const char *name, location_t location)
{
tree c;
else
{
- tree pushed_scope;
+ tree pushed_scope, auto_node;
decl = start_decl (declarator, &type_specifiers,
- /*initialized_p=*/false, attributes,
+ SD_INITIALIZED, attributes,
/*prefix_attributes=*/NULL_TREE,
&pushed_scope);
+ auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
if (cp_lexer_next_token_is (parser->lexer,
cp_parser_skip_to_end_of_statement (parser);
}
else if (CLASS_TYPE_P (TREE_TYPE (decl))
- || type_dependent_expression_p (decl))
+ || type_dependent_expression_p (decl)
+ || auto_node)
{
bool is_direct_init, is_non_constant_init;
&is_direct_init,
&is_non_constant_init);
+ if (auto_node && describable_type (init))
+ {
+ TREE_TYPE (decl)
+ = do_auto_deduction (TREE_TYPE (decl), init,
+ auto_node);
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl))
+ && !type_dependent_expression_p (decl))
+ goto non_class;
+ }
+
cp_finish_decl (decl, init, !is_non_constant_init,
asm_specification,
LOOKUP_ONLYCONVERTING);
cp_lexer_consume_token (parser->lexer);
init = cp_parser_assignment_expression (parser, false);
+ non_class:
if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
init = error_mark_node;
else