unsigned char flags;
/* Identifier for the pragma. */
ENUM_BITFIELD (pragma_kind) pragma_kind : 6;
- /* True if this token is from a system header. */
- BOOL_BITFIELD in_system_header : 1;
/* True if this token is from a context where it is implicitly extern "C" */
BOOL_BITFIELD implicit_extern_c : 1;
/* True for a CPP_NAME token that is not a keyword (i.e., for which
static cp_token eof_token =
{
- CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, false, 0, { NULL },
+ CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL },
0
};
lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
- token->in_system_header = in_system_header;
/* On some systems, some header files are surrounded by an
implicit extern "C" block. Set a flag in the token if it
/* Clear out the C_RID_CODE so we don't warn about this
particular identifier-turned-keyword again. */
- C_RID_CODE (token->u.value) = RID_MAX;
+ C_SET_RID_CODE (token->u.value, RID_MAX);
}
token->ambiguous_p = false;
}
}
-/* Update the globals input_location and in_system_header and the
- input file stack from TOKEN. */
+/* Update the globals input_location and the input file stack from TOKEN. */
static inline void
cp_lexer_set_source_position_from_token (cp_token *token)
{
if (token->type != CPP_EOF)
{
input_location = token->location;
- in_system_header = token->in_system_header;
}
}
return cp_lexer_peek_token (lexer)->keyword == keyword;
}
+/* Return true if the next token is not the indicated KEYWORD. */
+
+static inline bool
+cp_lexer_next_token_is_not_keyword (cp_lexer* lexer, enum rid keyword)
+{
+ return cp_lexer_peek_token (lexer)->keyword != keyword;
+}
+
/* Return true if the next token is a keyword for a decl-specifier. */
static bool
case RID_TYPENAME:
/* Simple type specifiers. */
case RID_CHAR:
+ case RID_CHAR16:
+ case RID_CHAR32:
case RID_WCHAR:
case RID_BOOL:
case RID_SHORT:
break;
case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
case CPP_WSTRING:
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
break;
VAR_DECLs or FUNCTION_DECLs) should do that directly. */
static cp_declarator *make_call_declarator
- (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, 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 exception_specification,
+ tree late_return_type)
{
cp_declarator *declarator;
declarator->u.function.parameters = parms;
declarator->u.function.qualifiers = cv_qualifiers;
declarator->u.function.exception_specification = exception_specification;
+ declarator->u.function.late_return_type = late_return_type;
if (target)
{
declarator->parameter_pack_p = target->parameter_pack_p;
/* No errors have occurred yet in this context. */
context->status = CP_PARSER_STATUS_KIND_NO_ERROR;
- /* If this is not the bottomost context, copy information that we
+ /* If this is not the bottommost context, copy information that we
need from the previous context. */
if (next)
{
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier
(cp_parser *, bool, bool, bool, bool);
-static tree cp_parser_class_or_namespace_name
+static tree cp_parser_qualifying_entity
(cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_postfix_expression
(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 *, enum cpp_ttype, tree, bool, cp_id_kind *);
+ (cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
static tree cp_parser_parenthesized_expression_list
(cp_parser *, bool, bool, bool, bool *);
static void cp_parser_pseudo_destructor_name
static tree cp_parser_cast_expression
(cp_parser *, bool, bool);
static tree cp_parser_binary_expression
- (cp_parser *, bool);
+ (cp_parser *, bool, enum cp_parser_prec);
static tree cp_parser_question_colon_clause
(cp_parser *, tree);
static tree cp_parser_assignment_expression
(cp_parser *, tree *, cp_cv_quals *);
static cp_cv_quals cp_parser_cv_qualifier_seq_opt
(cp_parser *);
+static tree cp_parser_late_return_type_opt
+ (cp_parser *);
static tree cp_parser_declarator_id
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
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 *);
(cp_parser *, bool *, bool *);
static tree cp_parser_initializer_clause
(cp_parser *, bool *);
+static tree cp_parser_braced_list
+ (cp_parser*, bool*);
static VEC(constructor_elt,gc) *cp_parser_initializer_list
(cp_parser *, bool *);
/* Utility Routines */
static tree cp_parser_lookup_name
- (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *);
+ (cp_parser *, tree, enum tag_types, bool, bool, bool, tree *, location_t);
static tree cp_parser_lookup_name_simple
- (cp_parser *, tree);
+ (cp_parser *, tree, location_t);
static tree cp_parser_maybe_treat_template_as_class
(tree, bool);
static bool cp_parser_check_declarator_template_parameters
- (cp_parser *, cp_declarator *);
+ (cp_parser *, cp_declarator *, location_t);
static bool cp_parser_check_template_parameters
- (cp_parser *, unsigned);
+ (cp_parser *, unsigned, location_t);
static tree cp_parser_simple_cast_expression
(cp_parser *);
static tree cp_parser_global_scope_opt
static bool cp_parser_declares_only_class_p
(cp_parser *);
static void cp_parser_set_storage_class
- (cp_parser *, cp_decl_specifier_seq *, enum rid);
+ (cp_parser *, cp_decl_specifier_seq *, enum rid, location_t);
static void cp_parser_set_decl_spec_type
- (cp_decl_specifier_seq *, tree, bool);
+ (cp_decl_specifier_seq *, tree, location_t, bool);
static bool cp_parser_friend_p
(const cp_decl_specifier_seq *);
static cp_token *cp_parser_require
static void cp_parser_check_class_key
(enum tag_types, tree type);
static void cp_parser_check_access_in_redeclaration
- (tree type);
+ (tree type, location_t location);
static bool cp_parser_optional_template_keyword
(cp_parser *);
static void cp_parser_pre_parsed_nested_name_specifier
(cp_parser *);
-static void cp_parser_cache_group
+static bool cp_parser_cache_group
(cp_parser *, enum cpp_ttype, unsigned);
static void cp_parser_parse_tentatively
(cp_parser *);
static void cp_parser_error
(cp_parser *, const char *);
static void cp_parser_name_lookup_error
- (cp_parser *, tree, tree, const char *);
+ (cp_parser *, tree, tree, const char *, location_t);
static bool cp_parser_simulate_error
(cp_parser *);
static bool cp_parser_check_type_definition
(cp_parser *);
static void cp_parser_check_for_definition_in_return_type
- (cp_declarator *, tree);
+ (cp_declarator *, tree, location_t type_location);
static void cp_parser_check_for_invalid_template_id
- (cp_parser *, tree);
+ (cp_parser *, tree, location_t location);
static bool cp_parser_non_integral_constant_expression
(cp_parser *, const char *);
static void cp_parser_diagnose_invalid_type_name
- (cp_parser *, tree, tree);
+ (cp_parser *, tree, tree, location_t);
static bool cp_parser_parse_and_diagnose_invalid_type_name
(cp_parser *);
static int cp_parser_skip_to_closing_parenthesis
static bool cp_parser_is_keyword
(cp_token *, enum rid);
static tree cp_parser_make_typename_type
- (cp_parser *, tree, tree);
+ (cp_parser *, tree, tree, location_t location);
static cp_declarator * cp_parser_make_indirect_declarator
(enum tree_code, tree, cp_cv_quals, cp_declarator *);
static bool
cp_parser_is_string_literal (cp_token* token)
{
- return (token->type == CPP_STRING || token->type == CPP_WSTRING);
+ return (token->type == CPP_STRING ||
+ token->type == CPP_STRING16 ||
+ token->type == CPP_STRING32 ||
+ token->type == CPP_WSTRING);
}
/* Returns nonzero if TOKEN is the indicated KEYWORD. */
if (token->type == CPP_PRAGMA)
{
- error ("%<#pragma%> is not allowed here");
+ error ("%H%<#pragma%> is not allowed here", &token->location);
cp_parser_skip_to_pragma_eol (parser, token);
return;
}
cp_parser_name_lookup_error (cp_parser* parser,
tree name,
tree decl,
- const char* desired)
+ const char* desired,
+ location_t location)
{
/* If name lookup completely failed, tell the user that NAME was not
declared. */
if (decl == error_mark_node)
{
if (parser->scope && parser->scope != global_namespace)
- error ("%<%E::%E%> has not been declared",
- parser->scope, name);
+ error ("%H%<%E::%E%> has not been declared",
+ &location, parser->scope, name);
else if (parser->scope == global_namespace)
- error ("%<::%E%> has not been declared", name);
+ error ("%H%<::%E%> has not been declared", &location, name);
else if (parser->object_scope
&& !CLASS_TYPE_P (parser->object_scope))
- error ("request for member %qE in non-class type %qT",
- name, parser->object_scope);
+ error ("%Hrequest for member %qE in non-class type %qT",
+ &location, name, parser->object_scope);
else if (parser->object_scope)
- error ("%<%T::%E%> has not been declared",
- parser->object_scope, name);
+ error ("%H%<%T::%E%> has not been declared",
+ &location, parser->object_scope, name);
else
- error ("%qE has not been declared", name);
+ error ("%H%qE has not been declared", &location, name);
}
else if (parser->scope && parser->scope != global_namespace)
- error ("%<%E::%E%> %s", parser->scope, name, desired);
+ error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
else if (parser->scope == global_namespace)
- error ("%<::%E%> %s", name, desired);
+ error ("%H%<::%E%> %s", &location, name, desired);
else
- error ("%qE %s", name, desired);
+ error ("%H%qE %s", &location, name, desired);
}
/* If we are parsing tentatively, remember that an error has occurred
/* Check for repeated decl-specifiers. */
static void
-cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs)
+cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
+ location_t location)
{
cp_decl_spec ds;
if (ds == ds_long)
{
if (count > 2)
- error ("%<long long long%> is too long for GCC");
+ error ("%H%<long long long%> is too long for GCC", &location);
else if (pedantic && !in_system_header && warn_long_long
&& cxx_dialect == cxx98)
- pedwarn ("ISO C++ 1998 does not support %<long long%>");
+ pedwarn (location, OPT_Wlong_long,
+ "ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
{
"__complex",
"__thread"
};
- error ("duplicate %qs", decl_spec_names[(int)ds]);
+ error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
}
}
}
/* If types are forbidden here, issue a message. */
if (parser->type_definition_forbidden_message)
{
- /* Use `%s' to print the string in case there are any escape
- characters in the message. */
- error ("%s", parser->type_definition_forbidden_message);
+ /* Don't use `%s' to print the string, because quotations (`%<', `%>')
+ in the message need to be interpreted. */
+ error (parser->type_definition_forbidden_message);
return false;
}
return true;
/* This function is called when the DECLARATOR is processed. The TYPE
was a type defined in the decl-specifiers. If it is invalid to
define a type in the decl-specifiers for DECLARATOR, an error is
- issued. */
+ issued. TYPE_LOCATION is the location of TYPE and is used
+ for error reporting. */
static void
cp_parser_check_for_definition_in_return_type (cp_declarator *declarator,
- tree type)
+ tree type, location_t type_location)
{
/* [dcl.fct] forbids type definitions in return types.
Unfortunately, it's not easy to know whether or not we are
if (declarator
&& declarator->kind == cdk_function)
{
- error ("new types may not be defined in a return type");
- inform ("(perhaps a semicolon is missing after the definition of %qT)",
+ error ("%Hnew types may not be defined in a return type", &type_location);
+ inform (type_location,
+ "(perhaps a semicolon is missing after the definition of %qT)",
type);
}
}
/* A type-specifier (TYPE) has been parsed which cannot be followed by
"<" in any valid C++ program. If the next token is indeed "<",
issue a message warning the user about what appears to be an
- invalid attempt to form a template-id. */
+ invalid attempt to form a template-id. LOCATION is the location
+ of the type-specifier (TYPE) */
static void
cp_parser_check_for_invalid_template_id (cp_parser* parser,
- tree type)
+ tree type, location_t location)
{
cp_token_position start = 0;
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
{
if (TYPE_P (type))
- error ("%qT is not a template", type);
+ error ("%H%qT is not a template", &location, type);
else if (TREE_CODE (type) == IDENTIFIER_NODE)
- error ("%qE is not a template", type);
+ error ("%H%qE is not a template", &location, type);
else
- error ("invalid template-id");
+ error ("%Hinvalid template-id", &location);
/* Remember the location of the invalid "<". */
if (cp_parser_uncommitted_to_tentative_parse_p (parser))
start = cp_lexer_token_position (parser->lexer, true);
{
if (!parser->allow_non_integral_constant_expression_p)
{
- error ("%s cannot appear in a constant-expression", thing);
+ /* Don't use `%s' to print THING, because quotations (`%<', `%>')
+ in the message need to be interpreted. */
+ char *message = concat (thing,
+ " cannot appear in a constant-expression",
+ NULL);
+ error (message);
+ free (message);
return true;
}
}
qualifying scope (or NULL, if none) for ID. This function commits
to the current active tentative parse, if any. (Otherwise, the
problematic construct might be encountered again later, resulting
- in duplicate error messages.) */
+ in duplicate error messages.) LOCATION is the location of ID. */
static void
-cp_parser_diagnose_invalid_type_name (cp_parser *parser, tree scope, tree id)
+cp_parser_diagnose_invalid_type_name (cp_parser *parser,
+ tree scope, tree id,
+ location_t location)
{
tree decl, old_scope;
/* Try to lookup the identifier. */
old_scope = parser->scope;
parser->scope = scope;
- decl = cp_parser_lookup_name_simple (parser, id);
+ decl = cp_parser_lookup_name_simple (parser, id, location);
parser->scope = old_scope;
/* If the lookup found a template-name, it means that the user forgot
to specify an argument list. Emit a useful error message. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
- error ("invalid use of template-name %qE without an argument list", decl);
+ error ("%Hinvalid use of template-name %qE without an argument list",
+ &location, decl);
else if (TREE_CODE (id) == BIT_NOT_EXPR)
- error ("invalid use of destructor %qD as a type", id);
+ error ("%Hinvalid use of destructor %qD as a type", &location, id);
else if (TREE_CODE (decl) == TYPE_DECL)
/* Something like 'unsigned A a;' */
- error ("invalid combination of multiple type-specifiers");
+ error ("%Hinvalid combination of multiple type-specifiers",
+ &location);
else if (!parser->scope)
{
/* Issue an error message. */
- error ("%qE does not name a type", id);
+ error ("%H%qE does not name a type", &location, id);
/* If we're in a template class, it's possible that the user was
referring to a type from a base class. For example:
if (TREE_CODE (field) == TYPE_DECL
&& DECL_NAME (field) == id)
{
- inform ("(perhaps %<typename %T::%E%> was intended)",
+ inform (location,
+ "(perhaps %<typename %T::%E%> was intended)",
BINFO_TYPE (b), id);
break;
}
else if (parser->scope != error_mark_node)
{
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
- error ("%qE in namespace %qE does not name a type",
- id, parser->scope);
+ error ("%H%qE in namespace %qE does not name a type",
+ &location, id, parser->scope);
else if (TYPE_P (parser->scope))
- error ("%qE in class %qT does not name a type", id, parser->scope);
+ error ("%H%qE in class %qT does not name a type",
+ &location, id, parser->scope);
else
gcc_unreachable ();
}
cp_parser_parse_and_diagnose_invalid_type_name (cp_parser *parser)
{
tree id;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
cp_parser_parse_tentatively (parser);
id = cp_parser_id_expression (parser,
return false;
/* Emit a diagnostic for the invalid type. */
- cp_parser_diagnose_invalid_type_name (parser, parser->scope, id);
+ cp_parser_diagnose_invalid_type_name (parser, parser->scope,
+ id, token->location);
/* Skip to the end of the declaration; there's no point in
trying to process it. */
cp_parser_skip_to_end_of_block_or_statement (parser);
cp_parser_consume_semicolon_at_end_of_statement (cp_parser *parser)
{
/* Look for the trailing `;'. */
- if (!cp_parser_require (parser, CPP_SEMICOLON, "`;'"))
+ if (!cp_parser_require (parser, CPP_SEMICOLON, "%<;%>"))
{
/* If there is additional (erroneous) input, skip to the end of
the statement. */
using cp_parser_diagnose_invalid_type_name. */
static tree
-cp_parser_make_typename_type (cp_parser *parser, tree scope, tree id)
+cp_parser_make_typename_type (cp_parser *parser, tree scope,
+ tree id, location_t id_location)
{
tree result;
if (TREE_CODE (id) == IDENTIFIER_NODE)
result = make_typename_type (scope, id, typename_type,
/*complain=*/tf_none);
if (result == error_mark_node)
- cp_parser_diagnose_invalid_type_name (parser, scope, id);
+ cp_parser_diagnose_invalid_type_name (parser, scope, id, id_location);
return result;
}
return make_typename_type (scope, id, typename_type, tf_error);
cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
tree value;
- bool wide = false;
size_t count;
struct obstack str_ob;
cpp_string str, istr, *strs;
cp_token *tok;
+ enum cpp_ttype type;
tok = cp_lexer_peek_token (parser->lexer);
if (!cp_parser_is_string_literal (tok))
return error_mark_node;
}
+ type = tok->type;
+
/* Try to avoid the overhead of creating and destroying an obstack
for the common case of just one string. */
if (!cp_parser_is_string_literal
str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
count = 1;
- if (tok->type == CPP_WSTRING)
- wide = true;
strs = &str;
}
count++;
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 (type != tok->type)
+ {
+ if (type == CPP_STRING)
+ type = tok->type;
+ else if (tok->type != CPP_STRING)
+ error ("%Hunsupported non-standard concatenation "
+ "of string literals", &tok->location);
+ }
obstack_grow (&str_ob, &str, sizeof (cpp_string));
strs = (cpp_string *) obstack_finish (&str_ob);
}
- if (wide && !wide_ok)
+ if (type != CPP_STRING && !wide_ok)
{
cp_parser_error (parser, "a wide string is invalid in this context");
- wide = false;
+ type = CPP_STRING;
}
if ((translate ? cpp_interpret_string : cpp_interpret_string_notranslate)
- (parse_in, strs, count, &istr, wide))
+ (parse_in, strs, count, &istr, type))
{
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;
+ switch (type)
+ {
+ default:
+ case CPP_STRING:
+ TREE_TYPE (value) = char_array_type_node;
+ break;
+ case CPP_STRING16:
+ TREE_TYPE (value) = char16_array_type_node;
+ break;
+ case CPP_STRING32:
+ TREE_TYPE (value) = char32_array_type_node;
+ break;
+ case CPP_WSTRING:
+ TREE_TYPE (value) = wchar_array_type_node;
+ break;
+ }
+
value = fix_string_type (value);
}
else
bool template_arg_p,
cp_id_kind *idk)
{
- cp_token *token;
+ cp_token *token = NULL;
/* Assume the primary expression is not an id-expression. */
*idk = CP_ID_KIND_NONE;
string-literal
boolean-literal */
case CPP_CHAR:
+ case CPP_CHAR16:
+ case CPP_CHAR32:
case CPP_WCHAR:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
return token->u.value;
case CPP_STRING:
+ case CPP_STRING16:
+ case CPP_STRING32:
case CPP_WSTRING:
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
/* Statement-expressions are not allowed by the standard. */
- if (pedantic)
- pedwarn ("ISO C++ forbids braced-groups within expressions");
+ pedwarn (token->location, OPT_pedantic,
+ "ISO C++ forbids braced-groups within expressions");
/* And they're not allowed outside of a function-body; you
cannot, for example, write:
if (!parser->in_function_body
|| parser->in_template_argument_list_p)
{
- error ("statement-expressions are not allowed outside "
- "functions nor in template-argument lists");
+ error ("%Hstatement-expressions are not allowed outside "
+ "functions nor in template-argument lists",
+ &token->location);
cp_parser_skip_to_end_of_block_or_statement (parser);
expr = error_mark_node;
}
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
/* Consume the `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_end_of_statement (parser);
return expr;
cp_lexer_consume_token (parser->lexer);
if (parser->local_variables_forbidden_p)
{
- error ("%<this%> may not be used in this context");
+ error ("%H%<this%> may not be used in this context",
+ &token->location);
return error_mark_node;
}
/* Pointers cannot appear in constant-expressions. */
- if (cp_parser_non_integral_constant_expression (parser,
- "`this'"))
+ if (cp_parser_non_integral_constant_expression (parser, "%<this%>"))
return error_mark_node;
return finish_this_expr ();
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:
{
`va_arg'. Consume the `__builtin_va_arg' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the opening `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Now, parse the assignment-expression. */
expression = cp_parser_assignment_expression (parser,
/*cast_p=*/false);
/* Look for the `,'. */
- cp_parser_require (parser, CPP_COMMA, "`,'");
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
/* Parse the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Using `va_arg' in a constant-expression is not
allowed. */
if (cp_parser_non_integral_constant_expression (parser,
- "`va_arg'"))
+ "%<va_arg%>"))
return error_mark_node;
return build_x_va_arg (expression, type);
}
const char *error_msg;
bool template_p;
bool done;
+ cp_token *id_expr_token;
id_expression:
/* Parse the id-expression. */
/*optional_p=*/false);
if (id_expression == error_mark_node)
return error_mark_node;
+ id_expr_token = token;
token = cp_lexer_peek_token (parser->lexer);
done = (token->type != CPP_OPEN_SQUARE
&& token->type != CPP_OPEN_PAREN
template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- &ambiguous_decls);
+ &ambiguous_decls,
+ id_expr_token->location);
/* If the lookup was ambiguous, an error will already have
been issued. */
if (ambiguous_decls)
decl = check_for_out_of_scope_variable (decl);
if (local_variable_p (decl))
{
- error ("local variable %qD may not appear in this context",
- decl);
+ error ("%Hlocal variable %qD may not appear in this context",
+ &id_expr_token->location, decl);
return error_mark_node;
}
}
&parser->non_integral_constant_expression_p,
template_p, done, address_p,
template_arg_p,
- &error_msg));
+ &error_msg,
+ id_expr_token->location));
if (error_msg)
cp_parser_error (parser, error_msg);
return decl;
if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("scope %qT before %<~%> is not a class-name", scope);
+ error ("%Hscope %qT before %<~%> is not a class-name",
+ &token->location, scope);
cp_parser_simulate_error (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
cp_lexer_consume_token (parser->lexer);
if (declarator_p && scope && !check_dtor_name (scope, type_decl))
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("declaration of %<~%T%> as member of %qT",
- type_decl, scope);
+ error ("%Hdeclaration of %<~%T%> as member of %qT",
+ &token->location, type_decl, scope);
cp_parser_simulate_error (parser);
return error_mark_node;
}
&& !DECL_IMPLICIT_TYPEDEF_P (type_decl)
&& !DECL_SELF_REFERENCE_P (type_decl)
&& !cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("typedef-name %qD used as destructor declarator",
- type_decl);
+ error ("%Htypedef-name %qD used as destructor declarator",
+ &token->location, type_decl);
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
/* Parse an (optional) nested-name-specifier.
- nested-name-specifier:
+ nested-name-specifier: [C++98]
class-or-namespace-name :: nested-name-specifier [opt]
class-or-namespace-name :: template nested-name-specifier [opt]
+ nested-name-specifier: [C++0x]
+ type-name ::
+ namespace-name ::
+ nested-name-specifier identifier ::
+ nested-name-specifier template [opt] simple-template-id ::
+
PARSER->SCOPE should be set appropriately before this function is
called. TYPENAME_KEYWORD_P is TRUE if the `typename' keyword is in
effect. TYPE_P is TRUE if we non-type bindings should be ignored
else
{
/* If the next token is not an identifier, then it is
- definitely not a class-or-namespace-name. */
+ definitely not a type-name or namespace-name. */
if (token->type != CPP_NAME)
break;
/* If the following token is neither a `<' (to begin a
/*only_current_p=*/false);
/* Parse the qualifying entity. */
new_scope
- = cp_parser_class_or_namespace_name (parser,
- typename_keyword_p,
- template_keyword_p,
- check_dependency_p,
- type_p,
- is_declaration);
+ = cp_parser_qualifying_entity (parser,
+ typename_keyword_p,
+ template_keyword_p,
+ check_dependency_p,
+ type_p,
+ is_declaration);
/* Look for the `::' token. */
- cp_parser_require (parser, CPP_SCOPE, "`::'");
+ cp_parser_require (parser, CPP_SCOPE, "%<::%>");
/* If we found what we wanted, we keep going; otherwise, we're
done. */
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- &ambiguous_decls);
+ &ambiguous_decls,
+ token->location);
if (TREE_CODE (decl) == TEMPLATE_DECL)
- error ("%qD used without template parameters", decl);
+ error ("%H%qD used without template parameters",
+ &token->location, decl);
else if (ambiguous_decls)
{
- error ("reference to %qD is ambiguous",
- token->u.value);
+ error ("%Hreference to %qD is ambiguous",
+ &token->location, token->u.value);
print_candidates (ambiguous_decls);
decl = error_mark_node;
}
else
- cp_parser_name_lookup_error
- (parser, token->u.value, decl,
- "is not a class or namespace");
+ {
+ const char* msg = "is not a class or namespace";
+ if (cxx_dialect != cxx98)
+ msg = "is not a class, namespace, or enumeration";
+ cp_parser_name_lookup_error
+ (parser, token->u.value, decl, msg,
+ token->location);
+ }
}
parser->scope = error_mark_node;
error_p = true;
&& !(TREE_CODE (new_scope) == TYPENAME_TYPE
&& (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
== TEMPLATE_ID_EXPR)))
- pedwarn (TYPE_P (new_scope)
- ? "%qT is not a template"
- : "%qD is not a template",
- new_scope);
+ permerror (input_location, TYPE_P (new_scope)
+ ? "%qT is not a template"
+ : "%qD is not a template",
+ new_scope);
/* If it is a class scope, try to complete it; we are about to
be looking up names inside the class. */
if (TYPE_P (new_scope)
return scope;
}
-/* Parse a class-or-namespace-name.
-
- class-or-namespace-name:
- class-name
- namespace-name
+/* Parse the qualifying entity in a nested-name-specifier. For C++98,
+ this is either a class-name or a namespace-name (which corresponds
+ to the class-or-namespace-name production in the grammar). For
+ C++0x, it can also be a type-name that refers to an enumeration
+ type.
TYPENAME_KEYWORD_P is TRUE iff the `typename' keyword is in effect.
TEMPLATE_KEYWORD_P is TRUE iff the `template' keyword is in effect.
ERROR_MARK_NODE is returned. */
static tree
-cp_parser_class_or_namespace_name (cp_parser *parser,
- bool typename_keyword_p,
- bool template_keyword_p,
- bool check_dependency_p,
- bool type_p,
- bool is_declaration)
+cp_parser_qualifying_entity (cp_parser *parser,
+ bool typename_keyword_p,
+ bool template_keyword_p,
+ bool check_dependency_p,
+ bool type_p,
+ bool is_declaration)
{
tree saved_scope;
tree saved_qualifying_scope;
tree saved_object_scope;
tree scope;
bool only_class_p;
+ bool successful_parse_p;
/* Before we try to parse the class-name, we must save away the
current PARSER->SCOPE since cp_parser_class_name will destroy
saved_object_scope = parser->object_scope;
/* Try for a class-name first. If the SAVED_SCOPE is a type, then
there is no need to look for a namespace-name. */
- only_class_p = template_keyword_p || (saved_scope && TYPE_P (saved_scope));
+ only_class_p = template_keyword_p
+ || (saved_scope && TYPE_P (saved_scope) && cxx_dialect == cxx98);
if (!only_class_p)
cp_parser_parse_tentatively (parser);
scope = cp_parser_class_name (parser,
check_dependency_p,
/*class_head_p=*/false,
is_declaration);
+ successful_parse_p = only_class_p || cp_parser_parse_definitely (parser);
+ /* If that didn't work and we're in C++0x mode, try for a type-name. */
+ if (!only_class_p
+ && cxx_dialect != cxx98
+ && !successful_parse_p)
+ {
+ /* Restore the saved scope. */
+ parser->scope = saved_scope;
+ parser->qualifying_scope = saved_qualifying_scope;
+ parser->object_scope = saved_object_scope;
+
+ /* Parse tentatively. */
+ cp_parser_parse_tentatively (parser);
+
+ /* Parse a typedef-name or enum-name. */
+ scope = cp_parser_nonclass_name (parser);
+ successful_parse_p = cp_parser_parse_definitely (parser);
+ }
/* If that didn't work, try for a namespace-name. */
- if (!only_class_p && !cp_parser_parse_definitely (parser))
+ if (!only_class_p && !successful_parse_p)
{
/* Restore the saved scope. */
parser->scope = saved_scope;
= "types may not be defined in casts";
/* Look for the opening `<'. */
- cp_parser_require (parser, CPP_LESS, "`<'");
+ cp_parser_require (parser, CPP_LESS, "%<<%>");
/* Parse the type to which we are casting. */
type = cp_parser_type_id (parser);
/* Look for the closing `>'. */
- cp_parser_require (parser, CPP_GREATER, "`>'");
+ cp_parser_require (parser, CPP_GREATER, "%<>%>");
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
/* And the expression which is being cast. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
expression = cp_parser_expression (parser, /*cast_p=*/true);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Only type conversions to integral or enumeration types
can be used in constant-expressions. */
/* Consume the `typeid' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `(' token. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Types cannot be defined in a `typeid' expression. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in a `typeid\' expression";
+ = "types may not be defined in a %<typeid%> expression";
/* We can't be sure yet whether we're looking at a type-id or an
expression. */
cp_parser_parse_tentatively (parser);
/* Look for the `)' token. Otherwise, we can't be sure that
we're not looking at an expression: consider `typeid (int
(3))', for example. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* If all went well, simply lookup the type-id. */
if (cp_parser_parse_definitely (parser))
postfix_expression = get_typeid (type);
/* Compute its typeid. */
postfix_expression = build_typeid (expression);
/* Look for the `)' token. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
}
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
/* `typeid' may not appear in an integral constant expression. */
if (cp_parser_non_integral_constant_expression(parser,
- "`typeid' operator"))
+ "%<typeid%> operator"))
return error_mark_node;
}
break;
type = cp_parser_type_id (parser);
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Look for the `{'. */
- cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
/* If things aren't going well, there's no need to
keep going. */
if (!cp_parser_error_occurred (parser))
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
/* Look for the final `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
/* If that worked, we're definitely looking at a
compound-literal expression. */
{
/* Warn the user that a compound literal is not
allowed in standard C++. */
- if (pedantic)
- pedwarn ("ISO C++ forbids compound-literals");
+ pedwarn (input_location, OPT_pedantic, "ISO C++ forbids compound-literals");
/* For simplicity, we disallow compound literals in
constant-expressions. We could
allow compound literals of integer type, whose
}
/* Form the representation of the compound-literal. */
postfix_expression
- = finish_compound_literal (type, initializer_list);
+ = (finish_compound_literal
+ (type, build_constructor (init_list_type_node,
+ initializer_list)));
break;
}
}
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;
}
postfix_expression
= cp_parser_postfix_dot_deref_expression (parser, token->type,
postfix_expression,
- false, &idk);
+ false, &idk,
+ token->location);
is_member_access = true;
break;
index = cp_parser_expression (parser, /*cast_p=*/false);
/* Look for the closing `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
/* Build the ARRAY_REF. */
postfix_expression = grok_array_decl (postfix_expression, index);
cp_parser_postfix_dot_deref_expression (cp_parser *parser,
enum cpp_ttype token_type,
tree postfix_expression,
- bool for_offsetof, cp_id_kind *idk)
+ bool for_offsetof, cp_id_kind *idk,
+ location_t location)
{
tree name;
bool dependent_p;
/* The type of the POSTFIX_EXPRESSION must be complete. */
if (scope == unknown_type_node)
{
- error ("%qE does not have class type", postfix_expression);
+ error ("%H%qE does not have class type", &location, postfix_expression);
scope = NULL_TREE;
}
else
ordinary class member access expression, rather than a
pseudo-destructor-name. */
bool template_p;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* Parse the id-expression. */
name = (cp_parser_id_expression
(parser,
TYPE_DECL here. That is invalid code. */
if (TREE_CODE (name) == TYPE_DECL)
{
- error ("invalid use of %qD", name);
+ error ("%Hinvalid use of %qD", &token->location, name);
postfix_expression = error_mark_node;
}
else
constant-expressions. */
if (!for_offsetof
&& (cp_parser_non_integral_constant_expression
- (parser, token_type == CPP_DEREF ? "'->'" : "`.'")))
+ (parser, token_type == CPP_DEREF ? "%<->%>" : "%<.%>")))
postfix_expression = error_mark_node;
return postfix_expression;
if (non_constant_p)
*non_constant_p = false;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return error_mark_node;
/* Within a parenthesized expression, a `>' token is always
}
else
{
+ bool expr_non_constant_p;
+
/* Parse the next assignment-expression. */
- if (non_constant_p)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ /* A braced-init-list. */
+ maybe_warn_cpp0x ("extended initializer lists");
+ expr = cp_parser_braced_list (parser, &expr_non_constant_p);
+ if (non_constant_p && expr_non_constant_p)
+ *non_constant_p = true;
+ }
+ else if (non_constant_p)
{
- bool expr_non_constant_p;
expr = (cp_parser_constant_expression
(parser, /*allow_non_constant_p=*/true,
&expr_non_constant_p));
cp_lexer_consume_token (parser->lexer);
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
{
int ending;
/*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. */
/*check_dependency_p=*/false,
/*is_declaration=*/true);
/* Look for the `::' token. */
- cp_parser_require (parser, CPP_SCOPE, "`::'");
+ cp_parser_require (parser, CPP_SCOPE, "%<::%>");
}
/* If the next token is not a `~', then there might be some
additional qualification. */
return;
/* Look for the `::' token. */
- cp_parser_require (parser, CPP_SCOPE, "`::'");
+ cp_parser_require (parser, CPP_SCOPE, "%<::%>");
}
else
*scope = NULL_TREE;
/* Look for the `~'. */
- cp_parser_require (parser, CPP_COMPL, "`~'");
+ cp_parser_require (parser, CPP_COMPL, "%<~%>");
/* Look for the type-name again. We are not responsible for
checking that it matches the first type-name. */
*type = cp_parser_nonclass_name (parser);
{
tree identifier;
tree expression;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
/* Consume the '&&' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the identifier. */
identifier = cp_parser_identifier (parser);
/* Create an expression representing the address. */
- expression = finish_label_address_expr (identifier);
+ expression = finish_label_address_expr (identifier, loc);
if (cp_parser_non_integral_constant_expression (parser,
"the address of a label"))
expression = error_mark_node;
switch (unary_operator)
{
case INDIRECT_REF:
- non_constant_p = "`*'";
+ non_constant_p = "%<*%>";
expression = build_x_indirect_ref (cast_expression, "unary *",
tf_warning_or_error);
break;
case ADDR_EXPR:
- non_constant_p = "`&'";
+ non_constant_p = "%<&%>";
/* Fall through. */
case BIT_NOT_EXPR:
expression = build_x_unary_op (unary_operator, cast_expression,
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
non_constant_p = (unary_operator == PREINCREMENT_EXPR
- ? "`++'" : "`--'");
+ ? "%<++%>" : "%<--%>");
/* Fall through. */
case UNARY_PLUS_EXPR:
case NEGATE_EXPR:
/*current_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the `new' operator. */
- cp_parser_require_keyword (parser, RID_NEW, "`new'");
+ cp_parser_require_keyword (parser, RID_NEW, "%<new%>");
/* There's no easy way to tell a new-placement from the
`( type-id )' construct. */
cp_parser_parse_tentatively (parser);
type-id. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
+ cp_token *token;
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
/* Parse the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+ token = cp_lexer_peek_token (parser->lexer);
/* There should not be a direct-new-declarator in this production,
but GCC used to allowed this, so we check and emit a sensible error
message for this case. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
- error ("array bound forbidden after parenthesized type-id");
- inform ("try removing the parentheses around the type-id");
+ error ("%Harray bound forbidden after parenthesized type-id",
+ &token->location);
+ inform (token->location,
+ "try removing the parentheses around the type-id");
cp_parser_direct_new_declarator (parser);
}
nelts = NULL_TREE;
else
type = cp_parser_new_type_id (parser, &nelts);
- /* If the next token is a `(', then we have a new-initializer. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ /* If the next token is a `(' or '{', then we have a new-initializer. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
+ || cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
initializer = cp_parser_new_initializer (parser);
else
initializer = NULL_TREE;
/* A new-expression may not appear in an integral constant
expression. */
- if (cp_parser_non_integral_constant_expression (parser, "`new'"))
+ if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
return error_mark_node;
/* Create a representation of the new-expression. */
tree expression;
/* Look for the opening `['. */
- cp_parser_require (parser, CPP_OPEN_SQUARE, "`['");
+ cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
/* The first expression is not required to be constant. */
if (!declarator)
{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
expression = cp_parser_expression (parser, /*cast_p=*/false);
/* The standard requires that the expression have integral
type. DR 74 adds enumeration types. We believe that the
/*complain=*/true);
if (!expression)
{
- error ("expression in new-declarator must have integral "
- "or enumeration type");
+ error ("%Hexpression in new-declarator must have integral "
+ "or enumeration type", &token->location);
expression = error_mark_node;
}
}
/*allow_non_constant=*/false,
NULL);
/* Look for the closing `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
/* Add this bound to the declarator. */
declarator = make_array_declarator (declarator, expression);
new-initializer:
( expression-list [opt] )
+ braced-init-list
Returns a representation of the expression-list. If there is no
expression-list, VOID_ZERO_NODE is returned. */
{
tree expression_list;
- expression_list = (cp_parser_parenthesized_expression_list
- (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL));
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ 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);
+ }
+ 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;
/*current_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the `delete' keyword. */
- cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
+ cp_parser_require_keyword (parser, RID_DELETE, "%<delete%>");
/* See if the array syntax is in use. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `]' token. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
/* Remember that this is the `[]' construct. */
array_p = true;
}
/* A delete-expression may not appear in an integral constant
expression. */
- if (cp_parser_non_integral_constant_expression (parser, "`delete'"))
+ if (cp_parser_non_integral_constant_expression (parser, "%<delete%>"))
return error_mark_node;
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:
/* Look for the type-id. */
type = cp_parser_type_id (parser);
/* Look for the closing `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
}
/* 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);
+
/* Warn about old-style casts, if so requested. */
if (warn_old_style_cast
&& !in_system_header
expr = build_c_cast (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
: binops_by_token[token->type].prec)
static tree
-cp_parser_binary_expression (cp_parser* parser, bool cast_p)
+cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+ enum cp_parser_prec prec)
{
cp_parser_expression_stack stack;
cp_parser_expression_stack_entry *sp = &stack[0];
tree lhs, rhs;
cp_token *token;
enum tree_code tree_type, lhs_type, rhs_type;
- enum cp_parser_prec prec = PREC_NOT_OPERATOR, new_prec, lookahead_prec;
+ enum cp_parser_prec new_prec, lookahead_prec;
bool overloaded_p;
/* Parse the first expression. */
}
overloaded_p = false;
+ /* ??? 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.
+ */
lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
&overloaded_p, tf_warning_or_error);
lhs_type = tree_type;
expr = cp_parser_expression (parser, /*cast_p=*/false);
/* The next token should be a `:'. */
- cp_parser_require (parser, CPP_COLON, "`:'");
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
/* Parse the assignment-expression. */
assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false);
else
{
/* Parse the binary expressions (logical-or-expression). */
- expr = cp_parser_binary_expression (parser, cast_p);
+ expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR);
/* 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))
= cp_parser_assignment_operator_opt (parser);
if (assignment_operator != ERROR_MARK)
{
- tree rhs;
+ bool non_constant_p;
/* Parse the right-hand side of the assignment. */
- rhs = cp_parser_assignment_expression (parser, cast_p);
+ tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
+
+ if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
+ maybe_warn_cpp0x ("extended initializer lists");
+
/* An assignment may not appear in a
constant-expression. */
if (cp_parser_non_integral_constant_expression (parser,
enum tree_code op;
cp_token *token;
- /* Peek at the next toen. */
+ /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
int save_ice_p, save_non_ice_p;
tree type, expr;
cp_id_kind dummy;
+ cp_token *token;
/* We're about to accept non-integral-constant things, but will
definitely yield an integral constant expression. Save and
/* Consume the "__builtin_offsetof" token. */
cp_lexer_consume_token (parser->lexer);
/* Consume the opening `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the type-id. */
type = cp_parser_type_id (parser);
/* Look for the `,'. */
- cp_parser_require (parser, CPP_COMMA, "`,'");
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
+ token = cp_lexer_peek_token (parser->lexer);
/* Build the (type *)null that begins the traditional offsetof macro. */
expr = build_static_cast (build_pointer_type (type), null_pointer_node,
/* Parse the offsetof-member-designator. We begin as if we saw "expr->". */
expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DEREF, expr,
- true, &dummy);
+ true, &dummy, token->location);
while (true)
{
- cp_token *token = cp_lexer_peek_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
switch (token->type)
{
case CPP_OPEN_SQUARE:
/* offsetof-member-designator "." identifier */
cp_lexer_consume_token (parser->lexer);
expr = cp_parser_postfix_dot_deref_expression (parser, CPP_DOT, expr,
- true, &dummy);
+ true, &dummy,
+ token->location);
break;
case CPP_CLOSE_PAREN:
default:
/* Error. We know the following require will fail, but
that gives the proper error message. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
cp_parser_skip_to_closing_parenthesis (parser, true, false, true);
expr = error_mark_node;
goto failure;
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
type1 = cp_parser_type_id (parser);
if (binary)
{
- cp_parser_require (parser, CPP_COMMA, "`,'");
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
type2 = cp_parser_type_id (parser);
/*initialized=*/0, /*attrlist=*/NULL);
}
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Complete the trait expression, which may mean either processing
the trait expr now or saving it for template instantiation. */
if (parser->in_switch_statement_p)
finish_case_label (expr, expr_hi);
else
- error ("case label %qE not within a switch statement", expr);
+ error ("%Hcase label %qE not within a switch statement",
+ &token->location, expr);
}
break;
if (parser->in_switch_statement_p)
finish_case_label (NULL_TREE, NULL_TREE);
else
- error ("case label not within a switch statement");
+ error ("%Hcase label not within a switch statement", &token->location);
break;
default:
}
/* Require the `:' token. */
- cp_parser_require (parser, CPP_COLON, "`:'");
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
}
/* Parse an expression-statement.
tree compound_stmt;
/* Consume the `{'. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
return error_mark_node;
/* Begin the compound-statement. */
compound_stmt = begin_compound_stmt (in_try ? BCS_TRY_BLOCK : 0);
/* Finish the compound-statement. */
finish_compound_stmt (compound_stmt);
/* Consume the `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
return compound_stmt;
}
else
{
token = cp_lexer_consume_token (parser->lexer);
- error ("%<else%> without a previous %<if%>");
+ error ("%H%<else%> without a previous %<if%>", &token->location);
}
}
tree condition;
/* Look for the `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
/* Parse the condition. */
condition = cp_parser_condition (parser);
/* Look for the `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
/* 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 ());
+ 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))
+ {
+ warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ OPT_Wempty_body, "suggest braces around "
+ "empty body in an %<else%> statement");
+ add_stmt (build_empty_stmt ());
+ 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
condition:
expression
- type-specifier-seq declarator = assignment-expression
+ type-specifier-seq declarator = initializer-clause
+ type-specifier-seq declarator braced-init-list
GNU Extension:
attributes = cp_parser_attributes_opt (parser);
/* Parse the asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
- /* If the next token is not an `=', then we might still be
+ /* If the next token is not an `=' or '{', then we might still be
looking at an expression. For example:
if (A(a).x)
looks like a decl-specifier-seq and a declarator -- but then
there is no `=', so this is an expression. */
- cp_parser_require (parser, CPP_EQ, "`='");
- /* If we did see an `=', then we are looking at a declaration
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_EQ)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE))
+ cp_parser_simulate_error (parser);
+
+ /* If we did see an `=' or '{', then we are looking at a declaration
for sure. */
if (cp_parser_parse_definitely (parser))
{
tree pushed_scope;
bool non_constant_p;
+ bool flags = LOOKUP_ONLYCONVERTING;
/* Create the declaration. */
decl = start_decl (declarator, &type_specifiers,
/*initialized_p=*/true,
attributes, /*prefix_attributes=*/NULL_TREE,
&pushed_scope);
- /* Parse the assignment-expression. */
- initializer
- = cp_parser_constant_expression (parser,
- /*allow_non_constant_p=*/true,
- &non_constant_p);
+
+ /* Parse the initializer. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ initializer = cp_parser_braced_list (parser, &non_constant_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (initializer) = 1;
+ flags = 0;
+ }
+ else
+ {
+ /* Consume the `='. */
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
+ initializer = cp_parser_initializer_clause (parser, &non_constant_p);
+ }
+ if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
+ maybe_warn_cpp0x ("extended initializer lists");
+
if (!non_constant_p)
initializer = fold_non_dependent_expr (initializer);
cp_finish_decl (decl,
initializer, !non_constant_p,
asm_specification,
- LOOKUP_ONLYCONVERTING);
+ flags);
if (pushed_scope)
pop_scope (pushed_scope);
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);
-}
-
/* Parse an iteration-statement.
iteration-statement:
/* Begin the while-statement. */
statement = begin_while_stmt ();
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* 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, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Parse the dependent statement. */
parser->in_statement = IN_ITERATION_STMT;
cp_parser_already_scoped_statement (parser);
parser->in_statement = in_statement;
finish_do_body (statement);
/* Look for the `while' keyword. */
- cp_parser_require_keyword (parser, RID_WHILE, "`while'");
+ cp_parser_require_keyword (parser, RID_WHILE, "%<while%>");
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the expression. */
expression = cp_parser_expression (parser, /*cast_p=*/false);
/* We're done with the do-statement. */
finish_do_stmt (expression, statement);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Look for the `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
}
break;
/* Begin the for-statement. */
statement = begin_for_stmt ();
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the initialization. */
cp_parser_for_init_statement (parser);
finish_for_init_stmt (statement);
condition = cp_parser_condition (parser);
finish_for_cond (condition, statement);
/* Look for the `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
/* 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);
finish_for_expr (expression, statement);
- check_empty_body (parser, "for");
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Parse the body of the for-statement. */
parser->in_statement = IN_ITERATION_STMT;
break ;
continue ;
return expression [opt] ;
+ return braced-init-list ;
goto identifier ;
GNU extension:
switch (in_statement)
{
case 0:
- error ("break statement not within loop or switch");
+ error ("%Hbreak statement not within loop or switch", &token->location);
break;
default:
gcc_assert ((in_statement & IN_SWITCH_STMT)
statement = finish_break_stmt ();
break;
case IN_OMP_BLOCK:
- error ("invalid exit from OpenMP structured block");
+ error ("%Hinvalid exit from OpenMP structured block", &token->location);
break;
case IN_OMP_FOR:
- error ("break statement used with OpenMP for loop");
+ error ("%Hbreak statement used with OpenMP for loop", &token->location);
break;
}
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
{
case 0:
- error ("continue statement not within a loop");
+ error ("%Hcontinue statement not within a loop", &token->location);
break;
case IN_ITERATION_STMT:
case IN_OMP_FOR:
statement = finish_continue_stmt ();
break;
case IN_OMP_BLOCK:
- error ("invalid exit from OpenMP structured block");
+ error ("%Hinvalid exit from OpenMP structured block", &token->location);
break;
default:
gcc_unreachable ();
case RID_RETURN:
{
tree expr;
+ bool expr_non_constant_p;
- /* If the next token is a `;', then there is no
- expression. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ maybe_warn_cpp0x ("extended initializer lists");
+ 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);
else
+ /* If the next token is a `;', then there is no
+ expression. */
expr = NULL_TREE;
/* Build the return-statement. */
statement = finish_return_stmt (expr);
if (cp_lexer_next_token_is (parser->lexer, CPP_MULT))
{
/* Issue a warning about this use of a GNU extension. */
- if (pedantic)
- pedwarn ("ISO C++ forbids computed gotos");
+ pedwarn (token->location, OPT_pedantic, "ISO C++ forbids computed gotos");
/* Consume the '*' token. */
cp_lexer_consume_token (parser->lexer);
/* Parse the dependent expression. */
{
/* 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, "`{'");
+ cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
cp_parser_statement_seq_opt (parser, NULL_TREE);
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
}
/* A declaration consisting of a single semicolon is
invalid. Allow it unless we're being pedantic. */
cp_lexer_consume_token (parser->lexer);
- if (pedantic && !in_system_header)
- pedwarn ("extra %<;%>");
+ if (!in_system_header)
+ pedwarn (input_location, OPT_pedantic, "extra %<;%>");
continue;
}
else if (token1->keyword == RID_LABEL)
{
cp_lexer_consume_token (parser->lexer);
- error ("%<__label__%> not at the beginning of a block");
+ error ("%H%<__label__%> not at the beginning of a block", &token1->location);
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))
is not a parenthesis, then we must be looking at a declaration.
(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_PAREN)
+ && 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
which is erroneous. */
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- error ("mixing declarations and function-definitions is forbidden");
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ error ("%Hmixing declarations and function-definitions is forbidden",
+ &token->location);
+ }
/* Otherwise, we're done with the list of declarators. */
else
{
}
/* Consume the `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
done:
pop_deferring_access_checks ();
int* declares_class_or_enum)
{
bool constructor_possible_p = !parser->in_declarator_p;
+ cp_token *start_token = NULL;
/* Clear DECL_SPECS. */
clear_decl_specs (decl_specs);
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
+
+ /* Save the first token of the decl spec list for error
+ reporting. */
+ if (!start_token)
+ start_token = token;
/* Handle attributes. */
if (token->keyword == RID_ATTRIBUTE)
{
GNU Extension:
thread */
case RID_AUTO:
- /* Consume the token. */
- cp_lexer_consume_token (parser->lexer);
-
if (cxx_dialect == cxx98)
{
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+
/* Complain about `auto' as a storage specifier, if
we're complaining about C++0x compatibility. */
warning
(OPT_Wc__0x_compat,
- "%<auto%> will change meaning in C++0x; please remove it");
+ "%H%<auto%> will change meaning in C++0x; please remove it",
+ &token->location);
/* Set the storage class anyway. */
- cp_parser_set_storage_class (parser, decl_specs, RID_AUTO);
+ cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
+ token->location);
}
- else
- /* We do not yet support the use of `auto' as a
- type-specifier. */
- error ("C++0x %<auto%> specifier not supported");
+ else
+ /* C++0x auto type-specifier. */
+ found_decl_spec = false;
break;
case RID_REGISTER:
case RID_MUTABLE:
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
- cp_parser_set_storage_class (parser, decl_specs, token->keyword);
+ cp_parser_set_storage_class (parser, decl_specs, token->keyword,
+ token->location);
break;
case RID_THREAD:
/* Consume the token. */
/*is_declaration=*/true,
&decl_spec_declares_class_or_enum,
&is_cv_qualifier);
-
*declares_class_or_enum |= decl_spec_declares_class_or_enum;
/* If this type-specifier referenced a user-defined type
flags |= CP_PARSER_FLAGS_OPTIONAL;
}
- cp_parser_check_decl_spec (decl_specs);
+ cp_parser_check_decl_spec (decl_specs, start_token->location);
/* Don't allow a friend specifier with a class definition. */
if (decl_specs->specs[(int) ds_friend] != 0
&& (*declares_class_or_enum & 2))
- error ("class definition may not be declared a friend");
+ error ("%Hclass definition may not be declared a friend",
+ &start_token->location);
}
/* Parse an (optional) storage-class-specifier.
cp_parser_function_specifier_opt (cp_parser* parser,
cp_decl_specifier_seq *decl_specs)
{
- switch (cp_lexer_peek_token (parser->lexer)->keyword)
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ switch (token->keyword)
{
case RID_INLINE:
if (decl_specs)
A member function template shall not be virtual. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
- error ("templates may not be %<virtual%>");
+ error ("%Htemplates may not be %<virtual%>", &token->location);
else if (decl_specs)
++decl_specs->specs[(int) ds_virtual];
break;
tree linkage;
/* Look for the `extern' keyword. */
- cp_parser_require_keyword (parser, RID_EXTERN, "`extern'");
+ cp_parser_require_keyword (parser, RID_EXTERN, "%<extern%>");
/* Look for the string-literal. */
linkage = cp_parser_string_literal (parser, false, false);
/* Parse the declarations. */
cp_parser_declaration_seq_opt (parser);
/* Look for the closing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
/* Otherwise, there's just one declaration. */
else
/* Look for the `static_assert' keyword. */
if (!cp_parser_require_keyword (parser, RID_STATIC_ASSERT,
- "`static_assert'"))
+ "%<static_assert%>"))
return;
/* We know we are in a static assertion; commit to any tentative
cp_parser_commit_to_tentative_parse (parser);
/* Parse the `(' starting the static assertion condition. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the constant-expression. */
condition =
/*non_constant_p=*/NULL);
/* Parse the separating `,'. */
- cp_parser_require (parser, CPP_COMMA, "`,'");
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
/* Parse the string-literal message. */
message = cp_parser_string_literal (parser,
/*wide_ok=*/true);
/* A `)' completes the static assertion. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
/* A semicolon terminates the declaration. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
/* Complete the static assertion, which may mean either processing
the static assert now or saving it for template instantiation. */
const char *saved_message;
bool saved_integral_constant_expression_p;
bool saved_non_integral_constant_expression_p;
+ cp_token *id_expr_start_token;
/* Look for the `decltype' token. */
- if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "`decltype'"))
+ if (!cp_parser_require_keyword (parser, RID_DECLTYPE, "%<decltype%>"))
return error_mark_node;
/* Types cannot be defined in a `decltype' expression. Save away the
/* And create the new one. */
parser->type_definition_forbidden_message
- = "types may not be defined in `decltype' expressions";
+ = "types may not be defined in %<decltype%> expressions";
/* The restrictions on constant-expressions do not apply inside
decltype expressions. */
++skip_evaluation;
/* Parse the opening `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return error_mark_node;
/* First, try parsing an id-expression. */
+ id_expr_start_token = cp_lexer_peek_token (parser->lexer);
cp_parser_parse_tentatively (parser);
expr = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ id_expr_start_token->location);
if (expr
&& expr != error_mark_node
/*done=*/true,
/*address_p=*/false,
/*template_arg_p=*/false,
- &error_msg));
+ &error_msg,
+ id_expr_start_token->location));
if (expr == error_mark_node)
/* We found an id-expression, but it was something that we
}
/* Parse to the closing `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
{
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
tree pushed_scope = NULL_TREE;
/* Look for the `operator' token. */
- if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+ if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
return error_mark_node;
/* When we parse the conversion-type-id, the current scope will be
reset. However, we need that information in able to look up the
/*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;
}
cp_parser_mem_initializer_list (cp_parser* parser)
{
tree mem_initializer_list = NULL_TREE;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* Let the semantic analysis code know that we are starting the
mem-initializer-list. */
if (!DECL_CONSTRUCTOR_P (current_function_decl))
- error ("only constructors take base initializers");
+ error ("%Honly constructors take base initializers",
+ &token->location);
/* Loop through the list. */
while (true)
{
tree mem_initializer;
+ token = cp_lexer_peek_token (parser->lexer);
/* Parse the mem-initializer. */
mem_initializer = cp_parser_mem_initializer (parser);
/* If the next token is a `...', we're expanding member initializers. */
if (mem_initializer != error_mark_node
&& !TYPE_P (TREE_PURPOSE (mem_initializer)))
{
- error ("cannot expand initializer for member %<%D%>",
- TREE_PURPOSE (mem_initializer));
+ error ("%Hcannot expand initializer for member %<%D%>",
+ &token->location, TREE_PURPOSE (mem_initializer));
mem_initializer = error_mark_node;
}
mem-initializer:
mem-initializer-id ( expression-list [opt] )
+ mem-initializer-id braced-init-list
GNU extension:
tree mem_initializer_id;
tree expression_list;
tree member;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* Find out what is being initialized. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
- pedwarn ("anachronistic old-style base class initializer");
+ permerror (token->location,
+ "anachronistic old-style base class initializer");
mem_initializer_id = NULL_TREE;
}
else
if (member && !DECL_P (member))
in_base_initializer = 1;
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ 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);
+ }
+ else
+ expression_list
+ = cp_parser_parenthesized_expression_list (parser, false,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
if (expression_list == error_mark_node)
return error_mark_node;
if (!expression_list)
bool template_p = false;
tree id;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
/* `typename' is not allowed in this context ([temp.res]). */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
{
- error ("keyword %<typename%> not allowed in this context (a qualified "
- "member initializer is implicitly a type)");
+ error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
+ "member initializer is implicitly a type)",
+ &token->location);
cp_lexer_consume_token (parser->lexer);
}
/* Look for the optional `::' operator. */
cp_parser_operator_function_id (cp_parser* parser)
{
/* Look for the `operator' keyword. */
- if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'"))
+ if (!cp_parser_require_keyword (parser, RID_OPERATOR, "%<operator%>"))
return error_mark_node;
/* And then the name of the operator itself. */
return cp_parser_operator (parser);
/* Consume the `[' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `]' token. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
id = ansi_opname (op == NEW_EXPR
? VEC_NEW_EXPR : VEC_DELETE_EXPR);
}
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return ansi_opname (CALL_EXPR);
case CPP_OPEN_SQUARE:
/* Consume the `['. */
cp_lexer_consume_token (parser->lexer);
/* Look for the matching `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
return ansi_opname (ARRAY_REF);
default:
while (true)
{
tree parameter;
- cp_token *token;
bool is_non_type;
bool is_parameter_pack;
parameter_list = chainon (parameter_list, err_parm);
}
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- /* If it's not a `,', we're done. */
- if (token->type != CPP_COMMA)
+ /* If the next token is not a `,', we're done. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
break;
/* Otherwise, consume the `,' token. */
cp_lexer_consume_token (parser->lexer);
appropriate diagnostic here. */
/* Consume the `='. */
+ cp_token *start_token = cp_lexer_peek_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
/* Find the name of the parameter pack. */
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
- error ("template parameter pack %qD cannot have a default argument",
- id_declarator->u.id.unqualified_name);
+ error ("%Htemplate parameter pack %qD cannot have a default argument",
+ &start_token->location, id_declarator->u.id.unqualified_name);
else
- error ("template parameter pack cannot have a default argument");
+ error ("%Htemplate parameter pack cannot have a default argument",
+ &start_token->location);
/* Parse the default argument, but throw away the result. */
cp_parser_default_argument (parser, /*template_parm_p=*/true);
/* Look for a keyword to tell us what kind of parameter this is. */
token = cp_parser_require (parser, CPP_KEYWORD,
- "`class', `typename', or `template'");
+ "%<class%>, %<typename%>, or %<template%>");
if (!token)
return error_mark_node;
if (*is_parameter_pack)
{
if (identifier)
- error ("template parameter pack %qD cannot have a default argument",
- identifier);
+ error ("%Htemplate parameter pack %qD cannot have a "
+ "default argument", &token->location, identifier);
else
- error ("template parameter packs cannot have default arguments");
+ error ("%Htemplate parameter packs cannot have "
+ "default arguments", &token->location);
default_argument = NULL_TREE;
}
pop_deferring_access_checks ();
tree default_argument;
/* Look for the `<'. */
- cp_parser_require (parser, CPP_LESS, "`<'");
+ cp_parser_require (parser, CPP_LESS, "%<<%>");
/* Parse the template-parameter-list. */
parameter_list = cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
- cp_parser_require (parser, CPP_GREATER, "`>'");
+ cp_parser_require (parser, CPP_GREATER, "%<>%>");
/* Look for the `class' keyword. */
- cp_parser_require_keyword (parser, RID_CLASS, "`class'");
+ cp_parser_require_keyword (parser, RID_CLASS, "%<class%>");
/* If the next token is an ellipsis, we have a template
argument pack. */
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
cp_lexer_consume_token (parser->lexer);
/* Parse the id-expression. */
push_deferring_access_checks (dk_no_deferred);
+ /* save token before parsing the id-expression, for error
+ reporting */
+ token = cp_lexer_peek_token (parser->lexer);
default_argument
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*is_template=*/is_template,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ token->location);
/* See if the default argument is valid. */
default_argument
= check_template_template_default_arg (default_argument);
if (*is_parameter_pack)
{
if (identifier)
- error ("template parameter pack %qD cannot have a default argument",
- identifier);
+ error ("%Htemplate parameter pack %qD cannot "
+ "have a default argument",
+ &token->location, identifier);
else
- error ("template parameter packs cannot have default arguments");
+ error ("%Htemplate parameter packs cannot "
+ "have default arguments",
+ &token->location);
default_argument = NULL_TREE;
}
pop_deferring_access_checks ();
bool is_declaration)
{
int i;
- tree template;
+ tree templ;
tree arguments;
tree template_id;
cp_token_position start_of_id = 0;
deferred_access_check *chk;
VEC (deferred_access_check,gc) *access_check;
- cp_token *next_token, *next_token_2;
+ cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
bool is_identifier;
/* If the next token corresponds to a template-id, there is no need
/* Parse the template-name. */
is_identifier = false;
- template = cp_parser_template_name (parser, template_keyword_p,
- check_dependency_p,
- is_declaration,
- &is_identifier);
- if (template == error_mark_node || is_identifier)
+ token = cp_lexer_peek_token (parser->lexer);
+ templ = cp_parser_template_name (parser, template_keyword_p,
+ check_dependency_p,
+ is_declaration,
+ &is_identifier);
+ if (templ == error_mark_node || is_identifier)
{
pop_deferring_access_checks ();
- return template;
+ return templ;
}
/* If we find the sequence `[:' after a template-name, it's probably
/* Consume the first token (CPP_OPEN_SQUARE - which we pretend it is
CPP_LESS. */
cp_lexer_consume_token (parser->lexer);
+
/* Parse the arguments. */
arguments = cp_parser_enclosed_template_argument_list (parser);
if (!cp_parser_parse_definitely (parser))
}
/* Otherwise, emit an error about the invalid digraph, but continue
parsing because we got our argument list. */
- permerror ("%<<::%> cannot begin a template-argument list");
- inform ("%<<:%> is an alternate spelling for %<[%>. Insert whitespace "
- "between %<<%> and %<::%>");
- if (!flag_permissive)
+ if (permerror (next_token->location,
+ "%<<::%> cannot begin a template-argument list"))
{
- static bool hint;
- if (!hint)
+ static bool hint = false;
+ inform (next_token->location,
+ "%<<:%> is an alternate spelling for %<[%>."
+ " Insert whitespace between %<<%> and %<::%>");
+ if (!hint && !flag_permissive)
{
- inform ("(if you use -fpermissive G++ will accept your code)");
+ inform (next_token->location, "(if you use %<-fpermissive%>"
+ " G++ will accept your code)");
hint = true;
}
}
else
{
/* Look for the `<' that starts the template-argument-list. */
- if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+ if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
{
pop_deferring_access_checks ();
return error_mark_node;
}
/* Build a representation of the specialization. */
- if (TREE_CODE (template) == IDENTIFIER_NODE)
- template_id = build_min_nt (TEMPLATE_ID_EXPR, template, arguments);
- else if (DECL_CLASS_TEMPLATE_P (template)
- || DECL_TEMPLATE_TEMPLATE_PARM_P (template))
+ if (TREE_CODE (templ) == IDENTIFIER_NODE)
+ template_id = build_min_nt (TEMPLATE_ID_EXPR, templ, arguments);
+ else if (DECL_CLASS_TEMPLATE_P (templ)
+ || DECL_TEMPLATE_TEMPLATE_PARM_P (templ))
{
bool entering_scope;
/* In "template <typename T> ... A<T>::", A<T> is the abstract A
&& cp_lexer_next_token_is (parser->lexer,
CPP_SCOPE));
template_id
- = finish_template_type (template, arguments, entering_scope);
+ = finish_template_type (templ, arguments, entering_scope);
}
else
{
/* If it's not a class-template or a template-template, it should be
a function-template. */
- gcc_assert ((DECL_FUNCTION_TEMPLATE_P (template)
- || TREE_CODE (template) == OVERLOAD
- || BASELINK_P (template)));
+ gcc_assert ((DECL_FUNCTION_TEMPLATE_P (templ)
+ || TREE_CODE (templ) == OVERLOAD
+ || BASELINK_P (templ)));
- template_id = lookup_template_function (template, arguments);
+ template_id = lookup_template_function (templ, arguments);
}
/* If parsing tentatively, replace the sequence of tokens that makes
user, as opposed to simply marking the tentative parse as
failed? */
if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
- error ("parse error in template argument list");
+ error ("%Hparse error in template argument list",
+ &token->location);
}
pop_deferring_access_checks ();
tree identifier;
tree decl;
tree fns;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* If the next token is `operator', then we have either an
operator-function-id or a conversion-function-id. */
cp_token_position start = 0;
/* Explain what went wrong. */
- error ("non-template %qD used as template", identifier);
- inform ("use %<%T::template %D%> to indicate that it is a template",
+ error ("%Hnon-template %qD used as template",
+ &token->location, identifier);
+ inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
parser->scope, identifier);
/* If parsing tentatively, find the location of the "<" token. */
if (cp_parser_simulate_error (parser))
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ token->location);
decl = maybe_get_template_decl_from_type_decl (decl);
/* If DECL is a template, then the name was a template-name. */
bool template_p;
bool address_p;
bool maybe_type_id = false;
- cp_token *token;
+ cp_token *token = NULL, *argument_start_token = NULL;
cp_id_kind idk;
/* There's really no way to know what we're looking at, so we just
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
argument = cp_parser_type_id (parser);
- /* If there was no error parsing the type-id but the next token is a '>>',
- we probably found a typo for '> >'. But there are type-id which are
- also valid expressions. For instance:
+ /* 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
+ are type-id which are also valid expressions. For instance:
struct X { int operator >> (int); };
template <int V> struct Foo {};
Here 'X()' is a valid type-id of a function type, but the user just
wanted to write the expression "X() >> 5". Thus, we remember that we
found a valid type-id, but we still try to parse the argument as an
- expression to see what happens. */
+ expression to see what happens.
+
+ In C++0x, the '>>' will be considered two separate '>'
+ tokens. */
if (!cp_parser_error_occurred (parser)
+ && cxx_dialect == cxx98
&& cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
{
maybe_type_id = true;
/* We're still not sure what the argument will be. */
cp_parser_parse_tentatively (parser);
/* Try a template. */
+ argument_start_token = cp_lexer_peek_token (parser->lexer);
argument = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*is_template=*/template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ argument_start_token->location);
if (TREE_CODE (argument) != TEMPLATE_DECL
&& TREE_CODE (argument) != UNBOUND_CLASS_TEMPLATE)
cp_parser_error (parser, "expected template-name");
{
cp_parser_parse_tentatively (parser);
argument = cp_parser_primary_expression (parser,
- /*adress_p=*/false,
+ /*address_p=*/false,
/*cast_p=*/false,
/*template_arg_p=*/true,
&idk);
int declares_class_or_enum;
cp_decl_specifier_seq decl_specifiers;
tree extension_specifier = NULL_TREE;
+ cp_token *token;
/* Look for an (optional) storage-class-specifier or
function-specifier. */
}
/* Look for the `template' keyword. */
- cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
+ cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
/* Let the front end know that we are processing an explicit
instantiation. */
begin_explicit_instantiation ();
control while processing explicit instantiation directives. */
push_deferring_access_checks (dk_no_check);
/* Parse a decl-specifier-seq. */
+ token = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
&decl_specifiers,
/*member_p=*/false);
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type (declarator,
- decl_specifiers.type);
+ decl_specifiers.type,
+ decl_specifiers.type_location);
if (declarator != cp_error_declarator)
{
decl = grokdeclarator (declarator, &decl_specifiers,
cp_parser_explicit_specialization (cp_parser* parser)
{
bool need_lang_pop;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
/* Look for the `template' keyword. */
- cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'");
+ cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>");
/* Look for the `<'. */
- cp_parser_require (parser, CPP_LESS, "`<'");
+ cp_parser_require (parser, CPP_LESS, "%<<%>");
/* Look for the `>'. */
- cp_parser_require (parser, CPP_GREATER, "`>'");
+ cp_parser_require (parser, CPP_GREATER, "%<>%>");
/* We have processed another parameter list. */
++parser->num_template_parameter_lists;
/* [temp]
linkage. */
if (current_lang_name == lang_name_c)
{
- error ("template specialization with C linkage");
+ error ("%Htemplate specialization with C linkage", &token->location);
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
+ token->location,
/*user_defined_p=*/true);
return type_spec;
}
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
+ token->location,
/*user_defined_p=*/true);
return type_spec;
}
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs,
type_spec,
+ token->location,
/*user_defined_p=*/true);
return type_spec;
simple-type-specifier:
auto
decltype ( expression )
+ char16_t
+ char32_t
GNU Extension:
decl_specs->explicit_char_p = true;
type = char_type_node;
break;
+ case RID_CHAR16:
+ type = char16_type_node;
+ break;
+ case RID_CHAR32:
+ type = char32_type_node;
+ break;
case RID_WCHAR:
type = wchar_type_node;
break;
break;
case RID_AUTO:
- if (cxx_dialect != cxx98)
- {
- /* Consume the token. */
- cp_lexer_consume_token (parser->lexer);
- /* We do not yet support the use of `auto' as a
- type-specifier. */
- error ("C++0x %<auto%> specifier not supported");
- }
+ maybe_warn_cpp0x ("C++0x auto");
+ type = make_auto ();
break;
case RID_DECLTYPE:
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
+ token->location,
/*user_defined_p=*/true);
return type;
if (decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
+ token->location,
/*user_defined_p=*/true);
return type;
&& token->keyword != RID_LONG))
cp_parser_set_decl_spec_type (decl_specs,
type,
+ token->location,
/*user_defined=*/false);
if (decl_specs)
decl_specs->any_specifiers_p = true;
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought
that the type was a template. */
- cp_parser_check_for_invalid_template_id (parser, type);
+ cp_parser_check_for_invalid_template_id (parser, type, token->location);
return TYPE_NAME (type);
}
/*type_p=*/false,
/*is_declaration=*/false)
!= NULL_TREE);
+ token = cp_lexer_peek_token (parser->lexer);
/* If we have seen a nested-name-specifier, and the next token
is `template', then we are using the template-id production. */
if (parser->scope
type = NULL_TREE;
if (type && decl_specs)
cp_parser_set_decl_spec_type (decl_specs, type,
+ token->location,
/*user_defined=*/true);
}
return qual_type;
}
- cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type));
+ cp_parser_check_for_invalid_template_id (parser, TREE_TYPE (type),
+ token->location);
}
return type;
tree type_decl;
tree identifier;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
return error_mark_node;
/* Look up the type-name. */
- type_decl = cp_parser_lookup_name_simple (parser, identifier);
+ type_decl = cp_parser_lookup_name_simple (parser, identifier, token->location);
if (TREE_CODE (type_decl) != TYPE_DECL
&& (objc_is_id (identifier) || objc_is_class_name (identifier)))
{
if (!cp_parser_simulate_error (parser))
cp_parser_name_lookup_error (parser, identifier, type_decl,
- "is not a type");
+ "is not a type", token->location);
return error_mark_node;
}
/* Remember that the name was used in the definition of the
elaborated-type-specifier:
class-key :: [opt] nested-name-specifier [opt] identifier
class-key :: [opt] nested-name-specifier [opt] template [opt] template-id
- enum :: [opt] nested-name-specifier [opt] identifier
+ enum-key :: [opt] nested-name-specifier [opt] identifier
typename :: [opt] nested-name-specifier identifier
typename :: [opt] nested-name-specifier template [opt]
template-id
tree identifier;
tree type = NULL_TREE;
tree attributes = NULL_TREE;
+ cp_token *token = NULL;
/* See if we're looking at the `enum' keyword. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ENUM))
cp_lexer_consume_token (parser->lexer);
/* Remember that it's an enumeration type. */
tag_type = enum_type;
+ /* Parse the optional `struct' or `class' key (for C++0x scoped
+ enums). */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
+ {
+ if (cxx_dialect == cxx98)
+ maybe_warn_cpp0x ("scoped enums");
+
+ /* Consume the `struct' or `class'. */
+ cp_lexer_consume_token (parser->lexer);
+ }
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
}
tag_type = typename_type;
/* The `typename' keyword is only allowed in templates. */
if (!processing_template_decl)
- pedwarn ("using %<typename%> outside of template");
+ permerror (input_location, "using %<typename%> outside of template");
}
/* Otherwise it must be a class-key. */
else
if (!template_p)
cp_parser_parse_tentatively (parser);
/* Parse the template-id. */
+ token = cp_lexer_peek_token (parser->lexer);
decl = cp_parser_template_id (parser, template_p,
/*check_dependency_p=*/true,
is_declaration);
if (!type)
{
+ token = cp_lexer_peek_token (parser->lexer);
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
if (tag_type == typename_type
&& TREE_CODE (parser->scope) != NAMESPACE_DECL)
return cp_parser_make_typename_type (parser, parser->scope,
- identifier);
+ identifier,
+ token->location);
/* Look up a qualified name in the usual way. */
if (parser->scope)
{
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- &ambiguous_decls);
+ &ambiguous_decls,
+ token->location);
/* If the lookup was ambiguous, an error will already have been
issued. */
{
cp_parser_diagnose_invalid_type_name (parser,
parser->scope,
- identifier);
+ identifier,
+ token->location);
return error_mark_node;
}
caught elsewhere in parsing. Those that are pointless arrive
here. */
- if (cp_parser_declares_only_class_p (parser)
+ if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)
&& !is_friend && !processing_explicit_instantiation)
warning (0, "declaration %qD does not declare anything", decl);
/* An unqualified name was used to reference this type, so
there were no qualifying templates. */
if (!cp_parser_check_template_parameters (parser,
- /*num_templates=*/0))
+ /*num_templates=*/0,
+ token->location))
return error_mark_node;
type = xref_tag (tag_type, identifier, ts, template_p);
}
/* A "<" cannot follow an elaborated type specifier. If that
happens, the user was probably trying to form a template-id. */
- cp_parser_check_for_invalid_template_id (parser, type);
+ cp_parser_check_for_invalid_template_id (parser, type, token->location);
return type;
}
/* Parse an enum-specifier.
enum-specifier:
- enum identifier [opt] { enumerator-list [opt] }
+ enum-key identifier [opt] enum-base [opt] { enumerator-list [opt] }
+
+ enum-key:
+ enum
+ enum class [C++0x]
+ enum struct [C++0x]
+
+ enum-base: [C++0x]
+ : type-specifier-seq
GNU Extensions:
- enum attributes[opt] identifier [opt] { enumerator-list [opt] }
- attributes[opt]
+ enum-key attributes[opt] identifier [opt] enum-base [opt]
+ { enumerator-list [opt] }attributes[opt]
Returns an ENUM_TYPE representing the enumeration, or NULL_TREE
if the token stream isn't an enum-specifier after all. */
tree identifier;
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
enum-specifier. */
the enumeration being defined. */
cp_lexer_consume_token (parser->lexer);
+ /* Parse the "class" or "struct", which indicates a scoped
+ enumeration type in C++0x. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_CLASS)
+ || cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
+ {
+ if (cxx_dialect == cxx98)
+ maybe_warn_cpp0x ("scoped enums");
+
+ /* Consume the `struct' or `class' token. */
+ cp_lexer_consume_token (parser->lexer);
+
+ scoped_enum_p = true;
+ }
+
attributes = cp_parser_attributes_opt (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
else
identifier = make_anon_name ();
- /* 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);
+ /* Check for the `:' that denotes a specified underlying type in C++0x. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_decl_specifier_seq type_specifiers;
- if (!cp_parser_parse_definitely (parser))
- return NULL_TREE;
+ /* At this point this is surely not elaborated type specifier. */
+ if (!cp_parser_parse_definitely (parser))
+ return NULL_TREE;
- /* Issue an error message if type-definitions are forbidden here. */
- if (!cp_parser_check_type_definition (parser))
- type = error_mark_node;
- else
- /* Create the new type. We do this before consuming the opening
- brace so the enum will be recorded as being on the line of its
- tag (or the 'enum' keyword, if there is no tag). */
- type = start_enum (identifier);
-
+ 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 that didn't work, stop. */
+ if (type_specifiers.type != error_mark_node)
+ {
+ underlying_type = grokdeclarator (NULL, &type_specifiers, TYPENAME,
+ /*initialized=*/0, NULL);
+ if (underlying_type == error_mark_node)
+ underlying_type = NULL_TREE;
+ }
+ }
+
+ /* Look for the `{' but don't consume it yet. */
+ if (!cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ cp_parser_error (parser, "expected %<{%>");
+ if (has_underlying_type)
+ return NULL_TREE;
+ }
+
+ 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_check_type_definition (parser))
+ type = error_mark_node;
+ else
+ /* Create the new type. We do this before consuming the opening
+ brace so the enum will be recorded as being on the line of its
+ tag (or the 'enum' keyword, if there is no tag). */
+ type = start_enum (identifier, underlying_type, scoped_enum_p);
+
/* Consume the opening brace. */
cp_lexer_consume_token (parser->lexer);
cp_parser_enumerator_list (parser, type);
/* Consume the final '}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
/* Look for trailing attributes to apply to this enumeration, and
apply them if appropriate. */
/* If the next token is a `}', there is a trailing comma. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
{
- if (pedantic && !in_system_header)
- pedwarn ("comma at end of enumerator list");
+ if (!in_system_header)
+ pedwarn (input_location, OPT_pedantic, "comma at end of enumerator list");
break;
}
}
tree identifier;
tree namespace_decl;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
/* Get the name of the namespace. */
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
During the lookup of a name preceding the :: scope resolution
operator, object, function, and enumerator names are ignored.
- (Note that cp_parser_class_or_namespace_name only calls this
+ (Note that cp_parser_qualifying_entity only calls this
function if the token after the name is the scope resolution
operator.) */
namespace_decl = cp_parser_lookup_name (parser, identifier,
/*is_template=*/false,
/*is_namespace=*/true,
/*check_dependency=*/true,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ token->location);
/* If it's not a namespace, issue an error. */
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("%qD is not a namespace-name", identifier);
+ error ("%H%qD is not a namespace-name", &token->location, identifier);
cp_parser_error (parser, "expected namespace-name");
namespace_decl = error_mark_node;
}
is_inline = false;
/* Look for the `namespace' keyword. */
- cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+ cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
/* Get the name of the namespace. We do not attempt to distinguish
between an original-namespace-definition and an
attribs = cp_parser_attributes_opt (parser);
/* Look for the `{' to start the namespace. */
- cp_parser_require (parser, CPP_OPEN_BRACE, "`{'");
+ cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
/* Start the namespace. */
push_namespace (identifier);
followed by a strong using directive. */
if (is_inline)
{
- tree namespace = current_namespace;
+ tree name_space = current_namespace;
/* Set up namespace association. */
- DECL_NAMESPACE_ASSOCIATIONS (namespace)
- = tree_cons (CP_DECL_CONTEXT (namespace), NULL_TREE,
- DECL_NAMESPACE_ASSOCIATIONS (namespace));
+ DECL_NAMESPACE_ASSOCIATIONS (name_space)
+ = tree_cons (CP_DECL_CONTEXT (name_space), NULL_TREE,
+ DECL_NAMESPACE_ASSOCIATIONS (name_space));
/* Import the contents of the inline namespace. */
pop_namespace ();
- do_using_directive (namespace);
+ do_using_directive (name_space);
push_namespace (identifier);
}
/* Finish the namespace. */
pop_namespace ();
/* Look for the final `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
/* Parse a namespace-body.
tree identifier;
tree namespace_specifier;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+
/* Look for the `namespace' keyword. */
- cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+ cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
/* Look for the identifier. */
identifier = cp_parser_identifier (parser);
if (identifier == error_mark_node)
if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- error ("%<namespace%> definition is not allowed here");
+ error ("%H%<namespace%> definition is not allowed here", &token->location);
/* Skip the definition. */
cp_lexer_consume_token (parser->lexer);
if (cp_parser_skip_to_closing_brace (parser))
cp_lexer_consume_token (parser->lexer);
return;
}
- cp_parser_require (parser, CPP_EQ, "`='");
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
/* Look for the qualified-namespace-specifier. */
namespace_specifier
= cp_parser_qualified_namespace_specifier (parser);
/* Look for the `;' token. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
/* Register the alias in the symbol table. */
do_namespace_alias (identifier, namespace_specifier);
else
{
/* Look for the `using' keyword. */
- cp_parser_require_keyword (parser, RID_USING, "`using'");
+ cp_parser_require_keyword (parser, RID_USING, "%<using%>");
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
cp_parser_parse_definitely will be false, as required. */
return cp_parser_parse_definitely (parser);
+ token = cp_lexer_peek_token (parser->lexer);
/* Parse the unqualified-id. */
identifier = cp_parser_unqualified_id (parser,
/*template_keyword_p=*/false,
/* [namespace.udecl]
A using declaration shall not name a template-id. */
- error ("a template-id may not appear in a using-declaration");
+ error ("%Ha template-id may not appear in a using-declaration",
+ &token->location);
else
{
if (at_class_scope_p ())
}
else
{
- decl = cp_parser_lookup_name_simple (parser, identifier);
+ decl = cp_parser_lookup_name_simple (parser,
+ identifier,
+ token->location);
if (decl == error_mark_node)
- cp_parser_name_lookup_error (parser, identifier, decl, NULL);
+ cp_parser_name_lookup_error (parser, identifier,
+ decl, NULL,
+ token->location);
else if (check_for_bare_parameter_packs (decl))
return false;
else if (!at_namespace_scope_p ())
}
/* Look for the final `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
return true;
}
tree attribs;
/* Look for the `using' keyword. */
- cp_parser_require_keyword (parser, RID_USING, "`using'");
+ cp_parser_require_keyword (parser, RID_USING, "%<using%>");
/* And the `namespace' keyword. */
- cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
+ cp_parser_require_keyword (parser, RID_NAMESPACE, "%<namespace%>");
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
/* And the optional nested-name-specifier. */
/* Update the symbol table. */
parse_using_directive (namespace_decl, attribs);
/* Look for the final `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
}
/* Parse an asm-definition.
bool invalid_outputs_p = false;
/* Look for the `asm' keyword. */
- cp_parser_require_keyword (parser, RID_ASM, "`asm'");
+ cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
/* See if the next token is `volatile'. */
if (cp_parser_allow_gnu_extensions_p (parser)
&& cp_lexer_next_token_is_keyword (parser->lexer, RID_VOLATILE))
cp_lexer_consume_token (parser->lexer);
}
/* Look for the opening `('. */
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return;
/* Look for the string. */
string = cp_parser_string_literal (parser, false, false);
}
}
/* Look for the closing `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
if (!invalid_inputs_p && !invalid_outputs_p)
{
int declares_class_or_enum,
bool* function_definition_p)
{
- cp_token *token;
+ cp_token *token = NULL, *asm_spec_start_token = NULL,
+ *attributes_start_token = NULL;
cp_declarator *declarator;
tree prefix_attributes;
tree attributes;
tree initializer;
tree decl = NULL_TREE;
tree scope;
- bool is_initialized;
+ int is_initialized;
/* Only valid if IS_INITIALIZED is true. In that case, CPP_EQ if
initialized with "= ..", CPP_OPEN_PAREN if initialized with
"(...)". */
enum cpp_ttype initialization_kind;
- bool is_parenthesized_init = false;
+ bool is_direct_init = false;
bool is_non_constant_init;
int ctor_dtor_or_conv_p;
bool friend_p;
resume_deferring_access_checks ();
/* Parse the declarator. */
+ token = cp_lexer_peek_token (parser->lexer);
declarator
= cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p,
return error_mark_node;
/* Check that the number of template-parameter-lists is OK. */
- if (!cp_parser_check_declarator_template_parameters (parser, declarator))
+ if (!cp_parser_check_declarator_template_parameters (parser, declarator,
+ token->location))
return error_mark_node;
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type (declarator,
- decl_specifiers->type);
+ decl_specifiers->type,
+ decl_specifiers->type_location);
/* Figure out what scope the entity declared by the DECLARATOR is
located in. `grokdeclarator' sometimes changes the scope, so
if (cp_parser_allow_gnu_extensions_p (parser))
{
/* Look for an asm-specification. */
+ asm_spec_start_token = cp_lexer_peek_token (parser->lexer);
asm_specification = cp_parser_asm_specification_opt (parser);
/* And attributes. */
+ attributes_start_token = cp_lexer_peek_token (parser->lexer);
attributes = cp_parser_attributes_opt (parser);
}
else
token = cp_lexer_peek_token (parser->lexer);
/* Check to see if the token indicates the start of a
function-definition. */
- if (cp_parser_token_starts_function_definition_p (token))
+ if (function_declarator_p (declarator)
+ && cp_parser_token_starts_function_definition_p (token))
{
if (!function_definition_allowed_p)
{
}
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)
- error ("an asm-specification is not allowed on a function-definition");
+ error ("%Han asm-specification is not allowed "
+ "on a function-definition",
+ &asm_spec_start_token->location);
if (attributes)
- error ("attributes are not allowed on a function-definition");
+ error ("%Hattributes are not allowed on a function-definition",
+ &attributes_start_token->location);
/* This is a function-definition. */
*function_definition_p = true;
= (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;
}
}
return error_mark_node;
}
- /* An `=' or an `(' indicates an initializer. */
+ /* An `=' or an `(', or an '{' in C++0x, indicates an initializer. */
if (token->type == CPP_EQ
- || token->type == CPP_OPEN_PAREN)
+ || token->type == CPP_OPEN_PAREN
+ || token->type == CPP_OPEN_BRACE)
{
- is_initialized = true;
+ is_initialized = SD_INITIALIZED;
initialization_kind = token->type;
+
+ if (token->type == CPP_EQ
+ && function_declarator_p (declarator))
+ {
+ cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (t2->keyword == RID_DEFAULT)
+ is_initialized = SD_DEFAULTED;
+ else if (t2->keyword == RID_DELETE)
+ is_initialized = SD_DELETED;
+ }
}
else
{
cp_parser_error (parser, "expected initializer");
return error_mark_node;
}
- is_initialized = false;
+ is_initialized = SD_UNINITIALIZED;
initialization_kind = CPP_EOF;
}
cp_parser_perform_template_parameter_access_checks (checks);
/* Perform the access control checks for the declarator and the
- the decl-specifiers. */
+ decl-specifiers. */
perform_deferred_access_checks ();
/* Restore the saved value. */
/* Parse the initializer. */
initializer = NULL_TREE;
- is_parenthesized_init = false;
+ is_direct_init = false;
is_non_constant_init = true;
if (is_initialized)
{
if (function_declarator_p (declarator))
{
+ cp_token *initializer_start_token = cp_lexer_peek_token (parser->lexer);
if (initialization_kind == CPP_EQ)
initializer = cp_parser_pure_specifier (parser);
else
know what the user intended, so just silently
consume the initializer. */
if (decl != error_mark_node)
- error ("initializer provided for function");
+ error ("%Hinitializer provided for function",
+ &initializer_start_token->location);
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
}
else
initializer = cp_parser_initializer (parser,
- &is_parenthesized_init,
+ &is_direct_init,
&is_non_constant_init);
}
initializer. Mark Mitchell proposed removing this functionality
on the GCC mailing lists on 2002-08-13. This parser accepts the
attributes -- but ignores them. */
- if (cp_parser_allow_gnu_extensions_p (parser) && is_parenthesized_init)
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && initialization_kind == CPP_OPEN_PAREN)
if (cp_parser_attributes_opt (parser))
warning (OPT_Wattributes,
"attributes after parenthesized initializer ignored");
a direct-initialization, which means that an
`explicit' constructor is OK. Otherwise, an
`explicit' constructor cannot be used. */
- ((is_parenthesized_init || !is_initialized)
- ? 0 : LOOKUP_ONLYCONVERTING));
+ ((is_direct_init || !is_initialized)
+ ? 0 : LOOKUP_ONLYCONVERTING));
}
else if ((cxx_dialect != cxx98) && friend_p
&& decl && TREE_CODE (decl) == FUNCTION_DECL)
int i (3);
The first is the declaration of a function while the
- second is a the definition of a variable, including its
+ second is the definition of a variable, including its
initializer.
Having seen only the parenthesis, we cannot know which of
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);
{
cp_cv_quals cv_quals;
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;
/* Consume the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Parse the cv-qualifier-seq. */
cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
exception_specification
= cp_parser_exception_specification_opt (parser);
+ late_return
+ = cp_parser_late_return_type_opt (parser);
+
/* Create the function-declarator. */
declarator = make_call_declarator (declarator,
params,
cv_quals,
- exception_specification);
+ exception_specification,
+ late_return);
/* Any subsequent parameter lists are to do with
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
parser->in_type_id_in_expr_p = saved_in_type_id_in_expr_p;
first = false;
/* Expect a `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
declarator = cp_error_declarator;
if (declarator == cp_error_declarator)
break;
in function scopes. */
else if (!parser->in_function_body)
{
- error ("array bound is not an integer constant");
+ error ("%Harray bound is not an integer constant",
+ &token->location);
bounds = error_mark_node;
}
}
else
bounds = NULL_TREE;
/* Look for the closing `]'. */
- if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>"))
{
declarator = cp_error_declarator;
break;
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);
}
}
+ 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;
/*only_current_p=*/false);
/* If that failed, the declarator is invalid. */
if (TREE_CODE (type) == TYPENAME_TYPE)
- error ("%<%T::%E%> is not a 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 (qualifying_scope
&& CLASSTYPE_USE_TEMPLATE (name_type))
{
- error ("invalid use of constructor as a template");
- inform ("use %<%T::%D%> instead of %<%T::%D%> to "
+ 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)),
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
/* Look for the nested-name specifier. */
+ token = cp_lexer_peek_token (parser->lexer);
cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/false,
/*check_dependency_p=*/true,
/* If we found it, and the next token is a `*', then we are
indeed looking at a pointer-to-member operator. */
if (!cp_parser_error_occurred (parser)
- && cp_parser_require (parser, CPP_MULT, "`*'"))
+ && cp_parser_require (parser, CPP_MULT, "%<*%>"))
{
/* Indicate that the `*' operator was used. */
code = INDIRECT_REF;
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
- error ("%qD is a namespace", parser->scope);
+ error ("%H%qD is a namespace", &token->location, parser->scope);
else
{
/* The type of which the member is a member is given by the
if (cv_quals & cv_qualifier)
{
- error ("duplicate cv-qualifier");
+ error ("%Hduplicate cv-qualifier", &token->location);
cp_lexer_purge_token (parser->lexer);
}
else
return cv_quals;
}
+/* Parse a late-specified return type, if any. This is not a separate
+ non-terminal, but part of a function declarator, which looks like
+
+ -> type-id
+
+ Returns the type indicated by the type-id. */
+
+static tree
+cp_parser_late_return_type_opt (cp_parser* parser)
+{
+ cp_token *token;
+
+ /* Peek at the next token. */
+ token = cp_lexer_peek_token (parser->lexer);
+ /* A late-specified return type is indicated by an initial '->'. */
+ if (token->type != CPP_DEREF)
+ return NULL_TREE;
+
+ /* Consume the ->. */
+ cp_lexer_consume_token (parser->lexer);
+
+ return cp_parser_type_id (parser);
+}
+
/* Parse a declarator-id.
declarator-id:
if (!cp_parser_parse_definitely (parser))
abstract_declarator = NULL;
+ if (type_specifier_seq.type
+ && type_uses_auto (type_specifier_seq.type))
+ {
+ error ("invalid use of %<auto%>");
+ return error_mark_node;
+ }
+
return groktypename (&type_specifier_seq, abstract_declarator);
}
{
bool seen_type_specifier = false;
cp_parser_flags flags = CP_PARSER_FLAGS_OPTIONAL;
+ cp_token *start_token = NULL;
/* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq);
continue;
}
+ /* record the token of the beginning of the type specifier seq,
+ for error reporting purposes*/
+ if (!start_token)
+ start_token = cp_lexer_peek_token (parser->lexer);
+
/* Look for the type-specifier. */
type_specifier = cp_parser_type_specifier (parser,
flags,
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
- cp_parser_check_decl_spec (type_specifier_seq);
+ cp_parser_check_decl_spec (type_specifier_seq, start_token->location);
}
/* Parse a parameter-declaration-clause.
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. */
cp_lexer_consume_token (parser->lexer);
/* Expect an ellipsis. */
ellipsis_p
- = (cp_parser_require (parser, CPP_ELLIPSIS, "`...'") != NULL);
+ = (cp_parser_require (parser, CPP_ELLIPSIS, "%<...%>") != NULL);
}
/* It might also be `...' if the optional trailing `,' was
omitted. */
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)
cp_decl_specifier_seq decl_specifiers;
cp_declarator *declarator;
tree default_argument;
- cp_token *token;
+ cp_token *token = NULL, *declarator_token_start = NULL;
const char *saved_message;
/* In a template parameter, `>' is not an operator.
&& cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_PAREN))
cp_parser_commit_to_tentative_parse (parser);
/* Parse the declarator. */
+ declarator_token_start = token;
declarator = cp_parser_declarator (parser,
CP_PARSER_DECLARATOR_EITHER,
/*ctor_dtor_or_conv_p=*/NULL,
&& TYPE_BEING_DEFINED (current_class_type))
{
unsigned depth = 0;
+ int maybe_template_id = 0;
cp_token *first_token;
cp_token *token;
/* In valid code, a default argument must be
immediately followed by a `,' `)', or `...'. */
case CPP_COMMA:
+ if (depth == 0 && maybe_template_id)
+ {
+ /* If we've seen a '<', we might be in a
+ template-argument-list. Until Core issue 325 is
+ resolved, we don't know how this situation ought
+ to be handled, so try to DTRT. We check whether
+ what comes after the comma is a valid parameter
+ declaration list. If it is, then the comma ends
+ the default argument; otherwise the default
+ argument continues. */
+ bool error = false;
+
+ /* Set ITALP so cp_parser_parameter_declaration_list
+ doesn't decide to commit to this parse. */
+ bool saved_italp = parser->in_template_argument_list_p;
+ parser->in_template_argument_list_p = true;
+
+ cp_parser_parse_tentatively (parser);
+ cp_lexer_consume_token (parser->lexer);
+ cp_parser_parameter_declaration_list (parser, &error);
+ if (!cp_parser_error_occurred (parser) && !error)
+ done = true;
+ cp_parser_abort_tentative_parse (parser);
+
+ parser->in_template_argument_list_p = saved_italp;
+ break;
+ }
case CPP_CLOSE_PAREN:
case CPP_ELLIPSIS:
/* If we run into a non-nested `;', `}', or `]',
++depth;
break;
+ case CPP_LESS:
+ if (depth == 0)
+ /* This might be the comparison operator, or it might
+ start a template argument list. */
+ ++maybe_template_id;
+ break;
+
case CPP_RSHIFT:
if (cxx_dialect == cxx98)
break;
cases. */
case CPP_GREATER:
- /* If we see a non-nested `>', and `>' is not an
- operator, then it marks the end of the default
- argument. */
- if (!depth && !greater_than_is_operator_p)
- done = true;
+ if (depth == 0)
+ {
+ /* This might be an operator, or it might close a
+ template argument list. But if a previous '<'
+ started a template argument list, this will have
+ closed it, so we can't be in one anymore. */
+ maybe_template_id -= 1 + (token->type == CPP_RSHIFT);
+ if (maybe_template_id < 0)
+ maybe_template_id = 0;
+ }
break;
/* If we run out of tokens, issue an error message. */
case CPP_EOF:
case CPP_PRAGMA_EOL:
- error ("file ends in default argument");
+ error ("%Hfile ends in default argument", &token->location);
done = true;
break;
/* Outside of a class definition, we can just parse the
assignment-expression. */
else
- default_argument
- = cp_parser_default_argument (parser, template_parm_p);
+ {
+ token = cp_lexer_peek_token (parser->lexer);
+ default_argument
+ = cp_parser_default_argument (parser, template_parm_p);
+ }
if (!parser->default_arg_ok_p)
{
- if (!flag_pedantic_errors)
+ if (flag_permissive)
warning (0, "deprecated use of default argument for parameter of non-function");
else
{
- error ("default arguments are only permitted for function parameters");
+ error ("%Hdefault arguments are only "
+ "permitted for function parameters",
+ &token->location);
default_argument = NULL_TREE;
}
}
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
- error ("%sparameter pack %qD cannot have a default argument",
+ error ("%H%sparameter pack %qD cannot have a default argument",
+ &declarator_token_start->location,
kind, id_declarator->u.id.unqualified_name);
else
- error ("%sparameter pack cannot have a default argument",
- kind);
+ error ("%H%sparameter pack cannot have a default argument",
+ &declarator_token_start->location, kind);
default_argument = NULL_TREE;
}
Returns an expression representing the initializer. If no
initializer is present, NULL_TREE is returned.
- *IS_PARENTHESIZED_INIT is set to TRUE if the `( expression-list )'
- production is used, and zero otherwise. *IS_PARENTHESIZED_INIT is
- set to FALSE if there is no initializer present. If there is an
+ *IS_DIRECT_INIT is set to FALSE if the `= initializer-clause'
+ production is used, and TRUE otherwise. *IS_DIRECT_INIT is
+ set to TRUE if there is no initializer present. If there is an
initializer, and it is not a constant-expression, *NON_CONSTANT_P
is set to true; otherwise it is set to false. */
static tree
-cp_parser_initializer (cp_parser* parser, bool* is_parenthesized_init,
+cp_parser_initializer (cp_parser* parser, bool* is_direct_init,
bool* non_constant_p)
{
cp_token *token;
/* Let our caller know whether or not this initializer was
parenthesized. */
- *is_parenthesized_init = (token->type == CPP_OPEN_PAREN);
+ *is_direct_init = (token->type != CPP_EQ);
/* Assume that the initializer is constant. */
*non_constant_p = false;
/*cast_p=*/false,
/*allow_expansion_p=*/true,
non_constant_p);
+ else if (token->type == CPP_OPEN_BRACE)
+ {
+ maybe_warn_cpp0x ("extended initializer lists");
+ init = cp_parser_braced_list (parser, non_constant_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
+ }
else
{
/* Anything else is an error. */
initializer-clause:
assignment-expression
- { initializer-list , [opt] }
- { }
+ braced-init-list
Returns an expression representing the initializer.
If the `assignment-expression' production is used the value
returned is simply a representation for the expression.
- Otherwise, a CONSTRUCTOR is returned. The CONSTRUCTOR_ELTS will be
- the elements of the initializer-list (or NULL, if the last
- production is used). The TREE_TYPE for the CONSTRUCTOR will be
- NULL_TREE. There is no way to detect whether or not the optional
- trailing `,' was provided. NON_CONSTANT_P is as for
- cp_parser_initializer. */
+ Otherwise, calls cp_parser_braced_list. */
static tree
cp_parser_initializer_clause (cp_parser* parser, bool* non_constant_p)
initializer = fold_non_dependent_expr (initializer);
}
else
+ initializer = cp_parser_braced_list (parser, non_constant_p);
+
+ return initializer;
+}
+
+/* Parse a brace-enclosed initializer list.
+
+ braced-init-list:
+ { initializer-list , [opt] }
+ { }
+
+ Returns a CONSTRUCTOR. The CONSTRUCTOR_ELTS will be
+ the elements of the initializer-list (or NULL, if the last
+ production is used). The TREE_TYPE for the CONSTRUCTOR will be
+ NULL_TREE. There is no way to detect whether or not the optional
+ trailing `,' was provided. NON_CONSTANT_P is as for
+ cp_parser_initializer. */
+
+static tree
+cp_parser_braced_list (cp_parser* parser, bool* non_constant_p)
+{
+ tree initializer;
+
+ /* Consume the `{' token. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Create a CONSTRUCTOR to represent the braced-initializer. */
+ initializer = make_node (CONSTRUCTOR);
+ /* If it's not a `}', then there is a non-trivial initializer. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
{
- /* Consume the `{' token. */
- cp_lexer_consume_token (parser->lexer);
- /* Create a CONSTRUCTOR to represent the braced-initializer. */
- initializer = make_node (CONSTRUCTOR);
- /* If it's not a `}', then there is a non-trivial initializer. */
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_BRACE))
- {
- /* Parse the initializer list. */
- CONSTRUCTOR_ELTS (initializer)
- = cp_parser_initializer_list (parser, non_constant_p);
- /* A trailing `,' token is allowed. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
- cp_lexer_consume_token (parser->lexer);
- }
- /* Now, there should be a trailing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ /* Parse the initializer list. */
+ CONSTRUCTOR_ELTS (initializer)
+ = cp_parser_initializer_list (parser, non_constant_p);
+ /* A trailing `,' token is allowed. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
+ cp_lexer_consume_token (parser->lexer);
}
-
+ /* Now, there should be a trailing `}'. */
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+ TREE_TYPE (initializer) = init_list_type_node;
return initializer;
}
&& cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_COLON)
{
/* Warn the user that they are using an extension. */
- if (pedantic)
- pedwarn ("ISO C++ does not allow designated initializers");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ does not allow designated initializers");
/* Consume the identifier. */
identifier = cp_lexer_consume_token (parser->lexer)->u.value;
/* Consume the `:'. */
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. */
/*is_template=*/false,
/*is_namespace=*/false,
check_dependency_p,
- &ambiguous_decls);
+ &ambiguous_decls,
+ identifier_token->location);
if (ambiguous_decls)
{
- error ("reference to %qD is ambiguous", identifier);
+ error ("%Hreference to %qD is ambiguous",
+ &identifier_token->location, identifier);
print_candidates (ambiguous_decls);
if (cp_parser_parsing_tentatively (parser))
{
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;
}
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;
}
/* Look for the `{'. */
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
{
pop_deferring_access_checks ();
return error_mark_node;
/* 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)
cp_parser_member_specification_opt (parser);
/* Look for the trailing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ 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);
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;
}
bool invalid_explicit_specialization_p = false;
tree pushed_scope = NULL_TREE;
unsigned num_templates;
-
+ cp_token *type_start_token = NULL, *nested_name_specifier_token_start = NULL;
/* Assume no nested-name-specifier will be present. */
*nested_name_specifier_p = false;
/* Assume no template parameter lists will be used in defining the
/* Determine the name of the class. Begin by looking for an
optional nested-name-specifier. */
+ nested_name_specifier_token_start = cp_lexer_peek_token (parser->lexer);
nested_name_specifier
= cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
identifier. */
if (nested_name_specifier)
{
+ type_start_token = cp_lexer_peek_token (parser->lexer);
/* Although the grammar says `identifier', it really means
`class-name' or `template-name'. You are only allowed to
define a class that has already been declared with this
if (!cp_parser_parse_definitely (parser))
{
invalid_nested_name_p = true;
+ type_start_token = cp_lexer_peek_token (parser->lexer);
id = cp_parser_identifier (parser);
if (id == error_mark_node)
id = NULL_TREE;
an identifier, or nothing at all. */
cp_parser_parse_tentatively (parser);
/* Check for a template-id. */
+ type_start_token = cp_lexer_peek_token (parser->lexer);
id = cp_parser_template_id (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
if (!cp_parser_parse_definitely (parser))
{
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
- id = cp_parser_identifier (parser);
+ {
+ type_start_token = cp_lexer_peek_token (parser->lexer);
+ id = cp_parser_identifier (parser);
+ }
else
id = NULL_TREE;
}
pop_deferring_access_checks ();
if (id)
- cp_parser_check_for_invalid_template_id (parser, id);
+ cp_parser_check_for_invalid_template_id (parser, id,
+ type_start_token->location);
/* If it's not a `:' or a `{' then we can't really be looking at a
class-head, since a class-head only appears as part of a
cp_parser_commit_to_tentative_parse (parser);
/* Issue the error about the overly-qualified name now. */
if (qualified_p)
- cp_parser_error (parser,
- "global qualification of class name is invalid");
+ {
+ cp_parser_error (parser,
+ "global qualification of class name is invalid");
+ return error_mark_node;
+ }
else if (invalid_nested_name_p)
- cp_parser_error (parser,
- "qualified name does not name a class");
+ {
+ cp_parser_error (parser,
+ "qualified name does not name a class");
+ return error_mark_node;
+ }
else if (nested_name_specifier)
{
tree scope;
/* Reject typedef-names in class heads. */
if (!DECL_IMPLICIT_TYPEDEF_P (type))
{
- error ("invalid class name in declaration of %qD", type);
+ error ("%Hinvalid class name in declaration of %qD",
+ &type_start_token->location, type);
type = NULL_TREE;
goto done;
}
if (scope && !is_ancestor (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);
+ error ("%Hdeclaration of %qD in namespace %qD which does not "
+ "enclose %qD",
+ &type_start_token->location,
+ type, scope, nested_name_specifier);
else
- error ("declaration of %qD in %qD which does not enclose %qD",
+ error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
+ &type_start_token->location,
type, scope, nested_name_specifier);
type = NULL_TREE;
goto done;
}
/* [dcl.meaning]
- A declarator-id shall not be qualified exception of the
+ A declarator-id shall not be qualified except for the
definition of a ... nested class outside of its class
- ... [or] a the definition or explicit instantiation of a
+ ... [or] the definition or explicit instantiation of a
class member of a namespace outside of its namespace. */
if (scope == nested_name_specifier)
{
- pedwarn ("extra qualification ignored");
+ permerror (input_location, "%Hextra qualification not allowed",
+ &nested_name_specifier_token_start->location);
nested_name_specifier = NULL_TREE;
num_templates = 0;
}
&& parser->num_template_parameter_lists == 0
&& template_id_p)
{
- error ("an explicit specialization must be preceded by %<template <>%>");
+ error ("%Han explicit specialization must be preceded by %<template <>%>",
+ &type_start_token->location);
invalid_explicit_specialization_p = true;
/* Take the same action that would have been taken by
cp_parser_explicit_specialization. */
use "goto done;" to return. */
/* Make sure that the right number of template parameters were
present. */
- if (!cp_parser_check_template_parameters (parser, num_templates))
+ if (!cp_parser_check_template_parameters (parser, num_templates,
+ type_start_token->location))
{
/* If something went wrong, there is no point in even trying to
process the class-definition. */
&& (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);
+ error ("%Hfunction template %qD redeclared as a class template",
+ &type_start_token->location, id);
type = error_mark_node;
}
else
}
}
- maybe_process_partial_specialization (TREE_TYPE (type));
+ if (maybe_process_partial_specialization (TREE_TYPE (type))
+ == error_mark_node)
+ {
+ type = NULL_TREE;
+ goto done;
+ }
+
class_type = current_class_type;
/* Enter the scope indicated by the nested-name-specifier. */
pushed_scope = push_scope (nested_name_specifier);
that's an error. */
if (type != error_mark_node && COMPLETE_TYPE_P (type))
{
- error ("redefinition of %q#T", type);
- error ("previous definition of %q+#T", type);
+ error ("%Hredefinition of %q#T",
+ &type_start_token->location, type);
+ error ("%Hprevious definition of %q+#T",
+ &type_start_token->location, type);
type = NULL_TREE;
goto done;
}
/* Remember which access-specifier is active. */
current_access_specifier = token->u.value;
/* Look for the `:'. */
- cp_parser_require (parser, CPP_COLON, "`:'");
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
break;
default:
tree decl;
int declares_class_or_enum;
bool friend_p;
- cp_token *token;
+ cp_token *token = NULL;
+ cp_token *decl_spec_token_start = NULL;
+ cp_token *initializer_token_start = NULL;
int saved_pedantic;
/* Check for the `__extension__' keyword. */
return;
/* Parse the decl-specifier-seq. */
+ decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
&decl_specifiers,
if (!decl_specifiers.any_specifiers_p)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- if (pedantic && !token->in_system_header)
- pedwarn ("%Hextra %<;%>", &token->location);
+ if (!in_system_header_at (token->location))
+ pedwarn (token->location, OPT_pedantic, "extra %<;%>");
}
else
{
/* If the `friend' keyword was present, the friend must
be introduced with a class-key. */
if (!declares_class_or_enum)
- error ("a class-key must be used when declaring a friend");
+ error ("%Ha class-key must be used when declaring a friend",
+ &decl_spec_token_start->location);
/* In this case:
template <typename T> struct A {
&& TYPE_P (decl_specifiers.type))
type = decl_specifiers.type;
if (!type || !TYPE_P (type))
- error ("friend declaration does not name a class or "
- "function");
+ error ("%Hfriend declaration does not name a class or "
+ "function", &decl_spec_token_start->location);
else
make_friend_class (current_class_type, type,
/*complain=*/true);
finish_member_declaration (decl);
}
else
- cp_parser_check_access_in_redeclaration (TYPE_NAME (type));
+ cp_parser_check_access_in_redeclaration
+ (TYPE_NAME (type),
+ decl_spec_token_start->location);
}
}
else
sfk_none)
: NULL,
&decl_specifiers,
- width);
- /* Apply the attributes. */
- cplus_decl_attributes (&decl, attributes, /*flags=*/0);
+ width,
+ attributes);
}
else
{
if (declares_class_or_enum & 2)
cp_parser_check_for_definition_in_return_type
- (declarator, decl_specifiers.type);
+ (declarator, decl_specifiers.type,
+ decl_specifiers.type_location);
/* Look for an asm-specification. */
asm_specification = cp_parser_asm_specification_opt (parser);
for a pure-specifier; otherwise, we look for a
constant-initializer. When we call `grokfield', it will
perform more stringent semantics checks. */
+ initializer_token_start = cp_lexer_peek_token (parser->lexer);
if (function_declarator_p (declarator))
initializer = cp_parser_pure_specifier (parser);
else
standard, since a pure function may be defined
outside of the class-specifier. */
if (initializer)
- error ("pure-specifier on function-definition");
+ error ("%Hpure-specifier on function-definition",
+ &initializer_token_start->location);
decl = cp_parser_save_member_function_body (parser,
&decl_specifiers,
declarator,
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,
}
}
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
}
/* Parse a pure-specifier.
cp_token *token;
/* Look for the `=' token. */
- if (!cp_parser_require (parser, CPP_EQ, "`='"))
+ if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
return error_mark_node;
/* Look for the `0' token. */
token = cp_lexer_consume_token (parser->lexer);
+
+ /* Accept = default or = delete in c++0x mode. */
+ if (token->keyword == RID_DEFAULT
+ || token->keyword == RID_DELETE)
+ {
+ maybe_warn_cpp0x ("defaulted and deleted functions");
+ return token->u.value;
+ }
+
/* c_lex_with_flags marks a single digit '0' with PURE_ZERO. */
if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
{
cp_parser_error (parser,
- "invalid pure specifier (only `= 0' is allowed)");
+ "invalid pure specifier (only %<= 0%> is allowed)");
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
- error ("templates may not be %<virtual%>");
+ error ("%Htemplates may not be %<virtual%>", &token->location);
return error_mark_node;
}
cp_parser_constant_initializer (cp_parser* parser)
{
/* Look for the `=' token. */
- if (!cp_parser_require (parser, CPP_EQ, "`='"))
+ if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
return error_mark_node;
/* It is invalid to write:
/* Skip the initializer. */
cp_parser_skip_to_closing_brace (parser);
/* Look for the trailing `}'. */
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
return error_mark_node;
}
tree bases = NULL_TREE;
/* Look for the `:' that begins the list. */
- cp_parser_require (parser, CPP_COLON, "`:'");
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
/* Scan the base-specifier-list. */
while (true)
as base classes. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
{
+ token = cp_lexer_peek_token (parser->lexer);
if (!processing_template_decl)
- error ("keyword %<typename%> not allowed outside of templates");
+ error ("%Hkeyword %<typename%> not allowed outside of templates",
+ &token->location);
else
- error ("keyword %<typename%> not allowed in this context "
- "(the base class is implicitly a type)");
+ error ("%Hkeyword %<typename%> not allowed in this context "
+ "(the base class is implicitly a type)",
+ &token->location);
cp_lexer_consume_token (parser->lexer);
}
cp_lexer_consume_token (parser->lexer);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
type_id_list = empty_except_spec;
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return type_id_list;
}
{
tree try_block;
- cp_parser_require_keyword (parser, RID_TRY, "`try'");
+ cp_parser_require_keyword (parser, RID_TRY, "%<try%>");
try_block = begin_try_block ();
cp_parser_compound_statement (parser, NULL, true);
finish_try_block (try_block);
bool ctor_initializer_p;
/* Look for the `try' keyword. */
- if (!cp_parser_require_keyword (parser, RID_TRY, "`try'"))
+ if (!cp_parser_require_keyword (parser, RID_TRY, "%<try%>"))
return false;
/* Let the rest of the front end know where we are. */
try_block = begin_function_try_block (&compound_stmt);
tree handler;
tree declaration;
- cp_parser_require_keyword (parser, RID_CATCH, "`catch'");
+ cp_parser_require_keyword (parser, RID_CATCH, "%<catch%>");
handler = begin_handler ();
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
declaration = cp_parser_exception_declaration (parser);
finish_handler_parms (declaration, handler);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
cp_parser_compound_statement (parser, NULL, false);
finish_handler (handler);
}
tree expression;
cp_token* token;
- cp_parser_require_keyword (parser, RID_THROW, "`throw'");
+ cp_parser_require_keyword (parser, RID_THROW, "%<throw%>");
token = cp_lexer_peek_token (parser->lexer);
/* Figure out whether or not there is an assignment-expression
following the "throw" keyword. */
/* Consume the `asm' token. */
cp_lexer_consume_token (parser->lexer);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Look for the string-literal. */
asm_specification = cp_parser_string_literal (parser, false, false);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`('");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return asm_specification;
}
name = build_string (IDENTIFIER_LENGTH (name),
IDENTIFIER_POINTER (name));
/* Look for the closing `]'. */
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
}
else
name = NULL_TREE;
string_literal = cp_parser_string_literal (parser, false, false);
/* Look for the `('. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Parse the expression. */
expression = cp_parser_expression (parser, /*cast_p=*/false);
/* Look for the `)'. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
if (name == error_mark_node
|| string_literal == error_mark_node
/* Consume the `__attribute__' keyword. */
cp_lexer_consume_token (parser->lexer);
/* Look for the two `(' tokens. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
attribute_list = NULL;
/* Look for the two `)' tokens. */
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* Add these new attributes to the list. */
attributes = chainon (attributes, attribute_list);
cp_parser_label_declaration (cp_parser* parser)
{
/* Look for the `__label__' keyword. */
- cp_parser_require_keyword (parser, RID_LABEL, "`__label__'");
+ cp_parser_require_keyword (parser, RID_LABEL, "%<__label__%>");
while (true)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
break;
/* Look for the `,' separating the label declarations. */
- cp_parser_require (parser, CPP_COMMA, "`,'");
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
}
/* Look for the final `;'. */
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
}
/* Support Functions */
bool is_template,
bool is_namespace,
bool check_dependency,
- tree *ambiguous_decls)
+ tree *ambiguous_decls,
+ location_t name_location)
{
int flags = 0;
tree decl;
decl = lookup_qualified_name (parser->scope, name,
tag_type != none_type,
/*complain=*/true);
+
+ /* If we have a single function from a using decl, pull it out. */
+ if (decl
+ && TREE_CODE (decl) == OVERLOAD
+ && !really_overloaded_fn (decl))
+ decl = OVL_FUNCTION (decl);
+
if (pushed_scope)
pop_scope (pushed_scope);
}
cp_parser_error, so we incorporate its actions directly. */
if (!cp_parser_simulate_error (parser))
{
- error ("reference to %qD is ambiguous", name);
+ error ("%Hreference to %qD is ambiguous",
+ &name_location, name);
print_candidates (decl);
}
return error_mark_node;
IS_NAMESPACE is FALSE, and CHECK_DEPENDENCY is TRUE. */
static tree
-cp_parser_lookup_name_simple (cp_parser* parser, tree name)
+cp_parser_lookup_name_simple (cp_parser* parser, tree name, location_t location)
{
return cp_parser_lookup_name (parser, name,
none_type,
/*is_template=*/false,
/*is_namespace=*/false,
/*check_dependency=*/true,
- /*ambiguous_decls=*/NULL);
+ /*ambiguous_decls=*/NULL,
+ location);
}
/* If DECL is a TEMPLATE_DECL that can be treated like a TYPE_DECL in
static bool
cp_parser_check_declarator_template_parameters (cp_parser* parser,
- cp_declarator *declarator)
+ cp_declarator *declarator,
+ location_t declarator_location)
{
unsigned num_templates;
++num_templates;
return cp_parser_check_template_parameters (parser,
- num_templates);
+ num_templates,
+ declarator_location);
case cdk_function:
case cdk_array:
case cdk_reference:
case cdk_ptrmem:
return (cp_parser_check_declarator_template_parameters
- (parser, declarator->declarator));
+ (parser, declarator->declarator, declarator_location));
case cdk_error:
return true;
static bool
cp_parser_check_template_parameters (cp_parser* parser,
- unsigned num_templates)
+ unsigned num_templates,
+ location_t location)
{
/* 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 ("too few template-parameter-lists");
+ error ("%Htoo few template-parameter-lists", &location);
return false;
}
/* If there are the same number of template classes and parameter
something like:
template <class T> template <class U> void S::f(); */
- error ("too many template-parameter-lists");
+ error ("%Htoo many template-parameter-lists", &location);
return false;
}
takes one parameter (of type `int') and returns a value of type
`S::S'. */
if (constructor_p
- && cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
{
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
bool saved_in_unbraced_linkage_specification_p;
bool saved_in_function_body;
unsigned saved_num_template_parameter_lists;
+ cp_token *token;
saved_in_function_body = parser->in_function_body;
parser->in_function_body = true;
/* If the next token is `return', then the code may be trying to
make use of the "named return value" extension that G++ used to
support. */
+ token = cp_lexer_peek_token (parser->lexer);
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_RETURN))
{
/* Consume the `return' keyword. */
returned. */
cp_parser_identifier (parser);
/* Issue an error message. */
- error ("named return values are no longer supported");
+ error ("%Hnamed return values are no longer supported",
+ &token->location);
/* Skip tokens until we reach the start of the function body. */
while (true)
{
tree parameter_list;
bool friend_p = false;
bool need_lang_pop;
+ cp_token *token;
/* Look for the `template' keyword. */
- if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "`template'"))
+ token = cp_lexer_peek_token (parser->lexer);
+ if (!cp_parser_require_keyword (parser, RID_TEMPLATE, "%<template%>"))
return;
/* And the `<'. */
- if (!cp_parser_require (parser, CPP_LESS, "`<'"))
+ if (!cp_parser_require (parser, CPP_LESS, "%<<%>"))
return;
if (at_class_scope_p () && current_function_decl)
{
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
- error ("invalid declaration of member template in local class");
+ error ("%Hinvalid declaration of member template in local class",
+ &token->location);
cp_parser_skip_to_end_of_block_or_statement (parser);
return;
}
A template ... shall not have C linkage. */
if (current_lang_name == lang_name_c)
{
- error ("template with C linkage");
+ error ("%Htemplate with C linkage", &token->location);
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
/* There are no access checks when parsing a template, as we do not
know if a specialization will be a friend. */
push_deferring_access_checks (dk_no_check);
+ token = cp_lexer_peek_token (parser->lexer);
decl = cp_parser_single_declaration (parser,
checks,
member_p,
if (member_p && !friend_p && decl)
{
if (TREE_CODE (decl) == TYPE_DECL)
- cp_parser_check_access_in_redeclaration (decl);
+ cp_parser_check_access_in_redeclaration (decl, token->location);
decl = finish_member_template_decl (decl);
}
tree decl = NULL_TREE;
cp_decl_specifier_seq decl_specifiers;
bool function_definition_p = false;
+ cp_token *decl_spec_token_start;
/* This function is only used when processing a template
declaration. */
/* Try the `decl-specifier-seq [opt] init-declarator [opt]'
alternative. */
+ decl_spec_token_start = cp_lexer_peek_token (parser->lexer);
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_OPTIONAL,
&decl_specifiers,
/* There are no template typedefs. */
if (decl_specifiers.specs[(int) ds_typedef])
{
- error ("template declaration of %qs", "typedef");
+ error ("%Htemplate declaration of %qs",
+ &decl_spec_token_start->location, "typedef");
decl = error_mark_node;
}
&& explicit_specialization_p
&& decl_specifiers.storage_class != sc_none)
{
- error ("explicit template specialization cannot have a storage class");
+ error ("%Hexplicit template specialization cannot have a storage class",
+ &decl_spec_token_start->location);
decl = error_mark_node;
}
}
/* Look for a trailing `;' after the declaration. */
if (!function_definition_p
&& (decl == error_mark_node
- || !cp_parser_require (parser, CPP_SEMICOLON, "`;'")))
+ || !cp_parser_require (parser, CPP_SEMICOLON, "%<;%>")))
cp_parser_skip_to_end_of_block_or_statement (parser);
return decl;
{
tree expression_list;
tree cast;
+ bool nonconst_p;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ maybe_warn_cpp0x ("extended initializer lists");
+ expression_list = cp_parser_braced_list (parser, &nonconst_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ return finish_compound_literal (type, expression_list);
+ }
expression_list
= cp_parser_parenthesized_expression_list (parser, false,
/*cast_p=*/true,
- /*allow_expansion_p=*/true,
+ /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL);
cast = build_functional_cast (type, expression_list,
/* Save away the tokens that make up the body of the
function. */
first = parser->lexer->next_token;
+ /* We can have braced-init-list mem-initializers before the fn body. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_OPEN_BRACE)
+ && cp_lexer_next_token_is_not_keyword (parser->lexer, RID_TRY))
+ {
+ /* cache_group will stop after an un-nested { } pair, too. */
+ if (cp_parser_cache_group (parser, CPP_CLOSE_PAREN, /*depth=*/0))
+ break;
+
+ /* variadic mem-inits have ... after the ')'. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
+ cp_lexer_consume_token (parser->lexer);
+ }
+ }
cp_parser_cache_group (parser, CPP_CLOSE_BRACE, /*depth=*/0);
/* Handle function try blocks. */
while (cp_lexer_next_token_is_keyword (parser->lexer, RID_CATCH))
is a typo for '>'. Emit an error message and continue.
Same deal about the token location, but here we can get it
right by consuming the '>>' before issuing the diagnostic. */
- cp_lexer_consume_token (parser->lexer);
- error ("spurious %<>>%>, use %<>%> to terminate "
- "a template argument list");
+ cp_token *token = cp_lexer_consume_token (parser->lexer);
+ error ("%Hspurious %<>>%>, use %<>%> to terminate "
+ "a template argument list", &token->location);
}
}
else
static tree
cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
{
- static const char *format;
tree expr = NULL_TREE;
const char *saved_message;
char *tmp;
bool saved_non_integral_constant_expression_p;
bool pack_expansion_p = false;
- /* Initialize FORMAT the first time we get here. */
- if (!format)
- format = "types may not be defined in '%s' expressions";
-
/* Types cannot be defined in a `sizeof' expression. Save away the
old message. */
saved_message = parser->type_definition_forbidden_message;
/* And create the new one. */
- parser->type_definition_forbidden_message = tmp
- = XNEWVEC (char, strlen (format)
- + strlen (IDENTIFIER_POINTER (ridpointers[keyword]))
- + 1 /* `\0' */);
- sprintf (tmp, format, IDENTIFIER_POINTER (ridpointers[keyword]));
+ tmp = concat ("types may not be defined in %<",
+ IDENTIFIER_POINTER (ridpointers[keyword]),
+ "%> expressions", NULL);
+ parser->type_definition_forbidden_message = tmp;
/* The restrictions on constant-expressions do not apply inside
sizeof expressions. */
static void
cp_parser_set_storage_class (cp_parser *parser,
cp_decl_specifier_seq *decl_specs,
- enum rid keyword)
+ enum rid keyword,
+ location_t location)
{
cp_storage_class storage_class;
if (parser->in_unbraced_linkage_specification_p)
{
- error ("invalid use of %qD in linkage specification",
- ridpointers[keyword]);
+ error ("%Hinvalid use of %qD in linkage specification",
+ &location, ridpointers[keyword]);
return;
}
else if (decl_specs->storage_class != sc_none)
if ((keyword == RID_EXTERN || keyword == RID_STATIC)
&& decl_specs->specs[(int) ds_thread])
{
- error ("%<__thread%> before %qD", ridpointers[keyword]);
+ error ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
decl_specs->specs[(int) ds_thread] = 0;
}
static void
cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
tree type_spec,
+ location_t location,
bool user_defined_p)
{
decl_specs->any_specifiers_p = true;
- /* If the user tries to redeclare bool or wchar_t (with, for
- example, in "typedef int wchar_t;") we remember that this is what
- happened. In system headers, we ignore these declarations so
- that G++ can work with system headers that are not C++-safe. */
+ /* If the user tries to redeclare bool, char16_t, char32_t, or wchar_t
+ (with, for example, in "typedef int wchar_t;") we remember that
+ this is what happened. In system headers, we ignore these
+ declarations so that G++ can work with system headers that are not
+ C++-safe. */
if (decl_specs->specs[(int) ds_typedef]
&& !user_defined_p
&& (type_spec == boolean_type_node
+ || type_spec == char16_type_node
+ || type_spec == char32_type_node
|| type_spec == wchar_type_node)
&& (decl_specs->type
|| decl_specs->specs[(int) ds_long]
{
decl_specs->type = type_spec;
decl_specs->user_defined_type_p = false;
+ decl_specs->type_location = location;
}
}
else if (decl_specs->type)
decl_specs->type = type_spec;
decl_specs->user_defined_type_p = user_defined_p;
decl_specs->redefined_builtin_type = NULL_TREE;
+ decl_specs->type_location = location;
}
}
cp_parser_check_class_key (enum tag_types class_key, tree type)
{
if ((TREE_CODE (type) == UNION_TYPE) != (class_key == union_type))
- pedwarn ("%qs tag used in naming %q#T",
+ permerror (input_location, "%qs tag used in naming %q#T",
class_key == union_type ? "union"
: class_key == record_type ? "struct" : "class",
type);
[class.mem/1]. */
static void
-cp_parser_check_access_in_redeclaration (tree decl)
+cp_parser_check_access_in_redeclaration (tree decl, location_t location)
{
if (!decl || !CLASS_TYPE_P (TREE_TYPE (decl)))
return;
!= (current_access_specifier == access_private_node))
|| (TREE_PROTECTED (decl)
!= (current_access_specifier == access_protected_node)))
- error ("%qD redeclared with different access", decl);
+ error ("%H%qD redeclared with different access", &location, decl);
}
/* Look for the `template' keyword, as a syntactic disambiguator.
template and what is not. */
if (!processing_template_decl)
{
- error ("%<template%> (as a disambiguator) is only allowed "
- "within templates");
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ error ("%H%<template%> (as a disambiguator) is only allowed "
+ "within templates", &token->location);
/* If this part of the token stream is rescanned, the same
error message would be generated. So, we purge the token
from the stream. */
parser->object_scope = NULL_TREE;
}
-/* Consume tokens up through a non-nested END token. */
+/* Consume tokens up through a non-nested END token. Returns TRUE if we
+ encounter the end of a block before what we were looking for. */
-static void
+static bool
cp_parser_cache_group (cp_parser *parser,
enum cpp_ttype end,
unsigned depth)
{
while (true)
{
- cp_token *token;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
- /* Abort a parenthesized expression if we encounter a brace. */
+ /* Abort a parenthesized expression if we encounter a semicolon. */
if ((end == CPP_CLOSE_PAREN || depth == 0)
- && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
- return;
+ && token->type == CPP_SEMICOLON)
+ return true;
/* If we've reached the end of the file, stop. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_EOF)
+ if (token->type == CPP_EOF
|| (end != CPP_PRAGMA_EOL
- && cp_lexer_next_token_is (parser->lexer, CPP_PRAGMA_EOL)))
- return;
- /* Consume the next token. */
- token = cp_lexer_consume_token (parser->lexer);
+ && token->type == CPP_PRAGMA_EOL))
+ return true;
+ if (token->type == CPP_CLOSE_BRACE && depth == 0)
+ /* We've hit the end of an enclosing block, so there's been some
+ kind of syntax error. */
+ return true;
+
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
/* See if it starts a new group. */
if (token->type == CPP_OPEN_BRACE)
{
cp_parser_cache_group (parser, CPP_CLOSE_BRACE, depth + 1);
+ /* In theory this should probably check end == '}', but
+ cp_parser_save_member_function_body needs it to exit
+ after either '}' or ')' when called with ')'. */
if (depth == 0)
- return;
+ return false;
}
else if (token->type == CPP_OPEN_PAREN)
- cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+ {
+ cp_parser_cache_group (parser, CPP_CLOSE_PAREN, depth + 1);
+ if (depth == 0 && end == CPP_CLOSE_PAREN)
+ return false;
+ }
else if (token->type == CPP_PRAGMA)
cp_parser_cache_group (parser, CPP_PRAGMA_EOL, depth + 1);
else if (token->type == end)
- return;
+ return false;
}
}
break;
}
default:
- error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+ error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+ &kwd->location, kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
cp_lexer_consume_token (parser->lexer); /* Eat '['. */
receiver = cp_parser_objc_message_receiver (parser);
messageargs = cp_parser_objc_message_args (parser);
- cp_parser_require (parser, CPP_CLOSE_SQUARE, "`]'");
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
return objc_build_message_expr (build_tree_list (receiver, messageargs));
}
return build_tree_list (selector, NULL_TREE);
maybe_unary_selector_p = false;
- cp_parser_require (parser, CPP_COLON, "`:'");
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
arg = cp_parser_assignment_expression (parser, false);
sel_args
cp_parser_objc_encode_expression (cp_parser* parser)
{
tree type;
+ cp_token *token;
cp_lexer_consume_token (parser->lexer); /* Eat '@encode'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
+ token = cp_lexer_peek_token (parser->lexer);
type = complete_type (cp_parser_type_id (parser));
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
if (!type)
{
- error ("%<@encode%> must specify a type as an argument");
+ error ("%H%<@encode%> must specify a type as an argument",
+ &token->location);
return error_mark_node;
}
tree name;
cp_lexer_consume_token (parser->lexer); /* Eat '@defs'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
name = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return objc_get_class_ivars (name);
}
tree proto;
cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
proto = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return objc_build_protocol_expr (proto);
}
cp_token *token;
cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
token = cp_lexer_peek_token (parser->lexer);
while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
}
finish_selector:
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
return objc_build_selector_expr (sel_seq);
}
{
cp_lexer_consume_token (parser->lexer); /* Eat '<'. */
protorefs = cp_parser_objc_identifier_list (parser);
- cp_parser_require (parser, CPP_GREATER, "`>'");
+ cp_parser_require (parser, CPP_GREATER, "%<>%>");
}
return protorefs;
static tree
cp_parser_objc_typename (cp_parser* parser)
{
- tree typename = NULL_TREE;
+ tree type_name = NULL_TREE;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
{
if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
cp_type = cp_parser_type_id (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
- typename = build_tree_list (proto_quals, cp_type);
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+ type_name = build_tree_list (proto_quals, cp_type);
}
- return typename;
+ return type_name;
}
/* Check to see if TYPE refers to an Objective-C selector name. */
if (!cp_parser_objc_selector_p (token->type))
{
- error ("invalid Objective-C++ selector name");
+ error ("%Hinvalid Objective-C++ selector name", &token->location);
return error_mark_node;
}
while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
{
- tree selector = NULL_TREE, typename, identifier;
+ tree selector = NULL_TREE, type_name, identifier;
if (token->type != CPP_COLON)
selector = cp_parser_objc_selector (parser);
return selector;
maybe_unary_selector_p = false;
- cp_parser_require (parser, CPP_COLON, "`:'");
- typename = cp_parser_objc_typename (parser);
+ cp_parser_require (parser, CPP_COLON, "%<:%>");
+ type_name = cp_parser_objc_typename (parser);
identifier = cp_parser_identifier (parser);
params
= chainon (params,
objc_build_keyword_decl (selector,
- typename,
+ type_name,
identifier));
token = cp_lexer_peek_token (parser->lexer);
attributes = chainon (prefix_attributes, attributes);
if (width)
- {
/* Create the bitfield declaration. */
- decl = grokbitfield (declarator, &declspecs, width);
- cplus_decl_attributes (&decl, attributes, /*flags=*/0);
- }
+ decl = grokbitfield (declarator, &declspecs,
+ width,
+ attributes);
else
decl = grokfield (declarator, &declspecs,
NULL_TREE, /*init_const_expr_p=*/false,
cp_lexer_consume_token (parser->lexer); /* Eat '@protocol'. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
{
- error ("identifier expected after %<@protocol%>");
+ tok = cp_lexer_peek_token (parser->lexer);
+ error ("%Hidentifier expected after %<@protocol%>", &tok->location);
goto finish;
}
{
cp_lexer_consume_token (parser->lexer); /* Eat '('. */
*categ = cp_parser_identifier (parser);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
}
}
cp_parser_objc_end_implementation (parser);
break;
default:
- error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+ error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+ &kwd->location, kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
}
location_t location;
tree stmt;
- cp_parser_require_keyword (parser, RID_AT_TRY, "`@try'");
+ cp_parser_require_keyword (parser, RID_AT_TRY, "%<@try%>");
location = cp_lexer_peek_token (parser->lexer)->location;
/* NB: The @try block needs to be wrapped in its own STATEMENT_LIST
node, lest it get absorbed into the surrounding block. */
tree parm;
cp_lexer_consume_token (parser->lexer);
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
parmdecl = cp_parser_parameter_declaration (parser, false, NULL);
parm = grokdeclarator (parmdecl->declarator,
&parmdecl->decl_specifiers,
PARM, /*initialized=*/0,
/*attrlist=*/NULL);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
objc_begin_catch_clause (parm);
cp_parser_compound_statement (parser, NULL, false);
objc_finish_catch_clause ();
location_t location;
tree lock, stmt;
- cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "`@synchronized'");
+ cp_parser_require_keyword (parser, RID_AT_SYNCHRONIZED, "%<@synchronized%>");
location = cp_lexer_peek_token (parser->lexer)->location;
- cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
+ cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
lock = cp_parser_expression (parser, false);
- cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
/* NB: The @synchronized block needs to be wrapped in its own STATEMENT_LIST
node, lest it get absorbed into the surrounding block. */
cp_parser_objc_throw_statement (cp_parser *parser) {
tree expr = NULL_TREE;
- cp_parser_require_keyword (parser, RID_AT_THROW, "`@throw'");
+ 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);
case RID_AT_THROW:
return cp_parser_objc_throw_statement (parser);
default:
- error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
+ error ("%Hmisplaced %<@%D%> Objective-C++ construct",
+ &kwd->location, kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
switch (p[0])
{
case 'c':
- if (!strcmp ("copyin", p))
+ if (!strcmp ("collapse", p))
+ result = PRAGMA_OMP_CLAUSE_COLLAPSE;
+ else if (!strcmp ("copyin", p))
result = PRAGMA_OMP_CLAUSE_COPYIN;
else if (!strcmp ("copyprivate", p))
result = PRAGMA_OMP_CLAUSE_COPYPRIVATE;
else if (!strcmp ("shared", p))
result = PRAGMA_OMP_CLAUSE_SHARED;
break;
+ case 'u':
+ if (!strcmp ("untied", p))
+ result = PRAGMA_OMP_CLAUSE_UNTIED;
+ break;
}
}
/* Validate that a clause of the given type does not already exist. */
static void
-check_no_duplicate_clause (tree clauses, enum tree_code code, const char *name)
+check_no_duplicate_clause (tree clauses, enum omp_clause_code code,
+ const char *name, location_t location)
{
tree c;
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == code)
{
- error ("too many %qs clauses", name);
+ error ("%Htoo many %qs clauses", &location, name);
break;
}
}
cp_parser_omp_var_list_no_open (cp_parser *parser, enum omp_clause_code kind,
tree list)
{
+ cp_token *token;
while (1)
{
tree name, decl;
+ token = cp_lexer_peek_token (parser->lexer);
name = cp_parser_id_expression (parser, /*template_p=*/false,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
if (name == error_mark_node)
goto skip_comma;
- decl = cp_parser_lookup_name_simple (parser, name);
+ decl = cp_parser_lookup_name_simple (parser, name, token->location);
if (decl == error_mark_node)
- cp_parser_name_lookup_error (parser, name, decl, NULL);
+ cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
else if (kind != 0)
{
tree u = build_omp_clause (kind);
cp_lexer_consume_token (parser->lexer);
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
{
int ending;
static tree
cp_parser_omp_var_list (cp_parser *parser, enum omp_clause_code kind, tree list)
{
- if (cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return cp_parser_omp_var_list_no_open (parser, kind, list);
return list;
}
+/* OpenMP 3.0:
+ collapse ( constant-expression ) */
+
+static tree
+cp_parser_omp_clause_collapse (cp_parser *parser, tree list, location_t location)
+{
+ tree c, num;
+ location_t loc;
+ HOST_WIDE_INT n;
+
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+ return list;
+
+ num = cp_parser_constant_expression (parser, false, NULL);
+
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
+
+ if (num == error_mark_node)
+ return list;
+ num = fold_non_dependent_expr (num);
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (num))
+ || !host_integerp (num, 0)
+ || (n = tree_low_cst (num, 0)) <= 0
+ || (int) n != n)
+ {
+ error ("%Hcollapse argument needs positive constant integer expression",
+ &loc);
+ return list;
+ }
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
+ c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+ OMP_CLAUSE_CHAIN (c) = list;
+ OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
+
+ return c;
+}
+
/* OpenMP 2.5:
default ( shared | none ) */
static tree
-cp_parser_omp_clause_default (cp_parser *parser, tree list)
+cp_parser_omp_clause_default (cp_parser *parser, tree list, location_t location)
{
enum omp_clause_default_kind kind = OMP_CLAUSE_DEFAULT_UNSPECIFIED;
tree c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
cp_parser_error (parser, "expected %<none%> or %<shared%>");
}
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
if (kind == OMP_CLAUSE_DEFAULT_UNSPECIFIED)
return list;
- check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default");
+ check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
c = build_omp_clause (OMP_CLAUSE_DEFAULT);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_DEFAULT_KIND (c) = kind;
if ( expression ) */
static tree
-cp_parser_omp_clause_if (cp_parser *parser, tree list)
+cp_parser_omp_clause_if (cp_parser *parser, tree list, location_t location)
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
t = cp_parser_condition (parser);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
- check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if");
+ check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
c = build_omp_clause (OMP_CLAUSE_IF);
OMP_CLAUSE_IF_EXPR (c) = t;
nowait */
static tree
-cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_nowait (cp_parser *parser ATTRIBUTE_UNUSED,
+ tree list, location_t location)
{
tree c;
- check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait");
+ check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
c = build_omp_clause (OMP_CLAUSE_NOWAIT);
OMP_CLAUSE_CHAIN (c) = list;
num_threads ( expression ) */
static tree
-cp_parser_omp_clause_num_threads (cp_parser *parser, tree list)
+cp_parser_omp_clause_num_threads (cp_parser *parser, tree list,
+ location_t location)
{
tree t, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
t = cp_parser_expression (parser, false);
if (t == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
- check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS, "num_threads");
+ check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
+ "num_threads", location);
c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
ordered */
static tree
-cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED, tree list)
+cp_parser_omp_clause_ordered (cp_parser *parser ATTRIBUTE_UNUSED,
+ tree list, location_t location)
{
tree c;
- check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED, "ordered");
+ check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
+ "ordered", location);
c = build_omp_clause (OMP_CLAUSE_ORDERED);
OMP_CLAUSE_CHAIN (c) = list;
enum tree_code code;
tree nlist, c;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
switch (cp_lexer_peek_token (parser->lexer)->type)
code = TRUTH_ORIF_EXPR;
break;
default:
- cp_parser_error (parser, "`+', `*', `-', `&', `^', `|', `&&', or `||'");
+ cp_parser_error (parser, "expected %<+%>, %<*%>, %<-%>, %<&%>, %<^%>, "
+ "%<|%>, %<&&%>, or %<||%>");
resync_fail:
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
}
cp_lexer_consume_token (parser->lexer);
- if (!cp_parser_require (parser, CPP_COLON, "`:'"))
+ if (!cp_parser_require (parser, CPP_COLON, "%<:%>"))
goto resync_fail;
nlist = cp_parser_omp_var_list_no_open (parser, OMP_CLAUSE_REDUCTION, list);
schedule ( schedule-kind , expression )
schedule-kind:
- static | dynamic | guided | runtime */
+ static | dynamic | guided | runtime | auto */
static tree
-cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
+cp_parser_omp_clause_schedule (cp_parser *parser, tree list, location_t location)
{
tree c, t;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
}
else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_STATIC))
OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_STATIC;
+ else if (cp_lexer_next_token_is_keyword (parser->lexer, RID_AUTO))
+ OMP_CLAUSE_SCHEDULE_KIND (c) = OMP_CLAUSE_SCHEDULE_AUTO;
else
goto invalid_kind;
cp_lexer_consume_token (parser->lexer);
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
+ cp_token *token;
cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
t = cp_parser_assignment_expression (parser, false);
if (t == error_mark_node)
goto resync_fail;
else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
- error ("schedule %<runtime%> does not take "
- "a %<chunk_size%> parameter");
+ error ("%Hschedule %<runtime%> does not take "
+ "a %<chunk_size%> parameter", &token->location);
+ else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
+ error ("%Hschedule %<auto%> does not take "
+ "a %<chunk_size%> parameter", &token->location);
else
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
goto resync_fail;
}
- else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`,' or `)'"))
+ else if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<,%> or %<)%>"))
goto resync_fail;
- check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule");
+ check_no_duplicate_clause (list, OMP_CLAUSE_SCHEDULE, "schedule", location);
OMP_CLAUSE_CHAIN (c) = list;
return c;
return list;
}
+/* OpenMP 3.0:
+ untied */
+
+static tree
+cp_parser_omp_clause_untied (cp_parser *parser ATTRIBUTE_UNUSED,
+ tree list, location_t location)
+{
+ tree c;
+
+ check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
+
+ c = build_omp_clause (OMP_CLAUSE_UNTIED);
+ OMP_CLAUSE_CHAIN (c) = list;
+ return c;
+}
+
/* Parse all OpenMP clauses. The set clauses allowed by the directive
is a bitmask in MASK. Return the list of clauses found; the result
of clause default goes in *pdefault. */
{
tree clauses = NULL;
bool first = true;
+ cp_token *token = NULL;
while (cp_lexer_next_token_is_not (parser->lexer, CPP_PRAGMA_EOL))
{
if (!first && cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
c_kind = cp_parser_omp_clause_name (parser);
first = false;
switch (c_kind)
{
+ case PRAGMA_OMP_CLAUSE_COLLAPSE:
+ clauses = cp_parser_omp_clause_collapse (parser, clauses,
+ token->location);
+ c_name = "collapse";
+ break;
case PRAGMA_OMP_CLAUSE_COPYIN:
clauses = cp_parser_omp_var_list (parser, OMP_CLAUSE_COPYIN, clauses);
c_name = "copyin";
c_name = "copyprivate";
break;
case PRAGMA_OMP_CLAUSE_DEFAULT:
- clauses = cp_parser_omp_clause_default (parser, clauses);
+ clauses = cp_parser_omp_clause_default (parser, clauses,
+ token->location);
c_name = "default";
break;
case PRAGMA_OMP_CLAUSE_FIRSTPRIVATE:
c_name = "firstprivate";
break;
case PRAGMA_OMP_CLAUSE_IF:
- clauses = cp_parser_omp_clause_if (parser, clauses);
+ clauses = cp_parser_omp_clause_if (parser, clauses, token->location);
c_name = "if";
break;
case PRAGMA_OMP_CLAUSE_LASTPRIVATE:
c_name = "lastprivate";
break;
case PRAGMA_OMP_CLAUSE_NOWAIT:
- clauses = cp_parser_omp_clause_nowait (parser, clauses);
+ clauses = cp_parser_omp_clause_nowait (parser, clauses, token->location);
c_name = "nowait";
break;
case PRAGMA_OMP_CLAUSE_NUM_THREADS:
- clauses = cp_parser_omp_clause_num_threads (parser, clauses);
+ clauses = cp_parser_omp_clause_num_threads (parser, clauses,
+ token->location);
c_name = "num_threads";
break;
case PRAGMA_OMP_CLAUSE_ORDERED:
- clauses = cp_parser_omp_clause_ordered (parser, clauses);
+ clauses = cp_parser_omp_clause_ordered (parser, clauses,
+ token->location);
c_name = "ordered";
break;
case PRAGMA_OMP_CLAUSE_PRIVATE:
c_name = "reduction";
break;
case PRAGMA_OMP_CLAUSE_SCHEDULE:
- clauses = cp_parser_omp_clause_schedule (parser, clauses);
+ clauses = cp_parser_omp_clause_schedule (parser, clauses,
+ token->location);
c_name = "schedule";
break;
case PRAGMA_OMP_CLAUSE_SHARED:
clauses);
c_name = "shared";
break;
+ case PRAGMA_OMP_CLAUSE_UNTIED:
+ clauses = cp_parser_omp_clause_untied (parser, clauses,
+ token->location);
+ c_name = "nowait";
+ break;
default:
cp_parser_error (parser, "expected %<#pragma omp%> clause");
goto saw_error;
/* Remove the invalid clause(s) from the list to avoid
confusing the rest of the compiler. */
clauses = prev;
- error ("%qs is not valid for %qs", c_name, where);
+ error ("%H%qs is not valid for %qs", &token->location, c_name, where);
}
}
saw_error:
name = cp_parser_identifier (parser);
if (name == error_mark_node
- || !cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
+ || !cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
/*or_comma=*/false,
/*consume_paren=*/true);
finish_omp_flush ();
}
-/* Parse the restricted form of the for statment allowed by OpenMP. */
+/* Helper function, to parse omp for increment expression. */
static tree
-cp_parser_omp_for_loop (cp_parser *parser)
+cp_parser_omp_for_cond (cp_parser *parser, tree decl)
{
- tree init, cond, incr, body, decl, pre_body;
- location_t loc;
+ tree lhs = cp_parser_cast_expression (parser, false, false), rhs;
+ enum tree_code op;
+ cp_token *token;
- if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ if (lhs != decl)
{
- cp_parser_error (parser, "for statement expected");
- return NULL;
+ cp_parser_skip_to_end_of_statement (parser);
+ return error_mark_node;
}
- loc = cp_lexer_consume_token (parser->lexer)->location;
- if (!cp_parser_require (parser, CPP_OPEN_PAREN, "`('"))
- return NULL;
- init = decl = NULL;
- pre_body = push_stmt_list ();
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ token = cp_lexer_peek_token (parser->lexer);
+ op = binops_by_token [token->type].tree_type;
+ switch (op)
{
- cp_decl_specifier_seq type_specifiers;
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_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;
+ }
+
+ return build2 (op, boolean_type_node, lhs, rhs);
+}
- /* First, try to parse as an initialized declaration. See
- cp_parser_condition, from whence the bulk of this is copied. */
+/* Helper function, to parse omp for increment expression. */
- cp_parser_parse_tentatively (parser);
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
- &type_specifiers);
- if (!cp_parser_error_occurred (parser))
+static tree
+cp_parser_omp_for_incr (cp_parser *parser, tree decl)
+{
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ enum tree_code op;
+ tree lhs, rhs;
+ cp_id_kind idk;
+ bool decl_first;
+
+ if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+ {
+ op = (token->type == CPP_PLUS_PLUS
+ ? PREINCREMENT_EXPR : PREDECREMENT_EXPR);
+ cp_lexer_consume_token (parser->lexer);
+ lhs = cp_parser_cast_expression (parser, false, false);
+ if (lhs != decl)
+ return error_mark_node;
+ return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+ }
+
+ lhs = cp_parser_primary_expression (parser, false, false, false, &idk);
+ if (lhs != decl)
+ return error_mark_node;
+
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_PLUS_PLUS || token->type == CPP_MINUS_MINUS)
+ {
+ op = (token->type == CPP_PLUS_PLUS
+ ? POSTINCREMENT_EXPR : POSTDECREMENT_EXPR);
+ cp_lexer_consume_token (parser->lexer);
+ return build2 (op, TREE_TYPE (decl), decl, NULL_TREE);
+ }
+
+ op = cp_parser_assignment_operator_opt (parser);
+ if (op == ERROR_MARK)
+ return error_mark_node;
+
+ if (op != NOP_EXPR)
+ {
+ rhs = cp_parser_assignment_expression (parser, false);
+ 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);
+ token = cp_lexer_peek_token (parser->lexer);
+ decl_first = lhs == decl;
+ if (decl_first)
+ lhs = NULL_TREE;
+ if (token->type != CPP_PLUS
+ && token->type != CPP_MINUS)
+ return error_mark_node;
+
+ do
+ {
+ 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);
+ token = cp_lexer_peek_token (parser->lexer);
+ if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
{
- tree asm_specification, attributes;
- cp_declarator *declarator;
-
- declarator = cp_parser_declarator (parser,
- CP_PARSER_DECLARATOR_NAMED,
- /*ctor_dtor_or_conv_p=*/NULL,
- /*parenthesized_p=*/NULL,
- /*member_p=*/false);
- attributes = cp_parser_attributes_opt (parser);
- asm_specification = cp_parser_asm_specification_opt (parser);
+ if (lhs == NULL_TREE)
+ {
+ if (op == PLUS_EXPR)
+ lhs = rhs;
+ else
+ lhs = build_x_unary_op (NEGATE_EXPR, rhs, tf_warning_or_error);
+ }
+ else
+ lhs = build_x_binary_op (op, lhs, ERROR_MARK, rhs, ERROR_MARK,
+ NULL, tf_warning_or_error);
+ }
+ }
+ while (token->type == CPP_PLUS || token->type == CPP_MINUS);
+
+ if (!decl_first)
+ {
+ if (rhs != decl || op == MINUS_EXPR)
+ return error_mark_node;
+ rhs = build2 (op, TREE_TYPE (decl), lhs, decl);
+ }
+ else
+ rhs = build2 (PLUS_EXPR, TREE_TYPE (decl), decl, lhs);
+
+ return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
+}
+
+/* Parse the restricted form of the for statement allowed by OpenMP. */
+
+static tree
+cp_parser_omp_for_loop (cp_parser *parser, tree clauses, tree *par_clauses)
+{
+ tree init, cond, incr, body, decl, pre_body = NULL_TREE, ret;
+ tree for_block = NULL_TREE, real_decl, initv, condv, incrv, declv;
+ tree this_pre_body, cl;
+ location_t loc_first;
+ bool collapse_err = false;
+ int i, collapse = 1, nbraces = 0;
+
+ for (cl = clauses; cl; cl = OMP_CLAUSE_CHAIN (cl))
+ if (OMP_CLAUSE_CODE (cl) == OMP_CLAUSE_COLLAPSE)
+ collapse = tree_low_cst (OMP_CLAUSE_COLLAPSE_EXPR (cl), 0);
+
+ gcc_assert (collapse >= 1);
+
+ declv = make_tree_vec (collapse);
+ initv = make_tree_vec (collapse);
+ condv = make_tree_vec (collapse);
+ incrv = make_tree_vec (collapse);
+
+ loc_first = cp_lexer_peek_token (parser->lexer)->location;
+
+ for (i = 0; i < collapse; i++)
+ {
+ int bracecount = 0;
+ bool add_private_clause = false;
+ location_t loc;
+
+ if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ {
+ cp_parser_error (parser, "for statement expected");
+ return NULL;
+ }
+ loc = cp_lexer_consume_token (parser->lexer)->location;
+
+ if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+ return NULL;
+
+ init = decl = real_decl = NULL;
+ this_pre_body = push_stmt_list ();
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ {
+ /* See 2.5.1 (in OpenMP 3.0, similar wording is in 2.5 standard too):
+
+ init-expr:
+ var = lb
+ integer-type var = lb
+ random-access-iterator-type var = lb
+ pointer-type var = lb
+ */
+ cp_decl_specifier_seq type_specifiers;
+
+ /* First, try to parse as an initialized declaration. See
+ cp_parser_condition, from whence the bulk of this is copied. */
- cp_parser_require (parser, CPP_EQ, "`='");
+ cp_parser_parse_tentatively (parser);
+ cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ &type_specifiers);
if (cp_parser_parse_definitely (parser))
{
- tree pushed_scope;
+ /* If parsing a type specifier seq succeeded, then this
+ MUST be a initialized declaration. */
+ tree asm_specification, attributes;
+ cp_declarator *declarator;
+
+ declarator = cp_parser_declarator (parser,
+ CP_PARSER_DECLARATOR_NAMED,
+ /*ctor_dtor_or_conv_p=*/NULL,
+ /*parenthesized_p=*/NULL,
+ /*member_p=*/false);
+ attributes = cp_parser_attributes_opt (parser);
+ asm_specification = cp_parser_asm_specification_opt (parser);
+
+ if (declarator == cp_error_declarator)
+ cp_parser_skip_to_end_of_statement (parser);
+
+ else
+ {
+ tree pushed_scope, auto_node;
+
+ decl = start_decl (declarator, &type_specifiers,
+ 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,
+ CPP_OPEN_PAREN))
+ error ("parenthesized initialization is not allowed in "
+ "OpenMP %<for%> loop");
+ else
+ /* Trigger an error. */
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
+
+ init = error_mark_node;
+ cp_parser_skip_to_end_of_statement (parser);
+ }
+ else if (CLASS_TYPE_P (TREE_TYPE (decl))
+ || type_dependent_expression_p (decl)
+ || auto_node)
+ {
+ bool is_direct_init, is_non_constant_init;
+
+ init = cp_parser_initializer (parser,
+ &is_direct_init,
+ &is_non_constant_init);
- decl = start_decl (declarator, &type_specifiers,
- /*initialized_p=*/false, attributes,
- /*prefix_attributes=*/NULL_TREE,
- &pushed_scope);
+ 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);
+ if (CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ for_block
+ = tree_cons (NULL, this_pre_body, for_block);
+ init = NULL_TREE;
+ }
+ else
+ init = pop_stmt_list (this_pre_body);
+ this_pre_body = NULL_TREE;
+ }
+ else
+ {
+ /* Consume '='. */
+ cp_lexer_consume_token (parser->lexer);
+ init = cp_parser_assignment_expression (parser, false);
- init = cp_parser_assignment_expression (parser, false);
+ non_class:
+ if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
+ init = error_mark_node;
+ else
+ cp_finish_decl (decl, NULL_TREE,
+ /*init_const_expr_p=*/false,
+ asm_specification,
+ LOOKUP_ONLYCONVERTING);
+ }
- if (TREE_CODE (TREE_TYPE (decl)) == REFERENCE_TYPE)
- init = error_mark_node;
+ if (pushed_scope)
+ pop_scope (pushed_scope);
+ }
+ }
+ else
+ {
+ cp_id_kind idk;
+ /* If parsing a type specifier sequence failed, then
+ this MUST be a simple expression. */
+ cp_parser_parse_tentatively (parser);
+ decl = cp_parser_primary_expression (parser, false, false,
+ false, &idk);
+ if (!cp_parser_error_occurred (parser)
+ && decl
+ && DECL_P (decl)
+ && CLASS_TYPE_P (TREE_TYPE (decl)))
+ {
+ tree rhs;
+
+ cp_parser_parse_definitely (parser);
+ cp_parser_require (parser, CPP_EQ, "%<=%>");
+ rhs = cp_parser_assignment_expression (parser, false);
+ finish_expr_stmt (build_x_modify_expr (decl, NOP_EXPR,
+ rhs,
+ tf_warning_or_error));
+ add_private_clause = true;
+ }
else
- cp_finish_decl (decl, NULL_TREE, /*init_const_expr_p=*/false,
- asm_specification, LOOKUP_ONLYCONVERTING);
+ {
+ decl = NULL;
+ cp_parser_abort_tentative_parse (parser);
+ init = cp_parser_expression (parser, false);
+ if (init)
+ {
+ if (TREE_CODE (init) == MODIFY_EXPR
+ || TREE_CODE (init) == MODOP_EXPR)
+ real_decl = TREE_OPERAND (init, 0);
+ }
+ }
+ }
+ }
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+ if (this_pre_body)
+ {
+ this_pre_body = pop_stmt_list (this_pre_body);
+ if (pre_body)
+ {
+ tree t = pre_body;
+ pre_body = push_stmt_list ();
+ add_stmt (t);
+ add_stmt (this_pre_body);
+ pre_body = pop_stmt_list (pre_body);
+ }
+ else
+ pre_body = this_pre_body;
+ }
- if (pushed_scope)
- pop_scope (pushed_scope);
+ if (decl)
+ real_decl = decl;
+ if (par_clauses != NULL && real_decl != NULL_TREE)
+ {
+ tree *c;
+ for (c = par_clauses; *c ; )
+ if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (*c) == real_decl)
+ {
+ error ("%Hiteration variable %qD should not be firstprivate",
+ &loc, real_decl);
+ *c = OMP_CLAUSE_CHAIN (*c);
+ }
+ else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
+ && OMP_CLAUSE_DECL (*c) == real_decl)
+ {
+ /* 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);
+ OMP_CLAUSE_DECL (l) = real_decl;
+ OMP_CLAUSE_CHAIN (l) = clauses;
+ CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
+ clauses = l;
+ OMP_CLAUSE_SET_CODE (*c, OMP_CLAUSE_SHARED);
+ CP_OMP_CLAUSE_INFO (*c) = NULL;
+ add_private_clause = false;
+ }
+ else
+ {
+ if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_PRIVATE
+ && OMP_CLAUSE_DECL (*c) == real_decl)
+ add_private_clause = false;
+ c = &OMP_CLAUSE_CHAIN (*c);
+ }
+ }
+
+ if (add_private_clause)
+ {
+ tree c;
+ for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
+ {
+ if ((OMP_CLAUSE_CODE (c) == OMP_CLAUSE_PRIVATE
+ || OMP_CLAUSE_CODE (c) == OMP_CLAUSE_LASTPRIVATE)
+ && OMP_CLAUSE_DECL (c) == decl)
+ break;
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_FIRSTPRIVATE
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("%Hiteration variable %qD should not be firstprivate",
+ &loc, decl);
+ else if (OMP_CLAUSE_CODE (c) == OMP_CLAUSE_REDUCTION
+ && OMP_CLAUSE_DECL (c) == decl)
+ error ("%Hiteration variable %qD should not be reduction",
+ &loc, decl);
+ }
+ if (c == NULL)
+ {
+ c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ OMP_CLAUSE_DECL (c) = decl;
+ c = finish_omp_clauses (c);
+ if (c)
+ {
+ OMP_CLAUSE_CHAIN (c) = clauses;
+ clauses = c;
+ }
}
}
- else
- cp_parser_abort_tentative_parse (parser);
- /* If parsing as an initialized declaration failed, try again as
- a simple expression. */
- if (decl == NULL)
- init = cp_parser_expression (parser, false);
- }
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
- pre_body = pop_stmt_list (pre_body);
+ 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);
+ }
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
- cond = NULL;
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- cond = cp_parser_condition (parser);
- cp_parser_require (parser, CPP_SEMICOLON, "`;'");
+ incr = NULL;
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
+ {
+ /* If decl is an iterator, preserve the operator on decl
+ until finish_omp_for. */
+ if (decl
+ && (type_dependent_expression_p (decl)
+ || CLASS_TYPE_P (TREE_TYPE (decl))))
+ incr = cp_parser_omp_for_incr (parser, decl);
+ else
+ incr = cp_parser_expression (parser, false);
+ }
- incr = NULL;
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN))
- incr = cp_parser_expression (parser, false);
+ if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+ cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
+ /*or_comma=*/false,
+ /*consume_paren=*/true);
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'"))
- cp_parser_skip_to_closing_parenthesis (parser, /*recovering=*/true,
- /*or_comma=*/false,
- /*consume_paren=*/true);
+ TREE_VEC_ELT (declv, i) = decl;
+ TREE_VEC_ELT (initv, i) = init;
+ TREE_VEC_ELT (condv, i) = cond;
+ TREE_VEC_ELT (incrv, i) = incr;
+
+ if (i == collapse - 1)
+ break;
+
+ /* FIXME: OpenMP 3.0 draft isn't very clear on what exactly is allowed
+ in between the collapsed for loops to be still considered perfectly
+ nested. Hopefully the final version clarifies this.
+ For now handle (multiple) {'s and empty statements. */
+ cp_parser_parse_tentatively (parser);
+ do
+ {
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
+ break;
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ bracecount++;
+ }
+ else if (bracecount
+ && cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ {
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+ error ("%Hnot enough collapsed for loops", &loc);
+ collapse_err = true;
+ cp_parser_abort_tentative_parse (parser);
+ declv = NULL_TREE;
+ break;
+ }
+ }
+ while (1);
+
+ if (declv)
+ {
+ cp_parser_parse_definitely (parser);
+ nbraces += bracecount;
+ }
+ }
/* Note that we saved the original contents of this flag when we entered
the structured block, and so we don't need to re-save it here. */
cp_parser_statement (parser, NULL_TREE, false, NULL);
body = pop_stmt_list (body);
- return finish_omp_for (loc, decl, init, cond, incr, body, pre_body);
+ if (declv == NULL_TREE)
+ ret = NULL_TREE;
+ else
+ ret = finish_omp_for (loc_first, declv, initv, condv, incrv, body,
+ pre_body, clauses);
+
+ while (nbraces)
+ {
+ if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_BRACE))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ nbraces--;
+ }
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
+ cp_lexer_consume_token (parser->lexer);
+ else
+ {
+ if (!collapse_err)
+ {
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
+ error ("%Hcollapsed loops not perfectly nested", &loc);
+ }
+ collapse_err = true;
+ cp_parser_statement_seq_opt (parser, NULL);
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+ }
+ }
+
+ while (for_block)
+ {
+ add_stmt (pop_stmt_list (TREE_VALUE (for_block)));
+ for_block = TREE_CHAIN (for_block);
+ }
+
+ return ret;
}
/* OpenMP 2.5:
| (1u << PRAGMA_OMP_CLAUSE_REDUCTION) \
| (1u << PRAGMA_OMP_CLAUSE_ORDERED) \
| (1u << PRAGMA_OMP_CLAUSE_SCHEDULE) \
- | (1u << PRAGMA_OMP_CLAUSE_NOWAIT))
+ | (1u << PRAGMA_OMP_CLAUSE_NOWAIT) \
+ | (1u << PRAGMA_OMP_CLAUSE_COLLAPSE))
static tree
cp_parser_omp_for (cp_parser *parser, cp_token *pragma_tok)
sb = begin_omp_structured_block ();
save = cp_parser_begin_omp_structured_block (parser);
- ret = cp_parser_omp_for_loop (parser);
- if (ret)
- OMP_FOR_CLAUSES (ret) = clauses;
+ ret = cp_parser_omp_for_loop (parser, clauses, NULL);
cp_parser_end_omp_structured_block (parser, save);
add_stmt (finish_omp_structured_block (sb));
bool error_suppress = false;
cp_token *tok;
- if (!cp_parser_require (parser, CPP_OPEN_BRACE, "`{'"))
+ if (!cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>"))
return NULL_TREE;
stmt = push_stmt_list ();
substmt = build1 (OMP_SECTION, void_type_node, substmt);
add_stmt (substmt);
}
- cp_parser_require (parser, CPP_CLOSE_BRACE, "`}'");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
substmt = pop_stmt_list (stmt);
case PRAGMA_OMP_PARALLEL_FOR:
c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
- stmt = cp_parser_omp_for_loop (parser);
- if (stmt)
- OMP_FOR_CLAUSES (stmt) = ws_clause;
+ cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
break;
case PRAGMA_OMP_PARALLEL_SECTIONS:
return add_stmt (stmt);
}
+/* OpenMP 3.0:
+ # pragma omp task task-clause[optseq] new-line
+ structured-block */
+
+#define OMP_TASK_CLAUSE_MASK \
+ ( (1u << PRAGMA_OMP_CLAUSE_IF) \
+ | (1u << PRAGMA_OMP_CLAUSE_UNTIED) \
+ | (1u << PRAGMA_OMP_CLAUSE_DEFAULT) \
+ | (1u << PRAGMA_OMP_CLAUSE_PRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_FIRSTPRIVATE) \
+ | (1u << PRAGMA_OMP_CLAUSE_SHARED))
+
+static tree
+cp_parser_omp_task (cp_parser *parser, cp_token *pragma_tok)
+{
+ tree clauses, block;
+ unsigned int save;
+
+ clauses = cp_parser_omp_all_clauses (parser, OMP_TASK_CLAUSE_MASK,
+ "#pragma omp task", pragma_tok);
+ block = begin_omp_task ();
+ save = cp_parser_begin_omp_structured_block (parser);
+ cp_parser_statement (parser, NULL_TREE, false, NULL);
+ cp_parser_end_omp_structured_block (parser, save);
+ return finish_omp_task (clauses, block);
+}
+
+/* OpenMP 3.0:
+ # pragma omp taskwait new-line */
+
+static void
+cp_parser_omp_taskwait (cp_parser *parser, cp_token *pragma_tok)
+{
+ cp_parser_require_pragma_eol (parser, pragma_tok);
+ finish_omp_taskwait ();
+}
+
/* OpenMP 2.5:
# pragma omp threadprivate (variable-list) */
case PRAGMA_OMP_SINGLE:
stmt = cp_parser_omp_single (parser, pragma_tok);
break;
+ case PRAGMA_OMP_TASK:
+ stmt = cp_parser_omp_task (parser, pragma_tok);
+ break;
default:
gcc_unreachable ();
}
cp_lexer_get_preprocessor_token (NULL, first_token);
if (first_token->type != CPP_PRAGMA_EOL)
- error ("junk at end of %<#pragma GCC pch_preprocess%>");
+ error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
+ &first_token->location);
}
else
- error ("expected string literal");
+ error ("%Hexpected string literal", &first_token->location);
/* Skip to the end of the pragma. */
while (first_token->type != CPP_PRAGMA_EOL && first_token->type != CPP_EOF)
switch (id)
{
case PRAGMA_GCC_PCH_PREPROCESS:
- error ("%<#pragma GCC pch_preprocess%> must be first");
+ error ("%H%<#pragma GCC pch_preprocess%> must be first",
+ &pragma_tok->location);
break;
case PRAGMA_OMP_BARRIER:
cp_parser_omp_barrier (parser, pragma_tok);
return false;
case pragma_stmt:
- error ("%<#pragma omp barrier%> may only be "
- "used in compound statements");
+ error ("%H%<#pragma omp barrier%> may only be "
+ "used in compound statements", &pragma_tok->location);
break;
default:
goto bad_stmt;
cp_parser_omp_flush (parser, pragma_tok);
return false;
case pragma_stmt:
- error ("%<#pragma omp flush%> may only be "
- "used in compound statements");
+ error ("%H%<#pragma omp flush%> may only be "
+ "used in compound statements", &pragma_tok->location);
+ break;
+ default:
+ goto bad_stmt;
+ }
+ break;
+
+ case PRAGMA_OMP_TASKWAIT:
+ switch (context)
+ {
+ case pragma_compound:
+ cp_parser_omp_taskwait (parser, pragma_tok);
+ return false;
+ case pragma_stmt:
+ error ("%H%<#pragma omp taskwait%> may only be "
+ "used in compound statements",
+ &pragma_tok->location);
break;
default:
goto bad_stmt;
case PRAGMA_OMP_PARALLEL:
case PRAGMA_OMP_SECTIONS:
case PRAGMA_OMP_SINGLE:
+ case PRAGMA_OMP_TASK:
if (context == pragma_external)
goto bad_stmt;
cp_parser_omp_construct (parser, pragma_tok);
return true;
case PRAGMA_OMP_SECTION:
- error ("%<#pragma omp section%> may only be used in "
- "%<#pragma omp sections%> construct");
+ error ("%H%<#pragma omp section%> may only be used in "
+ "%<#pragma omp sections%> construct", &pragma_tok->location);
break;
default: