diff options
author | Simon Martin <simartin@users.sourceforge.net> | 2006-12-16 08:51:42 +0000 |
---|---|---|
committer | Simon Martin <simartin@gcc.gnu.org> | 2006-12-16 08:51:42 +0000 |
commit | d6b418fa0b3d5dc88ffb3f1673f82e6dbf5da6d1 (patch) | |
tree | a7b346cda4d3b77e77b9aa9c9d5fdd0dbacf5afe /gcc/cp | |
parent | e6a98ba89323ec0f641df79101ea99dadda441ce (diff) | |
download | gcc-d6b418fa0b3d5dc88ffb3f1673f82e6dbf5da6d1.zip gcc-d6b418fa0b3d5dc88ffb3f1673f82e6dbf5da6d1.tar.gz gcc-d6b418fa0b3d5dc88ffb3f1673f82e6dbf5da6d1.tar.bz2 |
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
Diffstat (limited to 'gcc/cp')
-rw-r--r-- | gcc/cp/ChangeLog | 68 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 19 | ||||
-rw-r--r-- | gcc/cp/parser.c | 210 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 99 |
4 files changed, 265 insertions, 131 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5f8b607..b51ebc0 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,71 @@ +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 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 3f63b8f..3968f96 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -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); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 0521136..ae2b4a0 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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; diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 9192aff..41d2be9 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -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)) - goto found; + 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) - 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, |