aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/parser.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@codesourcery.com>2003-07-11 09:18:01 +0000
committerNathan Sidwell <nathan@gcc.gnu.org>2003-07-11 09:18:01 +0000
commit7efa3e22e56fdd56b73deb940c47a5beac0b866e (patch)
tree37b398ebca5e5e9e4db16502deb7f9b40fb49cff /gcc/cp/parser.c
parent87ca53f644a27a18266933cf0996e8bf1097cf24 (diff)
downloadgcc-7efa3e22e56fdd56b73deb940c47a5beac0b866e.zip
gcc-7efa3e22e56fdd56b73deb940c47a5beac0b866e.tar.gz
gcc-7efa3e22e56fdd56b73deb940c47a5beac0b866e.tar.bz2
re PR c++/11050 ("some string" __FUNCTION__ is accepted)
cp: PR c++/11050 * parser.c (cp_parser_expression_list): Rename to ... (cp_parser_parenthesized_expression_list): ... here. Add attribute parameter, parse the surounding parentheses. (cp_parser_skip_to_closing_parenthesis): Add recover and or_comma parameters. Return int. (cp_parser_skip_to_closing_parenthesis or comma): Remove. (cp_parser_postfix_expression): Adjust function call parsing. (cp_parser_new_placement): Adjust. (cp_parser_new_initializer): Likewise. (cp_parser_cast_expression): Likewise. (cp_parser_selection_statement): Likewise. (cp_parser_mem_initializer): Likewise. (cp_parser_asm_definition): Likewise. (cp_parser_init_declarator): Likewise. (cp_parser_declarator): Make cdtor_or_conv_p an int ptr. (cp_parser_direct_declarator): Likewise. Check for a parameter list on cdtors & conv functions. (cp_parser_initializer): Adjust. (cp_parser_member_declaration): Adjust. (cp_parser_attribute_list): Move code into cp_parser_parens_expression_list. (cp_parser_functional_cast): Adjust. * pt.c (type_dependent_expression_p): Erroneous expressions are non-dependent. testsuite: PR c++/11050 * g++.dg/parse/args1.C: New test. * g++.pt/defarg8.C: Change expected errors. From-SVN: r69230
Diffstat (limited to 'gcc/cp/parser.c')
-rw-r--r--gcc/cp/parser.c348
1 files changed, 163 insertions, 185 deletions
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index da8eb08..33c88b1 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -1324,8 +1324,8 @@ static tree cp_parser_class_or_namespace_name
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_postfix_expression
(cp_parser *, bool);
-static tree cp_parser_expression_list
- (cp_parser *);
+static tree cp_parser_parenthesized_expression_list
+ (cp_parser *, bool);
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression
@@ -1467,9 +1467,9 @@ static void cp_parser_linkage_specification
static tree cp_parser_init_declarator
(cp_parser *, tree, tree, bool, bool, bool *);
static tree cp_parser_declarator
- (cp_parser *, cp_parser_declarator_kind, bool *);
+ (cp_parser *, cp_parser_declarator_kind, int *);
static tree cp_parser_direct_declarator
- (cp_parser *, cp_parser_declarator_kind, bool *);
+ (cp_parser *, cp_parser_declarator_kind, int *);
static enum tree_code cp_parser_ptr_operator
(cp_parser *, tree *, tree *);
static tree cp_parser_cv_qualifier_seq_opt
@@ -1699,10 +1699,8 @@ static tree cp_parser_non_constant_id_expression
(tree);
static bool cp_parser_diagnose_invalid_type_name
(cp_parser *);
-static bool cp_parser_skip_to_closing_parenthesis
- (cp_parser *);
-static bool cp_parser_skip_to_closing_parenthesis_or_comma
- (cp_parser *);
+static int cp_parser_skip_to_closing_parenthesis
+ (cp_parser *, bool, bool);
static void cp_parser_skip_to_end_of_statement
(cp_parser *);
static void cp_parser_consume_semicolon_at_end_of_statement
@@ -1880,57 +1878,60 @@ cp_parser_diagnose_invalid_type_name (cp_parser *parser)
}
/* Consume tokens up to, and including, the next non-nested closing `)'.
- Returns TRUE iff we found a closing `)'. */
+ Returns 1 iff we found a closing `)'. RECOVERING is true, if we
+ are doing error recovery. Returns -1 if OR_COMMA is true and we
+ found an unnested comma. */
-static bool
-cp_parser_skip_to_closing_parenthesis (cp_parser *parser)
+static int
+cp_parser_skip_to_closing_parenthesis (cp_parser *parser,
+ bool recovering, bool or_comma)
{
- unsigned nesting_depth = 0;
+ unsigned paren_depth = 0;
+ unsigned brace_depth = 0;
+ if (recovering && !or_comma && cp_parser_parsing_tentatively (parser)
+ && !cp_parser_committed_to_tentative_parse (parser))
+ return 0;
+
while (true)
{
cp_token *token;
-
+
/* If we've run out of tokens, then there is no closing `)'. */
if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
- return false;
- /* Consume the token. */
- token = cp_lexer_consume_token (parser->lexer);
- /* If it is an `(', we have entered another level of nesting. */
- if (token->type == CPP_OPEN_PAREN)
- ++nesting_depth;
- /* If it is a `)', then we might be done. */
- else if (token->type == CPP_CLOSE_PAREN && nesting_depth-- == 0)
- return true;
- }
-}
-
-/* Consume tokens until the next token is a `)', or a `,'. Returns
- TRUE if the next token is a `,'. */
+ return 0;
-static bool
-cp_parser_skip_to_closing_parenthesis_or_comma (cp_parser *parser)
-{
- unsigned nesting_depth = 0;
-
- while (true)
- {
- cp_token *token = cp_lexer_peek_token (parser->lexer);
+ if (recovering)
+ {
+ token = cp_lexer_peek_token (parser->lexer);
- /* If we've run out of tokens, then there is no closing `)'. */
- if (token->type == CPP_EOF)
- return false;
- /* If it is a `,' stop. */
- else if (token->type == CPP_COMMA && nesting_depth-- == 0)
- return true;
- /* If it is a `)', stop. */
- else if (token->type == CPP_CLOSE_PAREN && nesting_depth-- == 0)
- return false;
- /* If it is an `(', we have entered another level of nesting. */
- else if (token->type == CPP_OPEN_PAREN)
- ++nesting_depth;
+ /* This matches the processing in skip_to_end_of_statement */
+ if (token->type == CPP_SEMICOLON && !brace_depth)
+ return 0;
+ if (token->type == CPP_OPEN_BRACE)
+ ++brace_depth;
+ if (token->type == CPP_CLOSE_BRACE)
+ {
+ if (!brace_depth--)
+ return 0;
+ }
+ if (or_comma && token->type == CPP_COMMA
+ && !brace_depth && !paren_depth)
+ return -1;
+ }
+
/* Consume the token. */
token = cp_lexer_consume_token (parser->lexer);
+
+ if (!brace_depth)
+ {
+ /* If it is an `(', we have entered another level of nesting. */
+ if (token->type == CPP_OPEN_PAREN)
+ ++paren_depth;
+ /* If it is a `)', then we might be done. */
+ else if (token->type == CPP_CLOSE_PAREN && !paren_depth--)
+ return 1;
+ }
}
}
@@ -3762,19 +3763,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
case CPP_OPEN_PAREN:
/* postfix-expression ( expression-list [opt] ) */
{
- tree args;
+ tree args = cp_parser_parenthesized_expression_list (parser, false);
- /* Consume the `(' token. */
- cp_lexer_consume_token (parser->lexer);
- /* If the next token is not a `)', then there are some
- arguments. */
- if (cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
- args = cp_parser_expression_list (parser);
- else
- args = NULL_TREE;
- /* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ if (args == error_mark_node)
+ {
+ postfix_expression = error_mark_node;
+ break;
+ }
+
/* Function calls are not permitted in
constant-expressions. */
if (parser->constant_expression_p)
@@ -4054,51 +4050,100 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
return error_mark_node;
}
-/* Parse an expression-list.
+/* Parse a parenthesized expression-list.
expression-list:
assignment-expression
expression-list, assignment-expression
+ attribute-list:
+ expression-list
+ identifier
+ identifier, expression-list
+
Returns a TREE_LIST. The TREE_VALUE of each node is a
representation of an assignment-expression. Note that a TREE_LIST
- is returned even if there is only a single expression in the list. */
+ is returned even if there is only a single expression in the list.
+ error_mark_node is returned if the ( and or ) are
+ missing. NULL_TREE is returned on no expressions. The parentheses
+ are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
+ list being parsed. */
static tree
-cp_parser_expression_list (cp_parser* parser)
+cp_parser_parenthesized_expression_list (cp_parser* parser, bool is_attribute_list)
{
tree expression_list = NULL_TREE;
-
+ tree identifier = NULL_TREE;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ return error_mark_node;
+
/* Consume expressions until there are no more. */
- while (true)
- {
- tree expr;
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+ while (true)
+ {
+ tree expr;
+
+ /* At the beginning of attribute lists, check to see if the
+ next token is an identifier. */
+ if (is_attribute_list
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
+ {
+ cp_token *token;
+
+ /* Consume the identifier. */
+ token = cp_lexer_consume_token (parser->lexer);
+ /* Save the identifier. */
+ identifier = token->value;
+ }
+ else
+ {
+ /* Parse the next assignment-expression. */
+ expr = cp_parser_assignment_expression (parser);
- /* Parse the next assignment-expression. */
- expr = cp_parser_assignment_expression (parser);
- /* Add it to the list. */
- expression_list = tree_cons (NULL_TREE, expr, expression_list);
+ /* Add it to the list. We add error_mark_node
+ expressions to the list, so that we can still tell if
+ the correct form for a parenthesized expression-list
+ is found. That gives better errors. */
+ expression_list = tree_cons (NULL_TREE, expr, expression_list);
- /* If the next token isn't a `,', then we are done. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
- {
- /* All uses of expression-list in the grammar are followed
- by a `)'. Therefore, if the next token is not a `)' an
- error will be issued, unless we are parsing tentatively.
- Skip ahead to see if there is another `,' before the `)';
- if so, we can go there and recover. */
- if (cp_parser_parsing_tentatively (parser)
- || cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
- || !cp_parser_skip_to_closing_parenthesis_or_comma (parser))
- break;
- }
+ if (expr == error_mark_node)
+ goto skip_comma;
+ }
- /* Otherwise, consume the `,' and keep going. */
- cp_lexer_consume_token (parser->lexer);
+ /* After the first item, attribute lists look the same as
+ expression lists. */
+ is_attribute_list = false;
+
+ get_comma:;
+ /* If the next token isn't a `,', then we are done. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+
+ /* Otherwise, consume the `,' and keep going. */
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ {
+ int ending;
+
+ skip_comma:;
+ /* We try and resync to an unnested comma, as that will give the
+ user better diagnostics. */
+ ending = cp_parser_skip_to_closing_parenthesis (parser, true, true);
+ if (ending < 0)
+ goto get_comma;
+ if (!ending)
+ return error_mark_node;
}
/* We built up the list in reverse order so we must reverse it now. */
- return nreverse (expression_list);
+ expression_list = nreverse (expression_list);
+ if (identifier)
+ expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+
+ return expression_list;
}
/* Parse a pseudo-destructor-name.
@@ -4463,13 +4508,8 @@ cp_parser_new_placement (cp_parser* parser)
{
tree expression_list;
- /* Look for the opening `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
- return error_mark_node;
/* Parse the expression-list. */
- expression_list = cp_parser_expression_list (parser);
- /* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ expression_list = cp_parser_parenthesized_expression_list (parser, false);
return expression_list;
}
@@ -4633,16 +4673,9 @@ cp_parser_new_initializer (cp_parser* parser)
{
tree expression_list;
- /* Look for the opening parenthesis. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
- /* If the next token is not a `)', then there is an
- expression-list. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
- expression_list = cp_parser_expression_list (parser);
- else
+ expression_list = cp_parser_parenthesized_expression_list (parser, false);
+ if (!expression_list)
expression_list = void_zero_node;
- /* Look for the closing parenthesis. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
return expression_list;
}
@@ -4738,7 +4771,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
If we find the closing `)', and the next token is a `{', then
we are looking at a compound-literal. */
compound_literal_p
- = (cp_parser_skip_to_closing_parenthesis (parser)
+ = (cp_parser_skip_to_closing_parenthesis (parser, false, false)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE));
/* Roll back the tokens we skipped. */
cp_lexer_rollback_tokens (parser->lexer);
@@ -5673,7 +5706,7 @@ cp_parser_selection_statement (cp_parser* parser)
condition = cp_parser_condition (parser);
/* Look for the `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
- cp_parser_skip_to_closing_parenthesis (parser);
+ cp_parser_skip_to_closing_parenthesis (parser, true, false);
if (keyword == RID_IF)
{
@@ -7072,17 +7105,10 @@ cp_parser_mem_initializer (cp_parser* parser)
member = expand_member_init (mem_initializer_id);
if (member && !DECL_P (member))
in_base_initializer = 1;
-
- /* Look for the opening `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
- /* Parse the expression-list. */
- if (cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
- expression_list = cp_parser_expression_list (parser);
- else
+
+ expression_list = cp_parser_parenthesized_expression_list (parser, false);
+ if (!expression_list)
expression_list = void_type_node;
- /* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
in_base_initializer = 0;
@@ -9401,7 +9427,7 @@ cp_parser_asm_definition (cp_parser* parser)
}
/* Look for the closing `)'. */
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
- cp_parser_skip_to_closing_parenthesis (parser);
+ cp_parser_skip_to_closing_parenthesis (parser, true, false);
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
/* Create the ASM_STMT. */
@@ -9462,7 +9488,7 @@ cp_parser_init_declarator (cp_parser* parser,
tree scope;
bool is_initialized;
bool is_parenthesized_init;
- bool ctor_dtor_or_conv_p;
+ int ctor_dtor_or_conv_p;
bool friend_p;
/* Assume that this is not the declarator for a function
@@ -9548,7 +9574,7 @@ cp_parser_init_declarator (cp_parser* parser,
We explicitly postpone this check past the point where we handle
function-definitions because we tolerate function-definitions
that are missing their return types in some modes. */
- if (!decl_specifiers && !ctor_dtor_or_conv_p)
+ if (!decl_specifiers && ctor_dtor_or_conv_p <= 0)
{
cp_parser_error (parser,
"expected constructor, destructor, or type conversion");
@@ -9720,10 +9746,12 @@ cp_parser_init_declarator (cp_parser* parser,
cv-qualifiers will be stored in the TREE_TYPE of the INDIRECT_REF
node.
- If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is set to
- true if this declarator represents a constructor, destructor, or
- type conversion operator. Otherwise, it is set to false.
-
+ If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
+ detect constructor, destructor or conversion operators. It is set
+ to -1 if the declarator is a name, and +1 if it is a
+ function. Otherwise it is set to zero. Usually you just want to
+ test for >0, but internally the negative value is used.
+
(The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have
a decl-specifier-seq unless it declares a constructor, destructor,
or conversion. It might seem that we could check this condition in
@@ -9735,7 +9763,7 @@ cp_parser_init_declarator (cp_parser* parser,
static tree
cp_parser_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
- bool* ctor_dtor_or_conv_p)
+ int* ctor_dtor_or_conv_p)
{
cp_token *token;
tree declarator;
@@ -9747,7 +9775,7 @@ cp_parser_declarator (cp_parser* parser,
/* Assume this is not a constructor, destructor, or type-conversion
operator. */
if (ctor_dtor_or_conv_p)
- *ctor_dtor_or_conv_p = false;
+ *ctor_dtor_or_conv_p = 0;
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_attributes_opt (parser);
@@ -9792,8 +9820,7 @@ cp_parser_declarator (cp_parser* parser,
}
/* Everything else is a direct-declarator. */
else
- declarator = cp_parser_direct_declarator (parser,
- dcl_kind,
+ declarator = cp_parser_direct_declarator (parser, dcl_kind,
ctor_dtor_or_conv_p);
if (attributes && declarator != error_mark_node)
@@ -9841,7 +9868,7 @@ cp_parser_declarator (cp_parser* parser,
static tree
cp_parser_direct_declarator (cp_parser* parser,
cp_parser_declarator_kind dcl_kind,
- bool* ctor_dtor_or_conv_p)
+ int* ctor_dtor_or_conv_p)
{
cp_token *token;
tree declarator = NULL_TREE;
@@ -9919,7 +9946,9 @@ cp_parser_direct_declarator (cp_parser* parser,
{
tree cv_qualifiers;
tree exception_specification;
-
+
+ if (ctor_dtor_or_conv_p)
+ *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
first = false;
/* Consume the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
@@ -9976,6 +10005,9 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse an array-declarator. */
tree bounds;
+ if (ctor_dtor_or_conv_p)
+ *ctor_dtor_or_conv_p = 0;
+
first = false;
parser->default_arg_ok_p = false;
parser->in_declarator_p = true;
@@ -10091,7 +10123,7 @@ cp_parser_direct_declarator (cp_parser* parser,
if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR
|| IDENTIFIER_TYPENAME_P (unqualified_name)
|| constructor_name_p (unqualified_name, class_type))
- *ctor_dtor_or_conv_p = true;
+ *ctor_dtor_or_conv_p = -1;
}
handle_declarator:;
@@ -11052,15 +11084,7 @@ cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init)
init = cp_parser_initializer_clause (parser);
}
else if (token->type == CPP_OPEN_PAREN)
- {
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Parse the expression-list. */
- init = cp_parser_expression_list (parser);
- /* Consume the `)' token. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
- cp_parser_skip_to_closing_parenthesis (parser);
- }
+ init = cp_parser_parenthesized_expression_list (parser, false);
else
{
/* Anything else is an error. */
@@ -12057,7 +12081,7 @@ cp_parser_member_declaration (cp_parser* parser)
tree declarator;
tree initializer;
tree asm_specification;
- bool ctor_dtor_or_conv_p;
+ int ctor_dtor_or_conv_p;
/* Parse the declarator. */
declarator
@@ -12923,47 +12947,11 @@ cp_parser_attribute_list (cp_parser* parser)
if (token->type == CPP_OPEN_PAREN)
{
tree arguments;
- int arguments_allowed_p = 1;
-
- /* Consume the `('. */
- cp_lexer_consume_token (parser->lexer);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* Check to see if the next token is an identifier. */
- if (token->type == CPP_NAME)
- {
- /* Save the identifier. */
- identifier = token->value;
- /* Consume the identifier. */
- cp_lexer_consume_token (parser->lexer);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If the next token is a `,', then there are some other
- expressions as well. */
- if (token->type == CPP_COMMA)
- /* Consume the comma. */
- cp_lexer_consume_token (parser->lexer);
- else
- arguments_allowed_p = 0;
- }
- else
- identifier = NULL_TREE;
- /* If there are arguments, parse them too. */
- if (arguments_allowed_p)
- arguments = cp_parser_expression_list (parser);
- else
- arguments = NULL_TREE;
-
- /* Combine the identifier and the arguments. */
- if (identifier)
- arguments = tree_cons (NULL_TREE, identifier, arguments);
+ arguments = cp_parser_parenthesized_expression_list (parser, true);
/* Save the identifier and arguments away. */
TREE_VALUE (attribute) = arguments;
-
- /* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
}
/* Add this attribute to the list. */
@@ -13926,17 +13914,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
{
tree expression_list;
- /* Look for the opening `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
- return error_mark_node;
- /* If the next token is not an `)', there are arguments to the
- cast. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
- expression_list = cp_parser_expression_list (parser);
- else
- expression_list = NULL_TREE;
- /* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ expression_list = cp_parser_parenthesized_expression_list (parser, false);
return build_functional_cast (type, expression_list);
}