Commit d6b418fa by Simon Martin Committed by Simon Martin

re PR c++/29475 (incomplete template diagnostics.)

2006-12-16  Simon Martin  <simartin@users.sourceforge.net>

	PR c++/29475
	* cp-tree.h (struct deferred_access_check): New structure to represent a
	deferred access check. It replaces the previous representation as a tree.
	(get_deferred_access_checks): Return a vector of struct
	deferred_access_check instead of a tree list.
	(perform_access_checks): Take a vector of struct deferred_access_check
	instead of a tree list.
	* semantics.c (struct deferred_access): Store the deferred access checks
	as a vector of struct deferred_access_check instead of a tree list.
	(push_deferring_access_checks): Handle the change in struct
	deferred_access.
	(get_deferred_access_checks): Likewise.
	(pop_to_parent_deferring_access_checks): Likewise.
	(perform_or_defer_access_check): Likewise.
	(perform_access_checks): Take a vector of struct deferred_access_check
	instead of a tree list.
	* parser.c (struct tree_check): New structure to store various data
	associated with a CPP_NESTED_NAME_SPECIFIER or CPP_TEMPLATE_ID token.
	(struct cp_token): Changed the value field to be a union with a pointer to
	a struct tree_check for CPP_NESTED_NAME_SPECIFIER or CPP_TEMPLATE_ID
	tokens and a tree field for all other tokens.
	(eof_token): Adjusted due to the change in struct cp_token.
	(cp_lexer_get_preprocessor_token): Likewise.
	(cp_lexer_purge_token): Likewise.
	(cp_lexer_purge_tokens_after): Likewise.
	(cp_lexer_print_token): Likewise.
	(cp_parser_error): Likewise.
	(cp_parser_identifier): Likewise.
	(cp_parser_string_literal): Likewise.
	(cp_parser_primary_expression): Likewise.
	(cp_parser_unqualified_id): Likewise.
	(cp_parser_parenthesized_expression_list): Likewise.
	(cp_parser_storage_class_specifier_opt): Likewise.
	(cp_parser_function_specifier_opt): Likewise.
	(cp_parser_type_specifier): Likewise.
	(cp_parser_simple_type_specifier): Likewise.
	(cp_parser_initializer_list): Likewise.
	(cp_parser_member_specification_opt): Likewise.
	(cp_parser_attribute_list): Likewise.
	(cp_parser_objc_expression): Likewise.
	(cp_parser_objc_protocol_qualifiers): Likewise.
	(cp_parser_objc_selector): Likewise.
	(cp_parser_objc_declaration): Likewise.
	(cp_parser_objc_statement): Likewise.
	(cp_parser_omp_clause_name): Likewise.
	(cp_parser_omp_clause_default): Likewise.
	(cp_parser_omp_clause_schedule): Likewise.
	(cp_parser_omp_parallel): Likewise.
	(cp_parser_initial_pragma): Likewise.
	(pragma_lex): Likewise.
	(cp_parser_pre_parsed_nested_name_specifier): Likewise.
	(cp_parser_nested_name_specifier_opt): Likewise.
	Use cp_token::u::tree_check_value to save the token's value, the
	associated deferred checks and its qualifying scope.
	(cp_parser_template_id): Likewise.
	(cp_parser_template_declaration_after_export): Adjusted the call to
	get_deferred_access_checks.
	(cp_parser_init_declarator): Take the access checks as a vector of struct
	deferred_access_check instead of a tree list.
	(cp_parser_single_declaration): Likewise.
	(cp_parser_perform_template_parameter_access_checks): Likewise.
	(cp_parser_simple_declaration): Adjusted the call to
	cp_parser_init_declarator.
	(cp_parser_explicit_specialization): Adjusted the call to
	cp_parser_single_declaration.

From-SVN: r119961
parent e6a98ba8
2006-12-16 Simon Martin <simartin@users.sourceforge.net>
PR c++/29475
* cp-tree.h (struct deferred_access_check): New structure to represent a
deferred access check. It replaces the previous representation as a tree.
(get_deferred_access_checks): Return a vector of struct
deferred_access_check instead of a tree list.
(perform_access_checks): Take a vector of struct deferred_access_check
instead of a tree list.
* semantics.c (struct deferred_access): Store the deferred access checks
as a vector of struct deferred_access_check instead of a tree list.
(push_deferring_access_checks): Handle the change in struct
deferred_access.
(get_deferred_access_checks): Likewise.
(pop_to_parent_deferring_access_checks): Likewise.
(perform_or_defer_access_check): Likewise.
(perform_access_checks): Take a vector of struct deferred_access_check
instead of a tree list.
* parser.c (struct tree_check): New structure to store various data
associated with a CPP_NESTED_NAME_SPECIFIER or CPP_TEMPLATE_ID token.
(struct cp_token): Changed the value field to be a union with a pointer to
a struct tree_check for CPP_NESTED_NAME_SPECIFIER or CPP_TEMPLATE_ID
tokens and a tree field for all other tokens.
(eof_token): Adjusted due to the change in struct cp_token.
(cp_lexer_get_preprocessor_token): Likewise.
(cp_lexer_purge_token): Likewise.
(cp_lexer_purge_tokens_after): Likewise.
(cp_lexer_print_token): Likewise.
(cp_parser_error): Likewise.
(cp_parser_identifier): Likewise.
(cp_parser_string_literal): Likewise.
(cp_parser_primary_expression): Likewise.
(cp_parser_unqualified_id): Likewise.
(cp_parser_parenthesized_expression_list): Likewise.
(cp_parser_storage_class_specifier_opt): Likewise.
(cp_parser_function_specifier_opt): Likewise.
(cp_parser_type_specifier): Likewise.
(cp_parser_simple_type_specifier): Likewise.
(cp_parser_initializer_list): Likewise.
(cp_parser_member_specification_opt): Likewise.
(cp_parser_attribute_list): Likewise.
(cp_parser_objc_expression): Likewise.
(cp_parser_objc_protocol_qualifiers): Likewise.
(cp_parser_objc_selector): Likewise.
(cp_parser_objc_declaration): Likewise.
(cp_parser_objc_statement): Likewise.
(cp_parser_omp_clause_name): Likewise.
(cp_parser_omp_clause_default): Likewise.
(cp_parser_omp_clause_schedule): Likewise.
(cp_parser_omp_parallel): Likewise.
(cp_parser_initial_pragma): Likewise.
(pragma_lex): Likewise.
(cp_parser_pre_parsed_nested_name_specifier): Likewise.
(cp_parser_nested_name_specifier_opt): Likewise.
Use cp_token::u::tree_check_value to save the token's value, the
associated deferred checks and its qualifying scope.
(cp_parser_template_id): Likewise.
(cp_parser_template_declaration_after_export): Adjusted the call to
get_deferred_access_checks.
(cp_parser_init_declarator): Take the access checks as a vector of struct
deferred_access_check instead of a tree list.
(cp_parser_single_declaration): Likewise.
(cp_parser_perform_template_parameter_access_checks): Likewise.
(cp_parser_simple_declaration): Adjusted the call to
cp_parser_init_declarator.
(cp_parser_explicit_specialization): Adjusted the call to
cp_parser_single_declaration.
2006-12-13 Ian Lance Taylor <iant@google.com>
PR c++/19564
......
......@@ -4234,14 +4234,29 @@ extern tree copied_binfo (tree, tree);
extern tree original_binfo (tree, tree);
extern int shared_member_p (tree);
/* The representation of a deferred access check. */
typedef struct deferred_access_check GTY(())
{
/* The base class in which the declaration is referenced. */
tree binfo;
/* The declaration whose access must be checked. */
tree decl;
/* The declaration that should be used in the error message. */
tree diag_decl;
} deferred_access_check;
DEF_VEC_O(deferred_access_check);
DEF_VEC_ALLOC_O(deferred_access_check,gc);
/* in semantics.c */
extern void push_deferring_access_checks (deferring_kind);
extern void resume_deferring_access_checks (void);
extern void stop_deferring_access_checks (void);
extern void pop_deferring_access_checks (void);
extern tree get_deferred_access_checks (void);
extern VEC (deferred_access_check,gc)* get_deferred_access_checks (void);
extern void pop_to_parent_deferring_access_checks (void);
extern void perform_access_checks (tree);
extern void perform_access_checks (VEC (deferred_access_check,gc)*);
extern void perform_deferred_access_checks (void);
extern void perform_or_defer_access_check (tree, tree, tree);
extern int stmts_are_full_exprs_p (void);
......
......@@ -45,6 +45,20 @@
/* The cp_lexer_* routines mediate between the lexer proper (in libcpp
and c-lex.c) and the C++ parser. */
/* A token's value and its associated deferred access checks and
qualifying scope. */
struct tree_check GTY(())
{
/* The value associated with the token. */
tree value;
/* The checks that have been associated with value. */
VEC (deferred_access_check, gc)* checks;
/* The token's qualifying scope (used when it is a
CPP_NESTED_NAME_SPECIFIER). */
tree qualifying_scope;
};
/* A C++ token. */
typedef struct cp_token GTY (())
......@@ -69,7 +83,12 @@ typedef struct cp_token GTY (())
/* The input file stack index at which this token was found. */
unsigned input_file_stack_index : INPUT_FILE_STACK_BITS;
/* The value associated with this token, if any. */
tree value;
union cp_token_value {
/* Used for CPP_NESTED_NAME_SPECIFIER and CPP_TEMPLATE_ID. */
struct tree_check* GTY((tag ("1"))) tree_check_value;
/* 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;
......@@ -81,7 +100,7 @@ DEF_VEC_ALLOC_P (cp_token_position,heap);
static const cp_token eof_token =
{
CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, NULL_TREE,
CPP_EOF, RID_MAX, 0, PRAGMA_NONE, 0, 0, false, 0, { NULL },
#if USE_MAPPED_LOCATION
0
#else
......@@ -394,7 +413,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
/* Get a new token from the preprocessor. */
token->type
= c_lex_with_flags (&token->value, &token->location, &token->flags);
= c_lex_with_flags (&token->u.value, &token->location, &token->flags);
token->input_file_stack_index = input_file_stack_tick;
token->keyword = RID_MAX;
token->pragma_kind = PRAGMA_NONE;
......@@ -410,17 +429,17 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
/* Check to see if this token is a keyword. */
if (token->type == CPP_NAME)
{
if (C_IS_RESERVED_WORD (token->value))
if (C_IS_RESERVED_WORD (token->u.value))
{
/* Mark this token as a keyword. */
token->type = CPP_KEYWORD;
/* Record which keyword. */
token->keyword = C_RID_CODE (token->value);
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->value = ridpointers[token->keyword];
token->u.value = ridpointers[token->keyword];
}
else
{
......@@ -432,7 +451,7 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
else if (token->type == CPP_AT_NAME)
{
token->type = CPP_KEYWORD;
switch (C_RID_CODE (token->value))
switch (C_RID_CODE (token->u.value))
{
/* Map 'class' to '@class', 'private' to '@private', etc. */
case RID_CLASS: token->keyword = RID_AT_CLASS; break;
......@@ -442,14 +461,14 @@ cp_lexer_get_preprocessor_token (cp_lexer *lexer ATTRIBUTE_UNUSED ,
case RID_THROW: token->keyword = RID_AT_THROW; break;
case RID_TRY: token->keyword = RID_AT_TRY; break;
case RID_CATCH: token->keyword = RID_AT_CATCH; break;
default: token->keyword = C_RID_CODE (token->value);
default: token->keyword = C_RID_CODE (token->u.value);
}
}
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->value);
token->value = NULL;
token->pragma_kind = TREE_INT_CST_LOW (token->u.value);
token->u.value = NULL_TREE;
}
}
......@@ -641,7 +660,7 @@ cp_lexer_purge_token (cp_lexer *lexer)
gcc_assert (tok != &eof_token);
tok->type = CPP_PURGED;
tok->location = UNKNOWN_LOCATION;
tok->value = NULL_TREE;
tok->u.value = NULL_TREE;
tok->keyword = RID_MAX;
do
......@@ -675,7 +694,7 @@ cp_lexer_purge_tokens_after (cp_lexer *lexer, cp_token *tok)
{
tok->type = CPP_PURGED;
tok->location = UNKNOWN_LOCATION;
tok->value = NULL_TREE;
tok->u.value = NULL_TREE;
tok->keyword = RID_MAX;
}
}
......@@ -753,16 +772,16 @@ cp_lexer_print_token (FILE * stream, cp_token *token)
case CPP_KEYWORD:
/* Some keywords have a value that is not an IDENTIFIER_NODE.
For example, `struct' is mapped to an INTEGER_CST. */
if (TREE_CODE (token->value) != IDENTIFIER_NODE)
if (TREE_CODE (token->u.value) != IDENTIFIER_NODE)
break;
/* else fall through */
case CPP_NAME:
fputs (IDENTIFIER_POINTER (token->value), stream);
fputs (IDENTIFIER_POINTER (token->u.value), stream);
break;
case CPP_STRING:
case CPP_WSTRING:
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->value));
fprintf (stream, " \"%s\"", TREE_STRING_POINTER (token->u.value));
break;
default:
......@@ -1606,7 +1625,7 @@ static void cp_parser_static_assert
/* Declarators [gram.dcl.decl] */
static tree cp_parser_init_declarator
(cp_parser *, cp_decl_specifier_seq *, tree, bool, bool, int, bool *);
(cp_parser *, cp_decl_specifier_seq *, VEC (deferred_access_check,gc)*, bool, bool, int, bool *);
static cp_declarator *cp_parser_declarator
(cp_parser *, cp_parser_declarator_kind, int *, bool *, bool);
static cp_declarator *cp_parser_direct_declarator
......@@ -1806,9 +1825,9 @@ static tree cp_parser_function_definition_after_declarator
static void cp_parser_template_declaration_after_export
(cp_parser *, bool);
static void cp_parser_perform_template_parameter_access_checks
(tree);
(VEC (deferred_access_check,gc)*);
static tree cp_parser_single_declaration
(cp_parser *, tree, bool, bool *);
(cp_parser *, VEC (deferred_access_check,gc)*, bool, bool *);
static tree cp_parser_functional_cast
(cp_parser *, tree);
static tree cp_parser_save_member_function_body
......@@ -1962,7 +1981,7 @@ cp_parser_error (cp_parser* parser, const char* message)
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
token->value);
token->u.value);
}
}
......@@ -2703,7 +2722,7 @@ cp_parser_identifier (cp_parser* parser)
/* Look for the identifier. */
token = cp_parser_require (parser, CPP_NAME, "identifier");
/* Return the value. */
return token ? token->value : error_mark_node;
return token ? token->u.value : error_mark_node;
}
/* Parse a sequence of adjacent string constants. Returns a
......@@ -2744,8 +2763,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
cp_lexer_consume_token (parser->lexer);
str.text = (const unsigned char *)TREE_STRING_POINTER (tok->value);
str.len = TREE_STRING_LENGTH (tok->value);
str.text = (const unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
count = 1;
if (tok->type == CPP_WSTRING)
wide = true;
......@@ -2761,8 +2780,8 @@ cp_parser_string_literal (cp_parser *parser, bool translate, bool wide_ok)
{
cp_lexer_consume_token (parser->lexer);
count++;
str.text = (unsigned char *)TREE_STRING_POINTER (tok->value);
str.len = TREE_STRING_LENGTH (tok->value);
str.text = (unsigned char *)TREE_STRING_POINTER (tok->u.value);
str.len = TREE_STRING_LENGTH (tok->u.value);
if (tok->type == CPP_WSTRING)
wide = true;
......@@ -2929,7 +2948,7 @@ cp_parser_primary_expression (cp_parser *parser,
/* Floating-point literals are only allowed in an integral
constant expression if they are cast to an integral or
enumeration type. */
if (TREE_CODE (token->value) == REAL_CST
if (TREE_CODE (token->u.value) == REAL_CST
&& parser->integral_constant_expression_p
&& pedantic)
{
......@@ -2966,7 +2985,7 @@ cp_parser_primary_expression (cp_parser *parser,
cp_parser_non_integral_constant_expression
(parser, "floating-point literal");
}
return token->value;
return token->u.value;
case CPP_STRING:
case CPP_WSTRING:
......@@ -3082,7 +3101,7 @@ cp_parser_primary_expression (cp_parser *parser,
Consume the token. */
token = cp_lexer_consume_token (parser->lexer);
/* Look up the name. */
return finish_fname (token->value);
return finish_fname (token->u.value);
case RID_VA_ARG:
{
......@@ -3519,7 +3538,7 @@ cp_parser_unqualified_id (cp_parser* parser,
&& token->type == CPP_NAME
&& (cp_lexer_peek_nth_token (parser->lexer, 2)->type
== CPP_OPEN_PAREN)
&& constructor_name_p (token->value, scope))
&& constructor_name_p (token->u.value, scope))
{
cp_lexer_consume_token (parser->lexer);
return build_nt (BIT_NOT_EXPR, scope);
......@@ -3820,7 +3839,7 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
tree decl;
tree ambiguous_decls;
decl = cp_parser_lookup_name (parser, token->value,
decl = cp_parser_lookup_name (parser, token->u.value,
none_type,
/*is_template=*/false,
/*is_namespace=*/false,
......@@ -3831,13 +3850,13 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
else if (ambiguous_decls)
{
error ("reference to %qD is ambiguous",
token->value);
token->u.value);
print_candidates (ambiguous_decls);
decl = error_mark_node;
}
else
cp_parser_name_lookup_error
(parser, token->value, decl,
(parser, token->u.value, decl,
"is not a class or namespace");
}
parser->scope = error_mark_node;
......@@ -3896,17 +3915,17 @@ cp_parser_nested_name_specifier_opt (cp_parser *parser,
if (success && start)
{
cp_token *token;
tree access_checks;
token = cp_lexer_token_at (parser->lexer, start);
/* Reset the contents of the START token. */
token->type = CPP_NESTED_NAME_SPECIFIER;
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
access_checks = get_deferred_access_checks ();
token->value = build_tree_list (copy_list (access_checks),
parser->scope);
TREE_TYPE (token->value) = parser->qualifying_scope;
token->u.tree_check_value = GGC_CNEW (struct tree_check);
token->u.tree_check_value->value = parser->scope;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->u.tree_check_value->qualifying_scope =
parser->qualifying_scope;
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
......@@ -4764,7 +4783,7 @@ cp_parser_parenthesized_expression_list (cp_parser* parser,
/* Consume the identifier. */
token = cp_lexer_consume_token (parser->lexer);
/* Save the identifier. */
identifier = token->value;
identifier = token->u.value;
}
else
{
......@@ -7451,7 +7470,7 @@ cp_parser_simple_declaration (cp_parser* parser,
/* Parse the init-declarator. */
decl = cp_parser_init_declarator (parser, &decl_specifiers,
/*checks=*/NULL_TREE,
/*checks=*/NULL,
function_definition_allowed_p,
/*member_p=*/false,
declares_class_or_enum,
......@@ -7789,7 +7808,7 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
case RID_MUTABLE:
case RID_THREAD:
/* Consume the token. */
return cp_lexer_consume_token (parser->lexer)->value;
return cp_lexer_consume_token (parser->lexer)->u.value;
default:
return NULL_TREE;
......@@ -7837,7 +7856,7 @@ cp_parser_function_specifier_opt (cp_parser* parser,
}
/* Consume the token. */
return cp_lexer_consume_token (parser->lexer)->value;
return cp_lexer_consume_token (parser->lexer)->u.value;
}
/* Parse a linkage-specification.
......@@ -8876,11 +8895,13 @@ cp_parser_template_id (cp_parser *parser,
bool check_dependency_p,
bool is_declaration)
{
int i;
tree template;
tree arguments;
tree template_id;
cp_token_position start_of_id = 0;
tree access_check = NULL_TREE;
deferred_access_check *chk;
VEC (deferred_access_check,gc) *access_check;
cp_token *next_token, *next_token_2;
bool is_identifier;
......@@ -8889,18 +8910,25 @@ cp_parser_template_id (cp_parser *parser,
next_token = cp_lexer_peek_token (parser->lexer);
if (next_token->type == CPP_TEMPLATE_ID)
{
tree value;
tree check;
struct tree_check *check_value;
/* Get the stored value. */
value = cp_lexer_consume_token (parser->lexer)->value;
check_value = cp_lexer_consume_token (parser->lexer)->u.tree_check_value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
perform_or_defer_access_check (TREE_PURPOSE (check),
TREE_VALUE (check),
TREE_VALUE (check));
access_check = check_value->checks;
if (access_check)
{
for (i = 0 ;
VEC_iterate (deferred_access_check, access_check, i, chk) ;
++i)
{
perform_or_defer_access_check (chk->binfo,
chk->decl,
chk->diag_decl);
}
}
/* Return the stored value. */
return TREE_VALUE (value);
return check_value->value;
}
/* Avoid performing name lookup if there is no possibility of
......@@ -9016,10 +9044,6 @@ cp_parser_template_id (cp_parser *parser,
template_id = lookup_template_function (template, arguments);
}
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
access_check = get_deferred_access_checks ();
/* If parsing tentatively, replace the sequence of tokens that makes
up the template-id with a CPP_TEMPLATE_ID token. That way,
should we re-parse the token stream, we will not have to repeat
......@@ -9032,7 +9056,11 @@ cp_parser_template_id (cp_parser *parser,
/* Reset the contents of the START_OF_ID token. */
token->type = CPP_TEMPLATE_ID;
token->value = build_tree_list (access_check, template_id);
/* Retrieve any deferred checks. Do not pop this access checks yet
so the memory will not be reclaimed during token replacing below. */
token->u.tree_check_value = GGC_CNEW (struct tree_check);
token->u.tree_check_value->value = template_id;
token->u.tree_check_value->checks = get_deferred_access_checks ();
token->keyword = RID_MAX;
/* Purge all subsequent tokens. */
......@@ -9697,7 +9725,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
else
/* Parse the dependent declaration. */
cp_parser_single_declaration (parser,
/*checks=*/NULL_TREE,
/*checks=*/NULL,
/*member_p=*/false,
/*friend_p=*/NULL);
/* We're done with the specialization. */
......@@ -9864,7 +9892,7 @@ cp_parser_type_specifier (cp_parser* parser,
++decl_specs->specs[(int)ds];
decl_specs->any_specifiers_p = true;
}
return cp_lexer_consume_token (parser->lexer)->value;
return cp_lexer_consume_token (parser->lexer)->u.value;
}
/* If we do not already have a type-specifier, assume we are looking
......@@ -10007,7 +10035,7 @@ cp_parser_simple_type_specifier (cp_parser* parser,
decl_specs->any_specifiers_p = true;
/* Consume the token. */
id = cp_lexer_consume_token (parser->lexer)->value;
id = cp_lexer_consume_token (parser->lexer)->u.value;
/* There is no valid C++ program where a non-template type is
followed by a "<". That usually indicates that the user thought
......@@ -11150,7 +11178,7 @@ cp_parser_asm_definition (cp_parser* parser)
static tree
cp_parser_init_declarator (cp_parser* parser,
cp_decl_specifier_seq *decl_specifiers,
tree checks,
VEC (deferred_access_check,gc)* checks,
bool function_definition_allowed_p,
bool member_p,
int declares_class_or_enum,
......@@ -12948,7 +12976,7 @@ cp_parser_initializer_list (cp_parser* parser, bool* non_constant_p)
if (pedantic)
pedwarn ("ISO C++ does not allow designated initializers");
/* Consume the identifier. */
identifier = cp_lexer_consume_token (parser->lexer)->value;
identifier = cp_lexer_consume_token (parser->lexer)->u.value;
/* Consume the `:'. */
cp_lexer_consume_token (parser->lexer);
}
......@@ -13753,7 +13781,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
/* Consume the access-specifier. */
cp_lexer_consume_token (parser->lexer);
/* Remember which access-specifier is active. */
current_access_specifier = token->value;
current_access_specifier = token->u.value;
/* Look for the `:'. */
cp_parser_require (parser, CPP_COLON, "`:'");
break;
......@@ -14933,7 +14961,7 @@ cp_parser_attribute_list (cp_parser* parser)
/* Save away the identifier that indicates which attribute
this is. */
identifier = token->value;
identifier = token->u.value;
attribute = build_tree_list (identifier, NULL_TREE);
/* Peek at the next token. */
......@@ -15766,7 +15794,7 @@ static void
cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
{
tree decl = NULL_TREE;
tree checks;
VEC (deferred_access_check,gc) *checks;
tree parameter_list;
bool friend_p = false;
bool need_lang_pop;
......@@ -15889,7 +15917,7 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
get_deferred_access_checks. */
static void
cp_parser_perform_template_parameter_access_checks (tree checks)
cp_parser_perform_template_parameter_access_checks (VEC (deferred_access_check,gc)* checks)
{
++processing_template_parmlist;
perform_access_checks (checks);
......@@ -15905,7 +15933,7 @@ cp_parser_perform_template_parameter_access_checks (tree checks)
static tree
cp_parser_single_declaration (cp_parser* parser,
tree checks,
VEC (deferred_access_check,gc)* checks,
bool member_p,
bool* friend_p)
{
......@@ -16851,19 +16879,29 @@ cp_parser_optional_template_keyword (cp_parser *parser)
static void
cp_parser_pre_parsed_nested_name_specifier (cp_parser *parser)
{
tree value;
tree check;
int i;
struct tree_check *check_value;
deferred_access_check *chk;
VEC (deferred_access_check,gc) *checks;
/* Get the stored value. */
value = cp_lexer_consume_token (parser->lexer)->value;
check_value = cp_lexer_consume_token (parser->lexer)->u.tree_check_value;
/* Perform any access checks that were deferred. */
for (check = TREE_PURPOSE (value); check; check = TREE_CHAIN (check))
perform_or_defer_access_check (TREE_PURPOSE (check),
TREE_VALUE (check),
TREE_VALUE (check));
checks = check_value->checks;
if (checks)
{
for (i = 0 ;
VEC_iterate (deferred_access_check, checks, i, chk) ;
++i)
{
perform_or_defer_access_check (chk->binfo,
chk->decl,
chk->diag_decl);
}
}
/* Set the scope from the stored value. */
parser->scope = TREE_VALUE (value);
parser->qualifying_scope = TREE_TYPE (value);
parser->scope = check_value->value;
parser->qualifying_scope = check_value->qualifying_scope;
parser->object_scope = NULL_TREE;
}
......@@ -17051,7 +17089,7 @@ cp_parser_objc_expression (cp_parser* parser)
case CPP_OBJC_STRING:
kwd = cp_lexer_consume_token (parser->lexer);
return objc_build_string_object (kwd->value);
return objc_build_string_object (kwd->u.value);
case CPP_KEYWORD:
switch (kwd->keyword)
......@@ -17069,7 +17107,7 @@ cp_parser_objc_expression (cp_parser* parser)
break;
}
default:
error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
......@@ -17459,7 +17497,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
tree quals = NULL_TREE, node;
cp_token *token = cp_lexer_peek_token (parser->lexer);
node = token->value;
node = token->u.value;
while (node && TREE_CODE (node) == IDENTIFIER_NODE
&& (node == ridpointers [(int) RID_IN]
......@@ -17472,7 +17510,7 @@ cp_parser_objc_protocol_qualifiers (cp_parser* parser)
quals = tree_cons (NULL_TREE, node, quals);
cp_lexer_consume_token (parser->lexer);
token = cp_lexer_peek_token (parser->lexer);
node = token->value;
node = token->u.value;
}
return quals;
......@@ -17543,7 +17581,7 @@ cp_parser_objc_selector (cp_parser* parser)
case CPP_OR_EQ: return get_identifier ("or_eq");
case CPP_XOR: return get_identifier ("xor");
case CPP_XOR_EQ: return get_identifier ("xor_eq");
default: return token->value;
default: return token->u.value;
}
}
......@@ -17992,7 +18030,7 @@ cp_parser_objc_declaration (cp_parser* parser)
cp_parser_objc_end_implementation (parser);
break;
default:
error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
}
......@@ -18123,7 +18161,7 @@ cp_parser_objc_statement (cp_parser * parser) {
case RID_AT_THROW:
return cp_parser_objc_throw_statement (parser);
default:
error ("misplaced %<@%D%> Objective-C++ construct", kwd->value);
error ("misplaced %<@%D%> Objective-C++ construct", kwd->u.value);
cp_parser_skip_to_end_of_block_or_statement (parser);
}
......@@ -18150,7 +18188,7 @@ cp_parser_omp_clause_name (cp_parser *parser)
result = PRAGMA_OMP_CLAUSE_PRIVATE;
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->value;
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
switch (p[0])
......@@ -18304,7 +18342,7 @@ cp_parser_omp_clause_default (cp_parser *parser, tree list)
return list;
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->value;
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
switch (p[0])
......@@ -18515,7 +18553,7 @@ cp_parser_omp_clause_schedule (cp_parser *parser, tree list)
if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->value;
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
switch (p[0])
......@@ -19164,7 +19202,7 @@ cp_parser_omp_parallel (cp_parser *parser, cp_token *pragma_tok)
}
else if (cp_lexer_next_token_is (parser->lexer, CPP_NAME))
{
tree id = cp_lexer_peek_token (parser->lexer)->value;
tree id = cp_lexer_peek_token (parser->lexer)->u.value;
const char *p = IDENTIFIER_POINTER (id);
if (strcmp (p, "sections") == 0)
{
......@@ -19320,7 +19358,7 @@ cp_parser_initial_pragma (cp_token *first_token)
cp_lexer_get_preprocessor_token (NULL, first_token);
if (first_token->type == CPP_STRING)
{
name = first_token->value;
name = first_token->u.value;
cp_lexer_get_preprocessor_token (NULL, first_token);
if (first_token->type != CPP_PRAGMA_EOL)
......@@ -19440,7 +19478,7 @@ pragma_lex (tree *value)
tok = cp_lexer_peek_token (the_parser->lexer);
ret = tok->type;
*value = tok->value;
*value = tok->u.value;
if (ret == CPP_PRAGMA_EOL || ret == CPP_EOF)
ret = CPP_EOF;
......
......@@ -96,7 +96,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
2. When a declaration such as a type, or a variable, is encountered,
the function `perform_or_defer_access_check' is called. It
maintains a TREE_LIST of all deferred checks.
maintains a VEC of all deferred checks.
3. The global `current_class_type' or `current_function_decl' is then
setup by the parser. `enforce_access' relies on these information
......@@ -104,7 +104,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
4. Upon exiting the context mentioned in step 1,
`perform_deferred_access_checks' is called to check all declaration
stored in the TREE_LIST. `pop_deferring_access_checks' is then
stored in the VEC. `pop_deferring_access_checks' is then
called to restore the previous access checking mode.
In case of parsing error, we simply call `pop_deferring_access_checks'
......@@ -112,7 +112,7 @@ static tree finalize_nrv_r (tree *, int *, void *);
typedef struct deferred_access GTY(())
{
/* A TREE_LIST representing name-lookups for which we have deferred
/* A VEC representing name-lookups for which we have deferred
checking access controls. We cannot check the accessibility of
names used in a decl-specifier-seq until we know what is being
declared because code like:
......@@ -124,12 +124,8 @@ typedef struct deferred_access GTY(())
A::B* A::f() { return 0; }
is valid, even though `A::B' is not generally accessible.
The TREE_PURPOSE of each node is the scope used to qualify the
name being looked up; the TREE_VALUE is the DECL to which the
name was resolved. */
tree deferred_access_checks;
is valid, even though `A::B' is not generally accessible. */
VEC (deferred_access_check,gc)* GTY(()) deferred_access_checks;
/* The current mode of access checks. */
enum deferring_kind deferring_access_checks_kind;
......@@ -157,7 +153,7 @@ push_deferring_access_checks (deferring_kind deferring)
deferred_access *ptr;
ptr = VEC_safe_push (deferred_access, gc, deferred_access_stack, NULL);
ptr->deferred_access_checks = NULL_TREE;
ptr->deferred_access_checks = NULL;
ptr->deferring_access_checks_kind = deferring;
}
}
......@@ -200,7 +196,7 @@ pop_deferring_access_checks (void)
access occurred; the TREE_VALUE is the declaration named.
*/
tree
VEC (deferred_access_check,gc)*
get_deferred_access_checks (void)
{
if (deferred_access_no_check)
......@@ -221,7 +217,7 @@ pop_to_parent_deferring_access_checks (void)
deferred_access_no_check--;
else
{
tree checks;
VEC (deferred_access_check,gc) *checks;
deferred_access *ptr;
checks = (VEC_last (deferred_access, deferred_access_stack)
......@@ -232,29 +228,31 @@ pop_to_parent_deferring_access_checks (void)
if (ptr->deferring_access_checks_kind == dk_no_deferred)
{
/* Check access. */
for (; checks; checks = TREE_CHAIN (checks))
enforce_access (TREE_PURPOSE (checks),
TREE_VALUE (checks), TREE_VALUE (checks));
perform_access_checks (checks);
}
else
{
/* Merge with parent. */
tree next;
tree original = ptr->deferred_access_checks;
int i, j;
deferred_access_check *chk, *probe;
for (; checks; checks = next)
for (i = 0 ;
VEC_iterate (deferred_access_check, checks, i, chk) ;
++i)
{
tree probe;
next = TREE_CHAIN (checks);
for (probe = original; probe; probe = TREE_CHAIN (probe))
if (TREE_VALUE (probe) == TREE_VALUE (checks)
&& TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
for (j = 0 ;
VEC_iterate (deferred_access_check,
ptr->deferred_access_checks, j, probe) ;
++j)
{
if (probe->binfo == chk->binfo &&
probe->decl == chk->decl &&
probe->diag_decl == chk->diag_decl)
goto found;
}
/* Insert into parent's checks. */
TREE_CHAIN (checks) = ptr->deferred_access_checks;
ptr->deferred_access_checks = checks;
VEC_safe_push (deferred_access_check, gc,
ptr->deferred_access_checks, chk);
found:;
}
}
......@@ -266,14 +264,16 @@ pop_to_parent_deferring_access_checks (void)
DECL node stored in the TREE_VALUE of the node. */
void
perform_access_checks (tree checks)
perform_access_checks (VEC (deferred_access_check,gc)* checks)
{
while (checks)
{
enforce_access (TREE_PURPOSE (checks),
TREE_VALUE (checks), TREE_VALUE (checks));
checks = TREE_CHAIN (checks);
}
int i;
deferred_access_check *chk;
if (!checks)
return;
for (i = 0 ; VEC_iterate (deferred_access_check, checks, i, chk) ; ++i)
enforce_access (chk->binfo, chk->decl, chk->diag_decl);
}
/* Perform the deferred access checks.
......@@ -304,8 +304,11 @@ perform_deferred_access_checks (void)
void
perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl)
{
tree check;
int i;
deferred_access *ptr;
deferred_access_check *chk;
deferred_access_check *new_access;
/* Exit if we are in a context that no access checking is performed.
*/
......@@ -324,14 +327,24 @@ perform_or_defer_access_check (tree binfo, tree decl, tree diag_decl)
}
/* See if we are already going to perform this check. */
for (check = ptr->deferred_access_checks;
check;
check = TREE_CHAIN (check))
if (TREE_VALUE (check) == decl && TREE_PURPOSE (check) == binfo)
for (i = 0 ;
VEC_iterate (deferred_access_check,
ptr->deferred_access_checks, i, chk) ;
++i)
{
if (chk->decl == decl && chk->binfo == binfo &&
chk->diag_decl == diag_decl)
{
return;
}
}
/* If not, record the check. */
ptr->deferred_access_checks
= tree_cons (binfo, decl, ptr->deferred_access_checks);
new_access =
VEC_safe_push (deferred_access_check, gc,
ptr->deferred_access_checks, 0);
new_access->binfo = binfo;
new_access->decl = decl;
new_access->diag_decl = diag_decl;
}
/* Returns nonzero if the current statement is a full expression,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment