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
This commit is contained in:
parent
1152b861f7
commit
91b004e5ec
@ -1,3 +1,22 @@
|
||||
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
|
||||
|
@ -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'",
|
||||
|
@ -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'",
|
||||
|
@ -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. */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
12
gcc/cp/pt.c
12
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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user