static tree cp_parser_primary_expression
(cp_parser *, bool, bool, bool, cp_id_kind *);
static tree cp_parser_id_expression
- (cp_parser *, bool, bool, bool *, bool, bool);
+ (cp_parser *, bool, bool, bool *, bool, bool, bool);
static tree cp_parser_unqualified_id
- (cp_parser *, bool, bool, bool, bool);
+ (cp_parser *, bool, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier_opt
(cp_parser *, bool, bool, bool, bool);
static tree cp_parser_nested_name_specifier
static tree cp_parser_simple_cast_expression
(cp_parser *);
static tree cp_parser_global_scope_opt
- (cp_parser *, bool);
+ (cp_parser *, bool, bool);
static bool cp_parser_constructor_declarator_p
(cp_parser *, bool);
static tree cp_parser_function_definition_from_specifiers_and_declarator
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/true,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_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. */
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
if (id_expression == error_mark_node)
return error_mark_node;
token = cp_lexer_peek_token (parser->lexer);
bool check_dependency_p,
bool *template_p,
bool declarator_p,
- bool optional_p)
+ bool optional_p,
+ bool member_p)
{
bool global_scope_p;
bool nested_name_specifier_p;
/* Look for the optional `::' operator. */
global_scope_p
- = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false)
+ = (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/member_p)
!= NULL_TREE);
+
/* Look for the optional nested-name-specifier. */
nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser,
unqualified_id = cp_parser_unqualified_id (parser, *template_p,
check_dependency_p,
declarator_p,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
/* Restore the SAVED_SCOPE for our caller. */
parser->scope = saved_scope;
parser->object_scope = saved_object_scope;
else
return cp_parser_unqualified_id (parser, template_keyword_p,
/*check_dependency_p=*/true,
- declarator_p,
- optional_p);
+ declarator_p, optional_p, member_p);
}
/* Parse an unqualified-id.
bool template_keyword_p,
bool check_dependency_p,
bool declarator_p,
- bool optional_p)
+ bool optional_p,
+ bool member_p)
{
cp_token *token;
if (cp_parser_parse_definitely (parser))
done = true;
}
+
/* In "N::S::~S", look in "N" as well. */
if (!done && scope && qualifying_scope)
{
if (cp_parser_parse_definitely (parser))
done = true;
}
- /* In "p->S::~T", look in the scope given by "*p" as well. */
- else if (!done && object_scope)
+ /* In "p->~T", look in the scope given by "*p" as well. */
+ else if (!done && member_p)
{
+ if (!object_scope)
+ {
+ /* It's a dependent expression, so just parse the
+ dtor name. */
+ tree id;
+
+ if (template_keyword_p)
+ /* It's a template-id. */
+ id = cp_parser_template_id (parser, true,
+ check_dependency_p,
+ declarator_p);
+ else
+ {
+ /* Otherwise, it's an ordinary identifier. */
+ id = cp_parser_identifier (parser);
+ /* If ID is a template type parm, then use that
+ directly. */
+ if (TREE_TYPE (id)
+ && TREE_CODE (TREE_TYPE (id)) == TEMPLATE_TYPE_PARM)
+ id = TREE_TYPE (id);
+ }
+
+ if (id != error_mark_node)
+ id = build_nt (BIT_NOT_EXPR, id);
+ return id;
+ }
+
cp_parser_parse_tentatively (parser);
parser->scope = object_scope;
parser->object_scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
type_decl
= cp_parser_class_name (parser,
- /*typename_keyword_p=*/false,
+ /*typename_keyword_p=*/false,
/*template_keyword_p=*/false,
none_type,
/*check_dependency=*/false,
/*class_head_p=*/false,
declarator_p);
+ /* The name is not qualified, so reset the parser scopes
+ so our callers do not get confused. */
+ parser->object_scope = object_scope;
+ parser->scope = NULL_TREE;
if (cp_parser_parse_definitely (parser))
done = true;
}
+
/* Look in the surrounding context. */
if (!done)
{
parser->qualifying_scope = NULL_TREE;
parser->object_scope = NULL_TREE;
*idk = CP_ID_KIND_NONE;
+
/* Enter the scope corresponding to the type of the object
given by the POSTFIX_EXPRESSION. */
- if (!dependent_p && TREE_TYPE (postfix_expression) != NULL_TREE)
+ scope = TREE_TYPE (postfix_expression);
+ if (!dependent_p && scope)
{
- scope = TREE_TYPE (postfix_expression);
/* According to the standard, no expression should ever have
reference type. Unfortunately, we do not currently match
the standard in this respect in that our internal representation
error ("%qE does not have class type", postfix_expression);
scope = NULL_TREE;
}
- else
+ else if (!dependent_p)
scope = complete_type_or_else (scope, NULL_TREE);
- /* Let the name lookup machinery know that we are processing a
- class member access expression. */
- parser->context->object_type = scope;
/* If something went wrong, we want to be able to discern that case,
as opposed to the case where there was no SCOPE due to the type
of expression being dependent. */
if (scope == error_mark_node)
postfix_expression = error_mark_node;
}
+ /* Let the name lookup machinery know that we are processing a class
+ member access expression. */
+ parser->context->object_type = scope;
+ parser->object_scope = scope;
/* Assume this expression is not a pseudo-destructor access. */
pseudo_destructor_p = false;
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false));
+ /*optional_p=*/false,
+ /*member_p=*/true));
/* 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;
*type = error_mark_node;
/* Look for the optional `::' operator. */
- cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/true);
+ cp_parser_global_scope_opt (parser,
+ /*current_scope_valid_p=*/true,
+ /*object_scop_valid_p=*/true);
/* Look for the optional nested-name-specifier. */
nested_name_specifier_p
= (cp_parser_nested_name_specifier_opt (parser,
/* Look for the optional `::' operator. */
global_scope_p
= (cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false)
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the `new' operator. */
cp_parser_require_keyword (parser, RID_NEW, "`new'");
/* Look for the optional `::' operator. */
global_scope_p
= (cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false)
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the `delete' keyword. */
cp_parser_require_keyword (parser, RID_DELETE, "`delete'");
/* Look for the optional `::' operator. */
global_scope_p
= (cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false)
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the optional nested-name-specifier. The simplest way to
implement:
/*check_dependency_p=*/true,
/*template_p=*/&is_template,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
if (TREE_CODE (default_argument) == TYPE_DECL)
/* If the id-expression was a template-id that refers to
a template-class, we already have the declaration here,
/*check_dependency_p=*/true,
&template_p,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
/* If the next token isn't a `,' or a `>', then this argument wasn't
really finished. */
if (!cp_parser_next_token_ends_template_argument_p (parser))
/* Look for the optional `::' operator. */
global_p
= (cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false)
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false)
!= NULL_TREE);
/* Look for the nested-name specifier. */
qualified_p
/* Look for the `::' operator. */
cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false);
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
if (tag_type == typename_type)
{
{
/* Look for the optional `::'. */
cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false);
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* Look for the optional nested-name-specifier. */
cp_parser_nested_name_specifier_opt (parser,
/* Look for the optional global scope qualification. */
global_scope_p
= (cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false)
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false)
!= NULL_TREE);
/* If we saw `typename', or didn't see `::', then there must be a
/*template_keyword_p=*/false,
/*check_dependency_p=*/true,
/*declarator_p=*/true,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
/* The function we call to handle a using-declaration is different
depending on what scope we are in. */
/* And the `namespace' keyword. */
cp_parser_require_keyword (parser, RID_NAMESPACE, "`namespace'");
/* Look for the optional `::' operator. */
- cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+ cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* And the optional nested-name-specifier. */
cp_parser_nested_name_specifier_opt (parser,
/*typename_keyword_p=*/false,
cp_parser_parse_tentatively (parser);
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false);
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* Look for the nested-name specifier. */
cp_parser_nested_name_specifier (parser,
/*typename_keyword_p=*/false,
/*check_dependency_p=*/false,
/*template_p=*/NULL,
/*declarator_p=*/true,
- optional_p);
+ optional_p,
+ /*member_p=*/false);
if (id && BASELINK_P (id))
id = BASELINK_FUNCTIONS (id);
return id;
issuing an error about it later if this really is a
class-head. If it turns out just to be an elaborated type
specifier, remain silent. */
- if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false))
+ if (cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false))
qualified_p = true;
push_deferring_access_checks (dk_no_check);
}
/* Look for the optional `::' operator. */
- cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false);
+ cp_parser_global_scope_opt (parser, /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. The simplest way to
implement:
present, and NULL_TREE otherwise. */
static tree
-cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p)
+cp_parser_global_scope_opt (cp_parser* parser, bool current_scope_valid_p,
+ bool object_scope_valid_p)
{
cp_token *token;
return parser->scope;
}
- else if (!current_scope_valid_p)
+
+ if (!current_scope_valid_p)
{
parser->scope = NULL_TREE;
parser->qualifying_scope = NULL_TREE;
- parser->object_scope = NULL_TREE;
}
+
+ if (!object_scope_valid_p)
+ parser->object_scope = NULL_TREE;
return NULL_TREE;
}
/* Look for the optional `::' operator. */
cp_parser_global_scope_opt (parser,
- /*current_scope_valid_p=*/false);
+ /*current_scope_valid_p=*/false,
+ /*object_scope_valid_p=*/false);
/* Look for the nested-name-specifier. */
nested_name_p
= (cp_parser_nested_name_specifier_opt (parser,
/*check_dependency_p=*/true,
/*template_p=*/NULL,
/*declarator_p=*/false,
- /*optional_p=*/false);
+ /*optional_p=*/false,
+ /*member_p=*/false);
if (name == error_mark_node)
goto skip_comma;