cp_token *token;
/* N is 1-based, not zero-based. */
- gcc_assert (n > 0 && lexer->next_token != &eof_token);
-
+ gcc_assert (n > 0);
+
if (cp_lexer_debugging_p (lexer))
fprintf (cp_lexer_debug_stream,
"cp_lexer: peeking ahead %ld at token: ", (long)n);
--n;
token = lexer->next_token;
+ gcc_assert (!n || token != &eof_token);
while (n != 0)
{
++token;
/* Expressions [gram.expr] */
static tree cp_parser_primary_expression
- (cp_parser *, bool, cp_id_kind *, tree *);
+ (cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression
(cp_parser *, bool, bool, bool *, bool);
static tree cp_parser_unqualified_id
declarator_obstack_base = obstack_next_free (&declarator_obstack);
}
- while (true)
+ cp_parser_declaration_seq_opt (parser);
+
+ /* If there are no tokens left then all went well. */
+ if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
+ {
+ /* Get rid of the token array; we don't need it any more. */
+ cp_lexer_destroy (parser->lexer);
+ parser->lexer = NULL;
+
+ /* This file might have been a context that's implicitly extern
+ "C". If so, pop the lang context. (Only relevant for PCH.) */
+ if (parser->implicit_extern_c)
+ {
+ pop_lang_context ();
+ parser->implicit_extern_c = false;
+ }
+
+ /* Finish up. */
+ finish_translation_unit ();
+
+ success = true;
+ }
+ else
{
- cp_parser_declaration_seq_opt (parser);
-
- /* If there are no tokens left then all went well. */
- if (cp_lexer_next_token_is (parser->lexer, CPP_EOF))
- {
- /* Get rid of the token array; we don't need it any more. */
- cp_lexer_destroy (parser->lexer);
- parser->lexer = NULL;
-
- /* This file might have been a context that's implicitly extern
- "C". If so, pop the lang context. (Only relevant for PCH.) */
- if (parser->implicit_extern_c)
- {
- pop_lang_context ();
- parser->implicit_extern_c = false;
- }
-
- /* Finish up. */
- finish_translation_unit ();
-
- success = true;
- break;
- }
- else
- {
- cp_parser_error (parser, "expected declaration");
- success = false;
- break;
- }
+ cp_parser_error (parser, "expected declaration");
+ success = false;
}
-
+
/* Make sure the declarator obstack was fully cleaned up. */
gcc_assert (obstack_next_free (&declarator_obstack)
== declarator_obstack_base);
literal:
__null
- CAST_P is true if this primary expression is the target of a cast.
-
- Returns a representation of the expression.
+ ADDRESS_P is true iff this expression was immediately preceded by
+ "&" and therefore might denote a pointer-to-member. CAST_P is true
+ iff this expression is the target of a cast. TEMPLATE_ARG_P is
+ true iff this expression is a tempalte argument.
- *IDK indicates what kind of id-expression (if any) was present.
-
- *QUALIFYING_CLASS is set to a non-NULL value if the id-expression can be
- used as the operand of a pointer-to-member. In that case,
- *QUALIFYING_CLASS gives the class that is used as the qualifying
- class in the pointer-to-member. */
+ Returns a representation of the expression. Upon return, *IDK
+ indicates what kind of id-expression (if any) was present. */
static tree
cp_parser_primary_expression (cp_parser *parser,
+ bool address_p,
bool cast_p,
- cp_id_kind *idk,
- tree *qualifying_class)
+ bool template_arg_p,
+ cp_id_kind *idk)
{
cp_token *token;
/* Assume the primary expression is not an id-expression. */
*idk = CP_ID_KIND_NONE;
- /* And that it cannot be used as pointer-to-member. */
- *qualifying_class = NULL_TREE;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* The end of the cast-expression. */
&& next_token->type != CPP_CLOSE_PAREN
/* The end of an array bound. */
- && next_token->type != CPP_CLOSE_SQUARE)
+ && next_token->type != CPP_CLOSE_SQUARE
+ /* The closing ">" in a template-argument-list. */
+ && (next_token->type != CPP_GREATER
+ || parser->greater_than_is_operator_p))
cast_p = false;
}
tree id_expression;
tree decl;
const char *error_msg;
+ bool template_p;
+ bool done;
id_expression:
/* Parse the id-expression. */
= cp_parser_id_expression (parser,
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
- /*template_p=*/NULL,
+ &template_p,
/*declarator_p=*/false);
if (id_expression == error_mark_node)
return error_mark_node;
+ token = cp_lexer_peek_token (parser->lexer);
+ done = (token->type != CPP_OPEN_SQUARE
+ && token->type != CPP_OPEN_PAREN
+ && token->type != CPP_DOT
+ && token->type != CPP_DEREF
+ && token->type != CPP_PLUS_PLUS
+ && token->type != CPP_MINUS_MINUS);
/* If we have a template-id, then no further lookup is
required. If the template-id was for a template-class, we
will sometimes have a TYPE_DECL at this point. */
- else if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR
- || TREE_CODE (id_expression) == TYPE_DECL)
+ if (TREE_CODE (id_expression) == TEMPLATE_ID_EXPR
+ || TREE_CODE (id_expression) == TYPE_DECL)
decl = id_expression;
/* Look up the name. */
else
decl = cp_parser_lookup_name (parser, id_expression,
none_type,
- /*is_template=*/false,
+ template_p,
/*is_namespace=*/false,
/*check_dependency=*/true,
&ambiguous_p);
decl = objc_lookup_ivar (decl, id_expression);
/* If name lookup gives us a SCOPE_REF, then the
- qualifying scope was dependent. Just propagate the
- name. */
+ qualifying scope was dependent. */
if (TREE_CODE (decl) == SCOPE_REF)
- {
- if (TYPE_P (TREE_OPERAND (decl, 0)))
- *qualifying_class = TREE_OPERAND (decl, 0);
- return decl;
- }
+ return decl;
/* Check to see if DECL is a local variable in a context
where that is forbidden. */
if (parser->local_variables_forbidden_p
}
}
- decl = finish_id_expression (id_expression, decl, parser->scope,
- idk, qualifying_class,
- parser->integral_constant_expression_p,
- parser->allow_non_integral_constant_expression_p,
- &parser->non_integral_constant_expression_p,
- &error_msg);
+ decl = (finish_id_expression
+ (id_expression, decl, parser->scope,
+ idk,
+ parser->integral_constant_expression_p,
+ parser->allow_non_integral_constant_expression_p,
+ &parser->non_integral_constant_expression_p,
+ template_p, done, address_p,
+ template_arg_p,
+ &error_msg));
if (error_msg)
cp_parser_error (parser, error_msg);
return decl;
/* Assume the `template' keyword was not used. */
if (template_p)
- *template_p = false;
+ *template_p = template_keyword_p;
/* Look for the optional `::' operator. */
global_scope_p
}
break;
}
-
/* We've found one valid nested-name-specifier. */
success = true;
- /* Make sure we look in the right scope the next time through
- the loop. */
- parser->scope = (TREE_CODE (new_scope) == TYPE_DECL
- ? TREE_TYPE (new_scope)
- : new_scope);
+ /* Name lookup always gives us a DECL. */
+ if (TREE_CODE (new_scope) == TYPE_DECL)
+ new_scope = TREE_TYPE (new_scope);
+ /* Uses of "template" must be followed by actual templates. */
+ if (template_keyword_p
+ && !(CLASS_TYPE_P (new_scope)
+ && ((CLASSTYPE_USE_TEMPLATE (new_scope)
+ && PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (new_scope)))
+ || CLASSTYPE_IS_TEMPLATE (new_scope)))
+ && !(TREE_CODE (new_scope) == TYPENAME_TYPE
+ && (TREE_CODE (TYPENAME_TYPE_FULLNAME (new_scope))
+ == TEMPLATE_ID_EXPR)))
+ pedwarn (TYPE_P (new_scope)
+ ? "%qT is not a template"
+ : "%qD is not a template",
+ new_scope);
/* If it is a class scope, try to complete it; we are about to
be looking up names inside the class. */
- if (TYPE_P (parser->scope)
+ if (TYPE_P (new_scope)
/* Since checking types for dependency can be expensive,
avoid doing it if the type is already complete. */
- && !COMPLETE_TYPE_P (parser->scope)
+ && !COMPLETE_TYPE_P (new_scope)
/* Do not try to complete dependent types. */
- && !dependent_type_p (parser->scope))
- complete_type (parser->scope);
+ && !dependent_type_p (new_scope))
+ new_scope = complete_type (new_scope);
+ /* Make sure we look in the right scope the next time through
+ the loop. */
+ parser->scope = new_scope;
}
/* Retrieve any deferred checks. Do not pop this access checks yet
enum rid keyword;
cp_id_kind idk = CP_ID_KIND_NONE;
tree postfix_expression = NULL_TREE;
- /* Non-NULL only if the current postfix-expression can be used to
- form a pointer-to-member. In that case, QUALIFYING_CLASS is the
- class used to qualify the member. */
- tree qualifying_class = NULL_TREE;
/* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer);
/* Consume the `typename' token. */
cp_lexer_consume_token (parser->lexer);
+
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
/*current_scope_valid_p=*/false);
return error_mark_node;
/* If we look up a template-id in a non-dependent qualifying
scope, there's no need to create a dependent type. */
- else if (TREE_CODE (id) == TYPE_DECL
- && !dependent_type_p (parser->scope))
+ if (TREE_CODE (id) == TYPE_DECL
+ && (!TYPE_P (scope)
+ || !dependent_type_p (parser->scope)))
type = TREE_TYPE (id);
/* Create a TYPENAME_TYPE to represent the type to which the
functional cast is being performed. */
}
/* It must be a primary-expression. */
- postfix_expression = cp_parser_primary_expression (parser,
- cast_p,
- &idk,
- &qualifying_class);
+ postfix_expression
+ = cp_parser_primary_expression (parser, address_p, cast_p,
+ /*template_arg_p=*/false,
+ &idk);
}
break;
}
- /* If we were avoiding committing to the processing of a
- qualified-id until we knew whether or not we had a
- pointer-to-member, we now know. */
- if (qualifying_class)
- {
- bool done;
-
- /* Peek at the next token. */
- token = cp_lexer_peek_token (parser->lexer);
- done = (token->type != CPP_OPEN_SQUARE
- && token->type != CPP_OPEN_PAREN
- && token->type != CPP_DOT
- && token->type != CPP_DEREF
- && token->type != CPP_PLUS_PLUS
- && token->type != CPP_MINUS_MINUS);
-
- postfix_expression = finish_qualified_id_expr (qualifying_class,
- postfix_expression,
- done,
- address_p);
- if (done)
- return postfix_expression;
- }
-
/* Keep looping until the postfix-expression is complete. */
while (true)
{
{
tree name;
bool dependent_p;
- bool template_p;
bool pseudo_destructor_p;
tree scope = NULL_TREE;
/* If the SCOPE is not a scalar type, we are looking at an
ordinary class member access expression, rather than a
pseudo-destructor-name. */
- template_p = cp_parser_optional_template_keyword (parser);
+ bool template_p;
/* Parse the id-expression. */
- name = cp_parser_id_expression (parser, template_p,
- /*check_dependency_p=*/true,
- /*template_p=*/NULL,
- /*declarator_p=*/false);
+ name = (cp_parser_id_expression
+ (parser,
+ cp_parser_optional_template_keyword (parser),
+ /*check_dependency_p=*/true,
+ &template_p,
+ /*declarator_p=*/false));
/* In general, build a SCOPE_REF if the member name is qualified.
However, if the name was not dependent and has already been
resolved; there is no need to build the SCOPE_REF. For example;
{
if (name != error_mark_node && !BASELINK_P (name) && parser->scope)
{
- name = build_nt (SCOPE_REF, parser->scope, name);
+ name = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope,
+ name,
+ template_p);
parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
adjust_result_of_qualified_name_lookup
(name, BINFO_TYPE (BASELINK_BINFO (name)), scope);
postfix_expression
- = finish_class_member_access_expr (postfix_expression, name);
+ = finish_class_member_access_expr (postfix_expression, name,
+ template_p);
}
}
cp_lexer_handle_pragma (parser->lexer);
return;
}
+ else if (token->type == CPP_EOF)
+ {
+ cp_parser_error (parser, "expected statement");
+ return;
+ }
/* Everything else must be a declaration-statement or an
expression-statement. Try for the declaration-statement
tree *arg_ary = fixed_args;
tree vec;
bool saved_in_template_argument_list_p;
+ bool saved_ice_p;
+ bool saved_non_ice_p;
saved_in_template_argument_list_p = parser->in_template_argument_list_p;
parser->in_template_argument_list_p = true;
+ /* Even if the template-id appears in an integral
+ constant-expression, the contents of the argument list do
+ not. */
+ saved_ice_p = parser->integral_constant_expression_p;
+ parser->integral_constant_expression_p = false;
+ saved_non_ice_p = parser->non_integral_constant_expression_p;
+ parser->non_integral_constant_expression_p = false;
+ /* Parse the arguments. */
do
{
tree argument;
if (arg_ary != fixed_args)
free (arg_ary);
+ 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;
return vec;
}
bool maybe_type_id = false;
cp_token *token;
cp_id_kind idk;
- tree qualifying_class;
/* There's really no way to know what we're looking at, so we just
try each alternative in order.
{
cp_parser_parse_tentatively (parser);
argument = cp_parser_primary_expression (parser,
+ /*adress_p=*/false,
/*cast_p=*/false,
- &idk,
- &qualifying_class);
+ /*template_arg_p=*/true,
+ &idk);
if (TREE_CODE (argument) != TEMPLATE_PARM_INDEX
|| !cp_parser_next_token_ends_template_argument_p (parser))
cp_parser_simulate_error (parser);
{
cp_parser_parse_tentatively (parser);
argument = cp_parser_primary_expression (parser,
+ address_p,
/*cast_p=*/false,
- &idk,
- &qualifying_class);
+ /*template_arg_p=*/true,
+ &idk);
if (cp_parser_error_occurred (parser)
|| !cp_parser_next_token_ends_template_argument_p (parser))
cp_parser_abort_tentative_parse (parser);
argument = TREE_OPERAND (argument, 0);
}
- if (qualifying_class)
- argument = finish_qualified_id_expr (qualifying_class,
- argument,
- /*done=*/true,
- address_p);
+ if (TREE_CODE (argument) == BASELINK)
+ /* We don't need the information about what class was used
+ to name the overloaded functions. */
+ argument = BASELINK_FUNCTIONS (argument);
+
if (TREE_CODE (argument) == VAR_DECL)
{
/* A variable without external linkage might still be a
declaration context. */
tag_scope ts;
+ bool template_p;
+
if (is_friend)
/* Friends have special name lookup rules. */
ts = ts_within_enclosing_non_class;
warning (OPT_Wattributes,
"type attributes are honored only at type definition");
- type = xref_tag (tag_type, identifier, ts,
- parser->num_template_parameter_lists);
+ template_p =
+ (parser->num_template_parameter_lists
+ && (cp_parser_next_token_starts_class_definition_p (parser)
+ || cp_lexer_next_token_is (parser->lexer, CPP_SEMICOLON)));
+ type = xref_tag (tag_type, identifier, ts, template_p);
}
}
if (tag_type != enum_type)
if (namespace_decl == error_mark_node
|| TREE_CODE (namespace_decl) != NAMESPACE_DECL)
{
+ if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+ error ("%qD is not a namespace-name", identifier);
cp_parser_error (parser, "expected namespace-name");
namespace_decl = error_mark_node;
}
}
decl = grokfield (declarator, decl_specifiers,
initializer, /*asmspec=*/NULL_TREE,
- /*attributes=*/NULL_TREE);
+ prefix_attributes);
if (decl && TREE_CODE (decl) == FUNCTION_DECL)
cp_parser_save_default_args (parser, decl);
}
tree fn;
tree class_type = NULL_TREE;
tree pushed_scope = NULL_TREE;
-
+
/* In a first pass, parse default arguments to the functions.
Then, in a second pass, parse the bodies of the functions.
This two-phased approach handles cases like:
{
/* Figure out which function we need to process. */
fn = TREE_VALUE (queue_entry);
-
- /* A hack to prevent garbage collection. */
- function_depth++;
-
/* Parse the function. */
cp_parser_late_parsing_for_member (parser, fn);
- function_depth--;
}
}
static tree
cp_parser_lookup_name (cp_parser *parser, tree name,
enum tag_types tag_type,
- bool is_template, bool is_namespace,
+ bool is_template,
+ bool is_namespace,
bool check_dependency,
bool *ambiguous_p)
{
+ int flags = 0;
tree decl;
tree object_type = parser->context->object_type;
+ if (!cp_parser_uncommitted_to_tentative_parse_p (parser))
+ flags |= LOOKUP_COMPLAIN;
+
/* Assume that the lookup will be unambiguous. */
if (ambiguous_p)
*ambiguous_p = false;
/*complain=*/1);
decl = TYPE_NAME (type);
}
- else if (is_template)
+ 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=*/1);
else
- decl = build_nt (SCOPE_REF, parser->scope, name);
+ decl = build_qualified_name (/*type=*/NULL_TREE,
+ parser->scope, name,
+ is_template);
}
else
{
/* Look it up in the enclosing context, too. */
decl = lookup_name_real (name, tag_type != none_type,
/*nonclass=*/0,
- /*block_p=*/true, is_namespace,
- /*flags=*/0);
+ /*block_p=*/true, is_namespace, flags);
parser->object_scope = object_type;
parser->qualifying_scope = NULL_TREE;
if (object_decl)
{
decl = lookup_name_real (name, tag_type != none_type,
/*nonclass=*/0,
- /*block_p=*/true, is_namespace,
- /*flags=*/0);
+ /*block_p=*/true, is_namespace, flags);
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
}
cast = build_functional_cast (type, expression_list);
/* [expr.const]/1: In an integral constant expression "only type
conversions to integral or enumeration type can be used". */
- if (cast != error_mark_node && !type_dependent_expression_p (type)
- && !INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (type)))
+ if (TREE_CODE (type) == TYPE_DECL)
+ type = TREE_TYPE (type);
+ if (cast != error_mark_node && !dependent_type_p (type)
+ && !INTEGRAL_OR_ENUMERATION_TYPE_P (type))
{
if (cp_parser_non_integral_constant_expression
(parser, "a call to a constructor"))
tree saved_qualifying_scope;
tree saved_object_scope;
bool saved_greater_than_is_operator_p;
+ bool saved_skip_evaluation;
/* [temp.names]
saved_scope = parser->scope;
saved_qualifying_scope = parser->qualifying_scope;
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;
/* Parse the template-argument-list itself. */
if (cp_lexer_next_token_is (parser->lexer, CPP_GREATER))
arguments = NULL_TREE;
parser->scope = saved_scope;
parser->qualifying_scope = saved_qualifying_scope;
parser->object_scope = saved_object_scope;
+ skip_evaluation = saved_skip_evaluation;
return arguments;
}
/* Parse the assignment-expression. */
parsed_arg = cp_parser_assignment_expression (parser, /*cast_p=*/false);
+ if (!processing_template_decl)
+ parsed_arg = check_default_argument (TREE_VALUE (parm), parsed_arg);
+
TREE_PURPOSE (parm) = parsed_arg;
/* Update any instantiations we've already created. */
return (token->type == CPP_COMMA || token->type == CPP_GREATER);
}
-/* Returns TRUE iff the n-th token is a ">", or the n-th is a "[" and the
+/* Returns TRUE iff the n-th token is a "<", or the n-th is a "[" and the
(n+1)-th is a ":" (which is a possible digraph typo for "< ::"). */
static bool
cp_parser_require (parser, CPP_OPEN_PAREN, "`('");
token = cp_lexer_peek_token (parser->lexer);
- while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON)
+ while (cp_parser_objc_selector_p (token->type) || token->type == CPP_COLON
+ || token->type == CPP_SCOPE)
{
tree selector = NULL_TREE;
- if (token->type != CPP_COLON)
+ if (token->type != CPP_COLON
+ || token->type == CPP_SCOPE)
selector = cp_parser_objc_selector (parser);
- /* Detect if we have a unary selector. */
- if (maybe_unary_selector_p
- && cp_lexer_next_token_is_not (parser->lexer, CPP_COLON))
+ if (cp_lexer_next_token_is_not (parser->lexer, CPP_COLON)
+ && cp_lexer_next_token_is_not (parser->lexer, CPP_SCOPE))
{
- sel_seq = selector;
- goto finish_selector;
+ /* Detect if we have a unary selector. */
+ if (maybe_unary_selector_p)
+ {
+ sel_seq = selector;
+ goto finish_selector;
+ }
+ else
+ {
+ cp_parser_error (parser, "expected %<:%>");
+ }
}
-
maybe_unary_selector_p = false;
- cp_parser_require (parser, CPP_COLON, "`:'");
-
- sel_seq
- = chainon (sel_seq,
- build_tree_list (selector, NULL_TREE));
+ token = cp_lexer_consume_token (parser->lexer);
+
+ if (token->type == CPP_SCOPE)
+ {
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (selector, NULL_TREE));
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (NULL_TREE, NULL_TREE));
+ }
+ else
+ sel_seq
+ = chainon (sel_seq,
+ build_tree_list (selector, NULL_TREE));
token = cp_lexer_peek_token (parser->lexer);
}