This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH 4.2] Backport of the fixes for PR c++/29475
- From: Simon Martin <simartin at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Tue, 20 Feb 2007 23:36:21 +0100
- Subject: [PATCH 4.2] Backport of the fixes for PR c++/29475
Hello all.
I attach a patch to backport into the 4.2 branch the two fixes done on the
mainline for PR c++/29475, submitted
- here: http://gcc.gnu.org/ml/gcc-patches/2006-11/msg00833.html, approved
here: http://gcc.gnu.org/ml/gcc-patches/2006-11/msg00912.html
- and here: http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00420.html, approved
here http://gcc.gnu.org/ml/gcc-patches/2006-12/msg00457.html
I've successfully regtested it on i686-pc-linux-gnu. Is it OK for 4.2?
Thanks in advance,
Simon
2007-02-20 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.
(enforce_access, perform_or_defer_access_check): Added an
extra argument that represents the declaration to use to print
potential error messages.
* 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.
(finish_non_static_data_member, check_accessibility_of_qualified_id,
finish_id_expression): Adjusted the call to perform_or_defer_access_check.
(pop_to_parent_deferring_access_checks, perform_access_checks,
perform_or_defer_access_check): Adjusted the call to enforce_access.
* 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.
(cp_parser_template_id, cp_parser_pre_parsed_nested_name_specifier):
Adjusted the call to perform_or_defer_access_check.
* init.c (build_offset_ref): Adjusted the call to
perform_or_defer_access_check.
* class.c (alter_access, resolve_address_of_overloaded_function):
Likewise.
* decl.c (make_typename_type, make_unbound_class_template): Likewise.
* search.c (lookup_member): Likewise.
* friend.c (add_friend): Likewise.
* call.c (enforce_access): Use the new extra argument to build the
error message.
(build_op_delete_call): Adjusted the call to
perform_or_defer_access_check.
(build_over_call): Likewise.
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c (revision 122171)
+++ gcc/cp/init.c (working copy)
@@ -1383,9 +1383,9 @@ build_offset_ref (tree type, tree member
(or any class derived from that class). */
if (address_p && DECL_P (t)
&& DECL_NONSTATIC_MEMBER_P (t))
- perform_or_defer_access_check (TYPE_BINFO (type), t);
+ perform_or_defer_access_check (TYPE_BINFO (type), t, t);
else
- perform_or_defer_access_check (basebinfo, t);
+ perform_or_defer_access_check (basebinfo, t, t);
if (DECL_STATIC_FUNCTION_P (t))
return t;
@@ -1398,7 +1398,7 @@ build_offset_ref (tree type, tree member
/* We need additional test besides the one in
check_accessibility_of_qualified_id in case it is
a pointer to non-static member. */
- perform_or_defer_access_check (TYPE_BINFO (type), member);
+ perform_or_defer_access_check (TYPE_BINFO (type), member, member);
if (!address_p)
{
Index: gcc/cp/class.c
===================================================================
--- gcc/cp/class.c (revision 122171)
+++ gcc/cp/class.c (working copy)
@@ -1129,7 +1129,7 @@ alter_access (tree t, tree fdecl, tree a
}
else
{
- perform_or_defer_access_check (TYPE_BINFO (t), fdecl);
+ perform_or_defer_access_check (TYPE_BINFO (t), fdecl, fdecl);
DECL_ACCESS (fdecl) = tree_cons (t, access, DECL_ACCESS (fdecl));
return 1;
}
@@ -5958,7 +5958,7 @@ resolve_address_of_overloaded_function (
if (DECL_FUNCTION_MEMBER_P (fn))
{
gcc_assert (access_path);
- perform_or_defer_access_check (access_path, fn);
+ perform_or_defer_access_check (access_path, fn, fn);
}
}
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c (revision 122171)
+++ gcc/cp/decl.c (working copy)
@@ -2865,7 +2865,7 @@ make_typename_type (tree context, tree n
}
if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), t);
+ perform_or_defer_access_check (TYPE_BINFO (context), t, t);
if (want_template)
return lookup_template_class (t, TREE_OPERAND (fullname, 1),
@@ -2928,7 +2928,7 @@ make_unbound_class_template (tree contex
}
if (complain & tf_error)
- perform_or_defer_access_check (TYPE_BINFO (context), tmpl);
+ perform_or_defer_access_check (TYPE_BINFO (context), tmpl, tmpl);
return tmpl;
}
Index: gcc/cp/call.c
===================================================================
--- gcc/cp/call.c (revision 122171)
+++ gcc/cp/call.c (working copy)
@@ -4101,7 +4101,7 @@ build_op_delete_call (enum tree_code cod
/* If the FN is a member function, make sure that it is
accessible. */
if (DECL_CLASS_SCOPE_P (fn))
- perform_or_defer_access_check (TYPE_BINFO (type), fn);
+ perform_or_defer_access_check (TYPE_BINFO (type), fn, fn);
if (pass == 0)
args = tree_cons (NULL_TREE, addr, args);
@@ -4132,21 +4132,22 @@ build_op_delete_call (enum tree_code cod
/* If the current scope isn't allowed to access DECL along
BASETYPE_PATH, give an error. The most derived class in
- BASETYPE_PATH is the one used to qualify DECL. */
+ BASETYPE_PATH is the one used to qualify DECL. DIAG_DECL is
+ the declaration to use in the error diagnostic. */
bool
-enforce_access (tree basetype_path, tree decl)
+enforce_access (tree basetype_path, tree decl, tree diag_decl)
{
gcc_assert (TREE_CODE (basetype_path) == TREE_BINFO);
if (!accessible_p (basetype_path, decl, true))
{
if (TREE_PRIVATE (decl))
- error ("%q+#D is private", decl);
+ error ("%q+#D is private", diag_decl);
else if (TREE_PROTECTED (decl))
- error ("%q+#D is protected", decl);
+ error ("%q+#D is protected", diag_decl);
else
- error ("%q+#D is inaccessible", decl);
+ error ("%q+#D is inaccessible", diag_decl);
error ("within this context");
return false;
}
@@ -4775,9 +4776,9 @@ build_over_call (struct z_candidate *can
if (DECL_TEMPLATE_INFO (fn)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
perform_or_defer_access_check (cand->access_path,
- DECL_TI_TEMPLATE (fn));
+ DECL_TI_TEMPLATE (fn), fn);
else
- perform_or_defer_access_check (cand->access_path, fn);
+ perform_or_defer_access_check (cand->access_path, fn, fn);
}
if (args && TREE_CODE (args) != TREE_LIST)
Index: gcc/cp/cp-tree.h
===================================================================
--- gcc/cp/cp-tree.h (revision 122171)
+++ gcc/cp/cp-tree.h (working copy)
@@ -3779,7 +3779,7 @@ extern tree build_op_delete_call (enum
extern bool can_convert (tree, tree);
extern bool can_convert_arg (tree, tree, tree, int);
extern bool can_convert_arg_bad (tree, tree, tree);
-extern bool enforce_access (tree, tree);
+extern bool enforce_access (tree, tree, tree);
extern tree convert_default_arg (tree, tree, tree, int);
extern tree convert_arg_to_ellipsis (tree);
extern tree build_x_va_arg (tree, tree);
@@ -4212,16 +4212,31 @@ 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);
+extern void perform_or_defer_access_check (tree, tree, tree);
extern int stmts_are_full_exprs_p (void);
extern void init_cp_semantics (void);
extern tree do_poplevel (tree);
Index: gcc/cp/search.c
===================================================================
--- gcc/cp/search.c (revision 122171)
+++ gcc/cp/search.c (working copy)
@@ -1273,7 +1273,7 @@ lookup_member (tree xbasetype, tree name
&& !really_overloaded_fn (rval)
&& !(TREE_CODE (rval) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (rval)))
- perform_or_defer_access_check (basetype_path, rval);
+ perform_or_defer_access_check (basetype_path, rval, rval);
if (errstr && protect)
{
Index: gcc/cp/friend.c
===================================================================
--- gcc/cp/friend.c (revision 122171)
+++ gcc/cp/friend.c (working copy)
@@ -171,7 +171,7 @@ add_friend (tree type, tree decl, bool c
ctx = DECL_CONTEXT (decl);
if (ctx && CLASS_TYPE_P (ctx) && !uses_template_parms (ctx))
- perform_or_defer_access_check (TYPE_BINFO (ctx), decl);
+ perform_or_defer_access_check (TYPE_BINFO (ctx), decl, decl);
maybe_add_class_template_decl_list (type, decl, /*friend_p=*/1);
Index: gcc/cp/semantics.c
===================================================================
--- gcc/cp/semantics.c (revision 122171)
+++ gcc/cp/semantics.c (working copy)
@@ -96,7 +96,7 @@ static tree finalize_nrv_r (tree *, int
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
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
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_
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 (v
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 (v
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));
+ perform_access_checks (checks);
}
else
{
/* Merge with parent. */
- tree next;
- tree original = ptr->deferred_access_checks;
-
- for (; checks; checks = next)
- {
- tree probe;
-
- next = TREE_CHAIN (checks);
+ int i, j;
+ deferred_access_check *chk, *probe;
- for (probe = original; probe; probe = TREE_CHAIN (probe))
- if (TREE_VALUE (probe) == TREE_VALUE (checks)
- && TREE_PURPOSE (probe) == TREE_PURPOSE (checks))
- goto found;
+ for (i = 0 ;
+ VEC_iterate (deferred_access_check, checks, i, chk) ;
+ ++i)
+ {
+ 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 (v
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));
- 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.
@@ -299,13 +299,16 @@ perform_deferred_access_checks (void)
}
/* Defer checking the accessibility of DECL, when looked up in
- BINFO. */
+ BINFO. DIAG_DECL is the declaration to use to print diagnostics. */
void
-perform_or_defer_access_check (tree binfo, tree decl)
+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.
*/
@@ -319,19 +322,29 @@ perform_or_defer_access_check (tree binf
/* If we are not supposed to defer access checks, just check now. */
if (ptr->deferring_access_checks_kind == dk_no_deferred)
{
- enforce_access (binfo, decl);
+ enforce_access (binfo, decl, diag_decl);
return;
}
/* 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)
- return;
+ 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,
@@ -1432,7 +1445,8 @@ finish_non_static_data_member (tree decl
DECL_NAME (decl),
/*template_p=*/false);
- perform_or_defer_access_check (TYPE_BINFO (access_type), decl);
+ perform_or_defer_access_check (TYPE_BINFO (access_type), decl,
+ decl);
/* If the data member was named `C::M', convert `*this' to `C'
first. */
@@ -1511,7 +1525,8 @@ check_accessibility_of_qualified_id (tre
or similar in a default argument value. */
&& CLASS_TYPE_P (qualifying_type)
&& !dependent_type_p (qualifying_type))
- perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl);
+ perform_or_defer_access_check (TYPE_BINFO (qualifying_type), decl,
+ decl);
}
/* EXPR is the result of a qualified-id. The QUALIFYING_CLASS was the
@@ -2846,7 +2861,7 @@ finish_id_expression (tree id_expression
tree path;
path = currently_open_derived_class (DECL_CONTEXT (decl));
- perform_or_defer_access_check (TYPE_BINFO (path), decl);
+ perform_or_defer_access_check (TYPE_BINFO (path), decl, decl);
}
decl = convert_from_reference (decl);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 122171)
+++ gcc/cp/parser.c (working copy)
@@ -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_lexe
/* 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_lexe
/* 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_lexe
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_lexe
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 *l
{
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_
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:
@@ -1597,7 +1616,7 @@ static void cp_parser_linkage_specificat
/* 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
@@ -1797,9 +1816,9 @@ static tree cp_parser_function_definitio
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
@@ -1953,7 +1972,7 @@ cp_parser_error (cp_parser* parser, cons
CPP_KEYWORD, keywords are treated like
identifiers. */
(token->type == CPP_KEYWORD ? CPP_NAME : token->type),
- token->value);
+ token->u.value);
}
}
@@ -2694,7 +2713,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
@@ -2735,8 +2754,8 @@ cp_parser_string_literal (cp_parser *par
{
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;
@@ -2752,8 +2771,8 @@ cp_parser_string_literal (cp_parser *par
{
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;
@@ -2920,7 +2939,7 @@ cp_parser_primary_expression (cp_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)
{
@@ -2957,7 +2976,7 @@ cp_parser_primary_expression (cp_parser
cp_parser_non_integral_constant_expression
(parser, "floating-point literal");
}
- return token->value;
+ return token->u.value;
case CPP_STRING:
case CPP_WSTRING:
@@ -3073,7 +3092,7 @@ cp_parser_primary_expression (cp_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:
{
@@ -3510,7 +3529,7 @@ cp_parser_unqualified_id (cp_parser* par
&& 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);
@@ -3811,7 +3830,7 @@ cp_parser_nested_name_specifier_opt (cp_
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,
@@ -3822,13 +3841,13 @@ cp_parser_nested_name_specifier_opt (cp_
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;
@@ -3887,17 +3906,17 @@ cp_parser_nested_name_specifier_opt (cp_
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. */
@@ -4755,7 +4774,7 @@ cp_parser_parenthesized_expression_list
/* Consume the identifier. */
token = cp_lexer_consume_token (parser->lexer);
/* Save the identifier. */
- identifier = token->value;
+ identifier = token->u.value;
}
else
{
@@ -7382,7 +7401,7 @@ cp_parser_simple_declaration (cp_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,
@@ -7720,7 +7739,7 @@ cp_parser_storage_class_specifier_opt (c
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;
@@ -7768,7 +7787,7 @@ cp_parser_function_specifier_opt (cp_par
}
/* Consume the token. */
- return cp_lexer_consume_token (parser->lexer)->value;
+ return cp_lexer_consume_token (parser->lexer)->u.value;
}
/* Parse a linkage-specification.
@@ -8745,11 +8764,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;
@@ -8758,17 +8779,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));
+ 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
@@ -8884,10 +8913,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
@@ -8900,7 +8925,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. */
@@ -9565,7 +9594,7 @@ cp_parser_explicit_specialization (cp_pa
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. */
@@ -9732,7 +9761,7 @@ cp_parser_type_specifier (cp_parser* par
++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
@@ -9875,7 +9904,7 @@ cp_parser_simple_type_specifier (cp_pars
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
@@ -11018,7 +11047,7 @@ cp_parser_asm_definition (cp_parser* par
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,
@@ -12816,7 +12845,7 @@ cp_parser_initializer_list (cp_parser* 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);
}
@@ -13621,7 +13650,7 @@ cp_parser_member_specification_opt (cp_p
/* 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;
@@ -14789,7 +14818,7 @@ cp_parser_attribute_list (cp_parser* par
/* 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. */
@@ -15612,7 +15641,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;
@@ -15735,7 +15764,7 @@ cp_parser_template_declaration_after_exp
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);
@@ -15751,7 +15780,7 @@ cp_parser_perform_template_parameter_acc
static tree
cp_parser_single_declaration (cp_parser* parser,
- tree checks,
+ VEC (deferred_access_check,gc)* checks,
bool member_p,
bool* friend_p)
{
@@ -16697,17 +16726,29 @@ cp_parser_optional_template_keyword (cp_
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));
+ 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;
}
@@ -16895,7 +16936,7 @@ cp_parser_objc_expression (cp_parser* pa
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)
@@ -16913,7 +16954,7 @@ cp_parser_objc_expression (cp_parser* pa
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);
}
@@ -17303,7 +17344,7 @@ cp_parser_objc_protocol_qualifiers (cp_p
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]
@@ -17316,7 +17357,7 @@ cp_parser_objc_protocol_qualifiers (cp_p
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;
@@ -17387,7 +17428,7 @@ cp_parser_objc_selector (cp_parser* pars
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;
}
}
@@ -17836,7 +17877,7 @@ cp_parser_objc_declaration (cp_parser* p
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);
}
}
@@ -17967,7 +18008,7 @@ cp_parser_objc_statement (cp_parser * pa
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);
}
@@ -18013,7 +18054,7 @@ cp_parser_omp_clause_name (cp_parser *pa
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])
@@ -18167,7 +18208,7 @@ cp_parser_omp_clause_default (cp_parser
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])
@@ -18378,7 +18419,7 @@ cp_parser_omp_clause_schedule (cp_parser
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])
@@ -19027,7 +19068,7 @@ cp_parser_omp_parallel (cp_parser *parse
}
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)
{
@@ -19183,7 +19224,7 @@ cp_parser_initial_pragma (cp_token *firs
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)
@@ -19303,7 +19344,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;
2007-02-20 Simon Martin <simartin@users.sourceforge.net>
PR c++/29475
* g++.dg/template/access19.C: New test.
* g++.old-deja/g++.other/access11.C: Adjusted the line where the error is
reported.
Index: gcc/testsuite/g++.old-deja/g++.other/access11.C
===================================================================
--- gcc/testsuite/g++.old-deja/g++.other/access11.C (revision 122171)
+++ gcc/testsuite/g++.old-deja/g++.other/access11.C (working copy)
@@ -5,12 +5,12 @@
class A
{
private:
- template <class T> void g(T t) {} // { dg-error "" } private
+ template <class T> void g(T t) {}
int i;
};
template <>
-void A::g<int>(int t) { i = 1; }
+void A::g<int>(int t) { i = 1; } // { dg-error "" } private
int main()
{
/* PR c++/29475 The error diagnostic contained "U = U" instead of "U = char" */
/* { dg-do "compile" } */
template< class T >
class explicit_t
{
public:
explicit_t( const T& c ): value( c ) { }
operator T&() { return value; }
private:
template< class U >
explicit_t( U t ); /* { dg-error "with U = char, T = int|is private" } */
T value;
};
int foo( int x, explicit_t< int > y )
{
return x + y;
}
int main()
{
return foo( 5, 'c' ); /* { dg-error "this context" } */
}