diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 82de3a9e19c..da4618abdc5 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,22 @@ +2004-02-29 Mark Mitchell + + PR c++/14138 + * name-lookup.h (push_scope): Change prototype. + * name-lookup.c (push_scope): Do not reenter the current class + scope. + * decl.c (grokfndecl): Check return code from push_scope before + calling pop_scope. + * decl2.c (check_classfn): Likewise. + * parser.c (cp_parser_conversion_function_id): Likewise. + (cp_parser_init_declarator): Likewise. + (cp_parser_direct_declarator): Likewise. + (cp_parser_class_specifier): Likewise. + (cp_parser_class_head): Likewise. + (cp_parser_lookup_name): Likewise. + (cp_parser_constructor_declarator_p): Likewise. + * pt.c (instantiate_class_template): Likewise. + (resolve_typename_type): Likewise. + 2004-02-29 Mark Mitchell PR c++/14267 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6a4d6efe80a..64aad7207a0 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -5733,6 +5733,7 @@ grokfndecl (tree ctype, if (old_decl) { tree ok; + bool pop_p; /* Since we've smashed OLD_DECL to its DECL_TEMPLATE_RESULT, we must do the same to DECL. */ @@ -5741,9 +5742,10 @@ grokfndecl (tree ctype, /* Attempt to merge the declarations. This can fail, in the case of some invalid specialization declarations. */ - push_scope (ctype); + pop_p = push_scope (ctype); ok = duplicate_decls (decl, old_decl); - pop_scope (ctype); + if (pop_p) + pop_scope (ctype); if (!ok) { error ("no `%#D' member function declared in class `%T'", diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index d5ee526381c..9d8043a2f46 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -652,9 +652,10 @@ check_classfn (tree ctype, tree function, bool template_header_p) tree methods = CLASSTYPE_METHOD_VEC (ctype); tree fndecls, fndecl = 0; bool is_conv_op; + bool pop_p; const char *format = NULL; - push_scope (ctype); + pop_p = push_scope (ctype); for (fndecls = TREE_VEC_ELT (methods, ix); fndecls; fndecls = OVL_NEXT (fndecls)) { @@ -690,7 +691,8 @@ check_classfn (tree ctype, tree function, bool template_header_p) == DECL_TI_TEMPLATE (fndecl)))) break; } - pop_scope (ctype); + if (pop_p) + pop_scope (ctype); if (fndecls) return OVL_CURRENT (fndecls); error ("prototype for `%#D' does not match any in class `%T'", diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c index cbdcd1ba21e..7d6239b67ed 100644 --- a/gcc/cp/name-lookup.c +++ b/gcc/cp/name-lookup.c @@ -2494,15 +2494,30 @@ is_ancestor (tree root, tree child) } } -/* Enter a class or namespace scope. */ +/* Enter the class or namespace scope indicated by T. Returns TRUE iff + pop_scope should be called later to exit this scope. */ -void +bool push_scope (tree t) { + bool pop = true; + if (TREE_CODE (t) == NAMESPACE_DECL) push_decl_namespace (t); - else if CLASS_TYPE_P (t) - push_nested_class (t); + else if (CLASS_TYPE_P (t)) + { + if (!at_class_scope_p () + || !same_type_p (current_class_type, t)) + push_nested_class (t); + else + /* T is the same as the current scope. There is therefore no + need to re-enter the scope. Since we are not actually + pushing a new scope, our caller should not call + pop_scope. */ + pop = false; + } + + return pop; } /* Leave scope pushed by push_scope. */ diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index f9764fcfdec..83775752053 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -267,7 +267,7 @@ extern void pop_from_top_level (void); extern void pop_everything (void); extern void keep_next_level (bool); extern bool is_ancestor (tree, tree); -extern void push_scope (tree); +extern bool push_scope (tree); extern void pop_scope (tree); extern void push_namespace (tree); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index a7ec5f065b3..bc887f89bf9 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -7035,6 +7035,7 @@ cp_parser_conversion_function_id (cp_parser* parser) tree saved_scope; tree saved_qualifying_scope; tree saved_object_scope; + bool pop_p = false; /* Look for the `operator' token. */ if (!cp_parser_require_keyword (parser, RID_OPERATOR, "`operator'")) @@ -7059,11 +7060,11 @@ cp_parser_conversion_function_id (cp_parser* parser) In order to see that `I' is a type-name in the definition, we must be in the scope of `S'. */ if (saved_scope) - push_scope (saved_scope); + pop_p = push_scope (saved_scope); /* Parse the conversion-type-id. */ type = cp_parser_conversion_type_id (parser); /* Leave the scope of the class, if any. */ - if (saved_scope) + if (pop_p) pop_scope (saved_scope); /* Restore the saved scope. */ parser->scope = saved_scope; @@ -9935,6 +9936,7 @@ cp_parser_init_declarator (cp_parser* parser, bool is_non_constant_init; int ctor_dtor_or_conv_p; bool friend_p; + bool pop_p = false; /* Assume that this is not the declarator for a function definition. */ @@ -10092,7 +10094,7 @@ cp_parser_init_declarator (cp_parser* parser, /* Enter the SCOPE. That way unqualified names appearing in the initializer will be looked up in SCOPE. */ if (scope) - push_scope (scope); + pop_p = push_scope (scope); /* Perform deferred access control checks, now that we know in which SCOPE the declared entity resides. */ @@ -10142,7 +10144,7 @@ cp_parser_init_declarator (cp_parser* parser, is important to do this before calling cp_finish_decl because it makes decisions about whether to create DECL_STMTs or not based on the current scope. */ - if (scope) + if (pop_p) pop_scope (scope); /* For an in-class declaration, use `grokfield' to create the @@ -10362,6 +10364,7 @@ cp_parser_direct_declarator (cp_parser* parser, bool saved_default_arg_ok_p = parser->default_arg_ok_p; bool saved_in_declarator_p = parser->in_declarator_p; bool first = true; + bool pop_p = false; while (true) { @@ -10632,9 +10635,9 @@ cp_parser_direct_declarator (cp_parser* parser, handle_declarator:; scope = get_scope_of_declarator (declarator); if (scope) - /* Any names that appear after the declarator-id for a member - are looked up in the containing scope. */ - push_scope (scope); + /* Any names that appear after the declarator-id for a + member are looked up in the containing scope. */ + pop_p = push_scope (scope); parser->in_declarator_p = true; if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p) || (declarator @@ -10659,7 +10662,7 @@ cp_parser_direct_declarator (cp_parser* parser, cp_parser_error (parser, "expected declarator"); /* If we entered a scope, we must exit it now. */ - if (scope) + if (pop_p) pop_scope (scope); parser->default_arg_ok_p = saved_default_arg_ok_p; @@ -11782,6 +11785,7 @@ cp_parser_class_specifier (cp_parser* parser) int has_trailing_semicolon; bool nested_name_specifier_p; unsigned saved_num_template_parameter_lists; + bool pop_p = false; push_deferring_access_checks (dk_no_deferred); @@ -11816,7 +11820,7 @@ cp_parser_class_specifier (cp_parser* parser) /* Start the class. */ if (nested_name_specifier_p) - push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type))); + pop_p = push_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type))); type = begin_class_definition (type); if (type == error_mark_node) /* If the type is erroneous, skip the entire body of the class. */ @@ -11841,7 +11845,7 @@ cp_parser_class_specifier (cp_parser* parser) TYPE_ATTRIBUTES (type) = NULL_TREE; type = finish_struct (type, attributes); } - if (nested_name_specifier_p) + if (pop_p) pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (type))); /* If this class is not itself within the scope of another class, then we need to parse the bodies of all of the queued function @@ -11959,6 +11963,7 @@ cp_parser_class_head (cp_parser* parser, bool qualified_p = false; bool invalid_nested_name_p = false; bool invalid_explicit_specialization_p = false; + bool pop_p = false; unsigned num_templates; /* Assume no nested-name-specifier will be present. */ @@ -12179,6 +12184,7 @@ cp_parser_class_head (cp_parser* parser, else { tree class_type; + bool pop_p = false; /* Given: @@ -12205,7 +12211,7 @@ cp_parser_class_head (cp_parser* parser, class_type = current_class_type; /* Enter the scope indicated by the nested-name-specifier. */ if (nested_name_specifier) - push_scope (nested_name_specifier); + pop_p = push_scope (nested_name_specifier); /* Get the canonical version of this type. */ type = TYPE_MAIN_DECL (TREE_TYPE (type)); if (PROCESSING_REAL_TEMPLATE_DECL_P () @@ -12215,7 +12221,8 @@ cp_parser_class_head (cp_parser* parser, if (nested_name_specifier) { *nested_name_specifier_p = true; - pop_scope (nested_name_specifier); + if (pop_p) + pop_scope (nested_name_specifier); } } /* Indicate whether this class was declared as a `class' or as a @@ -12232,7 +12239,7 @@ cp_parser_class_head (cp_parser* parser, is valid. */ if (nested_name_specifier) - push_scope (nested_name_specifier); + pop_p = push_scope (nested_name_specifier); /* Now, look for the base-clause. */ token = cp_lexer_peek_token (parser->lexer); if (token->type == CPP_COLON) @@ -12246,7 +12253,7 @@ cp_parser_class_head (cp_parser* parser, } /* Leave the scope given by the nested-name-specifier. We will enter the class scope itself while processing the members. */ - if (nested_name_specifier) + if (pop_p) pop_scope (nested_name_specifier); done: @@ -13677,20 +13684,22 @@ cp_parser_lookup_name (cp_parser *parser, tree name, } else { + bool pop_p = false; + /* If PARSER->SCOPE is a dependent type, then it must be a class type, and we must not be checking dependencies; otherwise, we would have processed this lookup above. So that PARSER->SCOPE is not considered a dependent base by lookup_member, we must enter the scope here. */ if (dependent_p) - push_scope (parser->scope); + pop_p = push_scope (parser->scope); /* If the PARSER->SCOPE is a a template specialization, it may be instantiated during name lookup. In that case, errors may be issued. Even if we rollback the current tentative parse, those errors are valid. */ decl = lookup_qualified_name (parser->scope, name, is_type, /*complain=*/true); - if (dependent_p) + if (pop_p) pop_scope (parser->scope); } parser->qualifying_scope = parser->scope; @@ -14122,6 +14131,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) && !cp_parser_storage_class_specifier_opt (parser)) { tree type; + bool pop_p = false; unsigned saved_num_template_parameter_lists; /* Names appearing in the type-specifier should be looked up @@ -14141,7 +14151,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) return false; } } - push_scope (type); + pop_p = push_scope (type); } /* Inside the constructor parameter list, surrounding @@ -14162,7 +14172,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p) = saved_num_template_parameter_lists; /* Leave the scope of the class. */ - if (type) + if (pop_p) pop_scope (type); constructor_p = !cp_parser_error_occurred (parser); diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 7a08edaf779..3fa25768d94 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5408,12 +5408,13 @@ instantiate_class_template (tree type) tree pbases = BINFO_BASETYPES (pbinfo); tree paccesses = BINFO_BASEACCESSES (pbinfo); tree context = TYPE_CONTEXT (type); + bool pop_p; int i; /* We must enter the scope containing the type, as that is where the accessibility of types named in dependent bases are looked up from. */ - push_scope (context ? context : global_namespace); + pop_p = push_scope (context ? context : global_namespace); /* Substitute into each of the bases to determine the actual basetypes. */ @@ -5442,7 +5443,8 @@ instantiate_class_template (tree type) information. */ xref_basetypes (type, base_list); - pop_scope (context ? context : global_namespace); + if (pop_p) + pop_scope (context ? context : global_namespace); } /* Now that our base classes are set up, enter the scope of the @@ -12019,6 +12021,7 @@ resolve_typename_type (tree type, bool only_current_p) tree name; tree decl; int quals; + bool pop_p; my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE, 20010702); @@ -12048,7 +12051,7 @@ resolve_typename_type (tree type, bool only_current_p) /* Enter the SCOPE so that name lookup will be resolved as if we were in the class definition. In particular, SCOPE will no longer be considered a dependent type. */ - push_scope (scope); + pop_p = push_scope (scope); /* Look up the declaration. */ decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true); /* Obtain the set of qualifiers applied to the TYPE. */ @@ -12078,7 +12081,8 @@ resolve_typename_type (tree type, bool only_current_p) if (type != error_mark_node && quals) type = cp_build_qualified_type (type, quals); /* Leave the SCOPE. */ - pop_scope (scope); + if (pop_p) + pop_scope (scope); return type; }