#include "target.h"
#include "cgraph.h"
#include "c-common.h"
+#include "plugin.h"
\f
/* The lexer. */
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
/* 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;
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);
static tree cp_parser_type_id
(cp_parser *);
+static tree cp_parser_template_type_arg
+ (cp_parser *);
+static tree cp_parser_type_id_1
+ (cp_parser *, bool);
static void cp_parser_type_specifier_seq
(cp_parser *, bool, cp_decl_specifier_seq *);
static tree cp_parser_parameter_declaration_clause
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
{
if (count > 2)
error ("%H%<long long long%> is too long for GCC", &location);
- else if (pedantic && !in_system_header && warn_long_long
- && cxx_dialect == cxx98)
- pedwarn (location, OPT_Wlong_long,
- "ISO C++ 1998 does not support %<long long%>");
+ else
+ pedwarn_cxx98 (location, OPT_Wlong_long,
+ "ISO C++ 1998 does not support %<long long%>");
}
else if (count > 1)
{
/* Stop if this is an unnested '}', or closes the outermost
nesting level. */
nesting_depth--;
+ if (nesting_depth < 0)
+ return;
if (!nesting_depth)
nesting_depth = -1;
break;
case CPP_WCHAR:
case CPP_NUMBER:
token = cp_lexer_consume_token (parser->lexer);
+ if (TREE_CODE (token->u.value) == FIXED_CST)
+ {
+ error ("%Hfixed-point types not supported in C++",
+ &token->location);
+ return error_mark_node;
+ }
/* Floating-point literals are only allowed in an integral
constant expression if they are cast to an integral or
enumeration type. */
/* 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
}
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)
{
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
if (!DECL_FUNCTION_MEMBER_P (fn))
{
koenig_p = true;
- postfix_expression
- = perform_koenig_lookup (postfix_expression, args);
+ if (!any_type_dependent_arguments_p (args))
+ postfix_expression
+ = perform_koenig_lookup (postfix_expression, args);
}
}
}
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;
}
new_declarator = NULL;
}
- type = groktypename (&type_specifier_seq, new_declarator);
+ type = groktypename (&type_specifier_seq, new_declarator, false);
return type;
}
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)
{
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')
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,
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))
/* Avoid calling cp_parser_compound_statement, so that we
don't create a new scope. Do everything else by hand. */
cp_parser_require (parser, CPP_OPEN_BRACE, "%<{%>");
+ /* If the next keyword is `__label__' we have a label declaration. */
+ while (cp_lexer_next_token_is_keyword (parser->lexer, RID_LABEL))
+ cp_parser_label_declaration (parser);
+ /* Parse an (optional) statement-seq. */
cp_parser_statement_seq_opt (parser, NULL_TREE);
cp_parser_require (parser, CPP_CLOSE_BRACE, "%<}%>");
}
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;
&& !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))
Therefore, we try a type-id first. */
cp_parser_parse_tentatively (parser);
- argument = cp_parser_type_id (parser);
+ argument = cp_parser_template_type_arg (parser);
/* If there was no error parsing the type-id but the next token is a
'>>', our behavior depends on which dialect of C++ we're
parsing. In C++98, we probably found a typo for '> >'. But there
was the only alternative that matched (albeit with a '>' after
it). We can assume it's just a typo from the user, and a
diagnostic will then be issued. */
- return cp_parser_type_id (parser);
+ return cp_parser_template_type_arg (parser);
}
/* Parse an explicit-instantiation.
if (!begin_specialization ())
{
end_specialization ();
- cp_parser_skip_to_end_of_block_or_statement (parser);
return;
}
cp_parser_parse_tentatively (parser);
/* Look for the class-specifier. */
type_spec = cp_parser_class_specifier (parser);
+ invoke_plugin_callbacks (PLUGIN_FINISH_TYPE, type_spec);
/* If that worked, we're done. */
if (cp_parser_parse_definitely (parser))
{
type = make_typename_type (parser->scope, decl,
typename_type,
/*complain=*/tf_error);
- else
+ /* If the `typename' keyword is in effect and DECL is not a type
+ decl. Then type is non existant. */
+ else if (tag_type == typename_type && TREE_CODE (decl) != TYPE_DECL)
+ type = NULL_TREE;
+ else
type = TREE_TYPE (decl);
}
there were no qualifying templates. */
if (!cp_parser_check_template_parameters (parser,
/*num_templates=*/0,
- token->location))
+ token->location,
+ /*declarator=*/NULL))
return error_mark_node;
type = xref_tag (tag_type, identifier, ts, template_p);
}
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);
}
&non_constant_p);
if (!non_constant_p)
bounds = fold_non_dependent_expr (bounds);
+ else if (processing_template_decl)
+ {
+ /* Remember this wasn't a constant-expression. */
+ bounds = build_nop (TREE_TYPE (bounds), bounds);
+ TREE_SIDE_EFFECTS (bounds) = 1;
+ }
+
/* Normally, the array bound must be an integral constant
expression. However, as an extension, we allow VLAs
in function scopes. */
Returns the TYPE specified. */
static tree
-cp_parser_type_id (cp_parser* parser)
+cp_parser_type_id_1 (cp_parser* parser, bool is_template_arg)
{
cp_decl_specifier_seq type_specifier_seq;
cp_declarator *abstract_declarator;
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);
+}
+
+static tree cp_parser_template_type_arg (cp_parser *parser)
+{
+ return cp_parser_type_id_1 (parser, true);
}
/* Parse a type-specifier-seq.
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);
/* 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. */
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
cannot look up the name if the scope is not a class type; it
might, for example, be a template type parameter. */
dependent_p = (TYPE_P (parser->scope)
- && !(parser->in_declarator_p
- && currently_open_class (parser->scope))
- && dependent_type_p (parser->scope));
+ && dependent_scope_p (parser->scope));
if ((check_dependency || !CLASS_TYPE_P (parser->scope))
- && dependent_p)
- {
- if (tag_type)
- {
- tree type;
-
- /* The resolution to Core Issue 180 says that `struct
- A::B' should be considered a type-name, even if `A'
- is dependent. */
- type = make_typename_type (parser->scope, name, tag_type,
- /*complain=*/tf_error);
- decl = TYPE_NAME (type);
- }
- else if (is_template
- && (cp_parser_next_token_ends_template_argument_p (parser)
- || cp_lexer_next_token_is (parser->lexer,
- CPP_CLOSE_PAREN)))
- decl = make_unbound_class_template (parser->scope,
- name, NULL_TREE,
- /*complain=*/tf_error);
- else
- decl = build_qualified_name (/*type=*/NULL_TREE,
- parser->scope, name,
- is_template);
- }
+ && dependent_p)
+ /* Defer lookup. */
+ decl = error_mark_node;
else
{
tree pushed_scope = NULL_TREE;
/*complain=*/true);
/* If we have a single function from a using decl, pull it out. */
- if (decl
- && TREE_CODE (decl) == OVERLOAD
+ if (TREE_CODE (decl) == OVERLOAD
&& !really_overloaded_fn (decl))
decl = OVL_FUNCTION (decl);
if (pushed_scope)
pop_scope (pushed_scope);
}
+
+ /* If the scope is a dependent type and either we deferred lookup or
+ we did lookup but didn't find the name, rememeber the name. */
+ if (decl == error_mark_node && TYPE_P (parser->scope)
+ && dependent_type_p (parser->scope))
+ {
+ if (tag_type)
+ {
+ tree type;
+
+ /* The resolution to Core Issue 180 says that `struct
+ A::B' should be considered a type-name, even if `A'
+ is dependent. */
+ type = make_typename_type (parser->scope, name, tag_type,
+ /*complain=*/tf_error);
+ decl = TYPE_NAME (type);
+ }
+ else if (is_template
+ && (cp_parser_next_token_ends_template_argument_p (parser)
+ || cp_lexer_next_token_is (parser->lexer,
+ CPP_CLOSE_PAREN)))
+ decl = make_unbound_class_template (parser->scope,
+ name, NULL_TREE,
+ /*complain=*/tf_error);
+ else
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope, name,
+ is_template);
+ }
parser->qualifying_scope = parser->scope;
parser->object_scope = NULL_TREE;
}
additional level of template parameters. */
++num_templates;
- return cp_parser_check_template_parameters (parser,
- num_templates,
- declarator_location);
+ return cp_parser_check_template_parameters
+ (parser, num_templates, declarator_location, declarator);
+
case cdk_function:
case cdk_array:
/* NUM_TEMPLATES were used in the current declaration. If that is
invalid, return FALSE and issue an error messages. Otherwise,
- return TRUE. */
+ return TRUE. If DECLARATOR is non-NULL, then we are checking a
+ declarator and we can print more accurate diagnostics. */
static bool
cp_parser_check_template_parameters (cp_parser* parser,
unsigned num_templates,
- location_t location)
+ location_t location,
+ cp_declarator *declarator)
{
+ /* If there are the same number of template classes and parameter
+ lists, that's OK. */
+ if (parser->num_template_parameter_lists == num_templates)
+ return true;
+ /* If there are more, but only one more, then we are referring to a
+ member template. That's OK too. */
+ if (parser->num_template_parameter_lists == num_templates + 1)
+ return true;
/* If there are more template classes than parameter lists, we have
something like:
template <class T> void S<T>::R<T>::f (); */
if (parser->num_template_parameter_lists < num_templates)
{
- error ("%Htoo few template-parameter-lists", &location);
+ if (declarator)
+ error_at (location, "specializing member %<%T::%E%> "
+ "requires %<template<>%> syntax",
+ declarator->u.id.qualifying_scope,
+ declarator->u.id.unqualified_name);
+ else
+ error_at (location, "too few template-parameter-lists");
return false;
}
- /* If there are the same number of template classes and parameter
- lists, that's OK. */
- if (parser->num_template_parameter_lists == num_templates)
- return true;
- /* If there are more, but only one more, then we are referring to a
- member template. That's OK too. */
- if (parser->num_template_parameter_lists == num_templates + 1)
- return true;
/* Otherwise, there are too many template parameter lists. We have
something like:
/* 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);
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)
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;
{
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);