static tree cp_parser_class_specifier
(cp_parser *);
static tree cp_parser_class_head
- (cp_parser *, bool *, tree *, tree *);
+ (cp_parser *, bool *);
static enum tag_types cp_parser_class_key
(cp_parser *);
static void cp_parser_member_specification_opt
otherwise. */
static bool
-cp_parser_token_starts_cast_expression (cp_token *token)
+cp_parser_tokens_start_cast_expression (cp_parser *parser)
{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
{
case CPP_COMMA:
case CPP_EOF:
return false;
+ case CPP_OPEN_PAREN:
+ /* In ((type ()) () the last () isn't a valid cast-expression,
+ so the whole must be parsed as postfix-expression. */
+ return cp_lexer_peek_nth_token (parser->lexer, 2)->type
+ != CPP_CLOSE_PAREN;
+
/* '[' may start a primary-expression in obj-c++. */
case CPP_OPEN_SQUARE:
return c_dialect_objc ();
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_tokens_start_cast_expression (parser))
{
cp_parser_parse_definitely (parser);
expr = cp_parser_cast_expression (parser,
parm_loc,
parameter,
is_non_type,
- is_parameter_pack,
- 0);
+ is_parameter_pack);
else
{
tree err_parm = build_tree_list (parameter, parameter);
typename_type,
/*complain=*/tf_error);
/* If the `typename' keyword is in effect and DECL is not a type
- decl. Then type is non existant. */
+ decl, then type is non existent. */
else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
- type = NULL_TREE;
- else
- type = check_elaborated_type_specifier (tag_type, decl,
+ ;
+ else if (TREE_CODE (decl) == TYPE_DECL)
+ type = check_elaborated_type_specifier (tag_type, decl,
/*allow_template_p=*/true);
+ else if (decl == error_mark_node)
+ type = error_mark_node;
}
if (!type)
cp_parser_require (parser, CPP_EQ, RT_EQ);
+ if (cp_parser_error_occurred (parser))
+ return error_mark_node;
+
/* Now we are going to parse the type-id of the declaration. */
/*
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
/* In C++11, [ could start a lambda-introducer. */
+ bool non_const = false;
+
cp_parser_parse_tentatively (parser);
cp_lexer_consume_token (parser->lexer);
- designator = cp_parser_constant_expression (parser, false, NULL);
+ designator = cp_parser_constant_expression (parser, true, &non_const);
cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE);
cp_parser_require (parser, CPP_EQ, RT_EQ);
if (!cp_parser_parse_definitely (parser))
designator = NULL_TREE;
+ else if (non_const)
+ require_potential_rvalue_constant_expression (designator);
}
else
designator = NULL_TREE;
bool saved_in_unbraced_linkage_specification_p;
tree old_scope = NULL_TREE;
tree scope = NULL_TREE;
- tree bases;
cp_token *closing_brace;
push_deferring_access_checks (dk_no_deferred);
/* Parse the class-head. */
type = cp_parser_class_head (parser,
- &nested_name_specifier_p,
- &attributes,
- &bases);
+ &nested_name_specifier_p);
/* If the class-head was a semantic disaster, skip the entire body
of the class. */
if (!type)
return error_mark_node;
}
- /* Process the base classes. If they're invalid, skip the
- entire class body. */
- if (!xref_basetypes (type, bases))
- {
- /* Consuming the closing brace yields better error messages
- later on. */
- if (cp_parser_skip_to_closing_brace (parser))
- cp_lexer_consume_token (parser->lexer);
- pop_deferring_access_checks ();
- return error_mark_node;
- }
-
/* Issue an error message if type-definitions are forbidden here. */
cp_parser_check_type_definition (parser);
/* Remember that we are defining one more class. */
scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
old_scope = push_inner_scope (scope);
}
- type = begin_class_definition (type, attributes);
+ type = begin_class_definition (type);
if (type == error_mark_node)
/* If the type is erroneous, skip the entire body of the class. */
static tree
cp_parser_class_head (cp_parser* parser,
- bool* nested_name_specifier_p,
- tree *attributes_p,
- tree *bases)
+ bool* nested_name_specifier_p)
{
tree nested_name_specifier;
enum tag_types class_key;
tree id = NULL_TREE;
tree type = NULL_TREE;
tree attributes;
+ tree bases;
cp_virt_specifiers virt_specifiers = VIRT_SPEC_UNSPECIFIED;
bool template_id_p = false;
bool qualified_p = false;
num_templates = 0;
parser->colon_corrects_to_scope_p = false;
- *bases = NULL_TREE;
-
/* Look for the class-key. */
class_key = cp_parser_class_key (parser);
if (class_key == none_type)
else if (type == error_mark_node)
type = NULL_TREE;
+ if (type)
+ {
+ /* Apply attributes now, before any use of the class as a template
+ argument in its base list. */
+ cplus_decl_attributes (&type, attributes, (int)ATTR_FLAG_TYPE_IN_PLACE);
+ fixup_attribute_variants (type);
+ }
+
/* We will have entered the scope containing the class; the names of
base classes should be looked up in that context. For example:
/* Get the list of base-classes, if there is one. */
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- *bases = cp_parser_base_clause (parser);
+ bases = cp_parser_base_clause (parser);
+ else
+ bases = NULL_TREE;
+
+ /* If we're really defining a class, process the base classes.
+ If they're invalid, fail. */
+ if (type && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
+ && !xref_basetypes (type, bases))
+ type = NULL_TREE;
done:
/* Leave the scope given by the nested-name-specifier. We will
if (type)
DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
- *attributes_p = attributes;
if (type && (virt_specifiers & VIRT_SPEC_FINAL))
CLASSTYPE_FINAL (type) = 1;
out:
{
/* Parse the template parameters. */
parameter_list = cp_parser_template_parameter_list (parser);
- fixup_template_parms ();
}
/* Get the deferred access checks from the parameter list. These