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.c129
1 files changed, 94 insertions, 35 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 3db7f2ee9f6..944efe185a3 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1510,7 +1510,7 @@ static tree cp_parser_declarator_id
static tree cp_parser_type_id
(cp_parser *);
static void cp_parser_type_specifier_seq
- (cp_parser *, cp_decl_specifier_seq *);
+ (cp_parser *, bool, cp_decl_specifier_seq *);
static cp_parameter_declarator *cp_parser_parameter_declaration_clause
(cp_parser *);
static cp_parameter_declarator *cp_parser_parameter_declaration_list
@@ -1787,6 +1787,16 @@ cp_parser_is_keyword (cp_token* token, enum rid keyword)
return token->keyword == keyword;
}
+/* A minimum or maximum operator has been seen. As these are
+ deprecated, issue a warning. */
+
+static inline void
+cp_parser_warn_min_max (void)
+{
+ if (warn_deprecated && !in_system_header)
+ warning ("minimum/maximum operators are deprecated");
+}
+
/* If not parsing tentatively, issue a diagnostic of the form
FILE:LINE: MESSAGE before TOKEN
where TOKEN is the next token in the input stream. MESSAGE
@@ -1995,7 +2005,8 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
template <typename T> struct B : public A<T> { X x; };
The user should have said "typename A<T>::X". */
- if (processing_template_decl && current_class_type)
+ if (processing_template_decl && current_class_type
+ && TYPE_BINFO (current_class_type))
{
tree b;
@@ -3860,18 +3871,22 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_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
@@ -3884,9 +3899,13 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_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
@@ -4954,7 +4973,8 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
parser->type_definition_forbidden_message
= "types may not be defined in a new-type-id";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifier_seq);
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
/* Parse the new-declarator. */
@@ -5392,6 +5412,9 @@ cp_parser_binary_expression (cp_parser* parser, bool cast_p)
{
/* Get an operator token. */
token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_MIN || token->type == CPP_MAX)
+ cp_parser_warn_min_max ();
+
new_prec = TOKEN_PRECEDENCE (token);
/* Popping an entry off the stack means we completed a subexpression:
@@ -5647,10 +5670,12 @@ cp_parser_assignment_operator_opt (cp_parser* parser)
case CPP_MIN_EQ:
op = MIN_EXPR;
+ cp_parser_warn_min_max ();
break;
case CPP_MAX_EQ:
op = MAX_EXPR;
+ cp_parser_warn_min_max ();
break;
default:
@@ -6281,7 +6306,8 @@ cp_parser_condition (cp_parser* parser)
parser->type_definition_forbidden_message
= "types may not be defined in conditions";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, &type_specifiers);
+ cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
+ &type_specifiers);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* If all is well, we might be looking at a declaration. */
@@ -7540,7 +7566,8 @@ cp_parser_conversion_type_id (cp_parser* parser)
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
/* Parse the type-specifiers. */
- cp_parser_type_specifier_seq (parser, &type_specifiers);
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifiers);
/* If that didn't work, stop. */
if (type_specifiers.type == error_mark_node)
return error_mark_node;
@@ -8030,18 +8057,22 @@ cp_parser_operator (cp_parser* parser)
/* Extensions. */
case CPP_MIN:
id = ansi_opname (MIN_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MAX:
id = ansi_opname (MAX_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MIN_EQ:
id = ansi_assopname (MIN_EXPR);
+ cp_parser_warn_min_max ();
break;
case CPP_MAX_EQ:
id = ansi_assopname (MAX_EXPR);
+ cp_parser_warn_min_max ();
break;
default:
@@ -8703,6 +8734,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
@@ -8710,16 +8743,13 @@ 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;
- for (fn = fns; fn; fn = OVL_NEXT (fn))
- if (TREE_CODE (OVL_CURRENT (fn)) == TEMPLATE_DECL)
- break;
- }
- else
+ if (!fn)
{
- /* Otherwise, the name does not name a template. */
+ /* The name does not name a template. */
cp_parser_error (parser, "expected template-name");
return error_mark_node;
}
@@ -11475,7 +11505,8 @@ cp_parser_type_id (cp_parser* parser)
cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifier_seq);
if (type_specifier_seq.type == error_mark_node)
return error_mark_node;
@@ -11503,13 +11534,18 @@ cp_parser_type_id (cp_parser* parser)
type-specifier-seq:
attributes type-specifier-seq [opt]
+ If IS_CONDITION is true, we are at the start of a "condition",
+ e.g., we've just seen "if (".
+
Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */
static void
cp_parser_type_specifier_seq (cp_parser* parser,
+ bool is_condition,
cp_decl_specifier_seq *type_specifier_seq)
{
bool seen_type_specifier = false;
+ cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
/* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq);
@@ -11518,6 +11554,7 @@ cp_parser_type_specifier_seq (cp_parser* parser,
while (true)
{
tree type_specifier;
+ bool is_cv_qualifier;
/* Check for attributes first. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
@@ -11530,25 +11567,45 @@ cp_parser_type_specifier_seq (cp_parser* parser,
/* Look for the type-specifier. */
type_specifier = cp_parser_type_specifier (parser,
- CP_PARSER_FLAGS_OPTIONAL,
+ flags,
type_specifier_seq,
/*is_declaration=*/false,
NULL,
- NULL);
- /* If the first type-specifier could not be found, this is not a
- type-specifier-seq at all. */
- if (!seen_type_specifier && !type_specifier)
+ &is_cv_qualifier);
+ if (!type_specifier)
{
- cp_parser_error (parser, "expected type-specifier");
- type_specifier_seq->type = error_mark_node;
- return;
+ /* If the first type-specifier could not be found, this is not a
+ type-specifier-seq at all. */
+ if (!seen_type_specifier)
+ {
+ cp_parser_error (parser, "expected type-specifier");
+ type_specifier_seq->type = error_mark_node;
+ return;
+ }
+ /* If subsequent type-specifiers could not be found, the
+ type-specifier-seq is complete. */
+ break;
}
- /* If subsequent type-specifiers could not be found, the
- type-specifier-seq is complete. */
- else if (seen_type_specifier && !type_specifier)
- break;
seen_type_specifier = true;
+ /* The standard says that a condition can be:
+
+ type-specifier-seq declarator = assignment-expression
+
+ However, given:
+
+ struct S {};
+ if (int S = ...)
+
+ we should treat the "S" as a declarator, not as a
+ type-specifier. The standard doesn't say that explicitly for
+ type-specifier-seq, but it does say that for
+ decl-specifier-seq in an ordinary declaration. Perhaps it
+ would be clearer just to allow a decl-specifier-seq here, and
+ then add a semantic restriction that if any decl-specifiers
+ that are not type-specifiers appear, the program is invalid. */
+ if (is_condition && !is_cv_qualifier)
+ flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
return;
@@ -12848,7 +12905,8 @@ cp_parser_class_head (cp_parser* parser,
{
error ("redefinition of %q#T", type);
cp_error_at ("previous definition of %q#T", type);
- type = error_mark_node;
+ type = NULL_TREE;
+ goto done;
}
/* We will have entered the scope containing the class; the names of
@@ -13801,7 +13859,8 @@ cp_parser_exception_declaration (cp_parser* parser)
= "types may not be defined in exception-declarations";
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, &type_specifiers);
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifiers);
/* If it's a `)', then there is no declarator. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
declarator = NULL;