This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR c++/14138


The test case for this PR looks like:

   struct S {
     int i1;
     ...
     int i1000;

     void S::f1();
     ...
     void S::f100();
   };

This code is invalid (because the qualification with "S" of the member
functions is not allowed), but we accept the code unless being
pedantic.

The problem was that when we saw S::f1() we wanted to do a lookup of
"f1", and that entailed entering the scope of "S".  Entering and
exiting scopes -- especially with lots of data members when the class
is not yet complete, and thus DECL_SORTED_FIELDS is not yet active --
is very expensive.

This patch avoids entering a class scope if we are already *in* that
class scope, which reduces the test case execution time to 3.6s on my
machine.  I killed the original compiler after 6 minutes, so I don't
know how long it would actually take to complete, but clearly much,
much longer.

Tested on i686-pc-linux-gnu, applied on the 3.4 branch and on the
mainline.

--
Mark Mitchell
CodeSourcery, LLC
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.

Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1174.2.9
diff -c -5 -p -r1.1174.2.9 decl.c
*** decl.c	16 Feb 2004 03:08:47 -0000	1.1174.2.9
--- decl.c	1 Mar 2004 06:15:37 -0000
*************** grokfndecl (tree ctype, 
*** 5739,5759 ****
  	error ("definition of implicitly-declared `%D'", old_decl);
  
        if (old_decl)
  	{
  	  tree ok;
  
  	  /* Since we've smashed OLD_DECL to its
  	     DECL_TEMPLATE_RESULT, we must do the same to DECL.  */
  	  if (TREE_CODE (decl) == TEMPLATE_DECL)
  	    decl = DECL_TEMPLATE_RESULT (decl);
  
  	  /* Attempt to merge the declarations.  This can fail, in
  	     the case of some invalid specialization declarations.  */
! 	  push_scope (ctype);
  	  ok = duplicate_decls (decl, old_decl);
! 	  pop_scope (ctype);
  	  if (!ok)
  	    {
  	      error ("no `%#D' member function declared in class `%T'",
  		     decl, ctype);
  	      return NULL_TREE;
--- 5739,5761 ----
  	error ("definition of implicitly-declared `%D'", old_decl);
  
        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.  */
  	  if (TREE_CODE (decl) == TEMPLATE_DECL)
  	    decl = DECL_TEMPLATE_RESULT (decl);
  
  	  /* Attempt to merge the declarations.  This can fail, in
  	     the case of some invalid specialization declarations.  */
! 	  pop_p = push_scope (ctype);
  	  ok = duplicate_decls (decl, old_decl);
! 	  if (pop_p)
! 	    pop_scope (ctype);
  	  if (!ok)
  	    {
  	      error ("no `%#D' member function declared in class `%T'",
  		     decl, ctype);
  	      return NULL_TREE;
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.695.4.3
diff -c -5 -p -r1.695.4.3 decl2.c
*** decl2.c	14 Feb 2004 02:32:47 -0000	1.695.4.3
--- decl2.c	1 Mar 2004 06:15:37 -0000
*************** check_classfn (tree ctype, tree function
*** 650,662 ****
    if (ix >= 0)
      {
        tree methods = CLASSTYPE_METHOD_VEC (ctype);
        tree fndecls, fndecl = 0;
        bool is_conv_op;
        const char *format = NULL;
        
!       push_scope (ctype);
        for (fndecls = TREE_VEC_ELT (methods, ix);
  	   fndecls; fndecls = OVL_NEXT (fndecls))
  	{
  	  tree p1, p2;
  	  
--- 650,663 ----
    if (ix >= 0)
      {
        tree methods = CLASSTYPE_METHOD_VEC (ctype);
        tree fndecls, fndecl = 0;
        bool is_conv_op;
+       bool pop_p;
        const char *format = NULL;
        
!       pop_p = push_scope (ctype);
        for (fndecls = TREE_VEC_ELT (methods, ix);
  	   fndecls; fndecls = OVL_NEXT (fndecls))
  	{
  	  tree p1, p2;
  	  
*************** check_classfn (tree ctype, tree function
*** 688,698 ****
  	      && (!DECL_TEMPLATE_SPECIALIZATION (function)
  		  || (DECL_TI_TEMPLATE (function) 
  		      == DECL_TI_TEMPLATE (fndecl))))
  	    break;
  	}
!       pop_scope (ctype);
        if (fndecls)
  	return OVL_CURRENT (fndecls);
        error ("prototype for `%#D' does not match any in class `%T'",
  	     function, ctype);
        is_conv_op = DECL_CONV_FN_P (fndecl);
--- 689,700 ----
  	      && (!DECL_TEMPLATE_SPECIALIZATION (function)
  		  || (DECL_TI_TEMPLATE (function) 
  		      == DECL_TI_TEMPLATE (fndecl))))
  	    break;
  	}
!       if (pop_p)
! 	pop_scope (ctype);
        if (fndecls)
  	return OVL_CURRENT (fndecls);
        error ("prototype for `%#D' does not match any in class `%T'",
  	     function, ctype);
        is_conv_op = DECL_CONV_FN_P (fndecl);
Index: name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.34.2.4
diff -c -5 -p -r1.34.2.4 name-lookup.c
*** name-lookup.c	20 Feb 2004 06:46:00 -0000	1.34.2.4
--- name-lookup.c	1 Mar 2004 06:15:39 -0000
*************** is_ancestor (tree root, tree child)
*** 2486,2504 ****
  	child = TYPE_NAME (child);
        child = DECL_CONTEXT (child);
      }
  }
  
! /* Enter a class or namespace scope.  */
  
! void
  push_scope (tree t)
  {
    if (TREE_CODE (t) == NAMESPACE_DECL)
      push_decl_namespace (t);
!   else if CLASS_TYPE_P (t)
!     push_nested_class (t);
  }
  
  /* Leave scope pushed by push_scope.  */
  
  void
--- 2486,2519 ----
  	child = TYPE_NAME (child);
        child = DECL_CONTEXT (child);
      }
  }
  
! /* Enter the class or namespace scope indicated by T.  Returns TRUE iff
!    pop_scope should be called later to exit this scope.  */
  
! bool
  push_scope (tree t)
  {
+   bool pop = true;
+ 
    if (TREE_CODE (t) == NAMESPACE_DECL)
      push_decl_namespace (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.  */
  
  void
Index: name-lookup.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.h,v
retrieving revision 1.15.2.2
diff -c -5 -p -r1.15.2.2 name-lookup.h
*** name-lookup.h	27 Jan 2004 02:35:21 -0000	1.15.2.2
--- name-lookup.h	1 Mar 2004 06:15:39 -0000
*************** extern void print_binding_level	(cxx_sco
*** 265,275 ****
  extern void push_to_top_level (void);
  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 void pop_scope (tree);
  
  extern void push_namespace (tree);
  extern void pop_namespace (void);
  extern void push_nested_namespace (tree);
--- 265,275 ----
  extern void push_to_top_level (void);
  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 bool push_scope (tree);
  extern void pop_scope (tree);
  
  extern void push_namespace (tree);
  extern void pop_namespace (void);
  extern void push_nested_namespace (tree);
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.157.2.15
diff -c -5 -p -r1.157.2.15 parser.c
*** parser.c	27 Feb 2004 00:30:46 -0000	1.157.2.15
--- parser.c	1 Mar 2004 06:15:42 -0000
*************** cp_parser_conversion_function_id (cp_par
*** 6948,6957 ****
--- 6948,6958 ----
  {
    tree type;
    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'"))
      return error_mark_node;
    /* When we parse the conversion-type-id, the current scope will be
*************** cp_parser_conversion_function_id (cp_par
*** 6972,6986 ****
         S::operator I() { ... }
  
       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);
    /* Parse the conversion-type-id.  */
    type = cp_parser_conversion_type_id (parser);
    /* Leave the scope of the class, if any.  */
!   if (saved_scope)
      pop_scope (saved_scope);
    /* Restore the saved scope.  */
    parser->scope = saved_scope;
    parser->qualifying_scope = saved_qualifying_scope;
    parser->object_scope = saved_object_scope;
--- 6973,6987 ----
         S::operator I() { ... }
  
       In order to see that `I' is a type-name in the definition, we
       must be in the scope of `S'.  */
    if (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 (pop_p)
      pop_scope (saved_scope);
    /* Restore the saved scope.  */
    parser->scope = saved_scope;
    parser->qualifying_scope = saved_qualifying_scope;
    parser->object_scope = saved_object_scope;
*************** cp_parser_init_declarator (cp_parser* pa
*** 9844,9853 ****
--- 9845,9855 ----
    bool is_initialized;
    bool is_parenthesized_init;
    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.  */
    if (function_definition_p)
      *function_definition_p = false;
*************** cp_parser_init_declarator (cp_parser* pa
*** 10001,10011 ****
      }
  
    /* Enter the SCOPE.  That way unqualified names appearing in the
       initializer will be looked up in SCOPE.  */
    if (scope)
!     push_scope (scope);
  
    /* Perform deferred access control checks, now that we know in which
       SCOPE the declared entity resides.  */
    if (!member_p && decl) 
      {
--- 10003,10013 ----
      }
  
    /* Enter the SCOPE.  That way unqualified names appearing in the
       initializer will be looked up in SCOPE.  */
    if (scope)
!     pop_p = push_scope (scope);
  
    /* Perform deferred access control checks, now that we know in which
       SCOPE the declared entity resides.  */
    if (!member_p && decl) 
      {
*************** cp_parser_init_declarator (cp_parser* pa
*** 10051,10061 ****
  
    /* Leave the SCOPE, now that we have processed the initializer.  It
       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)
      pop_scope (scope);
  
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
--- 10053,10063 ----
  
    /* Leave the SCOPE, now that we have processed the initializer.  It
       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 (pop_p)
      pop_scope (scope);
  
    /* For an in-class declaration, use `grokfield' to create the
       declaration.  */
    if (member_p)
*************** cp_parser_direct_declarator (cp_parser* 
*** 10271,10281 ****
    tree declarator = NULL_TREE;
    tree scope = NULL_TREE;
    bool saved_default_arg_ok_p = parser->default_arg_ok_p;
    bool saved_in_declarator_p = parser->in_declarator_p;
    bool first = true;
!   
    while (true)
      {
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
        if (token->type == CPP_OPEN_PAREN)
--- 10273,10284 ----
    tree declarator = NULL_TREE;
    tree scope = NULL_TREE;
    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)
      {
        /* Peek at the next token.  */
        token = cp_lexer_peek_token (parser->lexer);
        if (token->type == CPP_OPEN_PAREN)
*************** cp_parser_direct_declarator (cp_parser* 
*** 10541,10553 ****
  	    }
  
  	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);
  	  parser->in_declarator_p = true;
  	  if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
  	      || (declarator
  		  && (TREE_CODE (declarator) == SCOPE_REF
  		      || TREE_CODE (declarator) == IDENTIFIER_NODE)))
--- 10544,10556 ----
  	    }
  
  	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.  */
! 	    pop_p = push_scope (scope);
  	  parser->in_declarator_p = true;
  	  if ((ctor_dtor_or_conv_p && *ctor_dtor_or_conv_p)
  	      || (declarator
  		  && (TREE_CODE (declarator) == SCOPE_REF
  		      || TREE_CODE (declarator) == IDENTIFIER_NODE)))
*************** cp_parser_direct_declarator (cp_parser* 
*** 10568,10578 ****
       point.  That's an error; the declarator is not optional.  */
    if (!declarator)
      cp_parser_error (parser, "expected declarator");
  
    /* If we entered a scope, we must exit it now.  */
!   if (scope)
      pop_scope (scope);
  
    parser->default_arg_ok_p = saved_default_arg_ok_p;
    parser->in_declarator_p = saved_in_declarator_p;
    
--- 10571,10581 ----
       point.  That's an error; the declarator is not optional.  */
    if (!declarator)
      cp_parser_error (parser, "expected declarator");
  
    /* If we entered a scope, we must exit it now.  */
!   if (pop_p)
      pop_scope (scope);
  
    parser->default_arg_ok_p = saved_default_arg_ok_p;
    parser->in_declarator_p = saved_in_declarator_p;
    
*************** cp_parser_class_specifier (cp_parser* pa
*** 11691,11700 ****
--- 11694,11704 ----
    tree type;
    tree attributes = NULL_TREE;
    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);
  
    /* Parse the class-head.  */
    type = cp_parser_class_head (parser,
*************** cp_parser_class_specifier (cp_parser* pa
*** 11725,11735 ****
      = parser->num_template_parameter_lists; 
    parser->num_template_parameter_lists = 0;
  
    /* Start the class.  */
    if (nested_name_specifier_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.  */
      cp_parser_skip_to_closing_brace (parser);
    else
--- 11729,11739 ----
      = parser->num_template_parameter_lists; 
    parser->num_template_parameter_lists = 0;
  
    /* Start the class.  */
    if (nested_name_specifier_p)
!     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.  */
      cp_parser_skip_to_closing_brace (parser);
    else
*************** cp_parser_class_specifier (cp_parser* pa
*** 11750,11760 ****
      {
        attributes = chainon (TYPE_ATTRIBUTES (type), attributes);
        TYPE_ATTRIBUTES (type) = NULL_TREE;
        type = finish_struct (type, attributes);
      }
!   if (nested_name_specifier_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
       definitions.  Note that the queued functions defined in a class
       are not always processed immediately following the
--- 11754,11764 ----
      {
        attributes = chainon (TYPE_ATTRIBUTES (type), attributes);
        TYPE_ATTRIBUTES (type) = NULL_TREE;
        type = finish_struct (type, attributes);
      }
!   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
       definitions.  Note that the queued functions defined in a class
       are not always processed immediately following the
*************** cp_parser_class_head (cp_parser* parser,
*** 11868,11877 ****
--- 11872,11882 ----
    tree attributes;
    bool template_id_p = false;
    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.  */
    *nested_name_specifier_p = false;
    /* Assume no template parameter lists will be used in defining the
*************** cp_parser_class_head (cp_parser* parser,
*** 12088,12097 ****
--- 12093,12103 ----
  		       parser->num_template_parameter_lists);
      }
    else
      {
        tree class_type;
+       bool pop_p = false;
  
        /* Given:
  
  	    template <typename T> struct S { struct T };
  	    template <typename T> struct S<T>::T { };
*************** cp_parser_class_head (cp_parser* parser,
*** 12114,12134 ****
  
        maybe_process_partial_specialization (TREE_TYPE (type));
        class_type = current_class_type;
        /* Enter the scope indicated by the nested-name-specifier.  */
        if (nested_name_specifier)
! 	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 ()
  	  && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (type)))
  	type = push_template_decl (type);
        type = TREE_TYPE (type);
        if (nested_name_specifier)
  	{
  	  *nested_name_specifier_p = true;
! 	  pop_scope (nested_name_specifier);
  	}
      }
    /* Indicate whether this class was declared as a `class' or as a
       `struct'.  */
    if (TREE_CODE (type) == RECORD_TYPE)
--- 12120,12141 ----
  
        maybe_process_partial_specialization (TREE_TYPE (type));
        class_type = current_class_type;
        /* Enter the scope indicated by the nested-name-specifier.  */
        if (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 ()
  	  && !CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (type)))
  	type = push_template_decl (type);
        type = TREE_TYPE (type);
        if (nested_name_specifier)
  	{
  	  *nested_name_specifier_p = true;
! 	  if (pop_p)
! 	    pop_scope (nested_name_specifier);
  	}
      }
    /* Indicate whether this class was declared as a `class' or as a
       `struct'.  */
    if (TREE_CODE (type) == RECORD_TYPE)
*************** cp_parser_class_head (cp_parser* parser,
*** 12141,12151 ****
         struct A { struct B {}; struct C; };
         struct A::C : B {};
  
       is valid.  */
    if (nested_name_specifier)
!     push_scope (nested_name_specifier);
    /* Now, look for the base-clause.  */
    token = cp_lexer_peek_token (parser->lexer);
    if (token->type == CPP_COLON)
      {
        tree bases;
--- 12148,12158 ----
         struct A { struct B {}; struct C; };
         struct A::C : B {};
  
       is valid.  */
    if (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)
      {
        tree bases;
*************** cp_parser_class_head (cp_parser* parser,
*** 12155,12165 ****
        /* Process them.  */
        xref_basetypes (type, bases);
      }
    /* Leave the scope given by the nested-name-specifier.  We will
       enter the class scope itself while processing the members.  */
!   if (nested_name_specifier)
      pop_scope (nested_name_specifier);
  
   done:
    if (invalid_explicit_specialization_p)
      {
--- 12162,12172 ----
        /* Process them.  */
        xref_basetypes (type, bases);
      }
    /* Leave the scope given by the nested-name-specifier.  We will
       enter the class scope itself while processing the members.  */
!   if (pop_p)
      pop_scope (nested_name_specifier);
  
   done:
    if (invalid_explicit_specialization_p)
      {
*************** cp_parser_lookup_name (cp_parser *parser
*** 13580,13603 ****
  	  else
  	    decl = build_nt (SCOPE_REF, parser->scope, name);
  	}
        else
  	{
  	  /* 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);
  	  /* 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)
  	    pop_scope (parser->scope);
  	}
        parser->qualifying_scope = parser->scope;
        parser->object_scope = NULL_TREE;
      }
--- 13587,13612 ----
  	  else
  	    decl = build_nt (SCOPE_REF, parser->scope, 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)
! 	    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 (pop_p)
  	    pop_scope (parser->scope);
  	}
        parser->qualifying_scope = parser->scope;
        parser->object_scope = NULL_TREE;
      }
*************** cp_parser_constructor_declarator_p (cp_p
*** 14025,14034 ****
--- 14034,14044 ----
        if (cp_lexer_next_token_is_not (parser->lexer, CPP_CLOSE_PAREN)
  	  && cp_lexer_next_token_is_not (parser->lexer, CPP_ELLIPSIS)
  	  && !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
  	     in the scope of the class.  */
  	  if (current_class_type)
*************** cp_parser_constructor_declarator_p (cp_p
*** 14044,14054 ****
  		    {
  		      cp_parser_abort_tentative_parse (parser);
  		      return false;
  		    }
  		}
! 	      push_scope (type);
  	    }
  
  	  /* Inside the constructor parameter list, surrounding
  	     template-parameter-lists do not apply.  */
  	  saved_num_template_parameter_lists
--- 14054,14064 ----
  		    {
  		      cp_parser_abort_tentative_parse (parser);
  		      return false;
  		    }
  		}
! 	      pop_p = push_scope (type);
  	    }
  
  	  /* Inside the constructor parameter list, surrounding
  	     template-parameter-lists do not apply.  */
  	  saved_num_template_parameter_lists
*************** cp_parser_constructor_declarator_p (cp_p
*** 14065,14075 ****
  
  	  parser->num_template_parameter_lists
  	    = saved_num_template_parameter_lists;
  
  	  /* Leave the scope of the class.  */
! 	  if (type)
  	    pop_scope (type);
  
  	  constructor_p = !cp_parser_error_occurred (parser);
  	}
      }
--- 14075,14085 ----
  
  	  parser->num_template_parameter_lists
  	    = saved_num_template_parameter_lists;
  
  	  /* Leave the scope of the class.  */
! 	  if (pop_p)
  	    pop_scope (type);
  
  	  constructor_p = !cp_parser_error_occurred (parser);
  	}
      }
Index: pt.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/pt.c,v
retrieving revision 1.816.2.13
diff -c -5 -p -r1.816.2.13 pt.c
*** pt.c	27 Feb 2004 01:39:53 -0000	1.816.2.13
--- pt.c	1 Mar 2004 06:15:47 -0000
*************** instantiate_class_template (tree type)
*** 5404,5419 ****
      {
        tree base_list = NULL_TREE;
        tree pbases = BINFO_BASETYPES (pbinfo);
        tree paccesses = BINFO_BASEACCESSES (pbinfo);
        tree context = TYPE_CONTEXT (type);
        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);
    
        /* Substitute into each of the bases to determine the actual
  	 basetypes.  */
        for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
  	{
--- 5404,5420 ----
      {
        tree base_list = NULL_TREE;
        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.  */
!       pop_p = push_scope (context ? context : global_namespace);
    
        /* Substitute into each of the bases to determine the actual
  	 basetypes.  */
        for (i = 0; i < TREE_VEC_LENGTH (pbases); ++i)
  	{
*************** instantiate_class_template (tree type)
*** 5438,5448 ****
  
        /* Now call xref_basetypes to set up all the base-class
  	 information.  */
        xref_basetypes (type, base_list);
  
!       pop_scope (context ? context : global_namespace);
      }
  
    /* Now that our base classes are set up, enter the scope of the
       class, so that name lookups into base classes, etc. will work
       correctly.  This is precisely analogous to what we do in
--- 5439,5450 ----
  
        /* Now call xref_basetypes to set up all the base-class
  	 information.  */
        xref_basetypes (type, base_list);
  
!       if (pop_p)
! 	pop_scope (context ? context : global_namespace);
      }
  
    /* Now that our base classes are set up, enter the scope of the
       class, so that name lookups into base classes, etc. will work
       correctly.  This is precisely analogous to what we do in
*************** resolve_typename_type (tree type, bool o
*** 12015,12024 ****
--- 12017,12027 ----
  {
    tree scope;
    tree name;
    tree decl;
    int quals;
+   bool pop_p;
  
    my_friendly_assert (TREE_CODE (type) == TYPENAME_TYPE,
  		      20010702);
  
    scope = TYPE_CONTEXT (type);
*************** resolve_typename_type (tree type, bool o
*** 12044,12054 ****
       TYPE_FIELDS list, so use the original template.  */
    scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
    /* 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);
    /* Look up the declaration.  */
    decl = lookup_member (scope, name, /*protect=*/0, /*want_type=*/true);
    /* Obtain the set of qualifiers applied to the TYPE.  */
    quals = cp_type_quals (type);
    /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
--- 12047,12057 ----
       TYPE_FIELDS list, so use the original template.  */
    scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
    /* 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.  */
!   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.  */
    quals = cp_type_quals (type);
    /* For a TYPENAME_TYPE like "typename X::template Y<T>", we want to
*************** resolve_typename_type (tree type, bool o
*** 12074,12084 ****
      type = error_mark_node;
    /* Qualify the resulting type.  */
    if (type != error_mark_node && quals)
      type = cp_build_qualified_type (type, quals);
    /* Leave the SCOPE.  */
!   pop_scope (scope);
  
    return type;
  }
  
  /* EXPR is an expression which is not type-dependent.  Return a proxy
--- 12077,12088 ----
      type = error_mark_node;
    /* Qualify the resulting type.  */
    if (type != error_mark_node && quals)
      type = cp_build_qualified_type (type, quals);
    /* Leave the SCOPE.  */
!   if (pop_p)
!     pop_scope (scope);
  
    return type;
  }
  
  /* EXPR is an expression which is not type-dependent.  Return a proxy


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]