Commit 91b004e5 by Mark Mitchell Committed by Mark Mitchell

re PR c++/14138 (100x -O0 C++ Compile Time Regression {3.2,3.3} -> {3.4,4.0})

	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.

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