#include "coretypes.h"
#include "tm.h"
#include "dyn-string.h"
-#include "varray.h"
#include "cpplib.h"
#include "tree.h"
#include "cp-tree.h"
+#include "intl.h"
#include "c-pragma.h"
#include "decl.h"
#include "flags.h"
#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+#include "plugin.h"
\f
/* The lexer. */
/* A token's value and its associated deferred access checks and
qualifying scope. */
-struct tree_check GTY(())
-{
+struct GTY(()) tree_check {
/* The value associated with the token. */
tree value;
/* The checks that have been associated with value. */
/* A C++ token. */
-typedef struct cp_token GTY (())
-{
+typedef struct GTY (()) cp_token {
/* The kind of token. */
ENUM_BITFIELD (cpp_ttype) type : 8;
/* If this token is a keyword, this value indicates which keyword.
KEYWORD is RID_MAX) iff this name was looked up and found to be
ambiguous. An error has already been reported. */
BOOL_BITFIELD ambiguous_p : 1;
+ /* The location at which this token was found. */
+ location_t location;
/* The value associated with this token, if any. */
union cp_token_value {
/* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID. */
/* Use for all other tokens. */
tree GTY((tag ("0"))) value;
} GTY((desc ("(%1.type == CPP_TEMPLATE_ID) || (%1.type == CPP_NESTED_NAME_SPECIFIER)"))) u;
- /* The location at which this token was found. */
- location_t location;
} cp_token;
/* We use a stack of token pointer for saving token sets. */
static cp_token eof_token =
{
- CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, { NULL },
- 0
+ CPP_EOF, RID_MAX, 0, PRAGMA_NONE, false, 0, 0, { NULL }
};
/* The cp_lexer structure represents the C++ lexer. It is responsible
it to the parser. Tokens are never added to the cp_lexer after
it is created. */
-typedef struct cp_lexer GTY (())
-{
+typedef struct GTY (()) cp_lexer {
/* The memory allocated for the buffer. NULL if this lexer does not
own the token buffer. */
cp_token * GTY ((length ("%h.buffer_length"))) buffer;
a cp_token_cache, since everything in here is referenced through
a lexer. */
-typedef struct cp_token_cache GTY(())
-{
+typedef struct GTY(()) cp_token_cache {
/* The beginning of the token range. */
cp_token * GTY((skip)) first;
static FILE *cp_lexer_debug_stream;
#endif /* ENABLE_CHECKING */
+/* Nonzero if we are parsing an unevaluated operand: an operand to
+ sizeof, typeof, or alignof. */
+int cp_unevaluated_operand;
+
/* Create a new main C++ lexer, the lexer that gets tokens from the
preprocessor. */
/* Subsequent preprocessor diagnostics should use compiler
diagnostic functions to get the compiler source location. */
- cpp_get_options (parse_in)->client_diagnostic = true;
- cpp_get_callbacks (parse_in)->error = cp_cpp_error;
+ done_lexing = true;
gcc_assert (lexer->next_token->type != CPP_PURGED);
return lexer;
/* Get a new token from the preprocessor. */
token->type
= c_lex_with_flags (&token->u.value, &token->location, &token->flags,
- lexer == NULL ? 0 : C_LEX_RAW_STRINGS);
+ lexer == NULL ? 0 : C_LEX_STRING_NO_JOIN);
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
token->type = CPP_KEYWORD;
/* Record which keyword. */
token->keyword = C_RID_CODE (token->u.value);
- /* Update the value. Some keywords are mapped to particular
- entities, rather than simply having the value of the
- corresponding IDENTIFIER_NODE. For example, `__const' is
- mapped to `const'. */
- token->u.value = ridpointers[token->keyword];
}
else
{
/* Warn about the C++0x keyword (but still treat it as
an identifier). */
warning (OPT_Wc__0x_compat,
- "identifier %<%s%> will become a keyword in C++0x",
- IDENTIFIER_POINTER (token->u.value));
+ "identifier %qE will become a keyword in C++0x",
+ token->u.value);
/* Clear out the C_RID_CODE so we don't warn about this
particular identifier-turned-keyword again. */
else if (token->type == CPP_PRAGMA)
{
/* We smuggled the cpp_token->u.pragma value in an INTEGER_CST. */
- token->pragma_kind = TREE_INT_CST_LOW (token->u.value);
+ token->pragma_kind = ((enum pragma_kind)
+ TREE_INT_CST_LOW (token->u.value));
token->u.value = NULL_TREE;
}
}
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
+ case CPP_UTF8STRING:
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
break;
declarator->attributes = NULL_TREE;
declarator->declarator = NULL;
declarator->parameter_pack_p = false;
+ declarator->id_loc = UNKNOWN_LOCATION;
return declarator;
}
/* Flags that are passed to some parsing functions. These values can
be bitwise-ored together. */
-typedef enum cp_parser_flags
+enum
{
/* No flags. */
CP_PARSER_FLAGS_NONE = 0x0,
/* The construct is optional. If it is not present, then no error
should be issued. */
CP_PARSER_FLAGS_OPTIONAL = 0x1,
- /* When parsing a type-specifier, do not allow user-defined types. */
- CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2
-} cp_parser_flags;
+ /* When parsing a type-specifier, treat user-defined type-names
+ as non-type identifiers. */
+ CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES = 0x2,
+ /* When parsing a type-specifier, do not try to parse a class-specifier
+ or enum-specifier. */
+ CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS = 0x4
+};
+
+/* This type is used for parameters and variables which hold
+ combinations of the above flags. */
+typedef int cp_parser_flags;
/* The different kinds of declarators we want to parse. */
/* Tree code for the binary operation we are parsing. */
enum tree_code tree_type;
/* Precedence of the binary operation we are parsing. */
- int prec;
+ enum cp_parser_prec prec;
} cp_parser_expression_stack_entry;
/* The stack for storing partial expressions. We only need NUM_PREC_VALUES
cp_parser_expression_stack[NUM_PREC_VALUES];
/* Context that is saved and restored when parsing tentatively. */
-typedef struct cp_parser_context GTY (())
-{
+typedef struct GTY (()) cp_parser_context {
/* If this is a tentative parsing context, the status of the
tentative parse. */
enum cp_parser_status_kind status;
/* The cp_parser structure represents the C++ parser. */
-typedef struct cp_parser GTY(())
-{
+typedef struct GTY(()) cp_parser {
/* The lexer from which we are obtaining tokens. */
cp_lexer *lexer;
(cp_parser *, tree, bool);
static tree cp_parser_postfix_dot_deref_expression
(cp_parser *, enum cpp_ttype, tree, bool, cp_id_kind *, location_t);
-static tree cp_parser_parenthesized_expression_list
- (cp_parser *, bool, bool, bool, bool *);
+static VEC(tree,gc) *cp_parser_parenthesized_expression_list
+ (cp_parser *, int, bool, bool, bool *);
+/* Values for the second parameter of cp_parser_parenthesized_expression_list. */
+enum { non_attr = 0, normal_attr = 1, id_attr = 2 };
static void cp_parser_pseudo_destructor_name
(cp_parser *, tree *, tree *);
static tree cp_parser_unary_expression
(cp_token *);
static tree cp_parser_new_expression
(cp_parser *);
-static tree cp_parser_new_placement
+static VEC(tree,gc) *cp_parser_new_placement
(cp_parser *);
static tree cp_parser_new_type_id
(cp_parser *, tree *);
(cp_parser *);
static cp_declarator *cp_parser_direct_new_declarator
(cp_parser *);
-static tree cp_parser_new_initializer
+static VEC(tree,gc) *cp_parser_new_initializer
(cp_parser *);
static tree cp_parser_delete_expression
(cp_parser *);
static tree cp_parser_cast_expression
(cp_parser *, bool, bool, cp_id_kind *);
static tree cp_parser_binary_expression
- (cp_parser *, bool, enum cp_parser_prec, cp_id_kind *);
+ (cp_parser *, bool, bool, enum cp_parser_prec, cp_id_kind *);
static tree cp_parser_question_colon_clause
(cp_parser *, tree);
static tree cp_parser_assignment_expression
(cp_parser *, bool, bool *);
static tree cp_parser_builtin_offsetof
(cp_parser *);
+static tree cp_parser_lambda_expression
+ (cp_parser *);
+static void cp_parser_lambda_introducer
+ (cp_parser *, tree);
+static void cp_parser_lambda_declarator_opt
+ (cp_parser *, tree);
+static void cp_parser_lambda_body
+ (cp_parser *, tree);
/* Statements [gram.stmt.stmt] */
(cp_parser *, bool);
static tree cp_parser_type_id
(cp_parser *);
+static tree cp_parser_template_type_arg
+ (cp_parser *);
+static tree cp_parser_trailing_type_id (cp_parser *);
+static tree cp_parser_type_id_1
+ (cp_parser *, bool, bool);
static void cp_parser_type_specifier_seq
- (cp_parser *, bool, cp_decl_specifier_seq *);
+ (cp_parser *, bool, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause
(cp_parser *);
static tree cp_parser_parameter_declaration_list
(cp_parser *);
static tree cp_parser_asm_clobber_list
(cp_parser *);
+static tree cp_parser_asm_label_list
+ (cp_parser *);
static tree cp_parser_attributes_opt
(cp_parser *);
static tree cp_parser_attribute_list
static bool cp_parser_check_declarator_template_parameters
(cp_parser *, cp_declarator *, location_t);
static bool cp_parser_check_template_parameters
- (cp_parser *, unsigned, location_t);
+ (cp_parser *, unsigned, location_t, cp_declarator *);
static tree cp_parser_simple_cast_expression
(cp_parser *);
static tree cp_parser_global_scope_opt
return (token->type == CPP_STRING ||
token->type == CPP_STRING16 ||
token->type == CPP_STRING32 ||
- token->type == CPP_WSTRING);
+ token->type == CPP_WSTRING ||
+ token->type == CPP_UTF8STRING);
}
/* Returns nonzero if TOKEN is the indicated KEYWORD. */
if (token->type == CPP_PRAGMA)
{
- error ("%H%<#pragma%> is not allowed here", &token->location);
+ error_at (token->location,
+ "%<#pragma%> is not allowed here");
cp_parser_skip_to_pragma_eol (parser, token);
return;
}
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- token->u.value);
+ token->u.value, token->flags);
}
}
if (decl == error_mark_node)
{
if (parser->scope && parser->scope != global_namespace)
- error ("%H%<%E::%E%> has not been declared",
- &location, parser->scope, name);
+ error_at (location, "%<%E::%E%> has not been declared",
+ parser->scope, name);
else if (parser->scope == global_namespace)
- error ("%H%<::%E%> has not been declared", &location, name);
+ error_at (location, "%<::%E%> has not been declared", name);
else if (parser->object_scope
&& !CLASS_TYPE_P (parser->object_scope))
- error ("%Hrequest for member %qE in non-class type %qT",
- &location, name, parser->object_scope);
+ error_at (location, "request for member %qE in non-class type %qT",
+ name, parser->object_scope);
else if (parser->object_scope)
- error ("%H%<%T::%E%> has not been declared",
- &location, parser->object_scope, name);
+ error_at (location, "%<%T::%E%> has not been declared",
+ parser->object_scope, name);
else
- error ("%H%qE has not been declared", &location, name);
+ error_at (location, "%qE has not been declared", name);
}
else if (parser->scope && parser->scope != global_namespace)
- error ("%H%<%E::%E%> %s", &location, parser->scope, name, desired);
+ error_at (location, "%<%E::%E%> %s", parser->scope, name, desired);
else if (parser->scope == global_namespace)
- error ("%H%<::%E%> %s", &location, name, desired);
+ error_at (location, "%<::%E%> %s", name, desired);
else
- error ("%H%qE %s", &location, name, desired);
+ error_at (location, "%qE %s", name, desired);
}
/* If we are parsing tentatively, remember that an error has occurred
cp_parser_check_decl_spec (cp_decl_specifier_seq *decl_specs,
location_t location)
{
- cp_decl_spec ds;
+ int ds;
for (ds = ds_first; ds != ds_last; ++ds)
{
- unsigned count = decl_specs->specs[(int)ds];
+ unsigned count = decl_specs->specs[ds];
if (count < 2)
continue;
/* The "long" specifier is a special case because of "long long". */
if (ds == ds_long)
{
if (count > 2)
- error ("%H%<long long long%> is too long for GCC", &location);
- else if (pedantic && !in_system_header && warn_long_long
- && cxx_dialect == cxx98)
- pedwarn (location, OPT_Wlong_long,
- "ISO C++ 1998 does not support %<long long%>");
+ error_at (location, "%<long long long%> is too long for GCC");
+ else
+ pedwarn_cxx98 (location, OPT_Wlong_long,
+ "ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
{
"explicit",
"friend",
"typedef",
+ "constexpr",
"__complex",
"__thread"
};
- error ("%Hduplicate %qs", &location, decl_spec_names[(int)ds]);
+ error_at (location, "duplicate %qs", decl_spec_names[ds]);
}
}
}
if (declarator
&& declarator->kind == cdk_function)
{
- error ("%Hnew types may not be defined in a return type", &type_location);
+ error_at (type_location,
+ "new types may not be defined in a return type");
inform (type_location,
"(perhaps a semicolon is missing after the definition of %qT)",
type);
if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
{
if (TYPE_P (type))
- error ("%H%qT is not a template", &location, type);
+ error_at (location, "%qT is not a template", type);
else if (TREE_CODE (type) == IDENTIFIER_NODE)
- error ("%H%qE is not a template", &location, type);
+ error_at (location, "%qE is not a template", type);
else
- error ("%Hinvalid template-id", &location);
+ error_at (location, "invalid template-id");
/* Remember the location of the invalid "<". */
if (cp_parser_uncommitted_to_tentative_parse_p (parser))
start = cp_lexer_token_position (parser->lexer, true);
/* 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 ("%Hinvalid use of template-name %qE without an argument list",
- &location, decl);
+ error_at (location,
+ "invalid use of template-name %qE without an argument list",
+ decl);
else if (TREE_CODE (id) == BIT_NOT_EXPR)
- error ("%Hinvalid use of destructor %qD as a type", &location, id);
+ error_at (location, "invalid use of destructor %qD as a type", id);
else if (TREE_CODE (decl) == TYPE_DECL)
/* Something like 'unsigned A a;' */
- error ("%Hinvalid combination of multiple type-specifiers",
- &location);
+ error_at (location, "invalid combination of multiple type-specifiers");
else if (!parser->scope)
{
/* Issue an error message. */
- error ("%H%qE does not name a type", &location, id);
+ error_at (location, "%qE does not name a type", 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:
else if (parser->scope != error_mark_node)
{
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
- error ("%H%qE in namespace %qE does not name a type",
- &location, id, parser->scope);
+ error_at (location, "%qE in namespace %qE does not name a type",
+ id, parser->scope);
+ else if (CLASS_TYPE_P (parser->scope)
+ && constructor_name_p (id, parser->scope))
+ {
+ /* A<T>::A<T>() */
+ error_at (location, "%<%T::%E%> names the constructor, not"
+ " the type", parser->scope, id);
+ if (cp_lexer_next_token_is (parser->lexer, CPP_LESS))
+ error_at (location, "and %qT has no template constructors",
+ parser->scope);
+ }
+ else if (TYPE_P (parser->scope)
+ && dependent_scope_p (parser->scope))
+ error_at (location, "need %<typename%> before %<%T::%E%> because "
+ "%qT is a dependent scope",
+ parser->scope, id, parser->scope);
else if (TYPE_P (parser->scope))
- error ("%H%qE in class %qT does not name a type",
- &location, id, parser->scope);
+ error_at (location, "%qE in class %qT does not name a type",
+ id, parser->scope);
else
gcc_unreachable ();
}
tree id;
cp_token *token = cp_lexer_peek_token (parser->lexer);
+ /* Avoid duplicate error about ambiguous lookup. */
+ if (token->type == CPP_NESTED_NAME_SPECIFIER)
+ {
+ cp_token *next = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (next->type == CPP_NAME && next->ambiguous_p)
+ goto out;
+ }
+
cp_parser_parse_tentatively (parser);
id = cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*template_p=*/NULL,
/*declarator_p=*/true,
/*optional_p=*/false);
- /* After the id-expression, there should be a plain identifier,
- otherwise this is not a simple variable declaration. Also, if
- the scope is dependent, we cannot do much. */
- if (!cp_lexer_next_token_is (parser->lexer, CPP_NAME)
- || (parser->scope && TYPE_P (parser->scope)
- && dependent_type_p (parser->scope))
+ /* If the next token is a (, this is a function with no explicit return
+ type, i.e. constructor, destructor or conversion op. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN)
|| TREE_CODE (id) == TYPE_DECL)
{
cp_parser_abort_tentative_parse (parser);
/* Emit a diagnostic for the invalid type. */
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);
+ out:
+ /* If we aren't in the middle of a declarator (i.e. in a
+ parameter-declaration-clause), skip to the end of the declaration;
+ there's no point in trying to process it. */
+ if (!parser->in_declarator_p)
+ cp_parser_skip_to_end_of_block_or_statement (parser);
return true;
}
{
unsigned paren_depth = 0;
unsigned brace_depth = 0;
+ unsigned square_depth = 0;
if (recovering && !or_comma
&& cp_parser_uncommitted_to_tentative_parse_p (parser))
/* If we've run out of tokens, then there is no closing `)'. */
return 0;
+ /* This is good for lambda expression capture-lists. */
+ case CPP_OPEN_SQUARE:
+ ++square_depth;
+ break;
+ case CPP_CLOSE_SQUARE:
+ if (!square_depth--)
+ return 0;
+ break;
+
case CPP_SEMICOLON:
/* This matches the processing in skip_to_end_of_statement. */
if (!brace_depth)
break;
case CPP_COMMA:
- if (recovering && or_comma && !brace_depth && !paren_depth)
+ if (recovering && or_comma && !brace_depth && !paren_depth
+ && !square_depth)
return -1;
break;
/* Stop if this is an unnested '}', or closes the outermost
nesting level. */
nesting_depth--;
+ if (nesting_depth < 0)
+ return;
if (!nesting_depth)
nesting_depth = -1;
break;
if (type == CPP_STRING)
type = tok->type;
else if (tok->type != CPP_STRING)
- error ("%Hunsupported non-standard concatenation "
- "of string literals", &tok->location);
+ error_at (tok->location,
+ "unsupported non-standard concatenation "
+ "of string literals");
}
obstack_grow (&str_ob, &str, sizeof (cpp_string));
{
default:
case CPP_STRING:
+ case CPP_UTF8STRING:
TREE_TYPE (value) = char_array_type_node;
break;
case CPP_STRING16:
case CPP_WCHAR:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
+ if (TREE_CODE (token->u.value) == FIXED_CST)
+ {
+ error_at (token->location,
+ "fixed-point types not supported in C++");
+ return error_mark_node;
+ }
/* Floating-point literals are only allowed in an integral
constant expression if they are cast to an integral or
enumeration type. */
case CPP_STRING16:
case CPP_STRING32:
case CPP_WSTRING:
+ case CPP_UTF8STRING:
/* ??? Should wide strings be allowed when parser->translate_strings_p
is false (i.e. in attributes)? If not, we can kill the third
argument to cp_parser_string_literal. */
if (!parser->in_function_body
|| parser->in_template_argument_list_p)
{
- error ("%Hstatement-expressions are not allowed outside "
- "functions nor in template-argument lists",
- &token->location);
+ error_at (token->location,
+ "statement-expressions are not allowed outside "
+ "functions nor in template-argument lists");
cp_parser_skip_to_end_of_block_or_statement (parser);
expr = error_mark_node;
}
return expr;
}
+ case CPP_OPEN_SQUARE:
+ if (c_dialect_objc ())
+ /* We have an Objective-C++ message. */
+ return cp_parser_objc_expression (parser);
+ maybe_warn_cpp0x (CPP0X_LAMBDA_EXPR);
+ return cp_parser_lambda_expression (parser);
+
+ case CPP_OBJC_STRING:
+ if (c_dialect_objc ())
+ /* We have an Objective-C++ string literal. */
+ return cp_parser_objc_expression (parser);
+ cp_parser_error (parser, "expected primary-expression");
+ return error_mark_node;
+
case CPP_KEYWORD:
switch (token->keyword)
{
cp_lexer_consume_token (parser->lexer);
return null_node;
+ /* The `nullptr' literal. */
+ case RID_NULLPTR:
+ cp_lexer_consume_token (parser->lexer);
+ return nullptr_node;
+
/* Recognize the `this' keyword. */
case RID_THIS:
cp_lexer_consume_token (parser->lexer);
if (parser->local_variables_forbidden_p)
{
- error ("%H%<this%> may not be used in this context",
- &token->location);
+ error_at (token->location,
+ "%<this%> may not be used in this context");
return error_mark_node;
}
/* Pointers cannot appear in constant-expressions. */
case RID_IS_ENUM:
case RID_IS_POD:
case RID_IS_POLYMORPHIC:
+ case RID_IS_STD_LAYOUT:
+ case RID_IS_TRIVIAL:
case RID_IS_UNION:
return cp_parser_trait_expr (parser, token->keyword);
{
tree ambiguous_decls;
+ /* If we already know that this lookup is ambiguous, then
+ we've already issued an error message; there's no reason
+ to check again. */
+ if (id_expr_token->type == CPP_NAME
+ && id_expr_token->ambiguous_p)
+ {
+ cp_parser_simulate_error (parser);
+ return error_mark_node;
+ }
+
decl = cp_parser_lookup_name (parser, id_expression,
none_type,
template_p,
decl = check_for_out_of_scope_variable (decl);
if (local_variable_p (decl))
{
- error ("%Hlocal variable %qD may not appear in this context",
- &id_expr_token->location, decl);
+ error_at (id_expr_token->location,
+ "local variable %qD may not appear in this context",
+ decl);
return error_mark_node;
}
}
/* Anything else is an error. */
default:
- /* ...unless we have an Objective-C++ message or string literal,
- that is. */
- if (c_dialect_objc ()
- && (token->type == CPP_OPEN_SQUARE
- || token->type == CPP_OBJC_STRING))
- return cp_parser_objc_expression (parser);
-
cp_parser_error (parser, "expected primary-expression");
return error_mark_node;
}
if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("%Hscope %qT before %<~%> is not a class-name",
- &token->location, scope);
+ error_at (token->location,
+ "scope %qT before %<~%> is not a class-name",
+ scope);
cp_parser_simulate_error (parser);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
cp_lexer_consume_token (parser->lexer);
}
gcc_assert (!scope || TYPE_P (scope));
- /* If the name is of the form "X::~X" it's OK. */
+ /* If the name is of the form "X::~X" it's OK even if X is a
+ typedef. */
token = cp_lexer_peek_token (parser->lexer);
if (scope
&& token->type == CPP_NAME
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
- == CPP_OPEN_PAREN)
- && constructor_name_p (token->u.value, scope))
+ != CPP_LESS)
+ && (token->u.value == TYPE_IDENTIFIER (scope)
+ || constructor_name_p (token->u.value, scope)))
{
cp_lexer_consume_token (parser->lexer);
return build_nt (BIT_NOT_EXPR, scope);
}
/* If there was an explicit qualification (S::~T), first look
- in the scope given by the qualification (i.e., S). */
+ in the scope given by the qualification (i.e., S).
+
+ Note: in the calls to cp_parser_class_name below we pass
+ typename_type so that lookup finds the injected-class-name
+ rather than the constructor. */
done = false;
type_decl = NULL_TREE;
if (scope)
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
= cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
- none_type,
+ typename_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
/* We couldn't find a type with this name, so just accept
it and check for a match at instantiation time. */
type_decl = cp_parser_identifier (parser);
- return build_nt (BIT_NOT_EXPR, type_decl);
+ if (type_decl != error_mark_node)
+ type_decl = build_nt (BIT_NOT_EXPR, type_decl);
+ return type_decl;
}
}
/* If an error occurred, assume that the name of the
if (declarator_p && scope && !check_dtor_name (scope, type_decl))
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("%Hdeclaration of %<~%T%> as member of %qT",
- &token->location, type_decl, scope);
+ error_at (token->location,
+ "declaration of %<~%T%> as member of %qT",
+ 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 ("%Htypedef-name %qD used as destructor declarator",
- &token->location, type_decl);
+ error_at (token->location,
+ "typedef-name %qD used as destructor declarator",
+ type_decl);
return build_nt (BIT_NOT_EXPR, TREE_TYPE (type_decl));
}
&ambiguous_decls,
token->location);
if (TREE_CODE (decl) == TEMPLATE_DECL)
- error ("%H%qD used without template parameters",
- &token->location, decl);
+ error_at (token->location,
+ "%qD used without template parameters",
+ decl);
else if (ambiguous_decls)
{
- error ("%Hreference to %qD is ambiguous",
- &token->location, token->u.value);
+ error_at (token->location,
+ "reference to %qD is ambiguous",
+ token->u.value);
print_candidates (ambiguous_decls);
decl = error_mark_node;
}
/* Parse a typedef-name or enum-name. */
scope = cp_parser_nonclass_name (parser);
+
+ /* "If the name found does not designate a namespace or a class,
+ enumeration, or dependent type, the program is ill-formed."
+
+ We cover classes and dependent types above and namespaces below,
+ so this code is only looking for enums. */
+ if (!scope || TREE_CODE (scope) != TYPE_DECL
+ || TREE_CODE (TREE_TYPE (scope)) != ENUMERAL_TYPE)
+ cp_parser_simulate_error (parser);
+
successful_parse_p = cp_parser_parse_definitely (parser);
}
/* If that didn't work, try for a namespace-name. */
/* New types cannot be defined in the cast. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in casts";
+ = G_("types may not be defined in casts");
/* Look for the opening `<'. */
cp_parser_require (parser, CPP_LESS, "%<<%>");
/* 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";
+ = G_("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);
bool is_builtin_constant_p;
bool saved_integral_constant_expression_p = false;
bool saved_non_integral_constant_expression_p = false;
- tree args;
+ VEC(tree,gc) *args;
is_member_access = false;
parser->integral_constant_expression_p = false;
}
args = (cp_parser_parenthesized_expression_list
- (parser, /*is_attribute_list=*/false,
+ (parser, non_attr,
/*cast_p=*/false, /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
if (is_builtin_constant_p)
= saved_non_integral_constant_expression_p;
}
- if (args == error_mark_node)
+ if (args == NULL)
{
postfix_expression = error_mark_node;
break;
"a function call"))
{
postfix_expression = error_mark_node;
+ release_tree_vector (args);
break;
}
koenig_p = false;
- if (idk == CP_ID_KIND_UNQUALIFIED)
+ if (idk == CP_ID_KIND_UNQUALIFIED
+ || idk == CP_ID_KIND_TEMPLATE_ID)
{
if (TREE_CODE (postfix_expression) == IDENTIFIER_NODE)
{
- if (args)
+ if (!VEC_empty (tree, args))
{
koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ if (!any_type_dependent_arguments_p (args))
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
}
else
postfix_expression
/* We do not perform argument-dependent lookup if
normal lookup finds a non-function, in accordance
with the expected resolution of DR 218. */
- else if (args && is_overloaded_fn (postfix_expression))
+ else if (!VEC_empty (tree, args)
+ && is_overloaded_fn (postfix_expression))
{
tree fn = get_first_fn (postfix_expression);
+ fn = STRIP_TEMPLATE (fn);
- if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
- fn = OVL_CURRENT (TREE_OPERAND (fn, 0));
-
- /* Only do argument dependent lookup if regular
- lookup does not find a set of member functions.
- [basic.lookup.koenig]/2a */
- if (!DECL_FUNCTION_MEMBER_P (fn))
+ /* Do not do argument dependent lookup if regular
+ lookup finds a member function or a block-scope
+ function declaration. [basic.lookup.argdep]/3 */
+ if (!DECL_FUNCTION_MEMBER_P (fn)
+ && !DECL_LOCAL_FUNCTION_P (fn))
{
koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ if (!any_type_dependent_arguments_p (args))
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
}
}
}
|| any_type_dependent_arguments_p (args)))
{
postfix_expression
- = build_nt_call_list (postfix_expression, args);
+ = build_nt_call_vec (postfix_expression, args);
+ release_tree_vector (args);
break;
}
{
postfix_expression
= (build_new_method_call
- (instance, fn, args, NULL_TREE,
+ (instance, fn, &args, NULL_TREE,
(idk == CP_ID_KIND_QUALIFIED
? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL),
/*fn_p=*/NULL,
}
else
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
tf_warning_or_error);
|| TREE_CODE (postfix_expression) == MEMBER_REF
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
- (postfix_expression, args));
+ (postfix_expression, &args));
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/true,
koenig_p,
tf_warning_or_error);
else
/* All other function calls. */
postfix_expression
- = finish_call_expr (postfix_expression, args,
+ = finish_call_expr (postfix_expression, &args,
/*disallow_virtual=*/false,
koenig_p,
tf_warning_or_error);
- if (warn_disallowed_functions)
- warn_if_disallowed_function_p (postfix_expression);
-
/* The POSTFIX_EXPRESSION is certainly no longer an id. */
idk = CP_ID_KIND_NONE;
+
+ release_tree_vector (args);
}
break;
/* The type of the POSTFIX_EXPRESSION must be complete. */
if (scope == unknown_type_node)
{
- error ("%H%qE does not have class type", &location, postfix_expression);
+ error_at (location, "%qE does not have class type",
+ postfix_expression);
scope = NULL_TREE;
}
else
TYPE_DECL here. That is invalid code. */
if (TREE_CODE (name) == TYPE_DECL)
{
- error ("%Hinvalid use of %qD", &token->location, name);
+ error_at (token->location, "invalid use of %qD", name);
postfix_expression = error_mark_node;
}
else
ALLOW_EXPANSION_P is true if this expression allows expansion of an
argument pack.
- Returns a TREE_LIST. The TREE_VALUE of each node is a
- representation of an assignment-expression. Note that a TREE_LIST
- is returned even if there is only a single expression in the list.
- error_mark_node is returned if the ( and or ) are
- missing. NULL_TREE is returned on no expressions. The parentheses
- are eaten. IS_ATTRIBUTE_LIST is true if this is really an attribute
- list being parsed. If NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P
- indicates whether or not all of the expressions in the list were
- constant. */
-
-static tree
+ Returns a vector of trees. Each element is a representation of an
+ assignment-expression. NULL is returned if the ( and or ) are
+ missing. An empty, but allocated, vector is returned on no
+ expressions. The parentheses are eaten. IS_ATTRIBUTE_LIST is id_attr
+ if we are parsing an attribute list for an attribute that wants a
+ plain identifier argument, normal_attr for an attribute that wants
+ an expression, or non_attr if we aren't parsing an attribute list. If
+ NON_CONSTANT_P is non-NULL, *NON_CONSTANT_P indicates whether or
+ not all of the expressions in the list were constant. */
+
+static VEC(tree,gc) *
cp_parser_parenthesized_expression_list (cp_parser* parser,
- bool is_attribute_list,
+ int is_attribute_list,
bool cast_p,
bool allow_expansion_p,
bool *non_constant_p)
{
- tree expression_list = NULL_TREE;
- bool fold_expr_p = is_attribute_list;
+ VEC(tree,gc) *expression_list;
+ bool fold_expr_p = is_attribute_list != non_attr;
tree identifier = NULL_TREE;
bool saved_greater_than_is_operator_p;
*non_constant_p = false;
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
- return error_mark_node;
+ return NULL;
+
+ expression_list = make_tree_vector ();
/* Within a parenthesized expression, a `>' token is always
the greater-than operator. */
/* At the beginning of attribute lists, check to see if the
next token is an identifier. */
- if (is_attribute_list
+ if (is_attribute_list == id_attr
&& cp_lexer_peek_token (parser->lexer)->type == CPP_NAME)
{
cp_token *token;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
/* A braced-init-list. */
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expr = cp_parser_braced_list (parser, &expr_non_constant_p);
if (non_constant_p && expr_non_constant_p)
*non_constant_p = true;
expressions to the list, so that we can still tell if
the correct form for a parenthesized expression-list
is found. That gives better errors. */
- expression_list = tree_cons (NULL_TREE, expr, expression_list);
+ VEC_safe_push (tree, gc, expression_list, expr);
if (expr == error_mark_node)
goto skip_comma;
/* After the first item, attribute lists look the same as
expression lists. */
- is_attribute_list = false;
+ is_attribute_list = non_attr;
get_comma:;
/* If the next token isn't a `,', then we are done. */
{
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- return error_mark_node;
+ return NULL;
}
}
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
- /* We built up the list in reverse order so we must reverse it now. */
- expression_list = nreverse (expression_list);
if (identifier)
- expression_list = tree_cons (NULL_TREE, identifier, expression_list);
+ VEC_safe_insert (tree, gc, expression_list, 0, identifier);
return expression_list;
}
{
case INDIRECT_REF:
non_constant_p = "%<*%>";
- expression = build_x_indirect_ref (cast_expression, "unary *",
+ expression = build_x_indirect_ref (cast_expression, RO_UNARY_STAR,
tf_warning_or_error);
break;
cp_parser_new_expression (cp_parser* parser)
{
bool global_scope_p;
- tree placement;
+ VEC(tree,gc) *placement;
tree type;
- tree initializer;
+ VEC(tree,gc) *initializer;
tree nelts;
+ tree ret;
/* Look for the optional `::' operator. */
global_scope_p
placement = cp_parser_new_placement (parser);
/* If that didn't work out, there's no new-placement. */
if (!cp_parser_parse_definitely (parser))
- placement = NULL_TREE;
+ {
+ if (placement != NULL)
+ release_tree_vector (placement);
+ placement = NULL;
+ }
/* If the next token is a `(', then we have a parenthesized
type-id. */
message for this case. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_SQUARE))
{
- error ("%Harray bound forbidden after parenthesized type-id",
- &token->location);
+ error_at (token->location,
+ "array bound forbidden after parenthesized type-id");
inform (token->location,
"try removing the parentheses around the type-id");
cp_parser_direct_new_declarator (parser);
|| cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
initializer = cp_parser_new_initializer (parser);
else
- initializer = NULL_TREE;
+ initializer = NULL;
/* A new-expression may not appear in an integral constant
expression. */
if (cp_parser_non_integral_constant_expression (parser, "%<new%>"))
- return error_mark_node;
+ ret = error_mark_node;
+ else
+ {
+ /* Create a representation of the new-expression. */
+ ret = build_new (&placement, type, nelts, &initializer, global_scope_p,
+ tf_warning_or_error);
+ }
+
+ if (placement != NULL)
+ release_tree_vector (placement);
+ if (initializer != NULL)
+ release_tree_vector (initializer);
- /* Create a representation of the new-expression. */
- return build_new (placement, type, nelts, initializer, global_scope_p,
- tf_warning_or_error);
+ return ret;
}
/* Parse a new-placement.
Returns the same representation as for an expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_placement (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
/* Parse the expression-list. */
expression_list = (cp_parser_parenthesized_expression_list
- (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+ (parser, non_attr, /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
return expression_list;
complete.) */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in a new-type-id";
+ = G_("types may not be defined in a new-type-id");
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ /*is_trailing_return=*/false,
&type_specifier_seq);
/* Restore the old message. */
parser->type_definition_forbidden_message = saved_message;
new_declarator = NULL;
}
- type = groktypename (&type_specifier_seq, new_declarator);
+ type = groktypename (&type_specifier_seq, new_declarator, false);
return type;
}
/*complain=*/true);
if (!expression)
{
- error ("%Hexpression in new-declarator must have integral "
- "or enumeration type", &token->location);
+ error_at (token->location,
+ "expression in new-declarator must have integral "
+ "or enumeration type");
expression = error_mark_node;
}
}
( expression-list [opt] )
braced-init-list
- Returns a representation of the expression-list. If there is no
- expression-list, VOID_ZERO_NODE is returned. */
+ Returns a representation of the expression-list. */
-static tree
+static VEC(tree,gc) *
cp_parser_new_initializer (cp_parser* parser)
{
- tree expression_list;
+ VEC(tree,gc) *expression_list;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
+ tree t;
bool expr_non_constant_p;
- maybe_warn_cpp0x ("extended initializer lists");
- expression_list = cp_parser_braced_list (parser, &expr_non_constant_p);
- CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
- expression_list = build_tree_list (NULL_TREE, expression_list);
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
+ t = cp_parser_braced_list (parser, &expr_non_constant_p);
+ CONSTRUCTOR_IS_DIRECT_INIT (t) = 1;
+ expression_list = make_tree_vector_single (t);
}
else
expression_list = (cp_parser_parenthesized_expression_list
- (parser, false, /*cast_p=*/false, /*allow_expansion_p=*/true,
+ (parser, non_attr, /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
/*non_constant_p=*/NULL));
- if (!expression_list)
- expression_list = void_zero_node;
return expression_list;
}
/* Types may not be defined in a cast. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in casts";
+ = G_("types may not be defined in casts");
/* Consume the `('. */
cp_lexer_consume_token (parser->lexer);
/* A very tricky bit is that `(struct S) { 3 }' is a
return error_mark_node;
/* Perform the cast. */
- expr = build_c_cast (type, expr);
+ expr = build_c_cast (input_location, type, expr);
return expr;
}
else
static tree
cp_parser_binary_expression (cp_parser* parser, bool cast_p,
+ bool no_toplevel_fold_p,
enum cp_parser_prec prec,
cp_id_kind * pidk)
{
&& token->type == CPP_RSHIFT
&& !parser->greater_than_is_operator_p)
{
- warning (OPT_Wc__0x_compat,
- "%H%<>>%> operator will be treated as two right angle brackets in C++0x",
- &token->location);
- warning (OPT_Wc__0x_compat,
- "suggest parentheses around %<>>%> expression");
+ if (warning_at (token->location, OPT_Wc__0x_compat,
+ "%<>>%> operator will be treated as"
+ " two right angle brackets in C++0x"))
+ inform (token->location,
+ "suggest parentheses around %<>>%> expression");
}
new_prec = TOKEN_PRECEDENCE (token);
/* We used the operator token. */
cp_lexer_consume_token (parser->lexer);
+ /* For "false && x" or "true || x", x will never be executed;
+ disable warnings while evaluating it. */
+ if (tree_type == TRUTH_ANDIF_EXPR)
+ c_inhibit_evaluation_warnings += lhs == truthvalue_false_node;
+ else if (tree_type == TRUTH_ORIF_EXPR)
+ c_inhibit_evaluation_warnings += lhs == truthvalue_true_node;
+
/* Extract another operand. It may be the RHS of this expression
or the LHS of a new, higher priority expression. */
rhs = cp_parser_simple_cast_expression (parser);
goto get_rhs;
pop:
+ lookahead_prec = new_prec;
/* If the stack is not empty, we have parsed into LHS the right side
(`4' in the example above) of an expression we had suspended.
We can use the information on the stack to recover the LHS (`3')
lhs_type = sp->lhs_type;
}
+ /* Undo the disabling of warnings done above. */
+ if (tree_type == TRUTH_ANDIF_EXPR)
+ c_inhibit_evaluation_warnings -= lhs == truthvalue_false_node;
+ else if (tree_type == TRUTH_ORIF_EXPR)
+ c_inhibit_evaluation_warnings -= lhs == truthvalue_true_node;
+
overloaded_p = false;
/* ??? Currently we pass lhs_type == ERROR_MARK and rhs_type ==
ERROR_MARK for everything that is not a binary expression.
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);
+ if (no_toplevel_fold_p
+ && lookahead_prec <= prec
+ && sp == stack
+ && TREE_CODE_CLASS (tree_type) == tcc_comparison)
+ lhs = build2 (tree_type, boolean_type_node, lhs, rhs);
+ else
+ lhs = build_x_binary_op (tree_type, lhs, lhs_type, rhs, rhs_type,
+ &overloaded_p, tf_warning_or_error);
lhs_type = tree_type;
/* If the binary operator required the use of an overloaded operator,
cp_lexer_consume_token (parser->lexer);
if (cp_parser_allow_gnu_extensions_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_COLON))
- /* Implicit true clause. */
- expr = NULL_TREE;
+ {
+ /* Implicit true clause. */
+ expr = NULL_TREE;
+ c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_true_node;
+ }
else
- /* Parse the expression. */
- expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ {
+ /* Parse the expression. */
+ c_inhibit_evaluation_warnings += logical_or_expr == truthvalue_false_node;
+ expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ c_inhibit_evaluation_warnings +=
+ ((logical_or_expr == truthvalue_true_node)
+ - (logical_or_expr == truthvalue_false_node));
+ }
/* The next token should be a `:'. */
cp_parser_require (parser, CPP_COLON, "%<:%>");
/* Parse the assignment-expression. */
assignment_expr = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+ c_inhibit_evaluation_warnings -= logical_or_expr == truthvalue_true_node;
/* Build the conditional-expression. */
return build_x_conditional_expr (logical_or_expr,
else
{
/* Parse the binary expressions (logical-or-expression). */
- expr = cp_parser_binary_expression (parser, cast_p, PREC_NOT_OPERATOR, pidk);
+ expr = cp_parser_binary_expression (parser, cast_p, false,
+ PREC_NOT_OPERATOR, pidk);
/* If the next token is a `?' then we're actually looking at a
conditional-expression. */
if (cp_lexer_next_token_is (parser->lexer, CPP_QUERY))
tree rhs = cp_parser_initializer_clause (parser, &non_constant_p);
if (BRACE_ENCLOSED_INITIALIZER_P (rhs))
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
/* An assignment may not appear in a
constant-expression. */
case RID_IS_POLYMORPHIC:
kind = CPTK_IS_POLYMORPHIC;
break;
+ case RID_IS_STD_LAYOUT:
+ kind = CPTK_IS_STD_LAYOUT;
+ break;
+ case RID_IS_TRIVIAL:
+ kind = CPTK_IS_TRIVIAL;
+ break;
case RID_IS_UNION:
kind = CPTK_IS_UNION;
break;
return finish_trait_expr (kind, type1, type2);
}
+/* Lambdas that appear in variable initializer or default argument scope
+ get that in their mangling, so we need to record it. We might as well
+ use the count for function and namespace scopes as well. */
+static GTY(()) tree lambda_scope;
+static GTY(()) int lambda_count;
+typedef struct GTY(()) tree_int
+{
+ tree t;
+ int i;
+} tree_int;
+DEF_VEC_O(tree_int);
+DEF_VEC_ALLOC_O(tree_int,gc);
+static GTY(()) VEC(tree_int,gc) *lambda_scope_stack;
+
+static void
+start_lambda_scope (tree decl)
+{
+ tree_int ti;
+ gcc_assert (decl);
+ /* Once we're inside a function, we ignore other scopes and just push
+ the function again so that popping works properly. */
+ if (current_function_decl && TREE_CODE (decl) != FUNCTION_DECL)
+ decl = current_function_decl;
+ ti.t = lambda_scope;
+ ti.i = lambda_count;
+ VEC_safe_push (tree_int, gc, lambda_scope_stack, &ti);
+ if (lambda_scope != decl)
+ {
+ /* Don't reset the count if we're still in the same function. */
+ lambda_scope = decl;
+ lambda_count = 0;
+ }
+}
+
+static void
+record_lambda_scope (tree lambda)
+{
+ LAMBDA_EXPR_EXTRA_SCOPE (lambda) = lambda_scope;
+ LAMBDA_EXPR_DISCRIMINATOR (lambda) = lambda_count++;
+}
+
+static void
+finish_lambda_scope (void)
+{
+ tree_int *p = VEC_last (tree_int, lambda_scope_stack);
+ if (lambda_scope != p->t)
+ {
+ lambda_scope = p->t;
+ lambda_count = p->i;
+ }
+ VEC_pop (tree_int, lambda_scope_stack);
+}
+
+/* Parse a lambda expression.
+
+ lambda-expression:
+ lambda-introducer lambda-declarator [opt] compound-statement
+
+ Returns a representation of the expression. */
+
+static tree
+cp_parser_lambda_expression (cp_parser* parser)
+{
+ tree lambda_expr = build_lambda_expr ();
+ tree type;
+
+ LAMBDA_EXPR_LOCATION (lambda_expr)
+ = cp_lexer_peek_token (parser->lexer)->location;
+
+ if (cp_unevaluated_operand)
+ error_at (LAMBDA_EXPR_LOCATION (lambda_expr),
+ "lambda-expression in unevaluated context");
+
+ /* We may be in the middle of deferred access check. Disable
+ it now. */
+ push_deferring_access_checks (dk_no_deferred);
+
+ cp_parser_lambda_introducer (parser, lambda_expr);
+
+ type = begin_lambda_type (lambda_expr);
+
+ record_lambda_scope (lambda_expr);
+
+ /* Do this again now that LAMBDA_EXPR_EXTRA_SCOPE is set. */
+ determine_visibility (TYPE_NAME (type));
+
+ /* Now that we've started the type, add the capture fields for any
+ explicit captures. */
+ register_capture_members (LAMBDA_EXPR_CAPTURE_LIST (lambda_expr));
+
+ {
+ /* Inside the class, surrounding template-parameter-lists do not apply. */
+ unsigned int saved_num_template_parameter_lists
+ = parser->num_template_parameter_lists;
+
+ parser->num_template_parameter_lists = 0;
+
+ /* By virtue of defining a local class, a lambda expression has access to
+ the private variables of enclosing classes. */
+
+ cp_parser_lambda_declarator_opt (parser, lambda_expr);
+
+ cp_parser_lambda_body (parser, lambda_expr);
+
+ /* The capture list was built up in reverse order; fix that now. */
+ {
+ tree newlist = NULL_TREE;
+ tree elt, next;
+
+ for (elt = LAMBDA_EXPR_CAPTURE_LIST (lambda_expr);
+ elt; elt = next)
+ {
+ tree field = TREE_PURPOSE (elt);
+ char *buf;
+
+ next = TREE_CHAIN (elt);
+ TREE_CHAIN (elt) = newlist;
+ newlist = elt;
+
+ /* Also add __ to the beginning of the field name so that code
+ outside the lambda body can't see the captured name. We could
+ just remove the name entirely, but this is more useful for
+ debugging. */
+ if (field == LAMBDA_EXPR_THIS_CAPTURE (lambda_expr))
+ /* The 'this' capture already starts with __. */
+ continue;
+
+ buf = (char *) alloca (IDENTIFIER_LENGTH (DECL_NAME (field)) + 3);
+ buf[1] = buf[0] = '_';
+ memcpy (buf + 2, IDENTIFIER_POINTER (DECL_NAME (field)),
+ IDENTIFIER_LENGTH (DECL_NAME (field)) + 1);
+ DECL_NAME (field) = get_identifier (buf);
+ }
+ LAMBDA_EXPR_CAPTURE_LIST (lambda_expr) = newlist;
+ }
+
+ maybe_add_lambda_conv_op (type);
+
+ type = finish_struct (type, /*attributes=*/NULL_TREE);
+
+ parser->num_template_parameter_lists = saved_num_template_parameter_lists;
+ }
+
+ pop_deferring_access_checks ();
+
+ return build_lambda_object (lambda_expr);
+}
+
+/* Parse the beginning of a lambda expression.
+
+ lambda-introducer:
+ [ lambda-capture [opt] ]
+
+ LAMBDA_EXPR is the current representation of the lambda expression. */
+
+static void
+cp_parser_lambda_introducer (cp_parser* parser, tree lambda_expr)
+{
+ /* Need commas after the first capture. */
+ bool first = true;
+
+ /* Eat the leading `['. */
+ cp_parser_require (parser, CPP_OPEN_SQUARE, "%<[%>");
+
+ /* Record default capture mode. "[&" "[=" "[&," "[=," */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_AND)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->type != CPP_NAME)
+ LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_REFERENCE;
+ else if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) = CPLD_COPY;
+
+ if (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda_expr) != CPLD_NONE)
+ {
+ cp_lexer_consume_token (parser->lexer);
+ first = false;
+ }
+
+ while (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_SQUARE))
+ {
+ cp_token* capture_token;
+ tree capture_id;
+ tree capture_init_expr;
+ cp_id_kind idk = CP_ID_KIND_NONE;
+ bool explicit_init_p = false;
+
+ enum capture_kind_type
+ {
+ BY_COPY,
+ BY_REFERENCE
+ };
+ enum capture_kind_type capture_kind = BY_COPY;
+
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ {
+ error ("expected end of capture-list");
+ return;
+ }
+
+ if (first)
+ first = false;
+ else
+ cp_parser_require (parser, CPP_COMMA, "%<,%>");
+
+ /* Possibly capture `this'. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_THIS))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ add_capture (lambda_expr,
+ /*id=*/get_identifier ("__this"),
+ /*initializer=*/finish_this_expr(),
+ /*by_reference_p=*/false,
+ explicit_init_p);
+ continue;
+ }
+
+ /* Remember whether we want to capture as a reference or not. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_AND))
+ {
+ capture_kind = BY_REFERENCE;
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ /* Get the identifier. */
+ capture_token = cp_lexer_peek_token (parser->lexer);
+ capture_id = cp_parser_identifier (parser);
+
+ if (capture_id == error_mark_node)
+ /* Would be nice to have a cp_parser_skip_to_closing_x for general
+ delimiters, but I modified this to stop on unnested ']' as well. It
+ was already changed to stop on unnested '}', so the
+ "closing_parenthesis" name is no more misleading with my change. */
+ {
+ cp_parser_skip_to_closing_parenthesis (parser,
+ /*recovering=*/true,
+ /*or_comma=*/true,
+ /*consume_paren=*/true);
+ break;
+ }
+
+ /* Find the initializer for this capture. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EQ))
+ {
+ /* An explicit expression exists. */
+ cp_lexer_consume_token (parser->lexer);
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C++ does not allow initializers "
+ "in lambda expression capture lists");
+ capture_init_expr = cp_parser_assignment_expression (parser,
+ /*cast_p=*/true,
+ &idk);
+ explicit_init_p = true;
+ }
+ else
+ {
+ const char* error_msg;
+
+ /* Turn the identifier into an id-expression. */
+ capture_init_expr
+ = cp_parser_lookup_name
+ (parser,
+ capture_id,
+ none_type,
+ /*is_template=*/false,
+ /*is_namespace=*/false,
+ /*check_dependency=*/true,
+ /*ambiguous_decls=*/NULL,
+ capture_token->location);
+
+ capture_init_expr
+ = finish_id_expression
+ (capture_id,
+ capture_init_expr,
+ parser->scope,
+ &idk,
+ /*integral_constant_expression_p=*/false,
+ /*allow_non_integral_constant_expression_p=*/false,
+ /*non_integral_constant_expression_p=*/NULL,
+ /*template_p=*/false,
+ /*done=*/true,
+ /*address_p=*/false,
+ /*template_arg_p=*/false,
+ &error_msg,
+ capture_token->location);
+ }
+
+ if (TREE_CODE (capture_init_expr) == IDENTIFIER_NODE)
+ capture_init_expr
+ = unqualified_name_lookup_error (capture_init_expr);
+
+ add_capture (lambda_expr,
+ capture_id,
+ capture_init_expr,
+ /*by_reference_p=*/capture_kind == BY_REFERENCE,
+ explicit_init_p);
+ }
+
+ cp_parser_require (parser, CPP_CLOSE_SQUARE, "%<]%>");
+}
+
+/* Parse the (optional) middle of a lambda expression.
+
+ lambda-declarator:
+ ( parameter-declaration-clause [opt] )
+ attribute-specifier [opt]
+ mutable [opt]
+ exception-specification [opt]
+ lambda-return-type-clause [opt]
+
+ LAMBDA_EXPR is the current representation of the lambda expression. */
+
+static void
+cp_parser_lambda_declarator_opt (cp_parser* parser, tree lambda_expr)
+{
+ /* 5.1.1.4 of the standard says:
+ If a lambda-expression does not include a lambda-declarator, it is as if
+ the lambda-declarator were ().
+ This means an empty parameter list, no attributes, and no exception
+ specification. */
+ tree param_list = void_list_node;
+ tree attributes = NULL_TREE;
+ tree exception_spec = NULL_TREE;
+ tree t;
+
+ /* The lambda-declarator is optional, but must begin with an opening
+ parenthesis if present. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
+ {
+ cp_lexer_consume_token (parser->lexer);
+
+ begin_scope (sk_function_parms, /*entity=*/NULL_TREE);
+
+ /* Parse parameters. */
+ param_list = cp_parser_parameter_declaration_clause (parser);
+
+ /* Default arguments shall not be specified in the
+ parameter-declaration-clause of a lambda-declarator. */
+ for (t = param_list; t; t = TREE_CHAIN (t))
+ if (TREE_PURPOSE (t))
+ pedwarn (DECL_SOURCE_LOCATION (TREE_VALUE (t)), OPT_pedantic,
+ "default argument specified for lambda parameter");
+
+ cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
+
+ attributes = cp_parser_attributes_opt (parser);
+
+ /* Parse optional `mutable' keyword. */
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_MUTABLE))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ LAMBDA_EXPR_MUTABLE_P (lambda_expr) = 1;
+ }
+
+ /* Parse optional exception specification. */
+ exception_spec = cp_parser_exception_specification_opt (parser);
+
+ /* Parse optional trailing return type. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_DEREF))
+ {
+ cp_lexer_consume_token (parser->lexer);
+ LAMBDA_EXPR_RETURN_TYPE (lambda_expr) = cp_parser_type_id (parser);
+ }
+
+ /* The function parameters must be in scope all the way until after the
+ trailing-return-type in case of decltype. */
+ for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
+ pop_binding (DECL_NAME (t), t);
+
+ leave_scope ();
+ }
+
+ /* Create the function call operator.
+
+ Messing with declarators like this is no uglier than building up the
+ FUNCTION_DECL by hand, and this is less likely to get out of sync with
+ other code. */
+ {
+ cp_decl_specifier_seq return_type_specs;
+ cp_declarator* declarator;
+ tree fco;
+ int quals;
+ void *p;
+
+ clear_decl_specs (&return_type_specs);
+ if (LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+ return_type_specs.type = LAMBDA_EXPR_RETURN_TYPE (lambda_expr);
+ else
+ /* Maybe we will deduce the return type later, but we can use void
+ as a placeholder return type anyways. */
+ return_type_specs.type = void_type_node;
+
+ p = obstack_alloc (&declarator_obstack, 0);
+
+ declarator = make_id_declarator (NULL_TREE, ansi_opname (CALL_EXPR),
+ sfk_none);
+
+ quals = (LAMBDA_EXPR_MUTABLE_P (lambda_expr)
+ ? TYPE_UNQUALIFIED : TYPE_QUAL_CONST);
+ declarator = make_call_declarator (declarator, param_list, quals,
+ exception_spec,
+ /*late_return_type=*/NULL_TREE);
+ declarator->id_loc = LAMBDA_EXPR_LOCATION (lambda_expr);
+
+ fco = grokmethod (&return_type_specs,
+ declarator,
+ attributes);
+ DECL_INITIALIZED_IN_CLASS_P (fco) = 1;
+ DECL_ARTIFICIAL (fco) = 1;
+
+ finish_member_declaration (fco);
+
+ obstack_free (&declarator_obstack, p);
+ }
+}
+
+/* Parse the body of a lambda expression, which is simply
+
+ compound-statement
+
+ but which requires special handling.
+ LAMBDA_EXPR is the current representation of the lambda expression. */
+
+static void
+cp_parser_lambda_body (cp_parser* parser, tree lambda_expr)
+{
+ bool nested = (current_function_decl != NULL_TREE);
+ if (nested)
+ push_function_context ();
+
+ /* Finish the function call operator
+ - class_specifier
+ + late_parsing_for_member
+ + function_definition_after_declarator
+ + ctor_initializer_opt_and_function_body */
+ {
+ tree fco = lambda_function (lambda_expr);
+ tree body;
+ bool done = false;
+
+ /* Let the front end know that we are going to be defining this
+ function. */
+ start_preparsed_function (fco,
+ NULL_TREE,
+ SF_PRE_PARSED | SF_INCLASS_INLINE);
+
+ start_lambda_scope (fco);
+ body = begin_function_body ();
+
+ /* 5.1.1.4 of the standard says:
+ If a lambda-expression does not include a trailing-return-type, it
+ is as if the trailing-return-type denotes the following type:
+ * if the compound-statement is of the form
+ { return attribute-specifier [opt] expression ; }
+ the type of the returned expression after lvalue-to-rvalue
+ conversion (_conv.lval_ 4.1), array-to-pointer conversion
+ (_conv.array_ 4.2), and function-to-pointer conversion
+ (_conv.func_ 4.3);
+ * otherwise, void. */
+
+ /* In a lambda that has neither a lambda-return-type-clause
+ nor a deducible form, errors should be reported for return statements
+ in the body. Since we used void as the placeholder return type, parsing
+ the body as usual will give such desired behavior. */
+ if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr)
+ && cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE)
+ && cp_lexer_peek_nth_token (parser->lexer, 2)->keyword == RID_RETURN
+ && cp_lexer_peek_nth_token (parser->lexer, 3)->type != CPP_SEMICOLON)
+ {
+ tree compound_stmt;
+ tree expr = NULL_TREE;
+ cp_id_kind idk = CP_ID_KIND_NONE;
+
+ /* Parse tentatively in case there's more after the initial return
+ statement. */
+ cp_parser_parse_tentatively (parser);
+
+ cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+ cp_parser_require_keyword (parser, RID_RETURN, "%<return%>");
+
+ expr = cp_parser_expression (parser, /*cast_p=*/false, &idk);
+
+ cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
+ cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+
+ if (cp_parser_parse_definitely (parser))
+ {
+ apply_lambda_return_type (lambda_expr, lambda_return_type (expr));
+
+ compound_stmt = begin_compound_stmt (0);
+ /* Will get error here if type not deduced yet. */
+ finish_return_stmt (expr);
+ finish_compound_stmt (compound_stmt);
+
+ done = true;
+ }
+ }
+
+ if (!done)
+ {
+ if (!LAMBDA_EXPR_RETURN_TYPE (lambda_expr))
+ LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = true;
+ /* TODO: does begin_compound_stmt want BCS_FN_BODY?
+ cp_parser_compound_stmt does not pass it. */
+ cp_parser_function_body (parser);
+ LAMBDA_EXPR_DEDUCE_RETURN_TYPE_P (lambda_expr) = false;
+ }
+
+ finish_function_body (body);
+ finish_lambda_scope ();
+
+ /* Finish the function and generate code for it if necessary. */
+ expand_or_defer_fn (finish_function (/*inline*/2));
+ }
+
+ if (nested)
+ pop_function_context();
+}
+
/* Statements [gram.stmt.stmt] */
/* Parse a statement.
cp_parser_label_for_labeled_statement (cp_parser* parser)
{
cp_token *token;
+ tree label = NULL_TREE;
/* The next token should be an identifier. */
token = cp_lexer_peek_token (parser->lexer);
expr_hi = NULL_TREE;
if (parser->in_switch_statement_p)
- finish_case_label (expr, expr_hi);
+ finish_case_label (token->location, expr, expr_hi);
else
- error ("%Hcase label %qE not within a switch statement",
- &token->location, expr);
+ error_at (token->location,
+ "case label %qE not within a switch statement",
+ expr);
}
break;
cp_lexer_consume_token (parser->lexer);
if (parser->in_switch_statement_p)
- finish_case_label (NULL_TREE, NULL_TREE);
+ finish_case_label (token->location, NULL_TREE, NULL_TREE);
else
- error ("%Hcase label not within a switch statement", &token->location);
+ error_at (token->location, "case label not within a switch statement");
break;
default:
/* Anything else must be an ordinary label. */
- finish_label_stmt (cp_parser_identifier (parser));
+ label = finish_label_stmt (cp_parser_identifier (parser));
break;
}
/* Require the `:' token. */
cp_parser_require (parser, CPP_COLON, "%<:%>");
+
+ /* An ordinary label may optionally be followed by attributes.
+ However, this is only permitted if the attributes are then
+ followed by a semicolon. This is because, for backward
+ compatibility, when parsing
+ lab: __attribute__ ((unused)) int i;
+ we want the attribute to attach to "i", not "lab". */
+ if (label != NULL_TREE
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
+ {
+ tree attrs;
+
+ cp_parser_parse_tentatively (parser);
+ attrs = cp_parser_attributes_opt (parser);
+ if (attrs == NULL_TREE
+ || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
+ cp_parser_abort_tentative_parse (parser);
+ else if (!cp_parser_parse_definitely (parser))
+ ;
+ else
+ cplus_decl_attributes (&label, attrs, 0);
+ }
}
/* Parse an expression-statement.
cp_parser_expression_statement (cp_parser* parser, tree in_statement_expr)
{
tree statement = NULL_TREE;
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
/* If the next token is a ';', then there is no expression
statement. */
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
statement = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+ /* Give a helpful message for "A<T>::type t;" and the like. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
+ && !cp_parser_uncommitted_to_tentative_parse_p (parser))
+ {
+ if (TREE_CODE (statement) == SCOPE_REF)
+ error_at (token->location, "need %<typename%> before %qE because "
+ "%qT is a dependent scope",
+ statement, TREE_OPERAND (statement, 0));
+ else if (is_overloaded_fn (statement)
+ && DECL_CONSTRUCTOR_P (get_first_fn (statement)))
+ {
+ /* A::A a; */
+ tree fn = get_first_fn (statement);
+ error_at (token->location,
+ "%<%T::%D%> names the constructor, not the type",
+ DECL_CONTEXT (fn), DECL_NAME (fn));
+ }
+ }
+
/* Consume the final `;'. */
cp_parser_consume_semicolon_at_end_of_statement (parser);
else
{
token = cp_lexer_consume_token (parser->lexer);
- error ("%H%<else%> without a previous %<if%>", &token->location);
+ error_at (token->location, "%<else%> without a previous %<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 ());
+ add_stmt (build_empty_stmt (loc));
cp_lexer_consume_token (parser->lexer);
if (!cp_lexer_next_token_is_keyword (parser->lexer, RID_ELSE))
warning_at (loc, OPT_Wempty_body, "suggest braces around "
/* Parse the else-clause. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
{
- warning_at (cp_lexer_peek_token (parser->lexer)->location,
+ location_t loc;
+ loc = cp_lexer_peek_token (parser->lexer)->location;
+ warning_at (loc,
OPT_Wempty_body, "suggest braces around "
"empty body in an %<else%> statement");
- add_stmt (build_empty_stmt ());
+ add_stmt (build_empty_stmt (loc));
cp_lexer_consume_token (parser->lexer);
}
else
statement which does have an else clause. We warn
about the potential ambiguity. */
if (nested_if)
- warning (OPT_Wparentheses,
- ("%Hsuggest explicit braces "
- "to avoid ambiguous %<else%>"),
- EXPR_LOCUS (statement));
+ warning_at (EXPR_LOCATION (statement), OPT_Wparentheses,
+ "suggest explicit braces to avoid ambiguous"
+ " %<else%>");
}
/* Now we're all done with the if-statement. */
condition. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in conditions";
+ = G_("types may not be defined in conditions");
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition==*/true,
+ cp_parser_type_specifier_seq (parser, /*is_declaration==*/true,
+ /*is_trailing_return=*/false,
&type_specifiers);
/* Restore the saved message. */
parser->type_definition_forbidden_message = saved_message;
initializer = cp_parser_initializer_clause (parser, &non_constant_p);
}
if (BRACE_ENCLOSED_INITIALIZER_P (initializer))
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
if (!non_constant_p)
initializer = fold_non_dependent_expr (initializer);
return;
}
- cp_parser_expression_statement (parser, false);
+ cp_parser_expression_statement (parser, NULL_TREE);
}
/* Parse a jump-statement.
switch (in_statement)
{
case 0:
- error ("%Hbreak statement not within loop or switch", &token->location);
+ error_at (token->location, "break statement not within loop or switch");
break;
default:
gcc_assert ((in_statement & IN_SWITCH_STMT)
statement = finish_break_stmt ();
break;
case IN_OMP_BLOCK:
- error ("%Hinvalid exit from OpenMP structured block", &token->location);
+ error_at (token->location, "invalid exit from OpenMP structured block");
break;
case IN_OMP_FOR:
- error ("%Hbreak statement used with OpenMP for loop", &token->location);
+ error_at (token->location, "break statement used with OpenMP for loop");
break;
}
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
switch (parser->in_statement & ~(IN_SWITCH_STMT | IN_IF_STMT))
{
case 0:
- error ("%Hcontinue statement not within a loop", &token->location);
+ error_at (token->location, "continue statement not within a loop");
break;
case IN_ITERATION_STMT:
case IN_OMP_FOR:
statement = finish_continue_stmt ();
break;
case IN_OMP_BLOCK:
- error ("%Hinvalid exit from OpenMP structured block", &token->location);
+ error_at (token->location, "invalid exit from OpenMP structured block");
break;
default:
gcc_unreachable ();
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expr = cp_parser_braced_list (parser, &expr_non_constant_p);
}
else if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
/* Mark if () ; with a special NOP_EXPR. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer);
- statement = add_stmt (build_empty_stmt ());
+ statement = add_stmt (build_empty_stmt (loc));
}
/* if a compound is opened, we simply parse the statement directly. */
else if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
else if (token1->keyword == RID_LABEL)
{
cp_lexer_consume_token (parser->lexer);
- error ("%H%<__label__%> not at the beginning of a block", &token1->location);
+ error_at (token1->location, "%<__label__%> not at the beginning of a block");
cp_parser_skip_to_end_of_statement (parser);
/* If the next token is now a `;', consume it. */
if (cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON))
T t;
where "T" should name a type -- but does not. */
- if (!decl_specifiers.type
+ if (!decl_specifiers.any_type_specifiers_p
&& cp_parser_parse_and_diagnose_invalid_type_name (parser))
{
/* If parsing tentatively, we should commit; we really are
if (cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- error ("%Hmixing declarations and function-definitions is forbidden",
- &token->location);
+ error_at (token->location,
+ "mixing"
+ " declarations and function-definitions is forbidden");
}
/* Otherwise, we're done with the list of declarators. */
else
switch (token->keyword)
{
/* decl-specifier:
- friend */
+ friend
+ constexpr */
case RID_FRIEND:
if (!at_class_scope_p ())
{
- error ("%H%<friend%> used outside of class", &token->location);
+ error_at (token->location, "%<friend%> used outside of class");
cp_lexer_purge_token (parser->lexer);
}
else
}
break;
+ case RID_CONSTEXPR:
+ ++decl_specs->specs[(int) ds_constexpr];
+ cp_lexer_consume_token (parser->lexer);
+ break;
+
/* function-specifier:
inline
virtual
/* Complain about `auto' as a storage specifier, if
we're complaining about C++0x compatibility. */
- warning
- (OPT_Wc__0x_compat,
- "%H%<auto%> will change meaning in C++0x; please remove it",
- &token->location);
+ warning_at (token->location, OPT_Wc__0x_compat, "%<auto%>"
+ " will change meaning in C++0x; please remove it");
/* Set the storage class anyway. */
cp_parser_set_storage_class (parser, decl_specs, RID_AUTO,
{
constructor_possible_p = false;
found_decl_spec = true;
+ if (!is_cv_qualifier)
+ decl_specs->any_type_specifiers_p = true;
}
}
/* Don't allow a friend specifier with a class definition. */
if (decl_specs->specs[(int) ds_friend] != 0
&& (*declares_class_or_enum & 2))
- error ("%Hclass definition may not be declared a friend",
- &start_token->location);
+ error_at (start_token->location,
+ "class definition may not be declared a friend");
}
/* Parse an (optional) storage-class-specifier.
A member function template shall not be virtual. */
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
- error ("%Htemplates may not be %<virtual%>", &token->location);
+ error_at (token->location, "templates may not be %<virtual%>");
else if (decl_specs)
++decl_specs->specs[(int) ds_virtual];
break;
/* And create the new one. */
parser->type_definition_forbidden_message
- = "types may not be defined in %<decltype%> expressions";
+ = G_("types may not be defined in %<decltype%> expressions");
/* The restrictions on constant-expressions do not apply inside
decltype expressions. */
parser->integral_constant_expression_p = false;
/* Do not actually evaluate the expression. */
- ++skip_evaluation;
+ ++cp_unevaluated_operand;
+
+ /* Do not warn about problems with the expression. */
+ ++c_inhibit_evaluation_warnings;
/* Parse the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
cp_parser_parse_definitely (parser);
else
{
+ bool saved_greater_than_is_operator_p;
+
/* Abort our attempt to parse an id-expression or member access
expression. */
cp_parser_abort_tentative_parse (parser);
+ /* Within a parenthesized expression, a `>' token is always
+ the greater-than operator. */
+ saved_greater_than_is_operator_p
+ = parser->greater_than_is_operator_p;
+ parser->greater_than_is_operator_p = true;
+
/* Parse a full expression. */
expr = cp_parser_expression (parser, /*cast_p=*/false, NULL);
+
+ /* The `>' token might be the end of a template-id or
+ template-parameter-list now. */
+ parser->greater_than_is_operator_p
+ = saved_greater_than_is_operator_p;
}
/* Go back to evaluating expressions. */
- --skip_evaluation;
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
/* Restore the old message and the integral constant expression
flags. */
/* Parse the attributes. */
attributes = cp_parser_attributes_opt (parser);
/* Parse the type-specifiers. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ /*is_trailing_return=*/false,
&type_specifiers);
/* If that didn't work, stop. */
if (type_specifiers.type == error_mark_node)
/* Let the semantic analysis code know that we are starting the
mem-initializer-list. */
if (!DECL_CONSTRUCTOR_P (current_function_decl))
- error ("%Honly constructors take base initializers",
- &token->location);
+ error_at (token->location,
+ "only constructors take base initializers");
/* Loop through the list. */
while (true)
if (mem_initializer != error_mark_node
&& !TYPE_P (TREE_PURPOSE (mem_initializer)))
{
- error ("%Hcannot expand initializer for member %<%D%>",
- &token->location, TREE_PURPOSE (mem_initializer));
+ error_at (token->location,
+ "cannot expand initializer for member %<%D%>",
+ TREE_PURPOSE (mem_initializer));
mem_initializer = error_mark_node;
}
mem_initializer_id = NULL_TREE;
}
else
- mem_initializer_id = cp_parser_mem_initializer_id (parser);
+ {
+ mem_initializer_id = cp_parser_mem_initializer_id (parser);
+ if (mem_initializer_id == error_mark_node)
+ return mem_initializer_id;
+ }
member = expand_member_init (mem_initializer_id);
if (member && !DECL_P (member))
in_base_initializer = 1;
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
bool expr_non_constant_p;
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_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);
+ {
+ VEC(tree,gc)* vec;
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ return error_mark_node;
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
+
if (expression_list == error_mark_node)
return error_mark_node;
if (!expression_list)
/* `typename' is not allowed in this context ([temp.res]). */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TYPENAME))
{
- error ("%Hkeyword %<typename%> not allowed in this context (a qualified "
- "member initializer is implicitly a type)",
- &token->location);
+ error_at (token->location,
+ "keyword %<typename%> not allowed in this context (a qualified "
+ "member initializer is implicitly a type)");
cp_lexer_consume_token (parser->lexer);
}
/* Look for the optional `::' operator. */
return cp_parser_class_name (parser,
/*typename_keyword_p=*/true,
/*template_keyword_p=*/template_p,
- none_type,
+ typename_type,
/*check_dependency_p=*/true,
/*class_head_p=*/false,
/*is_declaration=*/true);
tree parameter;
bool is_non_type;
bool is_parameter_pack;
+ location_t parm_loc;
/* Parse the template-parameter. */
+ parm_loc = cp_lexer_peek_token (parser->lexer)->location;
parameter = cp_parser_template_parameter (parser,
&is_non_type,
&is_parameter_pack);
/* Add it to the list. */
if (parameter != error_mark_node)
parameter_list = process_template_parm (parameter_list,
+ parm_loc,
parameter,
is_non_type,
is_parameter_pack);
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
- error ("%Htemplate parameter pack %qD cannot have a default argument",
- &start_token->location, id_declarator->u.id.unqualified_name);
+ error_at (start_token->location,
+ "template parameter pack %qD cannot have a default argument",
+ id_declarator->u.id.unqualified_name);
else
- error ("%Htemplate parameter pack cannot have a default argument",
- &start_token->location);
+ error_at (start_token->location,
+ "template parameter pack cannot have a default argument");
/* Parse the default argument, but throw away the result. */
cp_parser_default_argument (parser, /*template_parm_p=*/true);
parm = grokdeclarator (parameter_declarator->declarator,
¶meter_declarator->decl_specifiers,
- PARM, /*initialized=*/0,
+ TPARM, /*initialized=*/0,
/*attrlist=*/NULL);
if (parm == error_mark_node)
return error_mark_node;
if (*is_parameter_pack)
{
if (identifier)
- error ("%Htemplate parameter pack %qD cannot have a "
- "default argument", &token->location, identifier);
+ error_at (token->location,
+ "template parameter pack %qD cannot have a "
+ "default argument", identifier);
else
- error ("%Htemplate parameter packs cannot have "
- "default arguments", &token->location);
+ error_at (token->location,
+ "template parameter packs cannot have "
+ "default arguments");
default_argument = NULL_TREE;
}
pop_deferring_access_checks ();
case RID_TEMPLATE:
{
- tree parameter_list;
tree identifier;
tree default_argument;
/* Look for the `<'. */
cp_parser_require (parser, CPP_LESS, "%<<%>");
/* Parse the template-parameter-list. */
- parameter_list = cp_parser_template_parameter_list (parser);
+ cp_parser_template_parameter_list (parser);
/* Look for the `>'. */
cp_parser_require (parser, CPP_GREATER, "%<>%>");
/* Look for the `class' keyword. */
if (*is_parameter_pack)
{
if (identifier)
- error ("%Htemplate parameter pack %qD cannot "
- "have a default argument",
- &token->location, identifier);
+ error_at (token->location,
+ "template parameter pack %qD cannot "
+ "have a default argument",
+ identifier);
else
- error ("%Htemplate parameter packs cannot "
- "have default arguments",
- &token->location);
+ error_at (token->location, "template parameter packs cannot "
+ "have default arguments");
default_argument = NULL_TREE;
}
pop_deferring_access_checks ();
cp_token_position start_of_id = 0;
deferred_access_check *chk;
VEC (deferred_access_check,gc) *access_check;
- cp_token *next_token = NULL, *next_token_2 = NULL, *token = NULL;
+ cp_token *next_token = NULL, *next_token_2 = NULL;
bool is_identifier;
/* If the next token corresponds to a template-id, there is no need
/* Parse the template-name. */
is_identifier = false;
- token = cp_lexer_peek_token (parser->lexer);
templ = cp_parser_template_name (parser, template_keyword_p,
check_dependency_p,
is_declaration,
user, as opposed to simply marking the tentative parse as
failed? */
if (cp_parser_error_occurred (parser) && template_id != error_mark_node)
- error ("%Hparse error in template argument list",
- &token->location);
+ error_at (token->location, "parse error in template argument list");
}
pop_deferring_access_checks ();
&& !template_keyword_p
&& parser->scope && TYPE_P (parser->scope)
&& check_dependency_p
- && dependent_type_p (parser->scope)
+ && dependent_scope_p (parser->scope)
/* Do not do this for dtors (or ctors), since they never
need the template keyword before their name. */
&& !constructor_name_p (identifier, parser->scope))
cp_token_position start = 0;
/* Explain what went wrong. */
- error ("%Hnon-template %qD used as template",
- &token->location, identifier);
- inform (input_location, "use %<%T::template %D%> to indicate that it is a template",
+ error_at (token->location, "non-template %qD used as template",
+ identifier);
+ inform (token->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))
/* Look up the name. */
decl = cp_parser_lookup_name (parser, identifier,
none_type,
- /*is_template=*/false,
+ /*is_template=*/true,
/*is_namespace=*/false,
check_dependency_p,
/*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. */
if (TREE_CODE (decl) == TEMPLATE_DECL)
argument pack. */
if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
+ if (argument == error_mark_node)
+ {
+ cp_token *token = cp_lexer_peek_token (parser->lexer);
+ error_at (token->location,
+ "expected parameter pack before %<...%>");
+ }
/* Consume the `...' token. */
cp_lexer_consume_token (parser->lexer);
parser->non_integral_constant_expression_p = saved_non_ice_p;
parser->integral_constant_expression_p = saved_ice_p;
parser->in_template_argument_list_p = saved_in_template_argument_list_p;
+#ifdef ENABLE_CHECKING
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT (vec, TREE_VEC_LENGTH (vec));
+#endif
return vec;
}
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
- argument = cp_parser_type_id (parser);
+ argument = cp_parser_template_type_arg (parser);
/* If there was no error parsing the type-id but the next token is a
'>>', our behavior depends on which dialect of C++ we're
parsing. In C++98, we probably found a typo for '> >'. But there
cp_parser_abort_tentative_parse (parser);
else
{
+ tree probe;
+
if (TREE_CODE (argument) == INDIRECT_REF)
{
gcc_assert (REFERENCE_REF_P (argument));
argument = TREE_OPERAND (argument, 0);
}
- if (TREE_CODE (argument) == VAR_DECL)
+ /* If we're in a template, we represent a qualified-id referring
+ to a static data member as a SCOPE_REF even if the scope isn't
+ dependent so that we can check access control later. */
+ probe = argument;
+ if (TREE_CODE (probe) == SCOPE_REF)
+ probe = TREE_OPERAND (probe, 1);
+ if (TREE_CODE (probe) == VAR_DECL)
{
/* A variable without external linkage might still be a
valid constant-expression, so no error is issued here
if the external-linkage check fails. */
- if (!address_p && !DECL_EXTERNAL_LINKAGE_P (argument))
+ if (!address_p && !DECL_EXTERNAL_LINKAGE_P (probe))
cp_parser_simulate_error (parser);
}
else if (is_overloaded_fn (argument))
was the only alternative that matched (albeit with a '>' after
it). We can assume it's just a typo from the user, and a
diagnostic will then be issued. */
- return cp_parser_type_id (parser);
+ return cp_parser_template_type_arg (parser);
}
/* Parse an explicit-instantiation.
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. */
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,
linkage. */
if (current_lang_name == lang_name_c)
{
- error ("%Htemplate specialization with C linkage", &token->location);
+ error_at (token->location, "template specialization with C linkage");
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
if (!begin_specialization ())
{
end_specialization ();
- cp_parser_skip_to_end_of_block_or_statement (parser);
return;
}
switch (keyword)
{
case RID_ENUM:
+ if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+ goto elaborated_type_specifier;
+
/* Look for the enum-specifier. */
type_spec = cp_parser_enum_specifier (parser);
/* If that worked, we're done. */
case RID_CLASS:
case RID_STRUCT:
case RID_UNION:
+ if ((flags & CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS))
+ goto elaborated_type_specifier;
+
/* Parse tentatively so that we can back up if we don't find a
class-specifier. */
cp_parser_parse_tentatively (parser);
/* Look for the class-specifier. */
type_spec = cp_parser_class_specifier (parser);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
break;
case RID_AUTO:
- maybe_warn_cpp0x ("C++0x auto");
+ maybe_warn_cpp0x (CPP0X_AUTO);
type = make_auto ();
break;
/* If the type-specifier was for a built-in type, we're done. */
if (type)
{
- tree id;
-
/* Record the type. */
if (decl_specs
&& (token->keyword != RID_SIGNED
decl_specs->any_specifiers_p = true;
/* Consume the token. */
- id = cp_lexer_consume_token (parser->lexer)->u.value;
+ cp_lexer_consume_token (parser->lexer);
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought
tree identifier;
tree type = NULL_TREE;
tree attributes = NULL_TREE;
+ tree globalscope;
cp_token *token = NULL;
/* See if we're looking at the `enum' keyword. */
|| cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
{
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
/* Consume the `struct' or `class'. */
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
/* Remember that it's a `typename' type. */
tag_type = typename_type;
- /* The `typename' keyword is only allowed in templates. */
- if (!processing_template_decl)
- permerror (input_location, "using %<typename%> outside of template");
}
/* Otherwise it must be a class-key. */
else
}
/* Look for the `::' operator. */
- cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false);
+ globalscope = cp_parser_global_scope_opt (parser,
+ /*current_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
- if (tag_type == typename_type)
+ if (tag_type == typename_type && !globalscope)
{
if (!cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/true,
type = make_typename_type (parser->scope, decl,
typename_type,
/*complain=*/tf_error);
- else
+ /* If the `typename' keyword is in effect and DECL is not a type
+ decl. Then type is non existant. */
+ else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
+ type = NULL_TREE;
+ else
type = TREE_TYPE (decl);
}
there were no qualifying templates. */
if (!cp_parser_check_template_parameters (parser,
/*num_templates=*/0,
- token->location))
+ token->location,
+ /*declarator=*/NULL))
return error_mark_node;
type = xref_tag (tag_type, identifier, ts, template_p);
}
|| cp_lexer_next_token_is_keyword (parser->lexer, RID_STRUCT))
{
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
/* Consume the `struct' or `class' token. */
cp_lexer_consume_token (parser->lexer);
else
identifier = make_anon_name ();
- /* Check for the `:' that denotes a specified underlying type in C++0x. */
+ /* Check for the `:' that denotes a specified underlying type in C++0x.
+ Note that a ':' could also indicate a bitfield width, however. */
if (cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
cp_decl_specifier_seq type_specifiers;
+ /* Consume the `:'. */
+ cp_lexer_consume_token (parser->lexer);
+
+ /* Parse the type-specifier-seq. */
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ /*is_trailing_return=*/false,
+ &type_specifiers);
+
/* At this point this is surely not elaborated type specifier. */
if (!cp_parser_parse_definitely (parser))
return NULL_TREE;
if (cxx_dialect == cxx98)
- maybe_warn_cpp0x ("scoped enums");
-
- /* Consume the `:'. */
- cp_lexer_consume_token (parser->lexer);
+ maybe_warn_cpp0x (CPP0X_SCOPED_ENUMS);
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)
{
if (cp_parser_allow_gnu_extensions_p (parser))
{
tree trailing_attr = cp_parser_attributes_opt (parser);
+ trailing_attr = chainon (trailing_attr, attributes);
cplus_decl_attributes (&type,
trailing_attr,
(int) ATTR_FLAG_TYPE_IN_PLACE);
else
value = NULL_TREE;
+ /* If we are processing a template, make sure the initializer of the
+ enumerator doesn't contain any bare template parameter pack. */
+ if (check_for_bare_parameter_packs (value))
+ value = error_mark_node;
+
/* Create the enumerator. */
build_enumerator (identifier, value, type);
}
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
- error ("%H%qD is not a namespace-name", &token->location, identifier);
+ error_at (token->location, "%qD is not a namespace-name", identifier);
cp_parser_error (parser, "expected namespace-name");
namespace_decl = error_mark_node;
}
#ifdef HANDLE_PRAGMA_VISIBILITY
if (has_visibility)
- pop_visibility ();
+ pop_visibility (1);
#endif
/* Finish the namespace. */
if (!cp_parser_uncommitted_to_tentative_parse_p (parser)
&& cp_lexer_next_token_is (parser->lexer, CPP_OPEN_BRACE))
{
- error ("%H%<namespace%> definition is not allowed here", &token->location);
+ error_at (token->location, "%<namespace%> definition is not allowed here");
/* Skip the definition. */
cp_lexer_consume_token (parser->lexer);
if (cp_parser_skip_to_closing_brace (parser))
/* [namespace.udecl]
A using declaration shall not name a template-id. */
- error ("%Ha template-id may not appear in a using-declaration",
- &token->location);
+ error_at (token->location,
+ "a template-id may not appear in a using-declaration");
else
{
if (at_class_scope_p ())
: asm-operand-list [opt] ) ;
asm volatile [opt] ( string-literal : asm-operand-list [opt]
: asm-operand-list [opt]
- : asm-operand-list [opt] ) ; */
+ : asm-clobber-list [opt] ) ;
+ asm volatile [opt] goto ( string-literal : : asm-operand-list [opt]
+ : asm-clobber-list [opt]
+ : asm-goto-list ) ; */
static void
cp_parser_asm_definition (cp_parser* parser)
tree outputs = NULL_TREE;
tree inputs = NULL_TREE;
tree clobbers = NULL_TREE;
+ tree labels = NULL_TREE;
tree asm_stmt;
bool volatile_p = false;
bool extended_p = false;
bool invalid_inputs_p = false;
bool invalid_outputs_p = false;
+ bool goto_p = false;
+ const char *missing = NULL;
/* Look for the `asm' keyword. */
cp_parser_require_keyword (parser, RID_ASM, "%<asm%>");
/* Consume the token. */
cp_lexer_consume_token (parser->lexer);
}
+ if (cp_parser_allow_gnu_extensions_p (parser)
+ && parser->in_function_body
+ && cp_lexer_next_token_is_keyword (parser->lexer, RID_GOTO))
+ {
+ /* Remember that we saw the `goto' keyword. */
+ goto_p = true;
+ /* Consume the token. */
+ cp_lexer_consume_token (parser->lexer);
+ }
/* Look for the opening `('. */
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return;
{
bool inputs_p = false;
bool clobbers_p = false;
+ bool labels_p = false;
/* The extended syntax was used. */
extended_p = true;
&& cp_lexer_next_token_is_not (parser->lexer,
CPP_SCOPE)
&& cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
+ CPP_CLOSE_PAREN)
+ && !goto_p)
outputs = cp_parser_asm_operand_list (parser);
if (outputs == error_mark_node)
if (cp_lexer_next_token_is_not (parser->lexer,
CPP_COLON)
&& cp_lexer_next_token_is_not (parser->lexer,
+ CPP_SCOPE)
+ && cp_lexer_next_token_is_not (parser->lexer,
CPP_CLOSE_PAREN))
inputs = cp_parser_asm_operand_list (parser);
if (clobbers_p
|| cp_lexer_next_token_is (parser->lexer, CPP_COLON))
{
+ clobbers_p = true;
/* Consume the `:' or `::'. */
cp_lexer_consume_token (parser->lexer);
/* Parse the clobbers. */
if (cp_lexer_next_token_is_not (parser->lexer,
- CPP_CLOSE_PAREN))
+ CPP_COLON)
+ && cp_lexer_next_token_is_not (parser->lexer,
+ CPP_CLOSE_PAREN))
clobbers = cp_parser_asm_clobber_list (parser);
}
+ else if (goto_p
+ && cp_lexer_next_token_is (parser->lexer, CPP_SCOPE))
+ /* The labels are coming next. */
+ labels_p = true;
+
+ /* Look for labels. */
+ if (labels_p
+ || (goto_p && cp_lexer_next_token_is (parser->lexer, CPP_COLON)))
+ {
+ labels_p = true;
+ /* Consume the `:' or `::'. */
+ cp_lexer_consume_token (parser->lexer);
+ /* Parse the labels. */
+ labels = cp_parser_asm_label_list (parser);
+ }
+
+ if (goto_p && !labels_p)
+ missing = clobbers_p ? "%<:%>" : "%<:%> or %<::%>";
}
+ else if (goto_p)
+ missing = "%<:%> or %<::%>";
+
/* Look for the closing `)'. */
- if (!cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>"))
+ if (!cp_parser_require (parser, missing ? CPP_COLON : CPP_CLOSE_PAREN,
+ missing ? missing : "%<)%>"))
cp_parser_skip_to_closing_parenthesis (parser, true, false,
/*consume_paren=*/true);
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
if (parser->in_function_body)
{
asm_stmt = finish_asm_stmt (volatile_p, string, outputs,
- inputs, clobbers);
+ inputs, clobbers, labels);
/* If the extended syntax was not used, mark the ASM_EXPR. */
if (!extended_p)
{
we compute it now. */
scope = get_scope_of_declarator (declarator);
+ /* Perform any lookups in the declared type which were thought to be
+ dependent, but are not in the scope of the declarator. */
+ decl_specifiers->type
+ = maybe_update_decl_type (decl_specifiers->type, scope);
+
/* If we're allowing GNU extensions, look for an asm-specification
and attributes. */
if (cp_parser_allow_gnu_extensions_p (parser))
/* Neither attributes nor an asm-specification are allowed
on a function-definition. */
if (asm_specification)
- error ("%Han asm-specification is not allowed "
- "on a function-definition",
- &asm_spec_start_token->location);
+ error_at (asm_spec_start_token->location,
+ "an asm-specification is not allowed "
+ "on a function-definition");
if (attributes)
- error ("%Hattributes are not allowed on a function-definition",
- &attributes_start_token->location);
+ error_at (attributes_start_token->location,
+ "attributes are not allowed on a function-definition");
/* This is a function-definition. */
*function_definition_p = true;
know what the user intended, so just silently
consume the initializer. */
if (decl != error_mark_node)
- error ("%Hinitializer provided for function",
- &initializer_start_token->location);
+ error_at (initializer_start_token->location,
+ "initializer provided for function");
cp_parser_skip_to_closing_parenthesis (parser,
/*recovering=*/true,
/*or_comma=*/false,
}
}
else
- initializer = cp_parser_initializer (parser,
- &is_direct_init,
- &is_non_constant_init);
+ {
+ /* We want to record the extra mangling scope for in-class
+ initializers of class members and initializers of static data
+ member templates. The former is a C++0x feature which isn't
+ implemented yet, and I expect it will involve deferring
+ parsing of the initializer until end of class as with default
+ arguments. So right here we only handle the latter. */
+ if (!member_p && processing_template_decl)
+ start_lambda_scope (decl);
+ initializer = cp_parser_initializer (parser,
+ &is_direct_init,
+ &is_non_constant_init);
+ if (!member_p && processing_template_decl)
+ finish_lambda_scope ();
+ }
}
/* The old parser allows attributes to appear after a parenthesized
bool* parenthesized_p,
bool member_p)
{
- cp_token *token;
cp_declarator *declarator;
enum tree_code code;
cp_cv_quals cv_quals;
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_attributes_opt (parser);
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
-
/* Check for the ptr-operator production. */
cp_parser_parse_tentatively (parser);
/* Parse the ptr-operator. */
bounds = fold_non_dependent_expr (bounds);
/* Normally, the array bound must be an integral constant
expression. However, as an extension, we allow VLAs
- in function scopes. */
- else if (!parser->in_function_body)
+ in function scopes as long as they aren't part of a
+ parameter declaration. */
+ else if (!parser->in_function_body
+ || current_binding_level->kind == sk_function_parms)
{
- error ("%Harray bound is not an integer constant",
- &token->location);
+ cp_parser_error (parser,
+ "array bound is not an integer constant");
bounds = error_mark_node;
}
+ else if (processing_template_decl && !error_operand_p (bounds))
+ {
+ /* Remember this wasn't a constant-expression. */
+ bounds = build_nop (TREE_TYPE (bounds), bounds);
+ TREE_SIDE_EFFECTS (bounds) = 1;
+ }
}
else
bounds = NULL_TREE;
}
else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
{
- tree qualifying_scope;
- tree unqualified_name;
- special_function_kind sfk;
- bool abstract_ok;
- bool pack_expansion_p = false;
- cp_token *declarator_id_start_token;
-
- /* Parse a declarator-id */
- abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
- if (abstract_ok)
- {
- cp_parser_parse_tentatively (parser);
+ {
+ tree qualifying_scope;
+ tree unqualified_name;
+ special_function_kind sfk;
+ bool abstract_ok;
+ bool pack_expansion_p = false;
+ cp_token *declarator_id_start_token;
+
+ /* Parse a declarator-id */
+ abstract_ok = (dcl_kind == CP_PARSER_DECLARATOR_EITHER);
+ if (abstract_ok)
+ {
+ cp_parser_parse_tentatively (parser);
- /* If we see an ellipsis, we should be looking at a
- parameter pack. */
- if (token->type == CPP_ELLIPSIS)
- {
- /* Consume the `...' */
- cp_lexer_consume_token (parser->lexer);
+ /* If we see an ellipsis, we should be looking at a
+ parameter pack. */
+ if (token->type == CPP_ELLIPSIS)
+ {
+ /* Consume the `...' */
+ cp_lexer_consume_token (parser->lexer);
- pack_expansion_p = true;
- }
- }
+ pack_expansion_p = true;
+ }
+ }
- declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
- unqualified_name
- = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
- qualifying_scope = parser->scope;
- if (abstract_ok)
- {
- bool okay = false;
-
- if (!unqualified_name && pack_expansion_p)
- {
- /* Check whether an error occurred. */
- okay = !cp_parser_error_occurred (parser);
-
- /* We already consumed the ellipsis to mark a
- parameter pack, but we have no way to report it,
- so abort the tentative parse. We will be exiting
- immediately anyway. */
- cp_parser_abort_tentative_parse (parser);
- }
- else
- okay = cp_parser_parse_definitely (parser);
-
- if (!okay)
- unqualified_name = error_mark_node;
- else if (unqualified_name
- && (qualifying_scope
- || (TREE_CODE (unqualified_name)
- != IDENTIFIER_NODE)))
- {
- cp_parser_error (parser, "expected unqualified-id");
- unqualified_name = error_mark_node;
- }
- }
+ declarator_id_start_token = cp_lexer_peek_token (parser->lexer);
+ unqualified_name
+ = cp_parser_declarator_id (parser, /*optional_p=*/abstract_ok);
+ qualifying_scope = parser->scope;
+ if (abstract_ok)
+ {
+ bool okay = false;
- if (!unqualified_name)
- return NULL;
- if (unqualified_name == error_mark_node)
- {
- declarator = cp_error_declarator;
- pack_expansion_p = false;
- declarator->parameter_pack_p = false;
- break;
- }
+ if (!unqualified_name && pack_expansion_p)
+ {
+ /* Check whether an error occurred. */
+ okay = !cp_parser_error_occurred (parser);
+
+ /* We already consumed the ellipsis to mark a
+ parameter pack, but we have no way to report it,
+ so abort the tentative parse. We will be exiting
+ immediately anyway. */
+ cp_parser_abort_tentative_parse (parser);
+ }
+ else
+ okay = cp_parser_parse_definitely (parser);
+
+ if (!okay)
+ unqualified_name = error_mark_node;
+ else if (unqualified_name
+ && (qualifying_scope
+ || (TREE_CODE (unqualified_name)
+ != IDENTIFIER_NODE)))
+ {
+ cp_parser_error (parser, "expected unqualified-id");
+ unqualified_name = error_mark_node;
+ }
+ }
- if (qualifying_scope && at_namespace_scope_p ()
- && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
- {
- /* In the declaration of a member of a template class
- outside of the class itself, the SCOPE will sometimes
- be a TYPENAME_TYPE. For example, given:
-
- template <typename T>
- int S<T>::R::i = 3;
-
- the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
- this context, we must resolve S<T>::R to an ordinary
- type, rather than a typename type.
-
- The reason we normally avoid resolving TYPENAME_TYPEs
- is that a specialization of `S' might render
- `S<T>::R' not a type. However, if `S' is
- specialized, then this `i' will not be used, so there
- is no harm in resolving the types here. */
- tree type;
+ if (!unqualified_name)
+ return NULL;
+ if (unqualified_name == error_mark_node)
+ {
+ declarator = cp_error_declarator;
+ pack_expansion_p = false;
+ declarator->parameter_pack_p = false;
+ break;
+ }
- /* Resolve the TYPENAME_TYPE. */
- type = resolve_typename_type (qualifying_scope,
- /*only_current_p=*/false);
- /* If that failed, the declarator is invalid. */
- if (TREE_CODE (type) == TYPENAME_TYPE)
- error ("%H%<%T::%E%> is not a type",
- &declarator_id_start_token->location,
- TYPE_CONTEXT (qualifying_scope),
- TYPE_IDENTIFIER (qualifying_scope));
- qualifying_scope = type;
- }
+ if (qualifying_scope && at_namespace_scope_p ()
+ && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
+ {
+ /* In the declaration of a member of a template class
+ outside of the class itself, the SCOPE will sometimes
+ be a TYPENAME_TYPE. For example, given:
+
+ template <typename T>
+ int S<T>::R::i = 3;
+
+ the SCOPE will be a TYPENAME_TYPE for `S<T>::R'. In
+ this context, we must resolve S<T>::R to an ordinary
+ type, rather than a typename type.
+
+ The reason we normally avoid resolving TYPENAME_TYPEs
+ is that a specialization of `S' might render
+ `S<T>::R' not a type. However, if `S' is
+ specialized, then this `i' will not be used, so there
+ is no harm in resolving the types here. */
+ tree type;
+
+ /* Resolve the TYPENAME_TYPE. */
+ type = resolve_typename_type (qualifying_scope,
+ /*only_current_p=*/false);
+ /* If that failed, the declarator is invalid. */
+ if (TREE_CODE (type) == TYPENAME_TYPE)
+ {
+ if (typedef_variant_p (type))
+ error_at (declarator_id_start_token->location,
+ "cannot define member of dependent typedef "
+ "%qT", type);
+ else
+ error_at (declarator_id_start_token->location,
+ "%<%T::%E%> is not a type",
+ TYPE_CONTEXT (qualifying_scope),
+ TYPE_IDENTIFIER (qualifying_scope));
+ }
+ qualifying_scope = type;
+ }
- sfk = sfk_none;
+ sfk = sfk_none;
- if (unqualified_name)
- {
- tree class_type;
+ if (unqualified_name)
+ {
+ tree class_type;
- if (qualifying_scope
- && CLASS_TYPE_P (qualifying_scope))
- class_type = qualifying_scope;
- else
- class_type = current_class_type;
+ if (qualifying_scope
+ && CLASS_TYPE_P (qualifying_scope))
+ class_type = qualifying_scope;
+ else
+ class_type = current_class_type;
- if (TREE_CODE (unqualified_name) == TYPE_DECL)
- {
- tree name_type = TREE_TYPE (unqualified_name);
- if (class_type && same_type_p (name_type, class_type))
- {
- if (qualifying_scope
- && CLASSTYPE_USE_TEMPLATE (name_type))
- {
- error ("%Hinvalid use of constructor as a template",
- &declarator_id_start_token->location);
- inform (input_location, "use %<%T::%D%> instead of %<%T::%D%> to "
- "name the constructor in a qualified name",
- class_type,
- DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
- class_type, name_type);
- declarator = cp_error_declarator;
- break;
- }
- else
- unqualified_name = constructor_name (class_type);
- }
- else
- {
- /* We do not attempt to print the declarator
- here because we do not have enough
- information about its original syntactic
- form. */
- cp_parser_error (parser, "invalid declarator");
- declarator = cp_error_declarator;
- break;
- }
- }
+ if (TREE_CODE (unqualified_name) == TYPE_DECL)
+ {
+ tree name_type = TREE_TYPE (unqualified_name);
+ if (class_type && same_type_p (name_type, class_type))
+ {
+ if (qualifying_scope
+ && CLASSTYPE_USE_TEMPLATE (name_type))
+ {
+ error_at (declarator_id_start_token->location,
+ "invalid use of constructor as a template");
+ inform (declarator_id_start_token->location,
+ "use %<%T::%D%> instead of %<%T::%D%> to "
+ "name the constructor in a qualified name",
+ class_type,
+ DECL_NAME (TYPE_TI_TEMPLATE (class_type)),
+ class_type, name_type);
+ declarator = cp_error_declarator;
+ break;
+ }
+ else
+ unqualified_name = constructor_name (class_type);
+ }
+ else
+ {
+ /* We do not attempt to print the declarator
+ here because we do not have enough
+ information about its original syntactic
+ form. */
+ cp_parser_error (parser, "invalid declarator");
+ declarator = cp_error_declarator;
+ break;
+ }
+ }
- if (class_type)
- {
- if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
- sfk = sfk_destructor;
- else if (IDENTIFIER_TYPENAME_P (unqualified_name))
- sfk = sfk_conversion;
- else if (/* There's no way to declare a constructor
- for an anonymous type, even if the type
- got a name for linkage purposes. */
- !TYPE_WAS_ANONYMOUS (class_type)
- && constructor_name_p (unqualified_name,
- class_type))
- {
- unqualified_name = constructor_name (class_type);
+ if (class_type)
+ {
+ if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
+ sfk = sfk_destructor;
+ else if (IDENTIFIER_TYPENAME_P (unqualified_name))
+ sfk = sfk_conversion;
+ else if (/* There's no way to declare a constructor
+ for an anonymous type, even if the type
+ got a name for linkage purposes. */
+ !TYPE_WAS_ANONYMOUS (class_type)
+ && constructor_name_p (unqualified_name,
+ class_type))
+ {
+ unqualified_name = constructor_name (class_type);
+ sfk = sfk_constructor;
+ }
+ else if (is_overloaded_fn (unqualified_name)
+ && DECL_CONSTRUCTOR_P (get_first_fn
+ (unqualified_name)))
sfk = sfk_constructor;
- }
-
- if (ctor_dtor_or_conv_p && sfk != sfk_none)
- *ctor_dtor_or_conv_p = -1;
- }
- }
- declarator = make_id_declarator (qualifying_scope,
- unqualified_name,
- sfk);
- declarator->id_loc = token->location;
- declarator->parameter_pack_p = pack_expansion_p;
- if (pack_expansion_p)
- maybe_warn_variadic_templates ();
+ if (ctor_dtor_or_conv_p && sfk != sfk_none)
+ *ctor_dtor_or_conv_p = -1;
+ }
+ }
+ declarator = make_id_declarator (qualifying_scope,
+ unqualified_name,
+ sfk);
+ declarator->id_loc = token->location;
+ declarator->parameter_pack_p = pack_expansion_p;
+
+ if (pack_expansion_p)
+ maybe_warn_variadic_templates ();
+ }
handle_declarator:;
scope = get_scope_of_declarator (declarator);
code = INDIRECT_REF;
if (TREE_CODE (parser->scope) == NAMESPACE_DECL)
- error ("%H%qD is a namespace", &token->location, parser->scope);
+ error_at (token->location, "%qD is a namespace", parser->scope);
else
{
/* The type of which the member is a member is given by the
if (cv_quals & cv_qualifier)
{
- error ("%Hduplicate cv-qualifier", &token->location);
+ error_at (token->location, "duplicate cv-qualifier");
cp_lexer_purge_token (parser->lexer);
}
else
/* 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
+ -> trailing-type-specifier-seq abstract-declarator(opt)
Returns the type indicated by the type-id. */
/* Consume the ->. */
cp_lexer_consume_token (parser->lexer);
- return cp_parser_type_id (parser);
+ return cp_parser_trailing_type_id (parser);
}
/* Parse a declarator-id.
Returns the TYPE specified. */
static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg,
+ bool is_trailing_return)
{
cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/false,
+ is_trailing_return,
&type_specifier_seq);
if (type_specifier_seq.type == error_mark_node)
return error_mark_node;
if (type_specifier_seq.type
&& type_uses_auto (type_specifier_seq.type))
{
- error ("invalid use of %<auto%>");
- return error_mark_node;
+ /* A type-id with type 'auto' is only ok if the abstract declarator
+ is a function declarator with a late-specified return type. */
+ if (abstract_declarator
+ && abstract_declarator->kind == cdk_function
+ && abstract_declarator->u.function.late_return_type)
+ /* OK */;
+ else
+ {
+ error ("invalid use of %<auto%>");
+ return error_mark_node;
+ }
}
- return groktypename (&type_specifier_seq, abstract_declarator);
+ return groktypename (&type_specifier_seq, abstract_declarator,
+ is_template_arg);
+}
+
+static tree cp_parser_type_id (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, false, false);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, true, false);
+}
+
+static tree cp_parser_trailing_type_id (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, false, true);
}
/* Parse a type-specifier-seq.
type-specifier-seq:
attributes type-specifier-seq [opt]
- If IS_CONDITION is true, we are at the start of a "condition",
- e.g., we've just seen "if (".
+ If IS_DECLARATION is true, we are at the start of a "condition" or
+ exception-declaration, so we might be followed by a declarator-id.
+
+ If IS_TRAILING_RETURN is true, we are in a trailing-return-type,
+ i.e. we've just seen "->".
Sets *TYPE_SPECIFIER_SEQ to represent the sequence. */
static void
cp_parser_type_specifier_seq (cp_parser* parser,
- bool is_condition,
+ bool is_declaration,
+ bool is_trailing_return,
cp_decl_specifier_seq *type_specifier_seq)
{
bool seen_type_specifier = false;
/* Clear the TYPE_SPECIFIER_SEQ. */
clear_decl_specs (type_specifier_seq);
+ /* In the context of a trailing return type, enum E { } is an
+ elaborated-type-specifier followed by a function-body, not an
+ enum-specifier. */
+ if (is_trailing_return)
+ flags |= CP_PARSER_FLAGS_NO_TYPE_DEFINITIONS;
+
/* Parse the type-specifiers and attributes. */
while (true)
{
would be clearer just to allow a decl-specifier-seq here, and
then add a semantic restriction that if any decl-specifiers
that are not type-specifiers appear, the program is invalid. */
- if (is_condition && !is_cv_qualifier)
+ if (is_declaration && !is_cv_qualifier)
flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
}
tree parameters = NULL_TREE;
tree *tail = ¶meters;
bool saved_in_unbraced_linkage_specification_p;
+ int index = 0;
/* Assume all will go well. */
*is_error = false;
if (DECL_NAME (decl))
decl = pushdecl (decl);
+ if (decl != error_mark_node)
+ {
+ retrofit_lang_decl (decl);
+ DECL_PARM_INDEX (decl) = ++index;
+ }
+
/* Add the new parameter to the list. */
*tail = build_tree_list (parameter->default_argument, decl);
tail = &TREE_CHAIN (*tail);
bool *parenthesized_p)
{
int declares_class_or_enum;
- bool greater_than_is_operator_p;
cp_decl_specifier_seq decl_specifiers;
cp_declarator *declarator;
tree default_argument;
template-parameter, the first non-nested `>' is taken as the end
of the template parameter-list rather than a greater-than
operator. */
- greater_than_is_operator_p = !template_parm_p;
/* Type definitions may not appear in parameter types. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in parameter types";
+ = G_("types may not be defined in parameter types");
/* Parse the declaration-specifiers. */
cp_parser_decl_specifier_seq (parser,
CP_PARSER_FLAGS_NONE,
&decl_specifiers,
&declares_class_or_enum);
+
+ /* Complain about missing 'typename' or other invalid type names. */
+ if (!decl_specifiers.any_type_specifiers_p)
+ cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
/* If an error occurred, there's no reason to attempt to parse the
rest of the declaration. */
if (cp_parser_error_occurred (parser))
/* If we are defining a class, then the tokens that make up the
default argument must be saved and processed later. */
if (!template_parm_p && at_class_scope_p ()
- && TYPE_BEING_DEFINED (current_class_type))
+ && TYPE_BEING_DEFINED (current_class_type)
+ && !LAMBDA_TYPE_P (current_class_type))
{
unsigned depth = 0;
int maybe_template_id = 0;
/* If we run out of tokens, issue an error message. */
case CPP_EOF:
case CPP_PRAGMA_EOL:
- error ("%Hfile ends in default argument", &token->location);
+ error_at (token->location, "file ends in default argument");
done = true;
break;
warning (0, "deprecated use of default argument for parameter of non-function");
else
{
- error ("%Hdefault arguments are only "
- "permitted for function parameters",
- &token->location);
+ error_at (token->location,
+ "default arguments are only "
+ "permitted for function parameters");
default_argument = NULL_TREE;
}
}
|| (decl_specifiers.type
&& PACK_EXPANSION_P (decl_specifiers.type)))
{
- const char* kind = template_parm_p? "template " : "";
-
/* Find the name of the parameter pack. */
cp_declarator *id_declarator = declarator;
while (id_declarator && id_declarator->kind != cdk_id)
id_declarator = id_declarator->declarator;
if (id_declarator && id_declarator->kind == cdk_id)
- error ("%H%sparameter pack %qD cannot have a default argument",
- &declarator_token_start->location,
- kind, id_declarator->u.id.unqualified_name);
+ error_at (declarator_token_start->location,
+ template_parm_p
+ ? "template parameter pack %qD"
+ " cannot have a default argument"
+ : "parameter pack %qD cannot have a default argument",
+ id_declarator->u.id.unqualified_name);
else
- error ("%H%sparameter pack cannot have a default argument",
- &declarator_token_start->location, kind);
+ error_at (declarator_token_start->location,
+ template_parm_p
+ ? "template parameter pack cannot have a default argument"
+ : "parameter pack cannot have a default argument");
default_argument = NULL_TREE;
}
appear in a default argument. */
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
- /* The default argument expression may cause implicitly
- defined member functions to be synthesized, which will
- result in garbage collection. We must treat this
- situation as if we were within the body of function so as
- to avoid collecting live data on the stack. */
- ++function_depth;
/* Parse the assignment-expression. */
if (template_parm_p)
push_deferring_access_checks (dk_no_deferred);
= cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
if (template_parm_p)
pop_deferring_access_checks ();
- /* Restore saved state. */
- --function_depth;
parser->greater_than_is_operator_p = saved_greater_than_is_operator_p;
parser->local_variables_forbidden_p = saved_local_variables_forbidden_p;
init = cp_parser_initializer_clause (parser, non_constant_p);
}
else if (token->type == CPP_OPEN_PAREN)
- init = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/false,
- /*allow_expansion_p=*/true,
- non_constant_p);
+ {
+ VEC(tree,gc) *vec;
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+ /*cast_p=*/false,
+ /*allow_expansion_p=*/true,
+ non_constant_p);
+ if (vec == NULL)
+ return error_mark_node;
+ init = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
else if (token->type == CPP_OPEN_BRACE)
{
- maybe_warn_cpp0x ("extended initializer lists");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
init = cp_parser_braced_list (parser, non_constant_p);
CONSTRUCTOR_IS_DIRECT_INIT (init) = 1;
}
identifier_token->location);
if (ambiguous_decls)
{
- error ("%Hreference to %qD is ambiguous",
- &identifier_token->location, identifier);
- print_candidates (ambiguous_decls);
if (cp_parser_parsing_tentatively (parser))
- {
- identifier_token->ambiguous_p = true;
- cp_parser_simulate_error (parser);
- }
+ cp_parser_simulate_error (parser);
return error_mark_node;
}
}
static tree
cp_parser_class_specifier (cp_parser* parser)
{
- cp_token *token;
tree type;
tree attributes = NULL_TREE;
- int has_trailing_semicolon;
bool nested_name_specifier_p;
unsigned saved_num_template_parameter_lists;
bool saved_in_function_body;
/* Look for the trailing `}'. */
cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
- /* We get better error messages by noticing a common problem: a
- missing trailing `;'. */
- token = cp_lexer_peek_token (parser->lexer);
- has_trailing_semicolon = (token->type == CPP_SEMICOLON);
/* Look for trailing attributes to apply to this class. */
if (cp_parser_allow_gnu_extensions_p (parser))
attributes = cp_parser_attributes_opt (parser);
/* Reject typedef-names in class heads. */
if (!DECL_IMPLICIT_TYPEDEF_P (type))
{
- error ("%Hinvalid class name in declaration of %qD",
- &type_start_token->location, type);
+ error_at (type_start_token->location,
+ "invalid class name in declaration of %qD",
+ type);
type = NULL_TREE;
goto done;
}
if (scope && !is_ancestor (scope, nested_name_specifier))
{
if (at_namespace_scope_p ())
- error ("%Hdeclaration of %qD in namespace %qD which does not "
- "enclose %qD",
- &type_start_token->location,
- type, scope, nested_name_specifier);
+ error_at (type_start_token->location,
+ "declaration of %qD in namespace %qD which does not "
+ "enclose %qD",
+ type, scope, nested_name_specifier);
else
- error ("%Hdeclaration of %qD in %qD which does not enclose %qD",
- &type_start_token->location,
- type, scope, nested_name_specifier);
+ error_at (type_start_token->location,
+ "declaration of %qD in %qD which does not enclose %qD",
+ type, scope, nested_name_specifier);
type = NULL_TREE;
goto done;
}
class member of a namespace outside of its namespace. */
if (scope == nested_name_specifier)
{
- permerror (input_location, "%Hextra qualification not allowed",
- &nested_name_specifier_token_start->location);
+ permerror (nested_name_specifier_token_start->location,
+ "extra qualification not allowed");
nested_name_specifier = NULL_TREE;
num_templates = 0;
}
&& parser->num_template_parameter_lists == 0
&& template_id_p)
{
- error ("%Han explicit specialization must be preceded by %<template <>%>",
- &type_start_token->location);
+ error_at (type_start_token->location,
+ "an explicit specialization must be preceded by %<template <>%>");
invalid_explicit_specialization_p = true;
/* Take the same action that would have been taken by
cp_parser_explicit_specialization. */
/* Make sure that the right number of template parameters were
present. */
if (!cp_parser_check_template_parameters (parser, num_templates,
- type_start_token->location))
+ type_start_token->location,
+ /*declarator=*/NULL))
{
/* If something went wrong, there is no point in even trying to
process the class-definition. */
&& (DECL_FUNCTION_TEMPLATE_P (TREE_OPERAND (id, 0))
|| TREE_CODE (TREE_OPERAND (id, 0)) == OVERLOAD))
{
- error ("%Hfunction template %qD redeclared as a class template",
- &type_start_token->location, id);
+ error_at (type_start_token->location,
+ "function template %qD redeclared as a class template", id);
type = error_mark_node;
}
else
that's an error. */
if (type != error_mark_node && COMPLETE_TYPE_P (type))
{
- error ("%Hredefinition of %q#T",
- &type_start_token->location, type);
- error ("%Hprevious definition of %q+#T",
- &type_start_token->location, type);
+ error_at (type_start_token->location, "redefinition of %q#T",
+ type);
+ error_at (type_start_token->location, "previous definition of %q+#T",
+ type);
type = NULL_TREE;
goto done;
}
end_specialization ();
--parser->num_template_parameter_lists;
}
+
+ if (type)
+ DECL_SOURCE_LOCATION (TYPE_NAME (type)) = type_start_token->location;
*attributes_p = attributes;
return type;
}
prefix_attributes = decl_specifiers.attributes;
decl_specifiers.attributes = NULL_TREE;
/* Check for an invalid type-name. */
- if (!decl_specifiers.type
+ if (!decl_specifiers.any_type_specifiers_p
&& cp_parser_parse_and_diagnose_invalid_type_name (parser))
return;
/* If there is no declarator, then the decl-specifier-seq should
/* If the `friend' keyword was present, the friend must
be introduced with a class-key. */
if (!declares_class_or_enum)
- error ("%Ha class-key must be used when declaring a friend",
- &decl_spec_token_start->location);
+ error_at (decl_spec_token_start->location,
+ "a class-key must be used when declaring a friend");
/* In this case:
template <typename T> struct A {
&& TYPE_P (decl_specifiers.type))
type = decl_specifiers.type;
if (!type || !TYPE_P (type))
- error ("%Hfriend declaration does not name a class or "
- "function", &decl_spec_token_start->location);
+ error_at (decl_spec_token_start->location,
+ "friend declaration does not name a class or "
+ "function");
else
make_friend_class (current_class_type, type,
/*complain=*/true);
know it is an anonymous aggregate. */
fixup_anonymous_aggr (type);
/* And make the corresponding data member. */
- decl = build_decl (FIELD_DECL, NULL_TREE, type);
+ decl = build_decl (decl_spec_token_start->location,
+ FIELD_DECL, NULL_TREE, type);
/* Add it to the class. */
finish_member_declaration (decl);
}
standard, since a pure function may be defined
outside of the class-specifier. */
if (initializer)
- error ("%Hpure-specifier on function-definition",
- &initializer_token_start->location);
+ error_at (initializer_token_start->location,
+ "pure-specifier on function-definition");
decl = cp_parser_save_member_function_body (parser,
&decl_specifiers,
declarator,
if (!cp_parser_require (parser, CPP_EQ, "%<=%>"))
return error_mark_node;
/* Look for the `0' token. */
- token = cp_lexer_consume_token (parser->lexer);
+ token = cp_lexer_peek_token (parser->lexer);
+
+ if (token->type == CPP_EOF
+ || token->type == CPP_PRAGMA_EOL)
+ return error_mark_node;
+
+ cp_lexer_consume_token (parser->lexer);
/* Accept = default or = delete in c++0x mode. */
if (token->keyword == RID_DEFAULT
|| token->keyword == RID_DELETE)
{
- maybe_warn_cpp0x ("defaulted and deleted functions");
+ maybe_warn_cpp0x (CPP0X_DEFAULTED_DELETED);
return token->u.value;
}
}
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
- error ("%Htemplates may not be %<virtual%>", &token->location);
+ error_at (token->location, "templates may not be %<virtual%>");
return error_mark_node;
}
{
token = cp_lexer_peek_token (parser->lexer);
if (!processing_template_decl)
- error ("%Hkeyword %<typename%> not allowed outside of templates",
- &token->location);
+ error_at (token->location,
+ "keyword %<typename%> not allowed outside of templates");
else
- error ("%Hkeyword %<typename%> not allowed in this context "
- "(the base class is implicitly a type)",
- &token->location);
+ error_at (token->location,
+ "keyword %<typename%> not allowed in this context "
+ "(the base class is implicitly a type)");
cp_lexer_consume_token (parser->lexer);
}
/* Types may not be defined in an exception-specification. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in an exception-specification";
+ = G_("types may not be defined in an exception-specification");
/* Parse the type-id-list. */
type_id_list = cp_parser_type_id_list (parser);
/* Restore the saved message. */
/* Types may not be defined in exception-declarations. */
saved_message = parser->type_definition_forbidden_message;
parser->type_definition_forbidden_message
- = "types may not be defined in exception-declarations";
+ = G_("types may not be defined in exception-declarations");
/* Parse the type-specifier-seq. */
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+ /*is_trailing_return=*/false,
&type_specifiers);
/* If it's a `)', then there is no declarator. */
if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
return clobbers;
}
+/* Parse an asm-label-list.
+
+ asm-label-list:
+ identifier
+ asm-label-list , identifier
+
+ Returns a TREE_LIST, indicating the labels in the order that they
+ appeared. The TREE_VALUE of each node is a label. */
+
+static tree
+cp_parser_asm_label_list (cp_parser* parser)
+{
+ tree labels = NULL_TREE;
+
+ while (true)
+ {
+ tree identifier, label, name;
+
+ /* Look for the identifier. */
+ identifier = cp_parser_identifier (parser);
+ if (!error_operand_p (identifier))
+ {
+ label = lookup_label (identifier);
+ if (TREE_CODE (label) == LABEL_DECL)
+ {
+ TREE_USED (label) = 1;
+ check_goto (label);
+ name = build_string (IDENTIFIER_LENGTH (identifier),
+ IDENTIFIER_POINTER (identifier));
+ labels = tree_cons (name, label, labels);
+ }
+ }
+ /* If the next token is not a `,', then the list is
+ complete. */
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COMMA))
+ break;
+ /* Consume the `,' token. */
+ cp_lexer_consume_token (parser->lexer);
+ }
+
+ return nreverse (labels);
+}
+
/* Parse an (optional) series of attributes.
attributes:
/* Save away the identifier that indicates which attribute
this is. */
- identifier = token->u.value;
+ identifier = (token->type == CPP_KEYWORD)
+ /* For keywords, use the canonical spelling, not the
+ parsed identifier. */
+ ? ridpointers[(int) token->keyword]
+ : token->u.value;
+
attribute = build_tree_list (identifier, NULL_TREE);
/* Peek at the next token. */
/* If it's an `(', then parse the attribute arguments. */
if (token->type == CPP_OPEN_PAREN)
{
- arguments = cp_parser_parenthesized_expression_list
- (parser, true, /*cast_p=*/false,
- /*allow_expansion_p=*/false,
- /*non_constant_p=*/NULL);
+ VEC(tree,gc) *vec;
+ int attr_flag = (attribute_takes_identifier_p (identifier)
+ ? id_attr : normal_attr);
+ vec = cp_parser_parenthesized_expression_list
+ (parser, attr_flag, /*cast_p=*/false,
+ /*allow_expansion_p=*/false,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ arguments = error_mark_node;
+ else
+ {
+ arguments = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
/* Save the arguments away. */
TREE_VALUE (attribute) = arguments;
}
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
dependent_p = (TYPE_P (parser->scope)
- && !(parser->in_declarator_p
- && currently_open_class (parser->scope))
- && dependent_type_p (parser->scope));
+ && dependent_scope_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
- && dependent_p)
- {
- if (tag_type)
- {
- tree type;
-
- /* The resolution to Core Issue 180 says that `struct
- A::B' should be considered a type-name, even if `A'
- is dependent. */
- type = make_typename_type (parser->scope, name, tag_type,
- /*complain=*/tf_error);
- decl = TYPE_NAME (type);
- }
- else if (is_template
- && (cp_parser_next_token_ends_template_argument_p (parser)
- || cp_lexer_next_token_is (parser->lexer,
- CPP_CLOSE_PAREN)))
- decl = make_unbound_class_template (parser->scope,
- name, NULL_TREE,
- /*complain=*/tf_error);
- else
- decl = build_qualified_name (/*type=*/NULL_TREE,
- parser->scope, name,
- is_template);
- }
+ && dependent_p)
+ /* Defer lookup. */
+ decl = error_mark_node;
else
{
tree pushed_scope = NULL_TREE;
lookup_member, we must enter the scope here. */
if (dependent_p)
pushed_scope = push_scope (parser->scope);
+
+ /* 3.4.3.1: In a lookup in which the constructor is an acceptable
+ lookup result and the nested-name-specifier nominates a class C:
+ * if the name specified after the nested-name-specifier, when
+ looked up in C, is the injected-class-name of C (Clause 9), or
+ * if the name specified after the nested-name-specifier is the
+ same as the identifier or the simple-template-id's template-
+ name in the last component of the nested-name-specifier,
+ the name is instead considered to name the constructor of
+ class C. [ Note: for example, the constructor is not an
+ acceptable lookup result in an elaborated-type-specifier so
+ the constructor would not be used in place of the
+ injected-class-name. --end note ] Such a constructor name
+ shall be used only in the declarator-id of a declaration that
+ names a constructor or in a using-declaration. */
+ if (tag_type == none_type
+ && CLASS_TYPE_P (parser->scope)
+ && constructor_name_p (name, parser->scope))
+ name = ctor_identifier;
+
/* If the PARSER->SCOPE is a template specialization, it
may be instantiated during name lookup. In that case,
errors may be issued. Even if we rollback the current
/*complain=*/true);
/* If we have a single function from a using decl, pull it out. */
- if (decl
- && TREE_CODE (decl) == OVERLOAD
+ if (TREE_CODE (decl) == OVERLOAD
&& !really_overloaded_fn (decl))
decl = OVL_FUNCTION (decl);
if (pushed_scope)
pop_scope (pushed_scope);
}
+
+ /* If the scope is a dependent type and either we deferred lookup or
+ we did lookup but didn't find the name, rememeber the name. */
+ if (decl == error_mark_node && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope))
+ {
+ if (tag_type)
+ {
+ tree type;
+
+ /* The resolution to Core Issue 180 says that `struct
+ A::B' should be considered a type-name, even if `A'
+ is dependent. */
+ type = make_typename_type (parser->scope, name, tag_type,
+ /*complain=*/tf_error);
+ decl = TYPE_NAME (type);
+ }
+ else if (is_template
+ && (cp_parser_next_token_ends_template_argument_p (parser)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_CLOSE_PAREN)))
+ decl = make_unbound_class_template (parser->scope,
+ name, NULL_TREE,
+ /*complain=*/tf_error);
+ else
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope, name,
+ is_template);
+ }
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
}
if (!decl || decl == error_mark_node)
return error_mark_node;
+ /* Pull out the template from an injected-class-name (or multiple). */
+ if (is_template)
+ decl = maybe_get_template_decl_from_type_decl (decl);
+
/* If it's a TREE_LIST, the result of the lookup was ambiguous. */
if (TREE_CODE (decl) == TREE_LIST)
{
cp_parser_error, so we incorporate its actions directly. */
if (!cp_parser_simulate_error (parser))
{
- error ("%Hreference to %qD is ambiguous",
- &name_location, name);
+ error_at (name_location, "reference to %qD is ambiguous",
+ name);
print_candidates (decl);
}
return error_mark_node;
if (declarator->u.id.qualifying_scope)
{
tree scope;
- tree member;
scope = declarator->u.id.qualifying_scope;
- member = declarator->u.id.unqualified_name;
while (scope && CLASS_TYPE_P (scope))
{
additional level of template parameters. */
++num_templates;
- return cp_parser_check_template_parameters (parser,
- num_templates,
- declarator_location);
+ return cp_parser_check_template_parameters
+ (parser, num_templates, declarator_location, declarator);
+
case cdk_function:
case cdk_array:
/* NUM_TEMPLATES were used in the current declaration. If that is
invalid, return FALSE and issue an error messages. Otherwise,
- return TRUE. */
+ return TRUE. If DECLARATOR is non-NULL, then we are checking a
+ declarator and we can print more accurate diagnostics. */
static bool
cp_parser_check_template_parameters (cp_parser* parser,
unsigned num_templates,
- location_t location)
+ location_t location,
+ cp_declarator *declarator)
{
+ /* If there are the same number of template classes and parameter
+ lists, that's OK. */
+ if (parser->num_template_parameter_lists == num_templates)
+ return true;
+ /* If there are more, but only one more, then we are referring to a
+ member template. That's OK too. */
+ if (parser->num_template_parameter_lists == num_templates + 1)
+ return true;
/* If there are more template classes than parameter lists, we have
something like:
template <class T> void S<T>::R<T>::f (); */
if (parser->num_template_parameter_lists < num_templates)
{
- error ("%Htoo few template-parameter-lists", &location);
+ if (declarator && !current_function_decl)
+ error_at (location, "specializing member %<%T::%E%> "
+ "requires %<template<>%> syntax",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
+ else if (declarator)
+ error_at (location, "invalid declaration of %<%T::%E%>",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
+ else
+ error_at (location, "too few template-parameter-lists");
return false;
}
- /* If there are the same number of template classes and parameter
- lists, that's OK. */
- if (parser->num_template_parameter_lists == num_templates)
- return true;
- /* If there are more, but only one more, then we are referring to a
- member template. That's OK too. */
- if (parser->num_template_parameter_lists == num_templates + 1)
- return true;
/* Otherwise, there are too many template parameter lists. We have
something like:
template <class T> template <class U> void S::f(); */
- error ("%Htoo many template-parameter-lists", &location);
+ error_at (location, "too many template-parameter-lists");
return false;
}
cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
{
bool constructor_p;
- tree type_decl = NULL_TREE;
- bool nested_name_p;
+ tree nested_name_specifier;
cp_token *next_token;
/* The common case is that this is not a constructor declarator, so
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
- nested_name_p
+ nested_name_specifier
= (cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
/*check_dependency_p=*/false,
/*type_p=*/false,
- /*is_declaration=*/false)
- != NULL_TREE);
+ /*is_declaration=*/false));
/* Outside of a class-specifier, there must be a
nested-name-specifier. */
- if (!nested_name_p &&
+ if (!nested_name_specifier &&
(!at_class_scope_p () || !TYPE_BEING_DEFINED (current_class_type)
|| friend_p))
constructor_p = false;
+ else if (nested_name_specifier == error_mark_node)
+ constructor_p = false;
+
+ /* If we have a class scope, this is easy; DR 147 says that S::S always
+ names the constructor, and no other qualified name could. */
+ if (constructor_p && nested_name_specifier
+ && TYPE_P (nested_name_specifier))
+ {
+ tree id = cp_parser_unqualified_id (parser,
+ /*template_keyword_p=*/false,
+ /*check_dependency_p=*/false,
+ /*declarator_p=*/true,
+ /*optional_p=*/false);
+ if (is_overloaded_fn (id))
+ id = DECL_NAME (get_first_fn (id));
+ if (!constructor_name_p (id, nested_name_specifier))
+ constructor_p = false;
+ }
/* If we still think that this might be a constructor-declarator,
look for a class-name. */
- if (constructor_p)
+ else if (constructor_p)
{
/* If we have:
- template <typename T> struct S { S(); };
- template <typename T> S<T>::S ();
-
- we must recognize that the nested `S' names a class.
- Similarly, for:
+ template <typename T> struct S {
+ S();
+ };
- template <typename T> S<T>::S<T> ();
-
- we must recognize that the nested `S' names a template. */
+ we must recognize that the nested `S' names a class. */
+ tree type_decl;
type_decl = cp_parser_class_name (parser,
/*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
/*is_declaration=*/false);
/* If there was no class-name, then this is not a constructor. */
constructor_p = !cp_parser_error_occurred (parser);
- }
- /* If we're still considering a constructor, we have to see a `(',
- to begin the parameter-declaration-clause, followed by either a
- `)', an `...', or a decl-specifier. We need to check for a
- type-specifier to avoid being fooled into thinking that:
+ /* If we're still considering a constructor, we have to see a `(',
+ to begin the parameter-declaration-clause, followed by either a
+ `)', an `...', or a decl-specifier. We need to check for a
+ type-specifier to avoid being fooled into thinking that:
- S::S (f) (int);
+ S (f) (int);
- is a constructor. (It is actually a function named `f' that
- takes one parameter (of type `int') and returns a value of type
- `S::S'. */
- if (constructor_p
- && cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
- {
- if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
+ is a constructor. (It is actually a function named `f' that
+ takes one parameter (of type `int') and returns a value of type
+ `S'. */
+ if (constructor_p
+ && !cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
+ constructor_p = false;
+
+ if (constructor_p
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
&& cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
/* A parameter declaration begins with a decl-specifier,
which is either the "attribute" keyword, a storage class
constructor_p = !cp_parser_error_occurred (parser);
}
}
- else
- constructor_p = false;
+
/* We did not really want to consume any tokens. */
cp_parser_abort_tentative_parse (parser);
/* Parse the part of a function-definition that follows the
declarator. INLINE_P is TRUE iff this function is an inline
- function defined with a class-specifier.
+ function defined within a class-specifier.
Returns the function defined. */
returned. */
cp_parser_identifier (parser);
/* Issue an error message. */
- error ("%Hnamed return values are no longer supported",
- &token->location);
+ error_at (token->location,
+ "named return values are no longer supported");
/* Skip tokens until we reach the start of the function body. */
while (true)
{
saved_num_template_parameter_lists
= parser->num_template_parameter_lists;
parser->num_template_parameter_lists = 0;
+
+ start_lambda_scope (current_function_decl);
+
/* If the next token is `try', then we are looking at a
function-try-block. */
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_TRY))
ctor_initializer_p
= cp_parser_ctor_initializer_opt_and_function_body (parser);
+ finish_lambda_scope ();
+
/* Finish the function. */
fn = finish_function ((ctor_initializer_p ? 1 : 0) |
(inline_p ? 2 : 0));
/* 14.5.2.2 [temp.mem]
A local class shall not have member templates. */
- error ("%Hinvalid declaration of member template in local class",
- &token->location);
+ error_at (token->location,
+ "invalid declaration of member template in local class");
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 ("%Htemplate with C linkage", &token->location);
+ error_at (token->location, "template with C linkage");
/* Give it C++ linkage to avoid confusing other parts of the
front end. */
push_lang_context (lang_name_cplusplus);
/* There are no template typedefs. */
if (decl_specifiers.specs[(int) ds_typedef])
{
- error ("%Htemplate declaration of %qs",
- &decl_spec_token_start->location, "typedef");
+ error_at (decl_spec_token_start->location,
+ "template declaration of %<typedef%>");
decl = error_mark_node;
}
cp_parser_perform_template_parameter_access_checks (checks);
}
}
+
+ /* Complain about missing 'typename' or other invalid type names. */
+ if (!decl_specifiers.any_type_specifiers_p)
+ cp_parser_parse_and_diagnose_invalid_type_name (parser);
+
/* If it's not a template class, try for a template function. If
the next token is a `;', then this declaration does not declare
anything. But, if there were errors in the decl-specifiers, then
&& explicit_specialization_p
&& decl_specifiers.storage_class != sc_none)
{
- error ("%Hexplicit template specialization cannot have a storage class",
- &decl_spec_token_start->location);
+ error_at (decl_spec_token_start->location,
+ "explicit template specialization cannot have a storage class");
decl = error_mark_node;
}
}
static tree
cp_parser_functional_cast (cp_parser* parser, tree type)
{
+ VEC(tree,gc) *vec;
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");
+ maybe_warn_cpp0x (CPP0X_INITIALIZER_LISTS);
expression_list = cp_parser_braced_list (parser, &nonconst_p);
CONSTRUCTOR_IS_DIRECT_INIT (expression_list) = 1;
if (TREE_CODE (type) == TYPE_DECL)
return finish_compound_literal (type, expression_list);
}
- expression_list
- = cp_parser_parenthesized_expression_list (parser, false,
- /*cast_p=*/true,
- /*allow_expansion_p=*/true,
- /*non_constant_p=*/NULL);
+
+ vec = cp_parser_parenthesized_expression_list (parser, non_attr,
+ /*cast_p=*/true,
+ /*allow_expansion_p=*/true,
+ /*non_constant_p=*/NULL);
+ if (vec == NULL)
+ expression_list = error_mark_node;
+ else
+ {
+ expression_list = build_tree_list_vec (vec);
+ release_tree_vector (vec);
+ }
cast = build_functional_cast (type, expression_list,
tf_warning_or_error);
cp_token *last;
tree fn;
- /* Create the function-declaration. */
- fn = start_method (decl_specifiers, declarator, attributes);
+ /* Create the FUNCTION_DECL. */
+ fn = grokmethod (decl_specifiers, declarator, attributes);
/* If something went badly wrong, bail out now. */
if (fn == error_mark_node)
{
friend templates are handled correctly. */
DECL_INITIALIZED_IN_CLASS_P (fn) = 1;
- /* We're done with the inline definition. */
- finish_method (fn);
-
/* Add FN to the queue of functions to be parsed later. */
TREE_VALUE (parser->unparsed_functions_queues)
= tree_cons (NULL_TREE, fn,
tree saved_qualifying_scope;
tree saved_object_scope;
bool saved_greater_than_is_operator_p;
- bool saved_skip_evaluation;
+ int saved_unevaluated_operand;
+ int saved_inhibit_evaluation_warnings;
/* [temp.names]
saved_object_scope = parser->object_scope;
/* We need to evaluate the template arguments, even though this
template-id may be nested within a "sizeof". */
- saved_skip_evaluation = skip_evaluation;
- skip_evaluation = false;
+ saved_unevaluated_operand = cp_unevaluated_operand;
+ cp_unevaluated_operand = 0;
+ saved_inhibit_evaluation_warnings = c_inhibit_evaluation_warnings;
+ c_inhibit_evaluation_warnings = 0;
/* Parse the template-argument-list itself. */
if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER)
|| cp_lexer_next_token_is (parser->lexer, CPP_RSHIFT))
global source location is still on the token before the
'>>', so we need to say explicitly where we want it. */
cp_token *token = cp_lexer_peek_token (parser->lexer);
- error ("%H%<>>%> should be %<> >%> "
- "within a nested template argument list",
- &token->location);
+ error_at (token->location, "%<>>%> should be %<> >%> "
+ "within a nested template argument list");
token->type = CPP_GREATER;
}
Same deal about the token location, but here we can get it
right by consuming the '>>' before issuing the diagnostic. */
cp_token *token = cp_lexer_consume_token (parser->lexer);
- error ("%Hspurious %<>>%>, use %<>%> to terminate "
- "a template argument list", &token->location);
+ error_at (token->location,
+ "spurious %<>>%>, use %<>%> to terminate "
+ "a template argument list");
}
}
else
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
- skip_evaluation = saved_skip_evaluation;
+ cp_unevaluated_operand = saved_unevaluated_operand;
+ c_inhibit_evaluation_warnings = saved_inhibit_evaluation_warnings;
return arguments;
}
cp_parser_late_parsing_default_args (cp_parser *parser, tree fn)
{
bool saved_local_variables_forbidden_p;
- tree parm;
+ tree parm, parmdecl;
/* While we're parsing the default args, we might (due to the
statement expression extension) encounter more classes. We want
saved_local_variables_forbidden_p = parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
- for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn));
- parm;
- parm = TREE_CHAIN (parm))
+ for (parm = TYPE_ARG_TYPES (TREE_TYPE (fn)),
+ parmdecl = DECL_ARGUMENTS (fn);
+ parm && parm != void_list_node;
+ parm = TREE_CHAIN (parm),
+ parmdecl = TREE_CHAIN (parmdecl))
{
cp_token_cache *tokens;
tree default_arg = TREE_PURPOSE (parm);
tokens = DEFARG_TOKENS (default_arg);
cp_parser_push_lexer_for_tokens (parser, tokens);
+ start_lambda_scope (parmdecl);
+
/* Parse the assignment-expression. */
parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false, NULL);
+ if (parsed_arg == error_mark_node)
+ {
+ cp_parser_pop_lexer (parser);
+ continue;
+ }
if (!processing_template_decl)
parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
VEC_iterate (tree, insts, ix, copy); ix++)
TREE_PURPOSE (copy) = parsed_arg;
+ finish_lambda_scope ();
+
/* If the token stream has not been completely used up, then
there was extra junk after the end of the default
argument. */
}
/* Do not actually evaluate the expression. */
- ++skip_evaluation;
+ ++cp_unevaluated_operand;
+ ++c_inhibit_evaluation_warnings;
/* If it's a `(', then we might be looking at the type-id
construction. */
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
expr = make_pack_expansion (expr);
/* Go back to evaluating expressions. */
- --skip_evaluation;
+ --cp_unevaluated_operand;
+ --c_inhibit_evaluation_warnings;
/* Free the message we created. */
free (tmp);
if (parser->in_unbraced_linkage_specification_p)
{
- error ("%Hinvalid use of %qD in linkage specification",
- &location, ridpointers[keyword]);
+ error_at (location, "invalid use of %qD in linkage specification",
+ 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 ("%H%<__thread%> before %qD", &location, ridpointers[keyword]);
+ error_at (location, "%<__thread%> before %qD", ridpointers[keyword]);
decl_specs->specs[(int) ds_thread] = 0;
}
!= (current_access_specifier == access_private_node))
|| (TREE_PROTECTED (decl)
!= (current_access_specifier == access_protected_node)))
- error ("%H%qD redeclared with different access", &location, decl);
+ error_at (location, "%qD redeclared with different access", decl);
}
/* Look for the `template' keyword, as a syntactic disambiguator.
if (!processing_template_decl)
{
cp_token *token = cp_lexer_peek_token (parser->lexer);
- error ("%H%<template%> (as a disambiguator) is only allowed "
- "within templates", &token->location);
+ error_at (token->location,
+ "%<template%> (as a disambiguator) is only allowed "
+ "within templates");
/* If this part of the token stream is rescanned, the same
error message would be generated. So, we purge the token
from the stream. */
break;
}
default:
- error ("%Hmisplaced %<@%D%> Objective-C++ construct",
- &kwd->location, kwd->u.value);
+ error_at (kwd->location,
+ "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
if (!type)
{
- error ("%H%<@encode%> must specify a type as an argument",
- &token->location);
+ error_at (token->location,
+ "%<@encode%> must specify a type as an argument");
return error_mark_node;
}
tree sel_seq = NULL_TREE;
bool maybe_unary_selector_p = true;
cp_token *token;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_lexer_consume_token (parser->lexer); /* Eat '@selector'. */
cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>");
finish_selector:
cp_parser_require (parser, CPP_CLOSE_PAREN, "%<)%>");
- return objc_build_selector_expr (sel_seq);
+ return objc_build_selector_expr (loc, sel_seq);
}
/* Parse a list of identifiers.
if (!cp_parser_objc_selector_p (token->type))
{
- error ("%Hinvalid Objective-C++ selector name", &token->location);
+ error_at (token->location, "invalid Objective-C++ selector name");
return error_mark_node;
}
if (cp_lexer_next_token_is_not (parser->lexer, CPP_NAME))
{
tok = cp_lexer_peek_token (parser->lexer);
- error ("%Hidentifier expected after %<@protocol%>", &tok->location);
+ error_at (tok->location, "identifier expected after %<@protocol%>");
goto finish;
}
cp_parser_objc_end_implementation (parser);
break;
default:
- error ("%Hmisplaced %<@%D%> Objective-C++ construct",
- &kwd->location, kwd->u.value);
+ error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
}
static tree
cp_parser_objc_throw_statement (cp_parser *parser) {
tree expr = NULL_TREE;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_keyword (parser, RID_AT_THROW, "%<@throw%>");
cp_parser_consume_semicolon_at_end_of_statement (parser);
- return objc_build_throw_stmt (expr);
+ return objc_build_throw_stmt (loc, expr);
}
/* Parse an Objective-C statement. */
case RID_AT_THROW:
return cp_parser_objc_throw_statement (parser);
default:
- error ("%Hmisplaced %<@%D%> Objective-C++ construct",
- &kwd->location, kwd->u.value);
+ error_at (kwd->location, "misplaced %<@%D%> Objective-C++ construct",
+ kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
for (c = clauses; c ; c = OMP_CLAUSE_CHAIN (c))
if (OMP_CLAUSE_CODE (c) == code)
{
- error ("%Htoo many %qs clauses", &location, name);
+ error_at (location, "too many %qs clauses", name);
break;
}
}
cp_parser_name_lookup_error (parser, name, decl, NULL, token->location);
else if (kind != 0)
{
- tree u = build_omp_clause (kind);
+ tree u = build_omp_clause (token->location, kind);
OMP_CLAUSE_DECL (u) = decl;
OMP_CLAUSE_CHAIN (u) = list;
list = u;
|| (n = tree_low_cst (num, 0)) <= 0
|| (int) n != n)
{
- error ("%Hcollapse argument needs positive constant integer expression",
- &loc);
+ error_at (loc, "collapse argument needs positive constant integer expression");
return list;
}
check_no_duplicate_clause (list, OMP_CLAUSE_COLLAPSE, "collapse", location);
- c = build_omp_clause (OMP_CLAUSE_COLLAPSE);
+ c = build_omp_clause (loc, OMP_CLAUSE_COLLAPSE);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_COLLAPSE_EXPR (c) = num;
return list;
check_no_duplicate_clause (list, OMP_CLAUSE_DEFAULT, "default", location);
- c = build_omp_clause (OMP_CLAUSE_DEFAULT);
+ c = build_omp_clause (location, OMP_CLAUSE_DEFAULT);
OMP_CLAUSE_CHAIN (c) = list;
OMP_CLAUSE_DEFAULT_KIND (c) = kind;
check_no_duplicate_clause (list, OMP_CLAUSE_IF, "if", location);
- c = build_omp_clause (OMP_CLAUSE_IF);
+ c = build_omp_clause (location, OMP_CLAUSE_IF);
OMP_CLAUSE_IF_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
check_no_duplicate_clause (list, OMP_CLAUSE_NOWAIT, "nowait", location);
- c = build_omp_clause (OMP_CLAUSE_NOWAIT);
+ c = build_omp_clause (location, OMP_CLAUSE_NOWAIT);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
check_no_duplicate_clause (list, OMP_CLAUSE_NUM_THREADS,
"num_threads", location);
- c = build_omp_clause (OMP_CLAUSE_NUM_THREADS);
+ c = build_omp_clause (location, OMP_CLAUSE_NUM_THREADS);
OMP_CLAUSE_NUM_THREADS_EXPR (c) = t;
OMP_CLAUSE_CHAIN (c) = list;
check_no_duplicate_clause (list, OMP_CLAUSE_ORDERED,
"ordered", location);
- c = build_omp_clause (OMP_CLAUSE_ORDERED);
+ c = build_omp_clause (location, OMP_CLAUSE_ORDERED);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
if (!cp_parser_require (parser, CPP_OPEN_PAREN, "%<(%>"))
return list;
- c = build_omp_clause (OMP_CLAUSE_SCHEDULE);
+ c = build_omp_clause (location, OMP_CLAUSE_SCHEDULE);
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
if (t == error_mark_node)
goto resync_fail;
else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_RUNTIME)
- error ("%Hschedule %<runtime%> does not take "
- "a %<chunk_size%> parameter", &token->location);
+ error_at (token->location, "schedule %<runtime%> does not take "
+ "a %<chunk_size%> parameter");
else if (OMP_CLAUSE_SCHEDULE_KIND (c) == OMP_CLAUSE_SCHEDULE_AUTO)
- error ("%Hschedule %<auto%> does not take "
- "a %<chunk_size%> parameter", &token->location);
+ error_at (token->location, "schedule %<auto%> does not take "
+ "a %<chunk_size%> parameter");
else
OMP_CLAUSE_SCHEDULE_CHUNK_EXPR (c) = t;
check_no_duplicate_clause (list, OMP_CLAUSE_UNTIED, "untied", location);
- c = build_omp_clause (OMP_CLAUSE_UNTIED);
+ c = build_omp_clause (location, OMP_CLAUSE_UNTIED);
OMP_CLAUSE_CHAIN (c) = list;
return c;
}
/* Remove the invalid clause(s) from the list to avoid
confusing the rest of the compiler. */
clauses = prev;
- error ("%H%qs is not valid for %qs", &token->location, c_name, where);
+ error_at (token->location, "%qs is not valid for %qs", c_name, where);
}
}
saw_error:
cp_parser_require_pragma_eol (parser, pragma_tok);
stmt = cp_parser_omp_structured_block (parser);
- return c_finish_omp_critical (stmt, name);
+ return c_finish_omp_critical (input_location, stmt, name);
}
/* OpenMP 2.5:
cp_parser_omp_flush (cp_parser *parser, cp_token *pragma_tok)
{
if (cp_lexer_next_token_is (parser->lexer, CPP_OPEN_PAREN))
- (void) cp_parser_omp_var_list (parser, 0, NULL);
+ (void) cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
cp_parser_require_pragma_eol (parser, pragma_tok);
finish_omp_flush ();
static tree
cp_parser_omp_for_cond (cp_parser *parser, tree decl)
{
- tree lhs = cp_parser_cast_expression (parser, false, false, NULL), rhs;
- enum tree_code op;
- cp_token *token;
+ tree cond = cp_parser_binary_expression (parser, false, true,
+ PREC_NOT_OPERATOR, NULL);
+ bool overloaded_p;
- if (lhs != decl)
+ if (cond == error_mark_node
+ || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
{
cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
- token = cp_lexer_peek_token (parser->lexer);
- op = binops_by_token [token->type].tree_type;
- switch (op)
+ switch (TREE_CODE (cond))
{
- case LT_EXPR:
- case LE_EXPR:
case GT_EXPR:
case GE_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
break;
default:
- cp_parser_skip_to_end_of_statement (parser);
return error_mark_node;
}
- cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false,
- PREC_RELATIONAL_EXPRESSION, NULL);
- if (rhs == error_mark_node
- || cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- {
- cp_parser_skip_to_end_of_statement (parser);
- return error_mark_node;
- }
+ /* If decl is an iterator, preserve LHS and RHS of the relational
+ expr until finish_omp_for. */
+ if (decl
+ && (type_dependent_expression_p (decl)
+ || CLASS_TYPE_P (TREE_TYPE (decl))))
+ return cond;
- return build2 (op, boolean_type_node, lhs, rhs);
+ return build_x_binary_op (TREE_CODE (cond),
+ TREE_OPERAND (cond, 0), ERROR_MARK,
+ TREE_OPERAND (cond, 1), ERROR_MARK,
+ &overloaded_p, tf_warning_or_error);
}
/* Helper function, to parse omp for increment expression. */
return build2 (MODIFY_EXPR, TREE_TYPE (decl), decl, rhs);
}
- lhs = cp_parser_binary_expression (parser, false,
+ lhs = cp_parser_binary_expression (parser, false, false,
PREC_ADDITIVE_EXPRESSION, NULL);
token = cp_lexer_peek_token (parser->lexer);
decl_first = lhs == decl;
{
op = token->type == CPP_PLUS ? PLUS_EXPR : MINUS_EXPR;
cp_lexer_consume_token (parser->lexer);
- rhs = cp_parser_binary_expression (parser, false,
+ rhs = cp_parser_binary_expression (parser, false, false,
PREC_ADDITIVE_EXPRESSION, NULL);
token = cp_lexer_peek_token (parser->lexer);
if (token->type == CPP_PLUS || token->type == CPP_MINUS || decl_first)
cp_parser_condition, from whence the bulk of this is copied. */
cp_parser_parse_tentatively (parser);
- cp_parser_type_specifier_seq (parser, /*is_condition=*/false,
+ cp_parser_type_specifier_seq (parser, /*is_declaration=*/true,
+ /*is_trailing_return=*/false,
&type_specifiers);
if (cp_parser_parse_definitely (parser))
{
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);
+ error_at (loc, "iteration variable %qD"
+ " should not be firstprivate", real_decl);
*c = OMP_CLAUSE_CHAIN (*c);
}
else if (OMP_CLAUSE_CODE (*c) == OMP_CLAUSE_LASTPRIVATE
{
/* Add lastprivate (decl) clause to OMP_FOR_CLAUSES,
change it to shared (decl) in OMP_PARALLEL_CLAUSES. */
- tree l = build_omp_clause (OMP_CLAUSE_LASTPRIVATE);
+ tree l = build_omp_clause (loc, OMP_CLAUSE_LASTPRIVATE);
OMP_CLAUSE_DECL (l) = real_decl;
OMP_CLAUSE_CHAIN (l) = clauses;
CP_OMP_CLAUSE_INFO (l) = CP_OMP_CLAUSE_INFO (*c);
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);
+ error_at (loc, "iteration variable %qD "
+ "should not be firstprivate",
+ 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);
+ error_at (loc, "iteration variable %qD should not be reduction",
+ decl);
}
if (c == NULL)
{
- c = build_omp_clause (OMP_CLAUSE_PRIVATE);
+ c = build_omp_clause (loc, OMP_CLAUSE_PRIVATE);
OMP_CLAUSE_DECL (c) = decl;
c = finish_omp_clauses (c);
if (c)
cond = NULL;
if (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON))
- {
- /* If decl is an iterator, preserve LHS and RHS of the relational
- expr until finish_omp_for. */
- if (decl
- && (type_dependent_expression_p (decl)
- || CLASS_TYPE_P (TREE_TYPE (decl))))
- cond = cp_parser_omp_for_cond (parser, decl);
- else
- cond = cp_parser_condition (parser);
- }
+ cond = cp_parser_omp_for_cond (parser, decl);
cp_parser_require (parser, CPP_SEMICOLON, "%<;%>");
incr = NULL;
else
{
loc = cp_lexer_peek_token (parser->lexer)->location;
- error ("%Hnot enough collapsed for loops", &loc);
+ error_at (loc, "not enough collapsed for loops");
collapse_err = true;
cp_parser_abort_tentative_parse (parser);
declv = NULL_TREE;
{
if (!collapse_err)
{
- location_t loc = cp_lexer_peek_token (parser->lexer)->location;
- error ("%Hcollapsed loops not perfectly nested", &loc);
+ error_at (cp_lexer_peek_token (parser->lexer)->location,
+ "collapsed loops not perfectly nested");
}
collapse_err = true;
cp_parser_statement_seq_opt (parser, NULL);
- cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ break;
}
}
cp_parser_omp_master (cp_parser *parser, cp_token *pragma_tok)
{
cp_parser_require_pragma_eol (parser, pragma_tok);
- return c_finish_omp_master (cp_parser_omp_structured_block (parser));
+ return c_finish_omp_master (input_location,
+ cp_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
static tree
cp_parser_omp_ordered (cp_parser *parser, cp_token *pragma_tok)
{
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
cp_parser_require_pragma_eol (parser, pragma_tok);
- return c_finish_omp_ordered (cp_parser_omp_structured_block (parser));
+ return c_finish_omp_ordered (loc, cp_parser_omp_structured_block (parser));
}
/* OpenMP 2.5:
tree stmt, clauses, par_clause, ws_clause, block;
unsigned int mask = OMP_PARALLEL_CLAUSE_MASK;
unsigned int save;
+ location_t loc = cp_lexer_peek_token (parser->lexer)->location;
if (cp_lexer_next_token_is_keyword (parser->lexer, RID_FOR))
{
break;
case PRAGMA_OMP_PARALLEL_FOR:
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
cp_parser_omp_for_loop (parser, ws_clause, &par_clause);
break;
case PRAGMA_OMP_PARALLEL_SECTIONS:
- c_split_parallel_clauses (clauses, &par_clause, &ws_clause);
+ c_split_parallel_clauses (loc, clauses, &par_clause, &ws_clause);
stmt = cp_parser_omp_sections_scope (parser);
if (stmt)
OMP_SECTIONS_CLAUSES (stmt) = ws_clause;
{
tree vars;
- vars = cp_parser_omp_var_list (parser, 0, NULL);
+ vars = cp_parser_omp_var_list (parser, OMP_CLAUSE_ERROR, NULL);
cp_parser_require_pragma_eol (parser, pragma_tok);
finish_omp_threadprivate (vars);
cp_lexer_get_preprocessor_token (NULL, first_token);
if (first_token->type != CPP_PRAGMA_EOL)
- error ("%Hjunk at end of %<#pragma GCC pch_preprocess%>",
- &first_token->location);
+ error_at (first_token->location,
+ "junk at end of %<#pragma GCC pch_preprocess%>");
}
else
- error ("%Hexpected string literal", &first_token->location);
+ error_at (first_token->location, "expected string literal");
/* 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 ("%H%<#pragma GCC pch_preprocess%> must be first",
- &pragma_tok->location);
+ error_at (pragma_tok->location,
+ "%<#pragma GCC pch_preprocess%> must be first");
break;
case PRAGMA_OMP_BARRIER:
cp_parser_omp_barrier (parser, pragma_tok);
return false;
case pragma_stmt:
- error ("%H%<#pragma omp barrier%> may only be "
- "used in compound statements", &pragma_tok->location);
+ error_at (pragma_tok->location, "%<#pragma omp barrier%> may only be "
+ "used in compound statements");
break;
default:
goto bad_stmt;
cp_parser_omp_flush (parser, pragma_tok);
return false;
case pragma_stmt:
- error ("%H%<#pragma omp flush%> may only be "
- "used in compound statements", &pragma_tok->location);
+ error_at (pragma_tok->location, "%<#pragma omp flush%> may only be "
+ "used in compound statements");
break;
default:
goto bad_stmt;
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);
+ error_at (pragma_tok->location,
+ "%<#pragma omp taskwait%> may only be "
+ "used in compound statements");
break;
default:
goto bad_stmt;
return true;
case PRAGMA_OMP_SECTION:
- error ("%H%<#pragma omp section%> may only be used in "
- "%<#pragma omp sections%> construct", &pragma_tok->location);
+ error_at (pragma_tok->location,
+ "%<#pragma omp section%> may only be used in "
+ "%<#pragma omp sections%> construct");
break;
default:
void
c_parse_file (void)
{
- bool error_occurred;
static bool already_called = false;
if (already_called)
the_parser = cp_parser_new ();
push_deferring_access_checks (flag_access_control
? dk_no_deferred : dk_no_check);
- error_occurred = cp_parser_translation_unit (the_parser);
+ cp_parser_translation_unit (the_parser);
the_parser = NULL;
}