/* C++ Parser.
Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005 Free Software Foundation, Inc.
+ 2005, 2007 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2, or (at your option)
+ the Free Software Foundation; either version 3, or (at your option)
any later version.
GCC is distributed in the hope that it will be useful, but
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
- 02110-1301, USA. */
+You should have received a copy of the GNU General Public License
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
DEF_VEC_P (cp_token_position);
DEF_VEC_ALLOC_P (cp_token_position,heap);
-static const cp_token eof_token =
+static cp_token eof_token =
{
CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL },
#if USE_MAPPED_LOCATION
allocating any memory. */
cp_parser_initial_pragma (&first_token);
- /* Tell c_lex_with_flags not to merge string constants. */
- c_lex_return_raw_strings = true;
-
c_common_no_more_pch ();
/* Allocate the memory. */
lexer->buffer = buffer;
lexer->buffer_length = alloc - space;
lexer->last_token = pos;
- lexer->next_token = lexer->buffer_length ? buffer : (cp_token *)&eof_token;
+ lexer->next_token = lexer->buffer_length ? buffer : &eof_token;
/* Subsequent preprocessor diagnostics should use compiler
diagnostic functions to get the compiler source location. */
/* We do not own the buffer. */
lexer->buffer = NULL;
lexer->buffer_length = 0;
- lexer->next_token = first == last ? (cp_token *)&eof_token : first;
+ lexer->next_token = first == last ? &eof_token : first;
lexer->last_token = last;
lexer->saved_tokens = VEC_alloc (cp_token_position, heap,
}
/* Store the next token from the preprocessor in *TOKEN. Return true
- if we reach EOF. */
+ if we reach EOF. If LEXER is NULL, assume we are handling an
+ initial #pragma pch_preprocess, and thus want the lexer to return
+ processed strings. */
static void
-cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
- cp_token *token)
+cp_lexer_get_preprocessor_token (cp_lexer *lexer, cp_token *token)
{
static int is_extern_c = 0;
/* Get a new token from the preprocessor. */
token->type
- = c_lex_with_flags (&token->u.value, &token->location, &token->flags);
+ = c_lex_with_flags (&token->u.value, &token->location, &token->flags,
+ lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
token->input_file_stack_index = input_file_stack_tick;
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
/* GNU extensions. */
case RID_ATTRIBUTE:
case RID_TYPEOF:
+ /* C++0x extensions. */
+ case RID_DECLTYPE:
return true;
default:
++token;
if (token == lexer->last_token)
{
- token = (cp_token *)&eof_token;
+ token = &eof_token;
break;
}
lexer->next_token++;
if (lexer->next_token == lexer->last_token)
{
- lexer->next_token = (cp_token *)&eof_token;
+ lexer->next_token = &eof_token;
break;
}
tok++;
if (tok == lexer->last_token)
{
- tok = (cp_token *)&eof_token;
+ tok = &eof_token;
break;
}
}
static tree cp_parser_class_or_namespace_name
(cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_postfix_expression
- (cp_parser *, bool, bool);
+ (cp_parser *, bool, bool, bool);
static tree cp_parser_postfix_open_square_expression
(cp_parser *, tree, bool);
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *);
static void cp_parser_static_assert
(cp_parser *, bool);
+static tree cp_parser_decltype
+ (cp_parser *);
/* Declarators [gram.dcl.decl] */
{
if (count > 2)
error ("%<long long long%> is too long for GCC");
- else if (pedantic && !in_system_header && warn_long_long)
- pedwarn ("ISO C++ does not support %<long long%>");
+ else if (pedantic && !in_system_header && warn_long_long
+ && cxx_dialect == cxx98)
+ pedwarn ("ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
{
{
cp_lexer_consume_token (parser->lexer);
count++;
- str.text = (unsigned char *)TREE_STRING_POINTER (tok->u.value);
+ str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
if (tok->type == CPP_WSTRING)
wide = true;
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
(parse_in, strs, count, &istr, wide))
{
- value = build_string (istr.len, (char *)istr.text);
- free ((void *)istr.text);
+ value = build_string (istr.len, (const char *)istr.text);
+ free (CONST_CAST (unsigned char *, istr.text));
TREE_TYPE (value) = wide ? wchar_array_type_node : char_array_type_node;
value = fix_string_type (value);
int i = ({ int j = 3; j + 1; });
at class or namespace scope. */
- if (!parser->in_function_body)
+ if (!parser->in_function_body
+ || parser->in_template_argument_list_p)
{
- error ("statement-expressions are allowed only inside functions");
+ error ("statement-expressions are not allowed outside "
+ "functions nor in template-argument lists");
cp_parser_skip_to_end_of_block_or_statement (parser);
expr = error_mark_node;
}
&& !COMPLETE_TYPE_P (new_scope)
/* Do not try to complete dependent types. */
&& !dependent_type_p (new_scope))
- new_scope = complete_type (new_scope);
+ {
+ new_scope = complete_type (new_scope);
+ /* If it is a typedef to current class, use the current
+ class instead, as the typedef won't have any names inside
+ it yet. */
+ if (!COMPLETE_TYPE_P (new_scope)
+ && currently_open_class (new_scope))
+ new_scope = TYPE_MAIN_VARIANT (new_scope);
+ }
/* Make sure we look in the right scope the next time through
the loop. */
parser->scope = new_scope;
`&' operator. CAST_P is true if this expression is the target of a
cast.
+ If MEMBER_ACCESS_ONLY_P, we only allow postfix expressions that are
+ class member access expressions [expr.ref].
+
Returns a representation of the expression. */
static tree
-cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
+ bool member_access_only_p)
{
cp_token *token;
enum rid keyword;
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
+ bool is_member_access = false;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
postfix_expression,
false);
idk = CP_ID_KIND_NONE;
+ is_member_access = false;
break;
case CPP_OPEN_PAREN:
bool saved_non_integral_constant_expression_p = false;
tree args;
+ is_member_access = false;
+
is_builtin_constant_p
= DECL_IS_BUILTIN_CONSTANT_P (postfix_expression);
if (is_builtin_constant_p)
= cp_parser_postfix_dot_deref_expression (parser, token->type,
postfix_expression,
false, &idk);
+
+ is_member_access = true;
break;
case CPP_PLUS_PLUS:
"an increment"))
postfix_expression = error_mark_node;
idk = CP_ID_KIND_NONE;
+ is_member_access = false;
break;
case CPP_MINUS_MINUS:
"a decrement"))
postfix_expression = error_mark_node;
idk = CP_ID_KIND_NONE;
+ is_member_access = false;
break;
default:
- return postfix_expression;
+ if (member_access_only_p)
+ return is_member_access? postfix_expression : error_mark_node;
+ else
+ return postfix_expression;
}
}
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))
+ we must be looking at a pseudo-destructor-name. If POSTFIX_EXPRESSION
+ is type dependent, it can be pseudo-destructor-name or something else.
+ Try to parse it as pseudo-destructor-name first. */
+ if ((scope && SCALAR_TYPE_P (scope)) || dependent_p)
{
tree s;
tree type;
/* Parse the pseudo-destructor-name. */
s = NULL_TREE;
cp_parser_pseudo_destructor_name (parser, &s, &type);
- if (cp_parser_parse_definitely (parser))
+ if (dependent_p
+ && (cp_parser_error_occurred (parser)
+ || TREE_CODE (type) != TYPE_DECL
+ || !SCALAR_TYPE_P (TREE_TYPE (type))))
+ cp_parser_abort_tentative_parse (parser);
+ else if (cp_parser_parse_definitely (parser))
{
pseudo_destructor_p = true;
postfix_expression
tree expression_list = NULL_TREE;
bool fold_expr_p = is_attribute_list;
tree identifier = NULL_TREE;
+ bool saved_greater_than_is_operator_p;
/* Assume all the expressions will be constant. */
if (non_constant_p)
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
return error_mark_node;
+ /* Within a parenthesized expression, a `>' token is always
+ the greater-than operator. */
+ saved_greater_than_is_operator_p
+ = parser->greater_than_is_operator_p;
+ parser->greater_than_is_operator_p = true;
+
/* Consume expressions until there are no more. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
while (true)
if (ending < 0)
goto get_comma;
if (!ending)
- return error_mark_node;
+ {
+ parser->greater_than_is_operator_p
+ = saved_greater_than_is_operator_p;
+ return error_mark_node;
+ }
}
+ parser->greater_than_is_operator_p
+ = saved_greater_than_is_operator_p;
+
/* We built up the list in reverse order so we must reverse it now. */
expression_list = nreverse (expression_list);
if (identifier)
&& token->type == CPP_AND_AND)
{
tree identifier;
+ tree expression;
/* Consume the '&&' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the identifier. */
identifier = cp_parser_identifier (parser);
/* Create an expression representing the address. */
- return finish_label_address_expr (identifier);
+ expression = finish_label_address_expr (identifier);
+ if (cp_parser_non_integral_constant_expression (parser,
+ "the address of a label"))
+ expression = error_mark_node;
+ return expression;
}
}
if (unary_operator != ERROR_MARK)
return expression;
}
- return cp_parser_postfix_expression (parser, address_p, cast_p);
+ return cp_parser_postfix_expression (parser, address_p, cast_p,
+ /*member_access_only_p=*/false);
}
/* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a
type1 = cp_parser_type_id (parser);
+ if (type1 == error_mark_node)
+ return error_mark_node;
+
/* Build a trivial decl-specifier-seq. */
clear_decl_specs (&decl_specs);
decl_specs.type = type1;
type2 = cp_parser_type_id (parser);
+ if (type2 == error_mark_node)
+ return error_mark_node;
+
/* Build a trivial decl-specifier-seq. */
clear_decl_specs (&decl_specs);
decl_specs.type = type2;
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- /* Complete the trait expr, which may mean either processing the
- static assert now or saving it for template instantiation. */
+ /* Complete the trait expression, which may mean either processing
+ the trait expr now or saving it for template instantiation. */
return finish_trait_expr (kind, type1, type2);
}
compound-statement:
{ statement-seq [opt] }
+ GNU extension:
+
+ compound-statement:
+ { label-declaration-seq [opt] statement-seq [opt] }
+
+ label-declaration-seq:
+ label-declaration
+ label-declaration-seq label-declaration
+
Returns a tree representing the statement. */
static tree
return error_mark_node;
/* Begin the compound-statement. */
compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
+ /* If the next keyword is `__label__' we have a label declaration. */
+ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
+ cp_parser_label_declaration (parser);
/* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, in_statement_expr);
/* Finish the compound-statement. */
block-declaration:
__extension__ block-declaration
- label-declaration
C++0x Extension:
cp_parser_using_declaration (parser,
/*access_declaration_p=*/false);
}
- /* If the next keyword is `__label__' we have a label declaration. */
+ /* If the next keyword is `__label__' we have a misplaced label
+ declaration. */
else if (token1->keyword == RID_LABEL)
{
- if (statement_p)
- cp_parser_commit_to_tentative_parse (parser);
- cp_parser_label_declaration (parser);
+ cp_lexer_consume_token (parser->lexer);
+ error ("%<__label__%> not at the beginning of a block");
+ cp_parser_skip_to_end_of_statement (parser);
+ /* If the next token is now a `;', consume it. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
}
/* If the next token is `static_assert' we have a static assertion. */
else if (token1->keyword == RID_STATIC_ASSERT)
finish_static_assert (condition, message, saved_loc, member_p);
}
+/* Parse a `decltype' type. Returns the type.
+
+ simple-type-specifier:
+ decltype ( expression ) */
+
+static tree
+cp_parser_decltype (cp_parser *parser)
+{
+ tree expr;
+ bool id_expression_or_member_access_p = false;
+ const char *saved_message;
+ bool saved_integral_constant_expression_p;
+ bool saved_non_integral_constant_expression_p;
+
+ /* Look for the `decltype' token. */
+ if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "`decltype'"))
+ return error_mark_node;
+
+ /* Types cannot be defined in a `decltype' expression. Save away the
+ old message. */
+ saved_message = parser->type_definition_forbidden_message;
+
+ /* And create the new one. */
+ parser->type_definition_forbidden_message
+ = "types may not be defined in `decltype' expressions";
+
+ /* The restrictions on constant-expressions do not apply inside
+ decltype expressions. */
+ saved_integral_constant_expression_p
+ = parser->integral_constant_expression_p;
+ saved_non_integral_constant_expression_p
+ = parser->non_integral_constant_expression_p;
+ parser->integral_constant_expression_p = false;
+
+ /* Do not actually evaluate the expression. */
+ ++skip_evaluation;
+
+ /* Parse the opening `('. */
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ return error_mark_node;
+
+ /* First, try parsing an id-expression. */
+ cp_parser_parse_tentatively (parser);
+ expr = cp_parser_id_expression (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/true,
+ /*template_p=*/NULL,
+ /*declarator_p=*/false,
+ /*optional_p=*/false);
+
+ if (!cp_parser_error_occurred (parser) && expr != error_mark_node)
+ {
+ bool non_integral_constant_expression_p = false;
+ tree id_expression = expr;
+ cp_id_kind idk;
+ const char *error_msg;
+
+ if (TREE_CODE (expr) == IDENTIFIER_NODE)
+ /* Lookup the name we got back from the id-expression. */
+ expr = cp_parser_lookup_name (parser, expr,
+ none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ /*ambiguous_decls=*/NULL);
+
+ if (expr
+ && expr != error_mark_node
+ && TREE_CODE (expr) != TEMPLATE_ID_EXPR
+ && TREE_CODE (expr) != TYPE_DECL
+ && (TREE_CODE (expr) != BIT_NOT_EXPR
+ || !TYPE_P (TREE_OPERAND (expr, 0)))
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+ {
+ /* Complete lookup of the id-expression. */
+ expr = (finish_id_expression
+ (id_expression, expr, parser->scope, &idk,
+ /*integral_constant_expression_p=*/false,
+ /*allow_non_integral_constant_expression_p=*/true,
+ &non_integral_constant_expression_p,
+ /*template_p=*/false,
+ /*done=*/true,
+ /*address_p=*/false,
+ /*template_arg_p=*/false,
+ &error_msg));
+
+ if (expr == error_mark_node)
+ /* We found an id-expression, but it was something that we
+ should not have found. This is an error, not something
+ we can recover from, so note that we found an
+ id-expression and we'll recover as gracefully as
+ possible. */
+ id_expression_or_member_access_p = true;
+ }
+
+ if (expr
+ && expr != error_mark_node
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+ /* We have an id-expression. */
+ id_expression_or_member_access_p = true;
+ }
+
+ if (!id_expression_or_member_access_p)
+ {
+ /* Abort the id-expression parse. */
+ cp_parser_abort_tentative_parse (parser);
+
+ /* Parsing tentatively, again. */
+ cp_parser_parse_tentatively (parser);
+
+ /* Parse a class member access. */
+ expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
+ /*cast_p=*/false,
+ /*member_access_only_p=*/true);
+
+ if (expr
+ && expr != error_mark_node
+ && cp_lexer_peek_token (parser->lexer)->type == CPP_CLOSE_PAREN)
+ /* We have an id-expression. */
+ id_expression_or_member_access_p = true;
+ }
+
+ if (id_expression_or_member_access_p)
+ /* We have parsed the complete id-expression or member access. */
+ cp_parser_parse_definitely (parser);
+ else
+ {
+ /* Abort our attempt to parse an id-expression or member access
+ expression. */
+ cp_parser_abort_tentative_parse (parser);
+
+ /* Parse a full expression. */
+ expr = cp_parser_expression (parser, /*cast_p=*/false);
+ }
+
+ /* Go back to evaluating expressions. */
+ --skip_evaluation;
+
+ /* Restore the old message and the integral constant expression
+ flags. */
+ parser->type_definition_forbidden_message = saved_message;
+ parser->integral_constant_expression_p
+ = saved_integral_constant_expression_p;
+ parser->non_integral_constant_expression_p
+ = saved_non_integral_constant_expression_p;
+
+ if (expr == error_mark_node)
+ {
+ /* Skip everything up to the closing `)'. */
+ cp_parser_skip_to_closing_parenthesis (parser, true, false,
+ /*consume_paren=*/true);
+ return error_mark_node;
+ }
+
+ /* Parse to the closing `)'. */
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ {
+ cp_parser_skip_to_closing_parenthesis (parser, true, false,
+ /*consume_paren=*/true);
+ return error_mark_node;
+ }
+
+ return finish_decltype_type (expr, id_expression_or_member_access_p);
+}
+
/* Special member functions [gram.special] */
/* Parse a conversion-function-id.
double
void
+ C++0x Extension:
+
+ simple-type-specifier:
+ decltype ( expression )
+
GNU Extension:
simple-type-specifier:
type = void_type_node;
break;
+ case RID_DECLTYPE:
+ /* Parse the `decltype' type. */
+ type = cp_parser_decltype (parser);
+
+ if (decl_specs)
+ cp_parser_set_decl_spec_type (decl_specs, type,
+ /*user_defined_p=*/true);
+
+ return type;
+
case RID_TYPEOF:
/* Consume the `typeof' token. */
cp_lexer_consume_token (parser->lexer);
cp_parser_namespace_definition (cp_parser* parser)
{
tree identifier, attribs;
+ bool has_visibility;
/* Look for the `namespace' keyword. */
cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
/* Look for the `{' to start the namespace. */
cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
/* Start the namespace. */
- push_namespace_with_attribs (identifier, attribs);
+ push_namespace (identifier);
+
+ has_visibility = handle_namespace_attrs (current_namespace, attribs);
+
/* Parse the body of the namespace. */
cp_parser_namespace_body (parser);
+
+#ifdef HANDLE_PRAGMA_VISIBILITY
+ if (has_visibility)
+ pop_visibility ();
+#endif
+
/* Finish the namespace. */
pop_namespace ();
/* Look for the final `}'. */
tree asm_stmt;
bool volatile_p = false;
bool extended_p = false;
+ bool invalid_inputs_p = false;
+ bool invalid_outputs_p = false;
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, "`asm'");
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
outputs = cp_parser_asm_operand_list (parser);
+
+ if (outputs == error_mark_node)
+ invalid_outputs_p = true;
}
/* If the next token is `::', there are no outputs, and the
next token is the beginning of the inputs. */
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
inputs = cp_parser_asm_operand_list (parser);
+
+ if (inputs == error_mark_node)
+ invalid_inputs_p = true;
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
/* The clobbers are coming next. */
/*consume_paren=*/true);
cp_parser_require (parser, CPP_SEMICOLON, "`;'");
- /* Create the ASM_EXPR. */
- if (parser->in_function_body)
+ if (!invalid_inputs_p && !invalid_outputs_p)
{
- asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
- inputs, clobbers);
- /* If the extended syntax was not used, mark the ASM_EXPR. */
- if (!extended_p)
+ /* Create the ASM_EXPR. */
+ if (parser->in_function_body)
{
- tree temp = asm_stmt;
- if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
- temp = TREE_OPERAND (temp, 0);
+ asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
+ inputs, clobbers);
+ /* If the extended syntax was not used, mark the ASM_EXPR. */
+ if (!extended_p)
+ {
+ tree temp = asm_stmt;
+ if (TREE_CODE (temp) == CLEANUP_POINT_EXPR)
+ temp = TREE_OPERAND (temp, 0);
- ASM_INPUT_P (temp) = 1;
+ ASM_INPUT_P (temp) = 1;
+ }
}
+ else
+ cgraph_add_asm_node (string);
}
- else
- cgraph_add_asm_node (string);
}
/* Declarators [gram.dcl.decl] */
token = cp_lexer_consume_token (parser->lexer);
}
- /* Create a DEFAULT_ARG to represented the unparsed default
+ /* Create a DEFAULT_ARG to represent the unparsed default
argument. */
default_argument = make_node (DEFAULT_ARG);
DEFARG_TOKENS (default_argument)
class was originally declared, the program is invalid. */
if (scope && !is_ancestor (scope, nested_name_specifier))
{
- error ("declaration of %qD in %qD which does not enclose %qD",
- type, scope, nested_name_specifier);
+ if (at_namespace_scope_p ())
+ error ("declaration of %qD in namespace %qD which does not "
+ "enclose %qD", type, scope, nested_name_specifier);
+ else
+ error ("declaration of %qD in %qD which does not enclose %qD",
+ type, scope, nested_name_specifier);
type = NULL_TREE;
goto done;
}
/* Look up the type. */
if (template_id_p)
{
- type = TREE_TYPE (id);
- type = maybe_process_partial_specialization (type);
+ if (TREE_CODE (id) == TEMPLATE_ID_EXPR
+ && (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
+ || TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
+ {
+ error ("function template %qD redeclared as a class template", id);
+ type = error_mark_node;
+ }
+ else
+ {
+ type = TREE_TYPE (id);
+ type = maybe_process_partial_specialization (type);
+ }
if (nested_name_specifier)
pushed_scope = push_scope (nested_name_specifier);
}
token = cp_lexer_peek_token (parser->lexer);
/* If the next token is a semicolon, consume it. */
if (token->type == CPP_SEMICOLON)
- {
- if (pedantic && !in_system_header)
- pedwarn ("extra %<;%>");
- cp_lexer_consume_token (parser->lexer);
- }
+ cp_lexer_consume_token (parser->lexer);
return;
}
else
/* Make this a pack expansion type. */
TREE_VALUE (base) = make_pack_expansion (TREE_VALUE (base));
else
- check_for_bare_parameter_packs (TREE_VALUE (base));
+ check_for_bare_parameter_packs (&TREE_VALUE (base));
TREE_CHAIN (base) = bases;
bases = base;
each node is the expression. The TREE_PURPOSE is itself a
TREE_LIST whose TREE_PURPOSE is a STRING_CST for the bracketed
string-literal (or NULL_TREE if not present) and whose TREE_VALUE
- is a STRING_CST for the string literal before the parenthesis. */
+ is a STRING_CST for the string literal before the parenthesis. Returns
+ ERROR_MARK_NODE if any of the operands are invalid. */
static tree
cp_parser_asm_operand_list (cp_parser* parser)
{
tree asm_operands = NULL_TREE;
+ bool invalid_operands = false;
while (true)
{
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ if (name == error_mark_node
+ || string_literal == error_mark_node
+ || expression == error_mark_node)
+ invalid_operands = true;
+
/* Add this operand to the list. */
asm_operands = tree_cons (build_tree_list (name, string_literal),
expression,
cp_lexer_consume_token (parser->lexer);
}
- return nreverse (asm_operands);
+ return invalid_operands ? error_mark_node : nreverse (asm_operands);
}
/* Parse an asm-clobber-list.
static const char *format;
tree expr = NULL_TREE;
const char *saved_message;
+ char *tmp;
bool saved_integral_constant_expression_p;
bool saved_non_integral_constant_expression_p;
bool pack_expansion_p = false;
old message. */
saved_message = parser->type_definition_forbidden_message;
/* And create the new one. */
- parser->type_definition_forbidden_message
- = XNEWVEC (const char, strlen (format)
+ parser->type_definition_forbidden_message = tmp
+ = XNEWVEC (char, strlen (format)
+ strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
+ 1 /* `\0' */);
- sprintf ((char *) parser->type_definition_forbidden_message,
- format, IDENTIFIER_POINTER (ridpointers[keyword]));
+ sprintf (tmp, format, IDENTIFIER_POINTER (ridpointers[keyword]));
/* The restrictions on constant-expressions do not apply inside
sizeof expressions. */
--skip_evaluation;
/* Free the message we created. */
- free ((char *) parser->type_definition_forbidden_message);
+ free (tmp);
/* And restore the old one. */
parser->type_definition_forbidden_message = saved_message;
parser->integral_constant_expression_p
static void
cp_parser_check_access_in_redeclaration (tree decl)
{
- if (!CLASS_TYPE_P (TREE_TYPE (decl)))
+ if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
return;
if ((TREE_PRIVATE (decl)
const char *where, cp_token *pragma_tok)
{
tree clauses = NULL;
+ bool first = true;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
- pragma_omp_clause c_kind = cp_parser_omp_clause_name (parser);
+ pragma_omp_clause c_kind;
const char *c_name;
tree prev = clauses;
+ if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
+
+ c_kind = cp_parser_omp_clause_name (parser);
+ first = false;
+
switch (c_kind)
{
case PRAGMA_OMP_CLAUSE_COPYIN:
switch (p_kind)
{
case PRAGMA_OMP_PARALLEL:
- cp_parser_already_scoped_statement (parser);
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
par_clause = clauses;
break;