/* C++ Parser.
Copyright (C) 2000, 2001, 2002, 2003, 2004,
- 2005, 2007, 2008 Free Software Foundation, Inc.
+ 2005, 2007, 2008, 2009 Free Software Foundation, Inc.
Written by Mark Mitchell <mark@codesourcery.com>.
This file is part of GCC.
#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+#include "plugin.h"
\f
/* The lexer. */
/* A token's value and its associated deferred access checks and
qualifying scope. */
-struct tree_check GTY(())
-{
+struct GTY(()) tree_check {
/* The value associated with the token. */
tree value;
/* The checks that have been associated with value. */
/* A C++ token. */
-typedef struct cp_token GTY (())
-{
+typedef struct GTY (()) cp_token {
/* The kind of token. */
ENUM_BITFIELD (cpp_ttype) type : 8;
/* If this token is a keyword, this value indicates which keyword.
KEYWORD is RID_MAX) iff this name was looked up and found to be
ambiguous. An error has already been reported. */
BOOL_BITFIELD ambiguous_p : 1;
+ /* The location at which this token was found. */
+ location_t location;
/* The value associated with this token, if any. */
union cp_token_value {
/* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID. */
/* Use for all other tokens. */
tree GTY((tag ("0"))) value;
} GTY((desc ("(%1.type == CPP_TEMPLATE_ID) || (%1.type == CPP_NESTED_NAME_SPECIFIER)"))) u;
- /* The location at which this token was found. */
- location_t location;
} cp_token;
/* We use a stack of token pointer for saving token sets. */
static cp_token eof_token =
{
- CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL },
- 0
+ CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, 0, { NULL }
};
/* The cp_lexer structure represents the C++ lexer. It is responsible
it to the parser. Tokens are never added to the cp_lexer after
it is created. */
-typedef struct cp_lexer GTY (())
-{
+typedef struct GTY (()) cp_lexer {
/* The memory allocated for the buffer. NULL if this lexer does not
own the token buffer. */
cp_token * GTY ((length ("%h.buffer_length"))) buffer;
a cp_token_cache, since everything in here is referenced through
a lexer. */
-typedef struct cp_token_cache GTY(())
-{
+typedef struct GTY(()) cp_token_cache {
/* The beginning of the token range. */
cp_token * GTY((skip)) first;
static FILE *cp_lexer_debug_stream;
#endif /* ENABLE_CHECKING */
+/* Nonzero if we are parsing an unevaluated operand: an operand to
+ sizeof, typeof, or alignof. */
+int cp_unevaluated_operand;
+
/* Create a new main C++ lexer, the lexer that gets tokens from the
preprocessor. */
/* Subsequent preprocessor diagnostics should use compiler
diagnostic functions to get the compiler source location. */
- cpp_get_options (parse_in)->client_diagnostic = true;
- cpp_get_callbacks (parse_in)->error = cp_cpp_error;
+ done_lexing = true;
gcc_assert (lexer->next_token->type != CPP_PURGED);
return lexer;
token->type = CPP_KEYWORD;
/* Record which keyword. */
token->keyword = C_RID_CODE (token->u.value);
- /* Update the value. Some keywords are mapped to particular
- entities, rather than simply having the value of the
- corresponding IDENTIFIER_NODE. For example, `__const' is
- mapped to `const'. */
- token->u.value = ridpointers[token->keyword];
}
else
{
/* Warn about the C++0x keyword (but still treat it as
an identifier). */
warning (OPT_Wc__0x_compat,
- "identifier %<%s%> will become a keyword in C++0x",
- IDENTIFIER_POINTER (token->u.value));
+ "identifier %qE will become a keyword in C++0x",
+ token->u.value);
/* Clear out the C_RID_CODE so we don't warn about this
particular identifier-turned-keyword again. */
else if (token->type == CPP_PRAGMA)
{
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
- token->pragma_kind = TREE_INT_CST_LOW (token->u.value);
+ token->pragma_kind = ((enum pragma_kind)
+ TREE_INT_CST_LOW (token->u.value));
token->u.value = NULL_TREE;
}
}
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree, tree);
+ (cp_declarator *, tree, cp_cv_quals, tree, tree);
static cp_declarator *make_array_declarator
(cp_declarator *, tree);
static cp_declarator *make_pointer_declarator
cp_declarator *
make_call_declarator (cp_declarator *target,
- cp_parameter_declarator *parms,
+ tree parms,
cp_cv_quals cv_qualifiers,
tree exception_specification,
tree late_return_type)
/* Flags that are passed to some parsing functions. These values can
be bitwise-ored together. */
-typedef enum cp_parser_flags
+enum
{
/* No flags. */
CP_PARSER_FLAGS_NONE = 0x0,
CP_PARSER_FLAGS_OPTIONAL = 0x1,
/* When parsing a type-specifier, do not allow user-defined types. */
CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
-} cp_parser_flags;
+};
+
+/* This type is used for parameters and variables which hold
+ combinations of the above flags. */
+typedef int cp_parser_flags;
/* The different kinds of declarators we want to parse. */
/* Tree code for the binary operation we are parsing. */
enum tree_code tree_type;
/* Precedence of the binary operation we are parsing. */
- int prec;
+ enum cp_parser_prec prec;
} cp_parser_expression_stack_entry;
/* The stack for storing partial expressions. We only need NUM_PREC_VALUES
cp_parser_expression_stack[NUM_PREC_VALUES];
/* Context that is saved and restored when parsing tentatively. */
-typedef struct cp_parser_context GTY (())
-{
+typedef struct GTY (()) cp_parser_context {
/* If this is a tentative parsing context, the status of the
tentative parse. */
enum cp_parser_status_kind status;
/* The cp_parser structure represents the C++ parser. */
-typedef struct cp_parser GTY(())
-{
+typedef struct GTY(()) cp_parser {
/* The lexer from which we are obtaining tokens. */
cp_lexer *lexer;
static tree cp_parser_qualifying_entity
(cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_postfix_expression
- (cp_parser *, bool, bool, bool);
+ (cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_postfix_open_square_expression
(cp_parser *, tree, bool);
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
-static tree cp_parser_parenthesized_expression_list
+static VEC(tree,gc) *cp_parser_parenthesized_expression_list
(cp_parser *, bool, bool, bool, bool *);
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression
- (cp_parser *, bool, bool);
+ (cp_parser *, bool, bool, cp_id_kind *);
static enum tree_code cp_parser_unary_operator
(cp_token *);
static tree cp_parser_new_expression
(cp_parser *);
-static tree cp_parser_new_placement
+static VEC(tree,gc) *cp_parser_new_placement
(cp_parser *);
static tree cp_parser_new_type_id
(cp_parser *, tree *);
(cp_parser *);
static cp_declarator *cp_parser_direct_new_declarator
(cp_parser *);
-static tree cp_parser_new_initializer
+static VEC(tree,gc) *cp_parser_new_initializer
(cp_parser *);
static tree cp_parser_delete_expression
(cp_parser *);
static tree cp_parser_cast_expression
- (cp_parser *, bool, bool);
+ (cp_parser *, bool, bool, cp_id_kind *);
static tree cp_parser_binary_expression
- (cp_parser *, bool, enum cp_parser_prec);
+ (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
static tree cp_parser_question_colon_clause
(cp_parser *, tree);
static tree cp_parser_assignment_expression
- (cp_parser *, bool);
+ (cp_parser *, bool, cp_id_kind *);
static enum tree_code cp_parser_assignment_operator_opt
(cp_parser *);
static tree cp_parser_expression
- (cp_parser *, bool);
+ (cp_parser *, bool, cp_id_kind *);
static tree cp_parser_constant_expression
(cp_parser *, bool, bool *);
static tree cp_parser_builtin_offsetof
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
+static tree cp_parser_template_type_arg
+ (cp_parser *);
+static tree cp_parser_type_id_1
+ (cp_parser *, bool);
static void cp_parser_type_specifier_seq
(cp_parser *, bool, cp_decl_specifier_seq *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_clause
+static tree cp_parser_parameter_declaration_clause
(cp_parser *);
-static cp_parameter_declarator *cp_parser_parameter_declaration_list
+static tree cp_parser_parameter_declaration_list
(cp_parser *, bool *);
static cp_parameter_declarator *cp_parser_parameter_declaration
(cp_parser *, bool, bool *);
static bool cp_parser_check_declarator_template_parameters
(cp_parser *, cp_declarator *, location_t);
static bool cp_parser_check_template_parameters
- (cp_parser *, unsigned, location_t);
+ (cp_parser *, unsigned, location_t, cp_declarator *);
static tree cp_parser_simple_cast_expression
(cp_parser *);
static tree cp_parser_global_scope_opt
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- token->u.value);
+ token->u.value, token->flags);
}
}
cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
location_t location)
{
- cp_decl_spec ds;
+ int ds;
for (ds = ds_first; ds != ds_last; ++ds)
{
- unsigned count = decl_specs->specs[(int)ds];
+ unsigned count = decl_specs->specs[ds];
if (count < 2)
continue;
/* The "long" specifier is a special case because of "long long". */
{
if (count > 2)
error ("%H%<long long long%> is too long for GCC", &location);
- else if (pedantic && !in_system_header && warn_long_long
- && cxx_dialect == cxx98)
- pedwarn (location, OPT_Wlong_long,
- "ISO C++ 1998 does not support %<long long%>");
+ else
+ pedwarn_cxx98 (location, OPT_Wlong_long,
+ "ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
{
"__complex",
"__thread"
};
- error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
+ error ("%Hduplicate %qs", &location, decl_spec_names[ds]);
}
}
}
/* Stop if this is an unnested '}', or closes the outermost
nesting level. */
nesting_depth--;
+ if (nesting_depth < 0)
+ return;
if (!nesting_depth)
nesting_depth = -1;
break;
case CPP_WCHAR:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
+ if (TREE_CODE (token->u.value) == FIXED_CST)
+ {
+ error ("%Hfixed-point types not supported in C++",
+ &token->location);
+ return error_mark_node;
+ }
/* Floating-point literals are only allowed in an integral
constant expression if they are cast to an integral or
enumeration type. */
else
{
/* Parse the parenthesized expression. */
- expr = cp_parser_expression (parser, cast_p);
+ expr = cp_parser_expression (parser, cast_p, idk);
/* Let the front end know that this expression was
enclosed in parentheses. This matters in case, for
example, the expression is of the form `A::B', since
case RID_FUNCTION_NAME:
case RID_PRETTY_FUNCTION_NAME:
case RID_C99_FUNCTION_NAME:
- /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
- __func__ are the names of variables -- but they are
- treated specially. Therefore, they are handled here,
- rather than relying on the generic id-expression logic
- below. Grammatically, these names are id-expressions.
+ {
+ const char *name;
- Consume the token. */
- token = cp_lexer_consume_token (parser->lexer);
- /* Look up the name. */
- return finish_fname (token->u.value);
+ /* The symbols __FUNCTION__, __PRETTY_FUNCTION__, and
+ __func__ are the names of variables -- but they are
+ treated specially. Therefore, they are handled here,
+ rather than relying on the generic id-expression logic
+ below. Grammatically, these names are id-expressions.
+
+ Consume the token. */
+ token = cp_lexer_consume_token (parser->lexer);
+
+ switch (token->keyword)
+ {
+ case RID_FUNCTION_NAME:
+ name = "%<__FUNCTION__%>";
+ break;
+ case RID_PRETTY_FUNCTION_NAME:
+ name = "%<__PRETTY_FUNCTION__%>";
+ break;
+ case RID_C99_FUNCTION_NAME:
+ name = "%<__func__%>";
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (cp_parser_non_integral_constant_expression (parser, name))
+ return error_mark_node;
+
+ /* Look up the name. */
+ return finish_fname (token->u.value);
+ }
case RID_VA_ARG:
{
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Now, parse the assignment-expression. */
expression = cp_parser_assignment_expression (parser,
- /*cast_p=*/false);
+ /*cast_p=*/false, NULL);
/* Look for the `,'. */
cp_parser_require (parser, CPP_COMMA, "%<,%>");
/* Parse the type-id. */
parser->scope = NULL_TREE;
parser->object_scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
+ if (processing_template_decl)
+ cp_parser_parse_tentatively (parser);
type_decl
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
+ if (processing_template_decl
+ && ! cp_parser_parse_definitely (parser))
+ {
+ /* We couldn't find a type with this name, so just accept
+ it and check for a match at instantiation time. */
+ type_decl = cp_parser_identifier (parser);
+ if (type_decl != error_mark_node)
+ type_decl = build_nt (BIT_NOT_EXPR, type_decl);
+ return type_decl;
+ }
}
/* If an error occurred, assume that the name of the
destructor is the same as the name of the qualifying
static tree
cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
- bool member_access_only_p)
+ bool member_access_only_p,
+ cp_id_kind * pidk_return)
{
cp_token *token;
enum rid keyword;
/* And the expression which is being cast. */
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
- expression = cp_parser_expression (parser, /*cast_p=*/true);
+ expression = cp_parser_expression (parser, /*cast_p=*/true, & idk);
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Only type conversions to integral or enumeration types
tree expression;
/* Look for an expression. */
- expression = cp_parser_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_expression (parser, /*cast_p=*/false, & idk);
/* Compute its typeid. */
postfix_expression = build_typeid (expression);
/* Look for the `)' token. */
bool is_builtin_constant_p;
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
- tree args;
+ VEC(tree,gc) *args;
is_member_access = false;
= saved_non_integral_constant_expression_p;
}
- if (args == error_mark_node)
+ if (args == NULL)
{
postfix_expression = error_mark_node;
break;
"a function call"))
{
postfix_expression = error_mark_node;
+ release_tree_vector (args);
break;
}
koenig_p = false;
- if (idk == CP_ID_KIND_UNQUALIFIED)
+ if (idk == CP_ID_KIND_UNQUALIFIED
+ || idk == CP_ID_KIND_TEMPLATE_ID)
{
if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
{
- if (args)
+ if (!VEC_empty (tree, args))
{
koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ if (!any_type_dependent_arguments_p (args))
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
}
else
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. */
- else if (args && is_overloaded_fn (postfix_expression))
+ else if (!VEC_empty (tree, args)
+ && is_overloaded_fn (postfix_expression))
{
tree fn = get_first_fn (postfix_expression);
if (!DECL_FUNCTION_MEMBER_P (fn))
{
koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ if (!any_type_dependent_arguments_p (args))
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
}
}
}
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
- = build_nt_call_list (postfix_expression, args);
+ = build_nt_call_vec (postfix_expression, args);
+ release_tree_vector (args);
break;
}
if (BASELINK_P (fn))
+ {
postfix_expression
= (build_new_method_call
- (instance, fn, args, NULL_TREE,
+ (instance, fn, &args, NULL_TREE,
(idk == CP_ID_KIND_QUALIFIED
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
/*fn_p=*/NULL,
tf_warning_or_error));
+ }
else
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
tf_warning_or_error);
|| TREE_CODE (postfix_expression) == MEMBER_REF
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
- (postfix_expression, args));
+ (postfix_expression, &args));
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/true,
koenig_p,
tf_warning_or_error);
else
/* All other function calls. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
koenig_p,
tf_warning_or_error);
- if (warn_disallowed_functions)
- warn_if_disallowed_function_p (postfix_expression);
-
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
+
+ release_tree_vector (args);
}
break;
break;
default:
+ if (pidk_return != NULL)
+ * pidk_return = idk;
if (member_access_only_p)
return is_member_access? postfix_expression : error_mark_node;
else
if (for_offsetof)
index = cp_parser_constant_expression (parser, false, NULL);
else
- index = cp_parser_expression (parser, /*cast_p=*/false);
+ index = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* Look for the closing `]'. */
cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
*idk = CP_ID_KIND_NONE;
+
/* Enter the scope corresponding to the type of the object
given by the POSTFIX_EXPRESSION. */
if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
ALLOW_EXPANSION_P is true if this expression allows expansion of an
argument pack.
- 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.
- 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. If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
- indicates whether or not all of the expressions in the list were
- constant. */
+ Returns a vector of trees. Each element is a representation of an
+ assignment-expression. NULL is returned if the ( and or ) are
+ missing. An empty, but allocated, vector is returned on no
+ expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is true
+ if this is really an attribute list being parsed. If
+ NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
+ not all of the expressions in the list were constant. */
-static tree
+static VEC(tree,gc) *
cp_parser_parenthesized_expression_list (cp_parser* parser,
bool is_attribute_list,
bool cast_p,
bool allow_expansion_p,
bool *non_constant_p)
{
- tree expression_list = NULL_TREE;
+ VEC(tree,gc) *expression_list;
bool fold_expr_p = is_attribute_list;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
*non_constant_p = false;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
- return error_mark_node;
+ return NULL;
+
+ expression_list = make_tree_vector ();
/* Within a parenthesized expression, a `>' token is always
the greater-than operator. */
*non_constant_p = true;
}
else
- expr = cp_parser_assignment_expression (parser, cast_p);
+ expr = cp_parser_assignment_expression (parser, cast_p, NULL);
if (fold_expr_p)
expr = fold_non_dependent_expr (expr);
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);
+ VEC_safe_push (tree, gc, expression_list, expr);
if (expr == error_mark_node)
goto skip_comma;
{
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- return error_mark_node;
+ return NULL;
}
}
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)
- expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+ VEC_safe_insert (tree, gc, expression_list, 0, identifier);
return expression_list;
}
/*typename_keyword_p=*/false,
/*check_dependency_p=*/true,
/*type_p=*/false,
- /*is_declaration=*/true)
+ /*is_declaration=*/false)
!= NULL_TREE);
/* Now, if we saw a nested-name-specifier, we might be doing the
second production. */
Returns a representation of the expression. */
static tree
-cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_unary_expression (cp_parser *parser, bool address_p, bool cast_p,
+ cp_id_kind * pidk)
{
cp_token *token;
enum tree_code unary_operator;
cast_expression
= cp_parser_cast_expression (parser,
unary_operator == ADDR_EXPR,
- /*cast_p=*/false);
+ /*cast_p=*/false, pidk);
/* Now, build an appropriate representation. */
switch (unary_operator)
{
}
return cp_parser_postfix_expression (parser, address_p, cast_p,
- /*member_access_only_p=*/false);
+ /*member_access_only_p=*/false,
+ pidk);
}
/* Returns ERROR_MARK if TOKEN is not a unary-operator. If TOKEN is a
cp_parser_new_expression (cp_parser* parser)
{
bool global_scope_p;
- tree placement;
+ VEC(tree,gc) *placement;
tree type;
- tree initializer;
+ VEC(tree,gc) *initializer;
tree nelts;
+ tree ret;
/* Look for the optional `::' operator. */
global_scope_p
placement = cp_parser_new_placement (parser);
/* If that didn't work out, there's no new-placement. */
if (!cp_parser_parse_definitely (parser))
- placement = NULL_TREE;
+ {
+ if (placement != NULL)
+ release_tree_vector (placement);
+ placement = NULL;
+ }
/* If the next token is a `(', then we have a parenthesized
type-id. */
|| cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
initializer = cp_parser_new_initializer (parser);
else
- initializer = NULL_TREE;
+ initializer = NULL;
/* A new-expression may not appear in an integral constant
expression. */
if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
- return error_mark_node;
+ ret = error_mark_node;
+ else
+ {
+ /* Create a representation of the new-expression. */
+ ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
+ tf_warning_or_error);
+ }
- /* Create a representation of the new-expression. */
- return build_new (placement, type, nelts, initializer, global_scope_p,
- tf_warning_or_error);
+ if (placement != NULL)
+ release_tree_vector (placement);
+ if (initializer != NULL)
+ release_tree_vector (initializer);
+
+ return ret;
}
/* Parse a new-placement.
Returns the same representation as for an expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_placement (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
/* Parse the expression-list. */
expression_list = (cp_parser_parenthesized_expression_list
new_declarator = NULL;
}
- type = groktypename (&type_specifier_seq, new_declarator);
+ type = groktypename (&type_specifier_seq, new_declarator, false);
return type;
}
if (!declarator)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- expression = cp_parser_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* The standard requires that the expression have integral
type. DR 74 adds enumeration types. We believe that the
real intent is that these expressions be handled like the
( expression-list [opt] )
braced-init-list
- Returns a representation of the expression-list. If there is no
- expression-list, VOID_ZERO_NODE is returned. */
+ Returns a representation of the expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_initializer (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
+ tree t;
bool expr_non_constant_p;
maybe_warn_cpp0x ("extended initializer lists");
- expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
- CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
- expression_list = build_tree_list (NULL_TREE, expression_list);
+ t = cp_parser_braced_list (parser, &expr_non_constant_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+ expression_list = make_tree_vector_single (t);
}
else
expression_list = (cp_parser_parenthesized_expression_list
(parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
- if (!expression_list)
- expression_list = void_zero_node;
return expression_list;
}
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
}
+/* Returns true if TOKEN may start a cast-expression and false
+ otherwise. */
+
+static bool
+cp_parser_token_starts_cast_expression (cp_token *token)
+{
+ switch (token->type)
+ {
+ case CPP_COMMA:
+ case CPP_SEMICOLON:
+ case CPP_QUERY:
+ case CPP_COLON:
+ case CPP_CLOSE_SQUARE:
+ case CPP_CLOSE_PAREN:
+ case CPP_CLOSE_BRACE:
+ case CPP_DOT:
+ case CPP_DOT_STAR:
+ case CPP_DEREF:
+ case CPP_DEREF_STAR:
+ case CPP_DIV:
+ case CPP_MOD:
+ case CPP_LSHIFT:
+ case CPP_RSHIFT:
+ case CPP_LESS:
+ case CPP_GREATER:
+ case CPP_LESS_EQ:
+ case CPP_GREATER_EQ:
+ case CPP_EQ_EQ:
+ case CPP_NOT_EQ:
+ case CPP_EQ:
+ case CPP_MULT_EQ:
+ case CPP_DIV_EQ:
+ case CPP_MOD_EQ:
+ case CPP_PLUS_EQ:
+ case CPP_MINUS_EQ:
+ case CPP_RSHIFT_EQ:
+ case CPP_LSHIFT_EQ:
+ case CPP_AND_EQ:
+ case CPP_XOR_EQ:
+ case CPP_OR_EQ:
+ case CPP_XOR:
+ case CPP_OR:
+ case CPP_OR_OR:
+ case CPP_EOF:
+ return false;
+
+ /* '[' may start a primary-expression in obj-c++. */
+ case CPP_OPEN_SQUARE:
+ return c_dialect_objc ();
+
+ default:
+ return true;
+ }
+}
+
/* Parse a cast-expression.
cast-expression:
Returns a representation of the expression. */
static tree
-cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p)
+cp_parser_cast_expression (cp_parser *parser, bool address_p, bool cast_p,
+ cp_id_kind * pidk)
{
/* If it's a `(', then we might be looking at a cast. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
- /* If ok so far, parse the dependent expression. We cannot be
- sure it is a cast. Consider `(T ())'. It is a parenthesized
- ctor of T, but looks like a cast to function returning T
- without a dependent expression. */
- if (!cp_parser_error_occurred (parser))
- expr = cp_parser_cast_expression (parser,
- /*address_p=*/false,
- /*cast_p=*/true);
-
- if (cp_parser_parse_definitely (parser))
+ /* At this point this can only be either a cast or a
+ 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_parse_definitely (parser);
+ expr = cp_parser_cast_expression (parser,
+ /*address_p=*/false,
+ /*cast_p=*/true, pidk);
+
/* Warn about old-style casts, if so requested. */
if (warn_old_style_cast
&& !in_system_header
return error_mark_node;
/* Perform the cast. */
- expr = build_c_cast (type, expr);
+ expr = build_c_cast (input_location, type, expr);
return expr;
}
+ else
+ cp_parser_abort_tentative_parse (parser);
}
/* If we get here, then it's not a cast, so it must be a
unary-expression. */
- return cp_parser_unary_expression (parser, address_p, cast_p);
+ return cp_parser_unary_expression (parser, address_p, cast_p, pidk);
}
/* Parse a binary expression of the general form:
static tree
cp_parser_binary_expression (cp_parser* parser, bool cast_p,
- enum cp_parser_prec prec)
+ bool no_toplevel_fold_p,
+ enum cp_parser_prec prec,
+ cp_id_kind * pidk)
{
cp_parser_expression_stack stack;
cp_parser_expression_stack_entry *sp = &stack[0];
bool overloaded_p;
/* Parse the first expression. */
- lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p);
+ lhs = cp_parser_cast_expression (parser, /*address_p=*/false, cast_p, pidk);
lhs_type = ERROR_MARK;
for (;;)
goto get_rhs;
pop:
+ lookahead_prec = new_prec;
/* If the stack is not empty, we have parsed into LHS the right side
(`4' in the example above) of an expression we had suspended.
We can use the information on the stack to recover the LHS (`3')
}
overloaded_p = false;
- lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
- &overloaded_p, tf_warning_or_error);
+ /* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
+ ERROR_MARK for everything that is not a binary expression.
+ This makes warn_about_parentheses miss some warnings that
+ involve unary operators. For unary expressions we should
+ pass the correct tree_code unless the unary expression was
+ surrounded by parentheses.
+ */
+ if (no_toplevel_fold_p
+ && lookahead_prec <= prec
+ && sp == stack
+ && TREE_CODE_CLASS (tree_type) == tcc_comparison)
+ lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
+ else
+ lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+ &overloaded_p, tf_warning_or_error);
lhs_type = tree_type;
/* If the binary operator required the use of an overloaded operator,
cp_lexer_consume_token (parser->lexer);
if (cp_parser_allow_gnu_extensions_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- /* Implicit true clause. */
- expr = NULL_TREE;
+ {
+ /* Implicit true clause. */
+ expr = NULL_TREE;
+ c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+ }
else
- /* Parse the expression. */
- expr = cp_parser_expression (parser, /*cast_p=*/false);
+ {
+ /* Parse the expression. */
+ c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ c_inhibit_evaluation_warnings +=
+ ((logical_or_expr == truthvalue_true_node)
+ - (logical_or_expr == truthvalue_false_node));
+ }
/* The next token should be a `:'. */
cp_parser_require (parser, CPP_COLON, "%<:%>");
/* Parse the assignment-expression. */
- assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+ assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+ c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
/* Build the conditional-expression. */
return build_x_conditional_expr (logical_or_expr,
Returns a representation for the expression. */
static tree
-cp_parser_assignment_expression (cp_parser* parser, bool cast_p)
+cp_parser_assignment_expression (cp_parser* parser, bool cast_p,
+ cp_id_kind * pidk)
{
tree expr;
else
{
/* Parse the binary expressions (logical-or-expression). */
- expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
+ expr = cp_parser_binary_expression (parser, cast_p, false,
+ PREC_NOT_OPERATOR, pidk);
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
Returns a representation of the expression. */
static tree
-cp_parser_expression (cp_parser* parser, bool cast_p)
+cp_parser_expression (cp_parser* parser, bool cast_p, cp_id_kind * pidk)
{
tree expression = NULL_TREE;
/* Parse the next assignment-expression. */
assignment_expression
- = cp_parser_assignment_expression (parser, cast_p);
+ = cp_parser_assignment_expression (parser, cast_p, pidk);
/* If this is the first assignment-expression, we can just
save it away. */
if (!expression)
For example, cp_parser_initializer_clauses uses this function to
determine whether a particular assignment-expression is in fact
constant. */
- expression = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
/* Restore the old settings. */
parser->integral_constant_expression_p
= saved_integral_constant_expression_p;
offsetof-member-designator:
id-expression
| offsetof-member-designator "." id-expression
- | offsetof-member-designator "[" expression "]" */
+ | offsetof-member-designator "[" expression "]"
+ | offsetof-member-designator "->" id-expression */
static tree
cp_parser_builtin_offsetof (cp_parser *parser)
expr = cp_parser_postfix_open_square_expression (parser, expr, true);
break;
+ case CPP_DEREF:
+ /* offsetof-member-designator "->" identifier */
+ expr = grok_array_decl (expr, integer_zero_node);
+ /* FALLTHRU */
+
case CPP_DOT:
/* offsetof-member-designator "." identifier */
cp_lexer_consume_token (parser->lexer);
- expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
- true, &dummy,
+ expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT,
+ expr, true, &dummy,
token->location);
break;
cp_parser_label_for_labeled_statement (cp_parser* parser)
{
cp_token *token;
+ tree label = NULL_TREE;
/* The next token should be an identifier. */
token = cp_lexer_peek_token (parser->lexer);
expr_hi = NULL_TREE;
if (parser->in_switch_statement_p)
- finish_case_label (expr, expr_hi);
+ finish_case_label (token->location, expr, expr_hi);
else
error ("%Hcase label %qE not within a switch statement",
&token->location, expr);
cp_lexer_consume_token (parser->lexer);
if (parser->in_switch_statement_p)
- finish_case_label (NULL_TREE, NULL_TREE);
+ finish_case_label (token->location, NULL_TREE, NULL_TREE);
else
error ("%Hcase label not within a switch statement", &token->location);
break;
default:
/* Anything else must be an ordinary label. */
- finish_label_stmt (cp_parser_identifier (parser));
+ label = finish_label_stmt (cp_parser_identifier (parser));
break;
}
/* Require the `:' token. */
cp_parser_require (parser, CPP_COLON, "%<:%>");
+
+ /* An ordinary label may optionally be followed by attributes.
+ However, this is only permitted if the attributes are then
+ followed by a semicolon. This is because, for backward
+ compatibility, when parsing
+ lab: __attribute__ ((unused)) int i;
+ we want the attribute to attach to "i", not "lab". */
+ if (label != NULL_TREE
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+ {
+ tree attrs;
+
+ cp_parser_parse_tentatively (parser);
+ attrs = cp_parser_attributes_opt (parser);
+ if (attrs == NULL_TREE
+ || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ cp_parser_abort_tentative_parse (parser);
+ else if (!cp_parser_parse_definitely (parser))
+ ;
+ else
+ cplus_decl_attributes (&label, attrs, 0);
+ }
}
/* Parse an expression-statement.
/* If the next token is a ';', then there is no expression
statement. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- statement = cp_parser_expression (parser, /*cast_p=*/false);
+ statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
/* Parse the then-clause. */
in_statement = parser->in_statement;
parser->in_statement |= IN_IF_STMT;
- cp_parser_implicitly_scoped_statement (parser, &nested_if);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ add_stmt (build_empty_stmt (loc));
+ cp_lexer_consume_token (parser->lexer);
+ if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
+ warning_at (loc, OPT_Wempty_body, "suggest braces around "
+ "empty body in an %<if%> statement");
+ nested_if = false;
+ }
+ else
+ cp_parser_implicitly_scoped_statement (parser, &nested_if);
parser->in_statement = in_statement;
finish_then_clause (statement);
cp_lexer_consume_token (parser->lexer);
begin_else_clause (statement);
/* Parse the else-clause. */
- cp_parser_implicitly_scoped_statement (parser, NULL);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ {
+ location_t loc;
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+ warning_at (loc,
+ OPT_Wempty_body, "suggest braces around "
+ "empty body in an %<else%> statement");
+ add_stmt (build_empty_stmt (loc));
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ cp_parser_implicitly_scoped_statement (parser, NULL);
+
finish_else_clause (statement);
/* If we are currently parsing a then-clause, then
else
{
/* Consume the `='. */
- cp_lexer_consume_token (parser->lexer);
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
initializer = cp_parser_initializer_clause (parser, &non_constant_p);
}
if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
cp_parser_abort_tentative_parse (parser);
/* Otherwise, we are looking at an expression. */
- return cp_parser_expression (parser, /*cast_p=*/false);
-}
-
-/* We check for a ) immediately followed by ; with no whitespacing
- between. This is used to issue a warning for:
-
- while (...);
-
- and:
-
- for (...);
-
- as the semicolon is probably extraneous.
-
- On parse errors, the next token might not be a ), so do nothing in
- that case. */
-
-static void
-check_empty_body (cp_parser* parser, const char* type)
-{
- cp_token *token;
- cp_token *close_paren;
- expanded_location close_loc;
- expanded_location semi_loc;
-
- close_paren = cp_lexer_peek_token (parser->lexer);
- if (close_paren->type != CPP_CLOSE_PAREN)
- return;
-
- close_loc = expand_location (close_paren->location);
- token = cp_lexer_peek_nth_token (parser->lexer, 2);
-
- if (token->type != CPP_SEMICOLON
- || (token->flags & PREV_WHITE))
- return;
-
- semi_loc = expand_location (token->location);
- if (close_loc.line == semi_loc.line
- && close_loc.column+1 == semi_loc.column)
- warning (OPT_Wempty_body,
- "suggest a space before %<;%> or explicit braces around empty "
- "body in %<%s%> statement",
- type);
+ return cp_parser_expression (parser, /*cast_p=*/false, NULL);
}
/* Parse an iteration-statement.
/* Parse the condition. */
condition = cp_parser_condition (parser);
finish_while_stmt_cond (condition, statement);
- check_empty_body (parser, "while");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Parse the dependent statement. */
/* Look for the `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the expression. */
- expression = cp_parser_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* We're done with the do-statement. */
finish_do_stmt (expression, statement);
/* Look for the `)'. */
/* If there's an expression, process it. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
- expression = cp_parser_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
finish_for_expr (expression, statement);
- check_empty_body (parser, "for");
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
expr = cp_parser_braced_list (parser, &expr_non_constant_p);
}
else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- expr = cp_parser_expression (parser, /*cast_p=*/false);
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
else
/* If the next token is a `;', then there is no
expression. */
/* Consume the '*' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the dependent expression. */
- finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false));
+ finish_goto_stmt (cp_parser_expression (parser, /*cast_p=*/false, NULL));
}
else
finish_goto_stmt (cp_parser_identifier (parser));
/* Mark if () ; with a special NOP_EXPR. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer);
- statement = add_stmt (build_empty_stmt ());
+ statement = add_stmt (build_empty_stmt (loc));
}
/* if a compound is opened, we simply parse the statement directly. */
else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
/* Avoid calling cp_parser_compound_statement, so that we
don't create a new scope. Do everything else by hand. */
cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+ /* 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, NULL_TREE);
cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
(After "int (" we might be looking at a functional cast.) */
if (decl_specifiers.any_specifiers_p
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN)
- && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+ && !cp_parser_error_occurred (parser))
cp_parser_commit_to_tentative_parse (parser);
/* Keep going until we hit the `;' at the end of the simple
parser->integral_constant_expression_p = false;
/* Do not actually evaluate the expression. */
- ++skip_evaluation;
+ ++cp_unevaluated_operand;
+
+ /* Do not warn about problems with the expression. */
+ ++c_inhibit_evaluation_warnings;
/* Parse the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
/* Parse a class member access. */
expr = cp_parser_postfix_expression (parser, /*address_p=*/false,
/*cast_p=*/false,
- /*member_access_only_p=*/true);
+ /*member_access_only_p=*/true, NULL);
if (expr
&& expr != error_mark_node
cp_parser_abort_tentative_parse (parser);
/* Parse a full expression. */
- expr = cp_parser_expression (parser, /*cast_p=*/false);
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
}
/* Go back to evaluating expressions. */
- --skip_evaluation;
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
/* Restore the old message and the integral constant expression
flags. */
/*initialized=*/0, &attributes);
if (attributes)
cplus_decl_attributes (&type_specified, attributes, /*flags=*/0);
+
+ /* Don't give this error when parsing tentatively. This happens to
+ work because we always parse this definitively once. */
+ if (! cp_parser_uncommitted_to_tentative_parse_p (parser)
+ && type_uses_auto (type_specified))
+ {
+ error ("invalid use of %<auto%> in conversion operator");
+ return error_mark_node;
+ }
+
return type_specified;
}
mem_initializer_id = NULL_TREE;
}
else
- mem_initializer_id = cp_parser_mem_initializer_id (parser);
+ {
+ mem_initializer_id = cp_parser_mem_initializer_id (parser);
+ if (mem_initializer_id == error_mark_node)
+ return mem_initializer_id;
+ }
member = expand_member_init (mem_initializer_id);
if (member && !DECL_P (member))
in_base_initializer = 1;
expression_list = build_tree_list (NULL_TREE, expression_list);
}
else
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ {
+ VEC(tree,gc)* vec;
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ return error_mark_node;
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
+
if (expression_list == error_mark_node)
return error_mark_node;
if (!expression_list)
tree parameter;
bool is_non_type;
bool is_parameter_pack;
+ location_t parm_loc;
/* Parse the template-parameter. */
+ parm_loc = cp_lexer_peek_token (parser->lexer)->location;
parameter = cp_parser_template_parameter (parser,
&is_non_type,
&is_parameter_pack);
/* Add it to the list. */
if (parameter != error_mark_node)
parameter_list = process_template_parm (parameter_list,
+ parm_loc,
parameter,
is_non_type,
is_parameter_pack);
&& !template_keyword_p
&& parser->scope && TYPE_P (parser->scope)
&& check_dependency_p
- && dependent_type_p (parser->scope)
+ && dependent_scope_p (parser->scope)
/* Do not do this for dtors (or ctors), since they never
need the template keyword before their name. */
&& !constructor_name_p (identifier, parser->scope))
argument pack. */
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
+ if (argument == error_mark_node)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ error ("%Hexpected parameter pack before %<...%>",
+ &token->location);
+ }
/* Consume the `...' token. */
cp_lexer_consume_token (parser->lexer);
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
- argument = cp_parser_type_id (parser);
+ argument = cp_parser_template_type_arg (parser);
/* If there was no error parsing the type-id but the next token is a
'>>', our behavior depends on which dialect of C++ we're
parsing. In C++98, we probably found a typo for '> >'. But there
was the only alternative that matched (albeit with a '>' after
it). We can assume it's just a typo from the user, and a
diagnostic will then be issued. */
- return cp_parser_type_id (parser);
+ return cp_parser_template_type_arg (parser);
}
/* Parse an explicit-instantiation.
if (!begin_specialization ())
{
end_specialization ();
- cp_parser_skip_to_end_of_block_or_statement (parser);
return;
}
cp_parser_parse_tentatively (parser);
/* Look for the class-specifier. */
type_spec = cp_parser_class_specifier (parser);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
type = make_typename_type (parser->scope, decl,
typename_type,
/*complain=*/tf_error);
- else
+ /* If the `typename' keyword is in effect and DECL is not a type
+ decl. Then type is non existant. */
+ else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
+ type = NULL_TREE;
+ else
type = TREE_TYPE (decl);
}
there were no qualifying templates. */
if (!cp_parser_check_template_parameters (parser,
/*num_templates=*/0,
- token->location))
+ token->location,
+ /*declarator=*/NULL))
return error_mark_node;
type = xref_tag (tag_type, identifier, ts, template_p);
}
tree type;
tree attributes;
bool scoped_enum_p = false;
+ bool has_underlying_type = false;
tree underlying_type = NULL_TREE;
/* Parse tentatively so that we can back up if we don't find a
scoped_enum_p = true;
}
-
+
attributes = cp_parser_attributes_opt (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
cp_decl_specifier_seq type_specifiers;
+ /* At this point this is surely not elaborated type specifier. */
+ if (!cp_parser_parse_definitely (parser))
+ return NULL_TREE;
+
if (cxx_dialect == cxx98)
maybe_warn_cpp0x ("scoped enums");
/* Consume the `:'. */
cp_lexer_consume_token (parser->lexer);
+ has_underlying_type = true;
+
/* Parse the type-specifier-seq. */
cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
&type_specifiers);
- if (type_specifiers.type == error_mark_node)
- return error_mark_node;
-
+
/* If that didn't work, stop. */
if (type_specifiers.type != error_mark_node)
{
if (underlying_type == error_mark_node)
underlying_type = NULL_TREE;
}
- else
- cp_parser_error (parser, "expected underlying type of enumeration");
}
/* Look for the `{' but don't consume it yet. */
if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
- cp_parser_simulate_error (parser);
+ {
+ cp_parser_error (parser, "expected %<{%>");
+ if (has_underlying_type)
+ return NULL_TREE;
+ }
- if (!cp_parser_parse_definitely (parser))
+ if (!has_underlying_type && !cp_parser_parse_definitely (parser))
return NULL_TREE;
/* Issue an error message if type-definitions are forbidden here. */
if (cp_parser_allow_gnu_extensions_p (parser))
{
tree trailing_attr = cp_parser_attributes_opt (parser);
+ trailing_attr = chainon (trailing_attr, attributes);
cplus_decl_attributes (&type,
trailing_attr,
(int) ATTR_FLAG_TYPE_IN_PLACE);
else
value = NULL_TREE;
+ /* If we are processing a template, make sure the initializer of the
+ enumerator doesn't contain any bare template parameter pack. */
+ if (check_for_bare_parameter_packs (value))
+ value = error_mark_node;
+
/* Create the enumerator. */
build_enumerator (identifier, value, type);
}
}
else
{
+ location_t func_brace_location
+ = cp_lexer_peek_token (parser->lexer)->location;
+
/* Neither attributes nor an asm-specification are allowed
on a function-definition. */
if (asm_specification)
= (cp_parser_function_definition_from_specifiers_and_declarator
(parser, decl_specifiers, prefix_attributes, declarator));
+ if (decl != error_mark_node && DECL_STRUCT_FUNCTION (decl))
+ {
+ /* This is where the prologue starts... */
+ DECL_STRUCT_FUNCTION (decl)->function_start_locus
+ = func_brace_location;
+ }
+
return decl;
}
}
if (!first || dcl_kind != CP_PARSER_DECLARATOR_NAMED)
{
- cp_parameter_declarator *params;
+ tree params;
unsigned saved_num_template_parameter_lists;
+ bool is_declarator = false;
+ tree t;
/* In a member-declarator, the only valid interpretation
of a parenthesis is the start of a
= parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0;
+ begin_scope (sk_function_parms, NULL_TREE);
+
/* Parse the parameter-declaration-clause. */
params = cp_parser_parameter_declaration_clause (parser);
tree exception_specification;
tree late_return;
+ is_declarator = true;
+
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
first = false;
return type, so are not those of the declared
function. */
parser->default_arg_ok_p = false;
-
- /* Repeat the main loop. */
- continue;
}
+
+ /* Remove the function parms from scope. */
+ for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+ pop_binding (DECL_NAME (t), t);
+ leave_scope();
+
+ if (is_declarator)
+ /* Repeat the main loop. */
+ continue;
}
/* If this is the first, we can try a parenthesized
&token->location);
bounds = error_mark_node;
}
+ else if (processing_template_decl && !error_operand_p (bounds))
+ {
+ /* Remember this wasn't a constant-expression. */
+ bounds = build_nop (TREE_TYPE (bounds), bounds);
+ TREE_SIDE_EFFECTS (bounds) = 1;
+ }
}
else
bounds = NULL_TREE;
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
- tree qualifying_scope;
- tree unqualified_name;
- special_function_kind sfk;
- bool abstract_ok;
- bool pack_expansion_p = false;
- cp_token *declarator_id_start_token;
-
- /* Parse a declarator-id */
- abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
- if (abstract_ok)
- {
- cp_parser_parse_tentatively (parser);
+ {
+ tree qualifying_scope;
+ tree unqualified_name;
+ special_function_kind sfk;
+ bool abstract_ok;
+ bool pack_expansion_p = false;
+ cp_token *declarator_id_start_token;
+
+ /* Parse a declarator-id */
+ abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
+ if (abstract_ok)
+ {
+ cp_parser_parse_tentatively (parser);
- /* If we see an ellipsis, we should be looking at a
- parameter pack. */
- if (token->type == CPP_ELLIPSIS)
- {
- /* Consume the `...' */
- cp_lexer_consume_token (parser->lexer);
+ /* If we see an ellipsis, we should be looking at a
+ parameter pack. */
+ if (token->type == CPP_ELLIPSIS)
+ {
+ /* Consume the `...' */
+ cp_lexer_consume_token (parser->lexer);
- pack_expansion_p = true;
- }
- }
+ pack_expansion_p = true;
+ }
+ }
- declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
- unqualified_name
- = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
- qualifying_scope = parser->scope;
- if (abstract_ok)
- {
- bool okay = false;
-
- if (!unqualified_name && pack_expansion_p)
- {
- /* Check whether an error occurred. */
- okay = !cp_parser_error_occurred (parser);
-
- /* We already consumed the ellipsis to mark a
- parameter pack, but we have no way to report it,
- so abort the tentative parse. We will be exiting
- immediately anyway. */
- cp_parser_abort_tentative_parse (parser);
- }
- else
- okay = cp_parser_parse_definitely (parser);
-
- if (!okay)
- unqualified_name = error_mark_node;
- else if (unqualified_name
- && (qualifying_scope
- || (TREE_CODE (unqualified_name)
- != IDENTIFIER_NODE)))
- {
- cp_parser_error (parser, "expected unqualified-id");
- unqualified_name = error_mark_node;
- }
- }
+ declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
+ unqualified_name
+ = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
+ qualifying_scope = parser->scope;
+ if (abstract_ok)
+ {
+ bool okay = false;
- if (!unqualified_name)
- return NULL;
- if (unqualified_name == error_mark_node)
- {
- declarator = cp_error_declarator;
- pack_expansion_p = false;
- declarator->parameter_pack_p = false;
- break;
- }
+ if (!unqualified_name && pack_expansion_p)
+ {
+ /* Check whether an error occurred. */
+ okay = !cp_parser_error_occurred (parser);
+
+ /* We already consumed the ellipsis to mark a
+ parameter pack, but we have no way to report it,
+ so abort the tentative parse. We will be exiting
+ immediately anyway. */
+ cp_parser_abort_tentative_parse (parser);
+ }
+ else
+ okay = cp_parser_parse_definitely (parser);
- if (qualifying_scope && at_namespace_scope_p ()
- && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
- {
- /* In the declaration of a member of a template class
- outside of the class itself, the SCOPE will sometimes
- be a TYPENAME_TYPE. For example, given:
-
- template <typename T>
- int S<T>::R::i = 3;
-
- the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
- this context, we must resolve S<T>::R to an ordinary
- type, rather than a typename type.
-
- The reason we normally avoid resolving TYPENAME_TYPEs
- is that a specialization of `S' might render
- `S<T>::R' not a type. However, if `S' is
- specialized, then this `i' will not be used, so there
- is no harm in resolving the types here. */
- tree type;
+ if (!okay)
+ unqualified_name = error_mark_node;
+ else if (unqualified_name
+ && (qualifying_scope
+ || (TREE_CODE (unqualified_name)
+ != IDENTIFIER_NODE)))
+ {
+ cp_parser_error (parser, "expected unqualified-id");
+ unqualified_name = error_mark_node;
+ }
+ }
- /* Resolve the TYPENAME_TYPE. */
- type = resolve_typename_type (qualifying_scope,
- /*only_current_p=*/false);
- /* If that failed, the declarator is invalid. */
- if (TREE_CODE (type) == TYPENAME_TYPE)
- error ("%H%<%T::%E%> is not a type",
- &declarator_id_start_token->location,
- TYPE_CONTEXT (qualifying_scope),
- TYPE_IDENTIFIER (qualifying_scope));
- qualifying_scope = type;
- }
+ if (!unqualified_name)
+ return NULL;
+ if (unqualified_name == error_mark_node)
+ {
+ declarator = cp_error_declarator;
+ pack_expansion_p = false;
+ declarator->parameter_pack_p = false;
+ break;
+ }
- sfk = sfk_none;
+ if (qualifying_scope && at_namespace_scope_p ()
+ && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
+ {
+ /* In the declaration of a member of a template class
+ outside of the class itself, the SCOPE will sometimes
+ be a TYPENAME_TYPE. For example, given:
+
+ template <typename T>
+ int S<T>::R::i = 3;
+
+ the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
+ this context, we must resolve S<T>::R to an ordinary
+ type, rather than a typename type.
+
+ The reason we normally avoid resolving TYPENAME_TYPEs
+ is that a specialization of `S' might render
+ `S<T>::R' not a type. However, if `S' is
+ specialized, then this `i' will not be used, so there
+ is no harm in resolving the types here. */
+ tree type;
+
+ /* Resolve the TYPENAME_TYPE. */
+ type = resolve_typename_type (qualifying_scope,
+ /*only_current_p=*/false);
+ /* If that failed, the declarator is invalid. */
+ if (TREE_CODE (type) == TYPENAME_TYPE)
+ error ("%H%<%T::%E%> is not a type",
+ &declarator_id_start_token->location,
+ TYPE_CONTEXT (qualifying_scope),
+ TYPE_IDENTIFIER (qualifying_scope));
+ qualifying_scope = type;
+ }
- if (unqualified_name)
- {
- tree class_type;
+ sfk = sfk_none;
- if (qualifying_scope
- && CLASS_TYPE_P (qualifying_scope))
- class_type = qualifying_scope;
- else
- class_type = current_class_type;
+ if (unqualified_name)
+ {
+ tree class_type;
- if (TREE_CODE (unqualified_name) == TYPE_DECL)
- {
- tree name_type = TREE_TYPE (unqualified_name);
- if (class_type && same_type_p (name_type, class_type))
- {
- if (qualifying_scope
- && CLASSTYPE_USE_TEMPLATE (name_type))
- {
- error ("%Hinvalid use of constructor as a template",
- &declarator_id_start_token->location);
- inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to "
- "name the constructor in a qualified name",
- class_type,
- DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
- class_type, name_type);
- declarator = cp_error_declarator;
- break;
- }
- else
- unqualified_name = constructor_name (class_type);
- }
- else
- {
- /* We do not attempt to print the declarator
- here because we do not have enough
- information about its original syntactic
- form. */
- cp_parser_error (parser, "invalid declarator");
- declarator = cp_error_declarator;
- break;
- }
- }
+ if (qualifying_scope
+ && CLASS_TYPE_P (qualifying_scope))
+ class_type = qualifying_scope;
+ else
+ class_type = current_class_type;
- if (class_type)
- {
- if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
- sfk = sfk_destructor;
- else if (IDENTIFIER_TYPENAME_P (unqualified_name))
- sfk = sfk_conversion;
- else if (/* There's no way to declare a constructor
- for an anonymous type, even if the type
- got a name for linkage purposes. */
- !TYPE_WAS_ANONYMOUS (class_type)
- && constructor_name_p (unqualified_name,
- class_type))
- {
- unqualified_name = constructor_name (class_type);
- sfk = sfk_constructor;
- }
+ if (TREE_CODE (unqualified_name) == TYPE_DECL)
+ {
+ tree name_type = TREE_TYPE (unqualified_name);
+ if (class_type && same_type_p (name_type, class_type))
+ {
+ if (qualifying_scope
+ && CLASSTYPE_USE_TEMPLATE (name_type))
+ {
+ error ("%Hinvalid use of constructor as a template",
+ &declarator_id_start_token->location);
+ inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to "
+ "name the constructor in a qualified name",
+ class_type,
+ DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+ class_type, name_type);
+ declarator = cp_error_declarator;
+ break;
+ }
+ else
+ unqualified_name = constructor_name (class_type);
+ }
+ else
+ {
+ /* We do not attempt to print the declarator
+ here because we do not have enough
+ information about its original syntactic
+ form. */
+ cp_parser_error (parser, "invalid declarator");
+ declarator = cp_error_declarator;
+ break;
+ }
+ }
- if (ctor_dtor_or_conv_p && sfk != sfk_none)
- *ctor_dtor_or_conv_p = -1;
- }
- }
- declarator = make_id_declarator (qualifying_scope,
- unqualified_name,
- sfk);
- declarator->id_loc = token->location;
- declarator->parameter_pack_p = pack_expansion_p;
+ if (class_type)
+ {
+ if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+ sfk = sfk_destructor;
+ else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+ sfk = sfk_conversion;
+ else if (/* There's no way to declare a constructor
+ for an anonymous type, even if the type
+ got a name for linkage purposes. */
+ !TYPE_WAS_ANONYMOUS (class_type)
+ && constructor_name_p (unqualified_name,
+ class_type))
+ {
+ unqualified_name = constructor_name (class_type);
+ sfk = sfk_constructor;
+ }
- if (pack_expansion_p)
- maybe_warn_variadic_templates ();
+ if (ctor_dtor_or_conv_p && sfk != sfk_none)
+ *ctor_dtor_or_conv_p = -1;
+ }
+ }
+ declarator = make_id_declarator (qualifying_scope,
+ unqualified_name,
+ sfk);
+ declarator->id_loc = token->location;
+ declarator->parameter_pack_p = pack_expansion_p;
+
+ if (pack_expansion_p)
+ maybe_warn_variadic_templates ();
+ }
handle_declarator:;
scope = get_scope_of_declarator (declarator);
Returns the TYPE specified. */
static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
{
cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
- return groktypename (&type_specifier_seq, abstract_declarator);
+ if (type_specifier_seq.type
+ && type_uses_auto (type_specifier_seq.type))
+ {
+ /* A type-id with type 'auto' is only ok if the abstract declarator
+ is a function declarator with a late-specified return type. */
+ if (abstract_declarator
+ && abstract_declarator->kind == cdk_function
+ && abstract_declarator->u.function.late_return_type)
+ /* OK */;
+ else
+ {
+ error ("invalid use of %<auto%>");
+ return error_mark_node;
+ }
+ }
+
+ return groktypename (&type_specifier_seq, abstract_declarator,
+ is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, true);
}
/* Parse a type-specifier-seq.
value of NULL indicates a parameter-declaration-clause consisting
only of an ellipsis. */
-static cp_parameter_declarator *
+static tree
cp_parser_parameter_declaration_clause (cp_parser* parser)
{
- cp_parameter_declarator *parameters;
+ tree parameters;
cp_token *token;
bool ellipsis_p;
bool is_error;
{
/* Consume the `...' token. */
cp_lexer_consume_token (parser->lexer);
- return NULL;
+ return NULL_TREE;
}
else if (token->type == CPP_CLOSE_PAREN)
/* There are no parameters. */
#ifndef NO_IMPLICIT_EXTERN_C
if (in_system_header && current_class_type == NULL
&& current_lang_name == lang_name_c)
- return NULL;
+ return NULL_TREE;
else
#endif
- return no_parameters;
+ return void_list_node;
}
/* Check for `(void)', too, which is a special case. */
else if (token->keyword == RID_VOID
/* Consume the `void' token. */
cp_lexer_consume_token (parser->lexer);
/* There are no parameters. */
- return no_parameters;
+ return void_list_node;
}
/* Parse the parameter-declaration-list. */
ellipsis_p = false;
/* Finish the parameter list. */
- if (parameters && ellipsis_p)
- parameters->ellipsis_p = true;
+ if (!ellipsis_p)
+ parameters = chainon (parameters, void_list_node);
return parameters;
}
`void_list_node' is never appended to the list. Upon return,
*IS_ERROR will be true iff an error occurred. */
-static cp_parameter_declarator *
+static tree
cp_parser_parameter_declaration_list (cp_parser* parser, bool *is_error)
{
- cp_parameter_declarator *parameters = NULL;
- cp_parameter_declarator **tail = ¶meters;
+ tree parameters = NULL_TREE;
+ tree *tail = ¶meters;
bool saved_in_unbraced_linkage_specification_p;
/* Assume all will go well. */
while (true)
{
cp_parameter_declarator *parameter;
+ tree decl = error_mark_node;
bool parenthesized_p;
/* Parse the parameter. */
parameter
/*template_parm_p=*/false,
&parenthesized_p);
+ /* We don't know yet if the enclosing context is deprecated, so wait
+ and warn in grokparms if appropriate. */
+ deprecated_state = DEPRECATED_SUPPRESS;
+
+ if (parameter)
+ decl = grokdeclarator (parameter->declarator,
+ ¶meter->decl_specifiers,
+ PARM,
+ parameter->default_argument != NULL_TREE,
+ ¶meter->decl_specifiers.attributes);
+
+ deprecated_state = DEPRECATED_NORMAL;
+
/* If a parse error occurred parsing the parameter declaration,
then the entire parameter-declaration-list is erroneous. */
- if (!parameter)
+ if (decl == error_mark_node)
{
*is_error = true;
- parameters = NULL;
+ parameters = error_mark_node;
break;
}
+
+ if (parameter->decl_specifiers.attributes)
+ cplus_decl_attributes (&decl,
+ parameter->decl_specifiers.attributes,
+ 0);
+ if (DECL_NAME (decl))
+ decl = pushdecl (decl);
+
/* Add the new parameter to the list. */
- *tail = parameter;
- tail = ¶meter->next;
+ *tail = build_tree_list (parameter->default_argument, decl);
+ tail = &TREE_CHAIN (*tail);
/* Peek at the next token. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN)
if (template_parm_p)
push_deferring_access_checks (dk_no_deferred);
default_argument
- = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+ = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
if (template_parm_p)
pop_deferring_access_checks ();
/* Restore saved state. */
init = cp_parser_initializer_clause (parser, non_constant_p);
}
else if (token->type == CPP_OPEN_PAREN)
- init = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- non_constant_p);
+ {
+ VEC(tree,gc) *vec;
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ non_constant_p);
+ if (vec == NULL)
+ return error_mark_node;
+ init = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
else if (token->type == CPP_OPEN_BRACE)
{
maybe_warn_cpp0x ("extended initializer lists");
tree scope;
bool typename_p;
cp_token *token;
+ tree identifier = NULL_TREE;
/* All class-names start with an identifier. */
token = cp_lexer_peek_token (parser->lexer);
&& !cp_parser_nth_token_starts_template_argument_list_p (parser, 2))
{
cp_token *identifier_token;
- tree identifier;
bool ambiguous_p;
/* Look for the identifier. */
if (decl == error_mark_node)
cp_parser_error (parser, "expected class-name");
+ else if (identifier && !parser->scope)
+ maybe_note_name_used_in_class (identifier, decl);
return decl;
}
static tree
cp_parser_class_specifier (cp_parser* parser)
{
- cp_token *token;
tree type;
tree attributes = NULL_TREE;
- int has_trailing_semicolon;
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
bool saved_in_function_body;
+ bool saved_in_unbraced_linkage_specification_p;
tree old_scope = NULL_TREE;
tree scope = NULL_TREE;
tree bases;
/* We are not in a function body. */
saved_in_function_body = parser->in_function_body;
parser->in_function_body = false;
+ /* We are not immediately inside an extern "lang" block. */
+ saved_in_unbraced_linkage_specification_p
+ = parser->in_unbraced_linkage_specification_p;
+ parser->in_unbraced_linkage_specification_p = false;
/* Start the class. */
if (nested_name_specifier_p)
/* Look for the trailing `}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
- /* We get better error messages by noticing a common problem: a
- missing trailing `;'. */
- token = cp_lexer_peek_token (parser->lexer);
- has_trailing_semicolon = (token->type == CPP_SEMICOLON);
/* Look for trailing attributes to apply to this class. */
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_attributes_opt (parser);
parser->in_function_body = saved_in_function_body;
parser->num_template_parameter_lists
= saved_num_template_parameter_lists;
+ parser->in_unbraced_linkage_specification_p
+ = saved_in_unbraced_linkage_specification_p;
return type;
}
/* Make sure that the right number of template parameters were
present. */
if (!cp_parser_check_template_parameters (parser, num_templates,
- type_start_token->location))
+ type_start_token->location,
+ /*declarator=*/NULL))
{
/* If something went wrong, there is no point in even trying to
process the class-definition. */
know it is an anonymous aggregate. */
fixup_anonymous_aggr (type);
/* And make the corresponding data member. */
- decl = build_decl (FIELD_DECL, NULL_TREE, type);
+ decl = build_decl (decl_spec_token_start->location,
+ FIELD_DECL, NULL_TREE, type);
/* Add it to the class. */
finish_member_declaration (decl);
}
return;
}
else
+ if (declarator->kind == cdk_function)
+ declarator->id_loc = token->location;
/* Create the declaration. */
decl = grokfield (declarator, &decl_specifiers,
initializer, /*init_const_expr_p=*/true,
if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
return error_mark_node;
/* Look for the `0' token. */
- token = cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_EOF
+ || token->type == CPP_PRAGMA_EOL)
+ return error_mark_node;
+
+ cp_lexer_consume_token (parser->lexer);
/* Accept = default or = delete in c++0x mode. */
if (token->keyword == RID_DEFAULT
expression = NULL_TREE;
else
expression = cp_parser_assignment_expression (parser,
- /*cast_p=*/false);
+ /*cast_p=*/false, NULL);
return build_throw (expression);
}
/* Look for the `('. */
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the expression. */
- expression = cp_parser_expression (parser, /*cast_p=*/false);
+ expression = cp_parser_expression (parser, /*cast_p=*/false, NULL);
/* Look for the `)'. */
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Save away the identifier that indicates which attribute
this is. */
- identifier = token->u.value;
+ identifier = (token->type == CPP_KEYWORD)
+ /* For keywords, use the canonical spelling, not the
+ parsed identifier. */
+ ? ridpointers[(int) token->keyword]
+ : token->u.value;
+
attribute = build_tree_list (identifier, NULL_TREE);
/* Peek at the next token. */
/* If it's an `(', then parse the attribute arguments. */
if (token->type == CPP_OPEN_PAREN)
{
- arguments = cp_parser_parenthesized_expression_list
- (parser, true, /*cast_p=*/false,
- /*allow_expansion_p=*/false,
- /*non_constant_p=*/NULL);
+ VEC(tree,gc) *vec;
+ vec = cp_parser_parenthesized_expression_list
+ (parser, true, /*cast_p=*/false,
+ /*allow_expansion_p=*/false,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ arguments = error_mark_node;
+ else
+ {
+ arguments = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
/* Save the arguments away. */
TREE_VALUE (attribute) = arguments;
}
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
dependent_p = (TYPE_P (parser->scope)
- && !(parser->in_declarator_p
- && currently_open_class (parser->scope))
- && dependent_type_p (parser->scope));
+ && dependent_scope_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
- && dependent_p)
- {
- if (tag_type)
- {
- tree type;
-
- /* The resolution to Core Issue 180 says that `struct
- A::B' should be considered a type-name, even if `A'
- is dependent. */
- type = make_typename_type (parser->scope, name, tag_type,
- /*complain=*/tf_error);
- decl = TYPE_NAME (type);
- }
- else if (is_template
- && (cp_parser_next_token_ends_template_argument_p (parser)
- || cp_lexer_next_token_is (parser->lexer,
- CPP_CLOSE_PAREN)))
- decl = make_unbound_class_template (parser->scope,
- name, NULL_TREE,
- /*complain=*/tf_error);
- else
- decl = build_qualified_name (/*type=*/NULL_TREE,
- parser->scope, name,
- is_template);
- }
+ && dependent_p)
+ /* Defer lookup. */
+ decl = error_mark_node;
else
{
tree pushed_scope = NULL_TREE;
/*complain=*/true);
/* If we have a single function from a using decl, pull it out. */
- if (decl
- && TREE_CODE (decl) == OVERLOAD
+ if (TREE_CODE (decl) == OVERLOAD
&& !really_overloaded_fn (decl))
decl = OVL_FUNCTION (decl);
if (pushed_scope)
pop_scope (pushed_scope);
}
+
+ /* If the scope is a dependent type and either we deferred lookup or
+ we did lookup but didn't find the name, rememeber the name. */
+ if (decl == error_mark_node && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope))
+ {
+ if (tag_type)
+ {
+ tree type;
+
+ /* The resolution to Core Issue 180 says that `struct
+ A::B' should be considered a type-name, even if `A'
+ is dependent. */
+ type = make_typename_type (parser->scope, name, tag_type,
+ /*complain=*/tf_error);
+ decl = TYPE_NAME (type);
+ }
+ else if (is_template
+ && (cp_parser_next_token_ends_template_argument_p (parser)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_CLOSE_PAREN)))
+ decl = make_unbound_class_template (parser->scope,
+ name, NULL_TREE,
+ /*complain=*/tf_error);
+ else
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope, name,
+ is_template);
+ }
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
}
additional level of template parameters. */
++num_templates;
- return cp_parser_check_template_parameters (parser,
- num_templates,
- declarator_location);
+ return cp_parser_check_template_parameters
+ (parser, num_templates, declarator_location, declarator);
+
case cdk_function:
case cdk_array:
/* NUM_TEMPLATES were used in the current declaration. If that is
invalid, return FALSE and issue an error messages. Otherwise,
- return TRUE. */
+ return TRUE. If DECLARATOR is non-NULL, then we are checking a
+ declarator and we can print more accurate diagnostics. */
static bool
cp_parser_check_template_parameters (cp_parser* parser,
unsigned num_templates,
- location_t location)
+ location_t location,
+ cp_declarator *declarator)
{
+ /* If there are the same number of template classes and parameter
+ lists, that's OK. */
+ if (parser->num_template_parameter_lists == num_templates)
+ return true;
+ /* If there are more, but only one more, then we are referring to a
+ member template. That's OK too. */
+ if (parser->num_template_parameter_lists == num_templates + 1)
+ return true;
/* If there are more template classes than parameter lists, we have
something like:
template <class T> void S<T>::R<T>::f (); */
if (parser->num_template_parameter_lists < num_templates)
{
- error ("%Htoo few template-parameter-lists", &location);
+ if (declarator)
+ error_at (location, "specializing member %<%T::%E%> "
+ "requires %<template<>%> syntax",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
+ else
+ error_at (location, "too few template-parameter-lists");
return false;
}
- /* If there are the same number of template classes and parameter
- lists, that's OK. */
- if (parser->num_template_parameter_lists == num_templates)
- return true;
- /* If there are more, but only one more, then we are referring to a
- member template. That's OK too. */
- if (parser->num_template_parameter_lists == num_templates + 1)
- return true;
/* Otherwise, there are too many template parameter lists. We have
something like:
cp_parser_simple_cast_expression (cp_parser *parser)
{
return cp_parser_cast_expression (parser, /*address_p=*/false,
- /*cast_p=*/false);
+ /*cast_p=*/false, NULL);
}
/* Parse a functional cast to TYPE. Returns an expression
static tree
cp_parser_functional_cast (cp_parser* parser, tree type)
{
+ VEC(tree,gc) *vec;
tree expression_list;
tree cast;
bool nonconst_p;
return finish_compound_literal (type, expression_list);
}
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/true,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+
+ vec = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/true,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ expression_list = error_mark_node;
+ else
+ {
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
cast = build_functional_cast (type, expression_list,
tf_warning_or_error);
tree saved_qualifying_scope;
tree saved_object_scope;
bool saved_greater_than_is_operator_p;
- bool saved_skip_evaluation;
+ int saved_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings;
/* [temp.names]
saved_object_scope = parser->object_scope;
/* We need to evaluate the template arguments, even though this
template-id may be nested within a "sizeof". */
- saved_skip_evaluation = skip_evaluation;
- skip_evaluation = false;
+ saved_unevaluated_operand = cp_unevaluated_operand;
+ cp_unevaluated_operand = 0;
+ saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+ c_inhibit_evaluation_warnings = 0;
/* Parse the template-argument-list itself. */
if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
|| cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
- skip_evaluation = saved_skip_evaluation;
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
return arguments;
}
cp_parser_push_lexer_for_tokens (parser, tokens);
/* Parse the assignment-expression. */
- parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+ parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+ if (parsed_arg == error_mark_node)
+ {
+ cp_parser_pop_lexer (parser);
+ continue;
+ }
if (!processing_template_decl)
parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
}
/* Do not actually evaluate the expression. */
- ++skip_evaluation;
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
/* If it's a `(', then we might be looking at the type-id
construction. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
looking at the unary-expression production. */
if (!expr)
expr = cp_parser_unary_expression (parser, /*address_p=*/false,
- /*cast_p=*/false);
+ /*cast_p=*/false, NULL);
if (pack_expansion_p)
/* Build a pack expansion. */
expr = make_pack_expansion (expr);
/* Go back to evaluating expressions. */
- --skip_evaluation;
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
/* Free the message we created. */
free (tmp);
/* An Objective-C message receiver may be either (1) a type
or (2) an expression. */
cp_parser_parse_tentatively (parser);
- rcv = cp_parser_expression (parser, false);
+ rcv = cp_parser_expression (parser, false, NULL);
if (cp_parser_parse_definitely (parser))
return rcv;
maybe_unary_selector_p = false;
cp_parser_require (parser, CPP_COLON, "%<:%>");
- arg = cp_parser_assignment_expression (parser, false);
+ arg = cp_parser_assignment_expression (parser, false, NULL);
sel_args
= chainon (sel_args,
tree arg;
cp_lexer_consume_token (parser->lexer);
- arg = cp_parser_assignment_expression (parser, false);
+ arg = cp_parser_assignment_expression (parser, false, NULL);
addl_args
= chainon (addl_args,
tree sel_seq = NULL_TREE;
bool maybe_unary_selector_p = true;
cp_token *token;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
finish_selector:
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
- return objc_build_selector_expr (sel_seq);
+ return objc_build_selector_expr (loc, sel_seq);
}
/* Parse a list of identifiers.
location = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
- lock = cp_parser_expression (parser, false);
+ lock = cp_parser_expression (parser, false, NULL);
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
static tree
cp_parser_objc_throw_statement (cp_parser *parser) {
tree expr = NULL_TREE;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_keyword (parser, RID_AT_THROW, "%<@throw%>");
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- expr = cp_parser_assignment_expression (parser, false);
+ expr = cp_parser_assignment_expression (parser, false, NULL);
cp_parser_consume_semicolon_at_end_of_statement (parser);
- return objc_build_throw_stmt (expr);
+ return objc_build_throw_stmt (loc, expr);
}
/* Parse an Objective-C statement. */
/* Validate that a clause of the given type does not already exist. */
static void
-check_no_duplicate_clause (tree clauses, enum tree_code code,
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
const char *name, location_t location)
{
tree c;
cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
else if (kind != 0)
{
- tree u = build_omp_clause (kind);
+ tree u = build_omp_clause (token->location, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
}
check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
- c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+ c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
return list;
check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
- c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+ c = build_omp_clause (location, OMP_CLAUSE_DEFAULT);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_DEFAULT_KIND (c) = kind;
check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
- c = build_omp_clause (OMP_CLAUSE_IF);
+ c = build_omp_clause (location, OMP_CLAUSE_IF);
OMP_CLAUSE_IF_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
- c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+ c = build_omp_clause (location, OMP_CLAUSE_NOWAIT);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
- t = cp_parser_expression (parser, false);
+ t = cp_parser_expression (parser, false, NULL);
if (t == error_mark_node
|| !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
"num_threads", location);
- c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+ c = build_omp_clause (location, OMP_CLAUSE_NUM_THREADS);
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
"ordered", location);
- c = build_omp_clause (OMP_CLAUSE_ORDERED);
+ c = build_omp_clause (location, OMP_CLAUSE_ORDERED);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
- c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+ c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
cp_lexer_consume_token (parser->lexer);
token = cp_lexer_peek_token (parser->lexer);
- t = cp_parser_assignment_expression (parser, false);
+ t = cp_parser_assignment_expression (parser, false, NULL);
if (t == error_mark_node)
goto resync_fail;
check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
- c = build_omp_clause (OMP_CLAUSE_UNTIED);
+ c = build_omp_clause (location, OMP_CLAUSE_UNTIED);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
cp_parser_require_pragma_eol (parser, pragma_tok);
lhs = cp_parser_unary_expression (parser, /*address_p=*/false,
- /*cast_p=*/false);
+ /*cast_p=*/false, NULL);
switch (TREE_CODE (lhs))
{
case ERROR_MARK:
}
cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_expression (parser, false);
+ rhs = cp_parser_expression (parser, false, NULL);
if (rhs == error_mark_node)
goto saw_error;
break;
cp_parser_require_pragma_eol (parser, pragma_tok);
stmt = cp_parser_omp_structured_block (parser);
- return c_finish_omp_critical (stmt, name);
+ return c_finish_omp_critical (input_location, stmt, name);
}
/* OpenMP 2.5:
cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
- (void) cp_parser_omp_var_list (parser, 0, NULL);
+ (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
cp_parser_require_pragma_eol (parser, pragma_tok);
finish_omp_flush ();
static tree
cp_parser_omp_for_cond (cp_parser *parser, tree decl)
{
- tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
- enum tree_code op;
- cp_token *token;
+ tree cond = cp_parser_binary_expression (parser, false, true,
+ PREC_NOT_OPERATOR, NULL);
+ bool overloaded_p;
- if (lhs != decl)
+ if (cond == error_mark_node
+ || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
- token = cp_lexer_peek_token (parser->lexer);
- op = binops_by_token [token->type].tree_type;
- switch (op)
+ switch (TREE_CODE (cond))
{
- case LT_EXPR:
- case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
break;
default:
- cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
- cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false,
- PREC_RELATIONAL_EXPRESSION);
- if (rhs == error_mark_node
- || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- {
- cp_parser_skip_to_end_of_statement (parser);
- return error_mark_node;
- }
+ /* If decl is an iterator, preserve LHS and RHS of the relational
+ expr until finish_omp_for. */
+ if (decl
+ && (type_dependent_expression_p (decl)
+ || CLASS_TYPE_P (TREE_TYPE (decl))))
+ return cond;
- return build2 (op, boolean_type_node, lhs, rhs);
+ return build_x_binary_op (TREE_CODE (cond),
+ TREE_OPERAND (cond, 0), ERROR_MARK,
+ TREE_OPERAND (cond, 1), ERROR_MARK,
+ &overloaded_p, tf_warning_or_error);
}
/* Helper function, to parse omp for increment expression. */
op = (token->type == CPP_PLUS_PLUS
? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
cp_lexer_consume_token (parser->lexer);
- lhs = cp_parser_cast_expression (parser, false, false);
+ lhs = cp_parser_cast_expression (parser, false, false, NULL);
if (lhs != decl)
return error_mark_node;
return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
if (op != NOP_EXPR)
{
- rhs = cp_parser_assignment_expression (parser, false);
+ rhs = cp_parser_assignment_expression (parser, false, NULL);
rhs = build2 (op, TREE_TYPE (decl), decl, rhs);
return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
}
- lhs = cp_parser_binary_expression (parser, false,
- PREC_ADDITIVE_EXPRESSION);
+ lhs = cp_parser_binary_expression (parser, false, false,
+ PREC_ADDITIVE_EXPRESSION, NULL);
token = cp_lexer_peek_token (parser->lexer);
decl_first = lhs == decl;
if (decl_first)
{
op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false,
- PREC_ADDITIVE_EXPRESSION);
+ rhs = cp_parser_binary_expression (parser, false, false,
+ PREC_ADDITIVE_EXPRESSION, NULL);
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
{
else
{
- tree pushed_scope;
+ tree pushed_scope, auto_node;
decl = start_decl (declarator, &type_specifiers,
- /*initialized_p=*/false, attributes,
+ SD_INITIALIZED, attributes,
/*prefix_attributes=*/NULL_TREE,
&pushed_scope);
+ auto_node = type_uses_auto (TREE_TYPE (decl));
if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ))
{
if (cp_lexer_next_token_is (parser->lexer,
cp_parser_skip_to_end_of_statement (parser);
}
else if (CLASS_TYPE_P (TREE_TYPE (decl))
- || type_dependent_expression_p (decl))
+ || type_dependent_expression_p (decl)
+ || auto_node)
{
bool is_direct_init, is_non_constant_init;
&is_direct_init,
&is_non_constant_init);
+ if (auto_node && describable_type (init))
+ {
+ TREE_TYPE (decl)
+ = do_auto_deduction (TREE_TYPE (decl), init,
+ auto_node);
+
+ if (!CLASS_TYPE_P (TREE_TYPE (decl))
+ && !type_dependent_expression_p (decl))
+ goto non_class;
+ }
+
cp_finish_decl (decl, init, !is_non_constant_init,
asm_specification,
LOOKUP_ONLYCONVERTING);
{
/* Consume '='. */
cp_lexer_consume_token (parser->lexer);
- init = cp_parser_assignment_expression (parser, false);
+ init = cp_parser_assignment_expression (parser, false, NULL);
+ non_class:
if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
init = error_mark_node;
else
cp_parser_parse_definitely (parser);
cp_parser_require (parser, CPP_EQ, "%<=%>");
- rhs = cp_parser_assignment_expression (parser, false);
+ rhs = cp_parser_assignment_expression (parser, false, NULL);
finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
rhs,
tf_warning_or_error));
{
decl = NULL;
cp_parser_abort_tentative_parse (parser);
- init = cp_parser_expression (parser, false);
+ init = cp_parser_expression (parser, false, NULL);
if (init)
{
if (TREE_CODE (init) == MODIFY_EXPR
{
/* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
change it to shared (decl) in OMP_PARALLEL_CLAUSES. */
- tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+ tree l = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (l) = real_decl;
OMP_CLAUSE_CHAIN (l) = clauses;
CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
}
if (c == NULL)
{
- c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (c) = decl;
c = finish_omp_clauses (c);
if (c)
cond = NULL;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- {
- /* If decl is an iterator, preserve LHS and RHS of the relational
- expr until finish_omp_for. */
- if (decl
- && (type_dependent_expression_p (decl)
- || CLASS_TYPE_P (TREE_TYPE (decl))))
- cond = cp_parser_omp_for_cond (parser, decl);
- else
- cond = cp_parser_condition (parser);
- }
+ cond = cp_parser_omp_for_cond (parser, decl);
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
incr = NULL;
|| CLASS_TYPE_P (TREE_TYPE (decl))))
incr = cp_parser_omp_for_incr (parser, decl);
else
- incr = cp_parser_expression (parser, false);
+ incr = cp_parser_expression (parser, false, NULL);
}
if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
- return c_finish_omp_master (cp_parser_omp_structured_block (parser));
+ return c_finish_omp_master (input_location,
+ cp_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
static tree
cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok)
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_pragma_eol (parser, pragma_tok);
- return c_finish_omp_ordered (cp_parser_omp_structured_block (parser));
+ return c_finish_omp_ordered (loc, cp_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
tree stmt, clauses, par_clause, ws_clause, block;
unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
{
break;
case PRAGMA_OMP_PARALLEL_FOR:
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
break;
case PRAGMA_OMP_PARALLEL_SECTIONS:
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
stmt = cp_parser_omp_sections_scope (parser);
if (stmt)
OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
{
tree vars;
- vars = cp_parser_omp_var_list (parser, 0, NULL);
+ vars = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
cp_parser_require_pragma_eol (parser, pragma_tok);
finish_omp_threadprivate (vars);