summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/parser.c')
-rw-r--r--contrib/gcc/cp/parser.c419
1 files changed, 280 insertions, 139 deletions
diff --git a/contrib/gcc/cp/parser.c b/contrib/gcc/cp/parser.c
index 344a8f5..fb0d1e3 100644
--- a/contrib/gcc/cp/parser.c
+++ b/contrib/gcc/cp/parser.c
@@ -1,5 +1,6 @@
/* C++ Parser.
- Copyright (C) 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002, 2003, 2004,
+ 2005 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
This file is part of GCC.
@@ -1483,9 +1484,9 @@ static void cp_parser_linkage_specification
static tree cp_parser_init_declarator
(cp_parser *, tree, tree, bool, bool, int, bool *);
static tree cp_parser_declarator
- (cp_parser *, cp_parser_declarator_kind, int *, bool *);
+ (cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
static tree cp_parser_direct_declarator
- (cp_parser *, cp_parser_declarator_kind, int *);
+ (cp_parser *, cp_parser_declarator_kind, int *, bool);
static enum tree_code cp_parser_ptr_operator
(cp_parser *, tree *, tree *);
static tree cp_parser_cv_qualifier_seq_opt
@@ -2701,7 +2702,7 @@ cp_parser_id_expression (cp_parser *parser,
/*typename_keyword_p=*/false,
check_dependency_p,
/*type_p=*/false,
- /*is_declarator=*/false)
+ declarator_p)
!= NULL_TREE);
/* If there is a nested-name-specifier, then we are looking at
the first qualified-id production. */
@@ -2850,6 +2851,7 @@ cp_parser_unqualified_id (cp_parser* parser,
tree qualifying_scope;
tree object_scope;
tree scope;
+ bool done;
/* Consume the `~' token. */
cp_lexer_consume_token (parser->lexer);
@@ -2906,6 +2908,8 @@ cp_parser_unqualified_id (cp_parser* parser,
/* If there was an explicit qualification (S::~T), first look
in the scope given by the qualification (i.e., S). */
+ done = false;
+ type_decl = NULL_TREE;
if (scope)
{
cp_parser_parse_tentatively (parser);
@@ -2917,10 +2921,10 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* In "N::S::~S", look in "N" as well. */
- if (scope && qualifying_scope)
+ if (!done && scope && qualifying_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = qualifying_scope;
@@ -2935,10 +2939,10 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* In "p->S::~T", look in the scope given by "*p" as well. */
- else if (object_scope)
+ else if (!done && object_scope)
{
cp_parser_parse_tentatively (parser);
parser->scope = object_scope;
@@ -2953,20 +2957,23 @@ cp_parser_unqualified_id (cp_parser* parser,
/*class_head_p=*/false,
declarator_p);
if (cp_parser_parse_definitely (parser))
- return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
+ done = true;
}
/* Look in the surrounding context. */
- parser->scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
- parser->qualifying_scope = NULL_TREE;
- type_decl
- = cp_parser_class_name (parser,
- /*typename_keyword_p=*/false,
- /*template_keyword_p=*/false,
- /*type_p=*/false,
- /*check_dependency=*/false,
- /*class_head_p=*/false,
- declarator_p);
+ if (!done)
+ {
+ parser->scope = NULL_TREE;
+ parser->object_scope = NULL_TREE;
+ parser->qualifying_scope = NULL_TREE;
+ type_decl
+ = cp_parser_class_name (parser,
+ /*typename_keyword_p=*/false,
+ /*template_keyword_p=*/false,
+ /*type_p=*/false,
+ /*check_dependency=*/false,
+ /*class_head_p=*/false,
+ declarator_p);
+ }
/* If an error occurred, assume that the name of the
destructor is the same as the name of the qualifying
class. That allows us to keep parsing after running
@@ -3141,6 +3148,16 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
might destroy it. */
old_scope = parser->scope;
saved_qualifying_scope = parser->qualifying_scope;
+ /* In a declarator-id like "X<T>::I::Y<T>" we must be able to
+ look up names in "X<T>::I" in order to determine that "Y" is
+ a template. So, if we have a typename at this point, we make
+ an effort to look through it. */
+ if (is_declaration
+ && !typename_keyword_p
+ && parser->scope
+ && TREE_CODE (parser->scope) == TYPENAME_TYPE)
+ parser->scope = resolve_typename_type (parser->scope,
+ /*only_current_p=*/false);
/* Parse the qualifying entity. */
new_scope
= cp_parser_class_or_namespace_name (parser,
@@ -3534,18 +3551,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
bool template_p = false;
tree id;
tree type;
+ tree scope;
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
- /* Look for the nested-name-specifier. */
- cp_parser_nested_name_specifier (parser,
- /*typename_keyword_p=*/true,
- /*check_dependency_p=*/true,
- /*type_p=*/true,
- /*is_declaration=*/true);
+ /* Look for the nested-name-specifier. In case of error here,
+ consume the trailing id to avoid subsequent error messages
+ for usual cases. */
+ scope = cp_parser_nested_name_specifier (parser,
+ /*typename_keyword_p=*/true,
+ /*check_dependency_p=*/true,
+ /*type_p=*/true,
+ /*is_declaration=*/true);
+
/* Look for the optional `template' keyword. */
template_p = cp_parser_optional_template_keyword (parser);
/* We don't know whether we're looking at a template-id or an
@@ -3558,9 +3579,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* If that didn't work, try an identifier. */
if (!cp_parser_parse_definitely (parser))
id = cp_parser_identifier (parser);
+
+ /* Don't process id if nested name specifier is invalid. */
+ if (scope == error_mark_node)
+ return error_mark_node;
/* If we look up a template-id in a non-dependent qualifying
scope, there's no need to create a dependent type. */
- if (TREE_CODE (id) == TYPE_DECL
+ else if (TREE_CODE (id) == TYPE_DECL
&& !dependent_type_p (parser->scope))
type = TREE_TYPE (id);
/* Create a TYPENAME_TYPE to represent the type to which the
@@ -3741,20 +3766,36 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
koenig_p = false;
if (idk == CP_ID_KIND_UNQUALIFIED)
{
+ if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
+ {
+ if (args)
+ {
+ koenig_p = true;
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
+ }
+ else
+ postfix_expression
+ = unqualified_fn_lookup_error (postfix_expression);
+ }
/* We do not perform argument-dependent lookup if
normal lookup finds a non-function, in accordance
with the expected resolution of DR 218. */
- if (args
- && (is_overloaded_fn (postfix_expression)
- || TREE_CODE (postfix_expression) == IDENTIFIER_NODE))
+ else if (args && is_overloaded_fn (postfix_expression))
{
- koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ tree fn = get_first_fn (postfix_expression);
+ if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
+ fn = OVL_CURRENT (TREE_OPERAND (fn, 0));
+ /* Only do argument dependent lookup if regular
+ lookup does not find a set of member functions.
+ [basic.lookup.koenig]/2a */
+ if (!DECL_FUNCTION_MEMBER_P (fn))
+ {
+ koenig_p = true;
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
+ }
}
- else if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
- postfix_expression
- = unqualified_fn_lookup_error (postfix_expression);
}
if (TREE_CODE (postfix_expression) == COMPONENT_REF)
@@ -3820,6 +3861,7 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
tree name;
bool dependent_p;
bool template_p;
+ bool pseudo_destructor_p;
tree scope = NULL_TREE;
enum cpp_ttype token_type = token->type;
@@ -3870,11 +3912,34 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
/* Consume the `.' or `->' operator. */
cp_lexer_consume_token (parser->lexer);
- /* If the SCOPE is not a scalar type, we are looking at an
- ordinary class member access expression, rather than a
- pseudo-destructor-name. */
- if (!scope || !SCALAR_TYPE_P (scope))
+
+ /* Assume this expression is not a pseudo-destructor access. */
+ pseudo_destructor_p = false;
+
+ /* If the SCOPE is a scalar type, then, if this is a valid program,
+ we must be looking at a pseudo-destructor-name. */
+ if (scope && SCALAR_TYPE_P (scope))
{
+ tree s = NULL_TREE;
+ tree type;
+
+ cp_parser_parse_tentatively (parser);
+ /* Parse the pseudo-destructor-name. */
+ cp_parser_pseudo_destructor_name (parser, &s, &type);
+ if (cp_parser_parse_definitely (parser))
+ {
+ pseudo_destructor_p = true;
+ postfix_expression
+ = finish_pseudo_destructor_expr (postfix_expression,
+ s, TREE_TYPE (type));
+ }
+ }
+
+ if (!pseudo_destructor_p)
+ {
+ /* If the SCOPE is not a scalar type, we are looking
+ at an ordinary class member access expression,
+ rather than a pseudo-destructor-name. */
template_p = cp_parser_optional_template_keyword (parser);
/* Parse the id-expression. */
name = cp_parser_id_expression (parser,
@@ -3914,19 +3979,6 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
postfix_expression
= finish_class_member_access_expr (postfix_expression, name);
}
- /* Otherwise, try the pseudo-destructor-name production. */
- else
- {
- tree s = NULL_TREE;
- tree type;
-
- /* Parse the pseudo-destructor-name. */
- cp_parser_pseudo_destructor_name (parser, &s, &type);
- /* Form the call. */
- postfix_expression
- = finish_pseudo_destructor_expr (postfix_expression,
- s, TREE_TYPE (type));
- }
/* We no longer need to look up names in the scope of the
object on the left-hand side of the `.' or `->'
@@ -5811,7 +5863,8 @@ cp_parser_condition (cp_parser* parser)
/* Parse the declarator. */
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
/* Parse the asm-specification. */
@@ -7992,6 +8045,13 @@ cp_parser_template_id (cp_parser *parser,
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
cp_lexer_purge_tokens_after (parser->lexer, token);
+
+ /* ??? Can we actually assume that, if template_id ==
+ error_mark_node, we will have issued a diagnostic to the
+ user, as opposed to simply marking the tentative parse as
+ failed? */
+ if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
+ error ("parse error in template argument list");
}
pop_deferring_access_checks ();
@@ -8095,6 +8155,7 @@ cp_parser_template_name (cp_parser* parser,
if (is_declaration
&& !template_keyword_p
&& parser->scope && TYPE_P (parser->scope)
+ && check_dependency_p
&& dependent_type_p (parser->scope)
/* Do not do this for dtors (or ctors), since they never
need the template keyword before their name. */
@@ -8170,6 +8231,8 @@ cp_parser_template_name (cp_parser* parser,
;
else
{
+ tree fn = NULL_TREE;
+
/* The standard does not explicitly indicate whether a name that
names a set of overloaded declarations, some of which are
templates, is a template-name. However, such a name should
@@ -8177,14 +8240,11 @@ cp_parser_template_name (cp_parser* parser,
template-id for the overloaded templates. */
fns = BASELINK_P (decl) ? BASELINK_FUNCTIONS (decl) : decl;
if (TREE_CODE (fns) == OVERLOAD)
- {
- tree fn;
-
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
- break;
- }
- else
+ for (fn = fns; fn; fn = OVL_NEXT (fn))
+ if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
+ break;
+
+ if (!fn)
{
/* Otherwise, the name does not name a template. */
cp_parser_error (parser, "expected template-name");
@@ -8548,7 +8608,8 @@ cp_parser_explicit_instantiation (cp_parser* parser)
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
/*ctor_dtor_or_conv_p=*/NULL,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
cp_parser_check_for_definition_in_return_type (declarator,
declares_class_or_enum);
if (declarator != error_mark_node)
@@ -8684,21 +8745,40 @@ cp_parser_type_specifier (cp_parser* parser,
keyword = token->keyword;
switch (keyword)
{
+ case RID_ENUM:
+ /* 'enum' [identifier] '{' introduces an enum-specifier;
+ 'enum' <anything else> introduces an elaborated-type-specifier. */
+ if (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_BRACE
+ || (cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_NAME
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type
+ == CPP_OPEN_BRACE))
+ {
+ if (parser->num_template_parameter_lists)
+ {
+ error ("template declaration of `enum'");
+ cp_parser_skip_to_end_of_block_or_statement (parser);
+ type_spec = error_mark_node;
+ }
+ else
+ type_spec = cp_parser_enum_specifier (parser);
+
+ if (declares_class_or_enum)
+ *declares_class_or_enum = 2;
+ return type_spec;
+ }
+ else
+ goto elaborated_type_specifier;
+
/* Any of these indicate either a class-specifier, or an
elaborated-type-specifier. */
case RID_CLASS:
case RID_STRUCT:
case RID_UNION:
- case RID_ENUM:
/* Parse tentatively so that we can back up if we don't find a
class-specifier or enum-specifier. */
cp_parser_parse_tentatively (parser);
- /* Look for the class-specifier or enum-specifier. */
- if (keyword == RID_ENUM)
- type_spec = cp_parser_enum_specifier (parser);
- else
- type_spec = cp_parser_class_specifier (parser);
-
+ /* Look for the class-specifier. */
+ type_spec = cp_parser_class_specifier (parser);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
@@ -8710,6 +8790,7 @@ cp_parser_type_specifier (cp_parser* parser,
/* Fall through. */
case RID_TYPENAME:
+ elaborated_type_specifier:
/* Look for an elaborated-type-specifier. */
type_spec = cp_parser_elaborated_type_specifier (parser,
is_friend,
@@ -9765,26 +9846,19 @@ cp_parser_asm_definition (cp_parser* parser)
/* If the next token is `::', there are no outputs, and the
next token is the beginning of the inputs. */
else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
- {
- /* Consume the `::' token. */
- cp_lexer_consume_token (parser->lexer);
- /* The inputs are coming next. */
- inputs_p = true;
- }
+ /* The inputs are coming next. */
+ inputs_p = true;
/* Look for inputs. */
if (inputs_p
|| cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
- if (!inputs_p)
- /* Consume the `:'. */
- cp_lexer_consume_token (parser->lexer);
+ /* Consume the `:' or `::'. */
+ cp_lexer_consume_token (parser->lexer);
/* Parse the output-operands. */
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_COLON)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_SCOPE)
- && cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
inputs = cp_parser_asm_operand_list (parser);
}
@@ -9796,9 +9870,8 @@ cp_parser_asm_definition (cp_parser* parser)
if (clobbers_p
|| cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
- if (!clobbers_p)
- /* Consume the `:'. */
- cp_lexer_consume_token (parser->lexer);
+ /* Consume the `:' or `::'. */
+ cp_lexer_consume_token (parser->lexer);
/* Parse the clobbers. */
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
@@ -9899,7 +9972,8 @@ cp_parser_init_declarator (cp_parser* parser,
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
/* Gather up the deferred checks. */
stop_deferring_access_checks ();
@@ -10182,13 +10256,16 @@ cp_parser_init_declarator (cp_parser* parser,
expression, not a declaration.)
If PARENTHESIZED_P is non-NULL, *PARENTHESIZED_P is set to true iff
- the declarator is a direct-declarator of the form "(...)". */
+ the declarator is a direct-declarator of the form "(...)".
+
+ MEMBER_P is true iff this declarator is a member-declarator. */
static tree
cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
int* ctor_dtor_or_conv_p,
- bool* parenthesized_p)
+ bool* parenthesized_p,
+ bool member_p)
{
cp_token *token;
tree declarator;
@@ -10229,7 +10306,8 @@ cp_parser_declarator (cp_parser* parser,
/* Parse the dependent declarator. */
declarator = cp_parser_declarator (parser, dcl_kind,
/*ctor_dtor_or_conv_p=*/NULL,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
/* If we are parsing an abstract-declarator, we must handle the
case where the dependent declarator is absent. */
@@ -10255,7 +10333,8 @@ cp_parser_declarator (cp_parser* parser,
*parenthesized_p = cp_lexer_next_token_is (parser->lexer,
CPP_OPEN_PAREN);
declarator = cp_parser_direct_declarator (parser, dcl_kind,
- ctor_dtor_or_conv_p);
+ ctor_dtor_or_conv_p,
+ member_p);
}
if (attributes && declarator != error_mark_node)
@@ -10303,7 +10382,8 @@ cp_parser_declarator (cp_parser* parser,
static tree
cp_parser_direct_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
- int* ctor_dtor_or_conv_p)
+ int* ctor_dtor_or_conv_p,
+ bool member_p)
{
cp_token *token;
tree declarator = NULL_TREE;
@@ -10362,7 +10442,14 @@ cp_parser_direct_declarator (cp_parser* parser,
tree params;
unsigned saved_num_template_parameter_lists;
- cp_parser_parse_tentatively (parser);
+ /* In a member-declarator, the only valid interpretation
+ of a parenthesis is the start of a
+ parameter-declaration-clause. (It is invalid to
+ initialize a static data member with a parenthesized
+ initializer; only the "=" form of initialization is
+ permitted.) */
+ if (!member_p)
+ cp_parser_parse_tentatively (parser);
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
@@ -10388,7 +10475,7 @@ cp_parser_direct_declarator (cp_parser* parser,
/* If all went well, parse the cv-qualifier-seq and the
exception-specification. */
- if (cp_parser_parse_definitely (parser))
+ if (member_p || cp_parser_parse_definitely (parser))
{
tree cv_qualifiers;
tree exception_specification;
@@ -10436,7 +10523,8 @@ cp_parser_direct_declarator (cp_parser* parser,
parser->in_type_id_in_expr_p = true;
declarator
= cp_parser_declarator (parser, dcl_kind, ctor_dtor_or_conv_p,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ member_p);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
first = false;
/* Expect a `)'. */
@@ -10854,7 +10942,8 @@ cp_parser_type_id (cp_parser* parser)
/* Look for the declarator. */
abstract_declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_ABSTRACT, NULL,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
/* Check to see if there really was a declarator. */
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL_TREE;
@@ -11212,7 +11301,8 @@ cp_parser_parameter_declaration (cp_parser *parser,
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL,
- parenthesized_p);
+ parenthesized_p,
+ /*member_p=*/false);
parser->default_arg_ok_p = saved_default_arg_ok_p;
/* After the declarator, allow more attributes. */
attributes = chainon (attributes, cp_parser_attributes_opt (parser));
@@ -11471,18 +11561,52 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
static tree
cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
{
- tree initializer;
+ tree initializer = NULL_TREE;
+
+ /* Assume the expression is constant. */
+ *non_constant_p = false;
/* If it is not a `{', then we are looking at an
assignment-expression. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
{
- initializer
- = cp_parser_constant_expression (parser,
- /*allow_non_constant_p=*/true,
- non_constant_p);
- if (!*non_constant_p)
- initializer = fold_non_dependent_expr (initializer);
+ /* Speed up common initializers (simply a literal). */
+ cp_token* token = cp_lexer_peek_token (parser->lexer);
+ cp_token* token2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+
+ if (token2->type == CPP_COMMA)
+ switch (token->type)
+ {
+ case CPP_CHAR:
+ case CPP_WCHAR:
+ case CPP_NUMBER:
+ token = cp_lexer_consume_token (parser->lexer);
+ initializer = token->value;
+ break;
+
+ case CPP_STRING:
+ case CPP_WSTRING:
+ token = cp_lexer_consume_token (parser->lexer);
+ if (TREE_CHAIN (token->value))
+ initializer = TREE_CHAIN (token->value);
+ else
+ initializer = token->value;
+ break;
+
+ default:
+ break;
+ }
+
+ /* Otherwise, fall back to the generic assignment expression. */
+ if (!initializer)
+ {
+ initializer
+ = cp_parser_constant_expression (parser,
+ /*allow_non_constant_p=*/true,
+ non_constant_p);
+ if (!*non_constant_p)
+ initializer = fold_non_dependent_expr (initializer);
+ }
}
else
{
@@ -11742,6 +11866,7 @@ cp_parser_class_specifier (cp_parser* parser)
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
bool pop_p = false;
+ tree scope = NULL_TREE;
push_deferring_access_checks (dk_no_deferred);
@@ -11777,7 +11902,10 @@ cp_parser_class_specifier (cp_parser* parser)
/* Start the class. */
if (nested_name_specifier_p)
- pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+ {
+ scope = CP_DECL_CONTEXT (TYPE_MAIN_DECL (type));
+ pop_p = push_scope (scope);
+ }
type = begin_class_definition (type);
if (type == error_mark_node)
/* If the type is erroneous, skip the entire body of the class. */
@@ -11800,7 +11928,7 @@ cp_parser_class_specifier (cp_parser* parser)
if (type != error_mark_node)
type = finish_struct (type, attributes);
if (pop_p)
- pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type)));
+ pop_scope (scope);
/* If this class is not itself within the scope of another class,
then we need to parse the bodies of all of the queued function
definitions. Note that the queued functions defined in a class
@@ -12071,6 +12199,15 @@ cp_parser_class_head (cp_parser* parser,
else if (nested_name_specifier)
{
tree scope;
+
+ /* Reject typedef-names in class heads. */
+ if (!DECL_IMPLICIT_TYPEDEF_P (type))
+ {
+ error ("invalid class name in declaration of `%D'", type);
+ type = NULL_TREE;
+ goto done;
+ }
+
/* Figure out in what scope the declaration is being placed. */
scope = current_scope ();
if (!scope)
@@ -12528,7 +12665,8 @@ cp_parser_member_declaration (cp_parser* parser)
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/true);
/* If something went wrong parsing the declarator, make sure
that we at least consume some tokens. */
@@ -13144,7 +13282,8 @@ cp_parser_exception_declaration (cp_parser* parser)
else
declarator = cp_parser_declarator (parser, CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL,
- /*parenthesized_p=*/NULL);
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
@@ -13409,36 +13548,39 @@ cp_parser_attribute_list (cp_parser* parser)
/* Look for the identifier. We also allow keywords here; for
example `__attribute__ ((const))' is legal. */
token = cp_lexer_peek_token (parser->lexer);
- if (token->type != CPP_NAME
- && token->type != CPP_KEYWORD)
- return error_mark_node;
- /* Consume the token. */
- token = cp_lexer_consume_token (parser->lexer);
-
- /* Save away the identifier that indicates which attribute this is. */
- identifier = token->value;
- attribute = build_tree_list (identifier, NULL_TREE);
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's an `(', then parse the attribute arguments. */
- if (token->type == CPP_OPEN_PAREN)
+ if (token->type == CPP_NAME
+ || token->type == CPP_KEYWORD)
{
- tree arguments;
+ /* Consume the token. */
+ token = cp_lexer_consume_token (parser->lexer);
- arguments = (cp_parser_parenthesized_expression_list
- (parser, true, /*non_constant_p=*/NULL));
- /* Save the identifier and arguments away. */
- TREE_VALUE (attribute) = arguments;
- }
+ /* Save away the identifier that indicates which attribute
+ this is. */
+ identifier = token->value;
+ attribute = build_tree_list (identifier, NULL_TREE);
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* If it's an `(', then parse the attribute arguments. */
+ if (token->type == CPP_OPEN_PAREN)
+ {
+ tree arguments;
+
+ arguments = (cp_parser_parenthesized_expression_list
+ (parser, true, /*non_constant_p=*/NULL));
+ /* Save the identifier and arguments away. */
+ TREE_VALUE (attribute) = arguments;
+ }
- /* Add this attribute to the list. */
- TREE_CHAIN (attribute) = attribute_list;
- attribute_list = attribute;
+ /* Add this attribute to the list. */
+ TREE_CHAIN (attribute) = attribute_list;
+ attribute_list = attribute;
- /* Now, look for more attributes. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If the next token isn't a `,', we're done. */
+ /* Now, look for more attributes. */
+ token = cp_lexer_peek_token (parser->lexer);
+ }
+ /* Now, look for more attributes. If the next token isn't a
+ `,', we're done. */
if (token->type != CPP_COMMA)
break;
@@ -14728,10 +14870,12 @@ cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
/* Parse the assignment-expression. */
- if (DECL_CLASS_SCOPE_P (fn))
+ if (DECL_FRIEND_CONTEXT (fn))
+ push_nested_class (DECL_FRIEND_CONTEXT (fn));
+ else if (DECL_CLASS_SCOPE_P (fn))
push_nested_class (DECL_CONTEXT (fn));
TREE_PURPOSE (parameters) = cp_parser_assignment_expression (parser);
- if (DECL_CLASS_SCOPE_P (fn))
+ if (DECL_FRIEND_CONTEXT (fn) || DECL_CLASS_SCOPE_P (fn))
pop_nested_class ();
/* If the token stream has not been completely used up, then
@@ -14998,9 +15142,7 @@ cp_parser_next_token_starts_class_definition_p (cp_parser *parser)
}
/* Returns TRUE iff the next token is the "," or ">" ending a
- template-argument. ">>" is also accepted (after the full
- argument was parsed) because it's probably a typo for "> >",
- and there is a specific diagnostic for this. */
+ template-argument. */
static bool
cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
@@ -15008,8 +15150,7 @@ cp_parser_next_token_ends_template_argument_p (cp_parser *parser)
cp_token *token;
token = cp_lexer_peek_token (parser->lexer);
- return (token->type == CPP_COMMA || token->type == CPP_GREATER
- || token->type == CPP_RSHIFT);
+ return (token->type == CPP_COMMA || token->type == CPP_GREATER);
}
/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
OpenPOWER on IntegriCloud