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: Squeeze memory consumption a bit further


This patch reduces memory consumption by the C++ front end in two
ways:

1) We avoid building SCOPE_REFs for qualified names in declarators.
   These SCOPE_REFs were relics of the time before we had separate
   declarator structures; when the new structures were created, we did
   not change the representation for declarator-ids.

   Eliminating these SCOPE_REFs is important because they are a common
   case; every out-of-class definition of a member function resulted
   in one such SCOPE_REF.

2) We cal ggc_free in duplicate_decls on the new declaration.  This is
   important because every out-of-class definition of a member
   function results in a call to duplicate_decls.  In the old days,
   the new declaration was allocated on an obstack, and we freed the
   obstack storage; this is the equivalent optimization in our new
   world.   Yes, it would be nicer just to rely on the GC, but this
   optimization is quite significant, and there is no plausible way to
   avoid creating both declarations.

The total savings is on the order of 0.5% of compile time.

Tested on x86_64-unknown-linux-gnu, applied on the mainline.

--
Mark Mitchell
CodeSourcery, LLC
mark@codesourcery.com

2004-12-30  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (cp_declarator): Split "name" field into
	qualifying_scope and unqualified_name.
	* decl.c (get_scope_of_declarator): Adjust accordingly.
	(grokdeclarator): Likewise.
	* decl2.c (grokfield): Likewise, and adjust call to
	do_class_using_decl.
	* name-lookup.c (do_class_using_decl): Split "decl" into
	"scope" and "name".  Remove unnecessary code.
	* name-lookup.h (do_class_using_decl): Adjust declaration.
	* parser.c (make_id_declarator): Split "id" into qualifying_scope
	and unqualified_name.
	(cp_parser_using_declaration): Adjust call to do_class_using_decl.
	(cp_parser_direct_declarator): Adjust to handle the fact that
	cp_parser_declarator_id no longer returns a SCOPE_REF.
	(cp_parser_direct_declarator): Likewise.
	(cp_parser_declarator_id): Do not create a SCOPE_REF for qualified
	names.
	(cp_parser_member_declaration): Adjust call to make_id_declarator.
	(cp_parser_check_declarator_template_parameters): Do not expect a
	SCOPE_REF. 
	
	* decl.c (duplicate_decls): Call ggc_free on declarations we will
	not be needing any longer.
  
Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.1085
diff -c -5 -p -r1.1085 cp-tree.h
*** cp-tree.h	21 Dec 2004 17:54:21 -0000	1.1085
--- cp-tree.h	30 Dec 2004 23:28:01 -0000
*************** struct cp_declarator {
*** 3589,3601 ****
       cdk_id and cdk_error, guaranteed to be NULL.  */
    cp_declarator *declarator;
    union {
      /* For identifiers.  */
      struct {
!       /* The name of the function -- an IDENTIFIER_NODE, BIT_NOT_EXPR,
! 	 TEMPLATE_ID_EXPR, or SCOPE_REF.  */
!       tree name;
        /* If this is the name of a function, what kind of special
  	 function (if any).  */
        special_function_kind sfk;
      } id;
      /* For functions.  */
--- 3589,3604 ----
       cdk_id and cdk_error, guaranteed to be NULL.  */
    cp_declarator *declarator;
    union {
      /* For identifiers.  */
      struct {
!       /* If non-NULL, the qualifiying scope (a NAMESPACE_DECL or
!          *_TYPE) for this identifier.  */
!       tree qualifying_scope;
!       /* The unqualified name of the entity -- an IDENTIFIER_NODE,
! 	 BIT_NOT_EXPR, or TEMPLATE_ID_EXPR.  */
!       tree unqualified_name;
        /* If this is the name of a function, what kind of special
  	 function (if any).  */
        special_function_kind sfk;
      } id;
      /* For functions.  */
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1348
diff -c -5 -p -r1.1348 decl.c
*** decl.c	28 Dec 2004 04:36:46 -0000	1.1348
--- decl.c	30 Dec 2004 23:28:01 -0000
*************** duplicate_decls (tree newdecl, tree oldd
*** 1936,1945 ****
--- 1936,1954 ----
      {
        DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
        DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
      }
  
+   /* The DECL_LANG_SPECIFIC information in OLDDECL will be replaced
+      with that from NEWDECL below.  */
+   if (DECL_LANG_SPECIFIC (olddecl))
+     {
+       gcc_assert (DECL_LANG_SPECIFIC (olddecl) 
+ 		  != DECL_LANG_SPECIFIC (newdecl));
+       ggc_free (DECL_LANG_SPECIFIC (olddecl));
+     }
+ 
    if (TREE_CODE (newdecl) == FUNCTION_DECL)
      {
        int function_size;
  
        function_size = sizeof (struct tree_decl);
*************** duplicate_decls (tree newdecl, tree oldd
*** 1997,2006 ****
--- 2006,2020 ----
        && (TREE_CODE (olddecl) == FUNCTION_DECL
  	  || (TREE_CODE (olddecl) == VAR_DECL
  	      && TREE_STATIC (olddecl))))
      make_decl_rtl (olddecl);
  
+   /* The NEWDECL will no longer be needed.  Because every out-of-class
+      declaration of a member results in a call to duplicate_decls,
+      freeing these nodes represents in a significant savings.  */
+   ggc_free (newdecl);
+ 
    return olddecl;
  }
  
  /* Return zero if the declaration NEWDECL is valid
     when the declaration OLDDECL (assumed to be for the same name)
*************** get_scope_of_declarator (const cp_declar
*** 6325,6337 ****
      declarator = declarator->declarator;
  
    /* If the declarator-id is a SCOPE_REF, the scope in which the
       declaration occurs is the first operand.  */
    if (declarator
!       && declarator->u.id.name
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF)
!     return TREE_OPERAND (declarator->u.id.name, 0);
  
    /* Otherwise, the declarator is not a qualified name; the entity will
       be declared in the current scope.  */
    return NULL_TREE;
  }
--- 6339,6350 ----
      declarator = declarator->declarator;
  
    /* If the declarator-id is a SCOPE_REF, the scope in which the
       declaration occurs is the first operand.  */
    if (declarator
!       && declarator->u.id.qualifying_scope)
!     return declarator->u.id.qualifying_scope;
  
    /* Otherwise, the declarator is not a qualified name; the entity will
       be declared in the current scope.  */
    return NULL_TREE;
  }
*************** grokdeclarator (const cp_declarator *dec
*** 6626,6669 ****
  	    }
  	  break;
  
  	case cdk_id:
  	  {
! 	    tree decl = id_declarator->u.id.name;
  	    if (!decl)
  	      break;
! 	    if (TREE_CODE (decl) == SCOPE_REF)
  	      {
! 		tree qualifying_scope = TREE_OPERAND (decl, 0);
! 
! 		/* It is valid to write:
! 
! 		   class C { void f(); };
! 		   typedef C D;
! 		   void D::f();
! 
! 		 The standard is not clear about whether `typedef const C D' is
! 		 legal; as of 2002-09-15 the committee is considering
! 		 that question.  EDG 3.0 allows that syntax.
! 		 Therefore, we do as well.  */
! 		if (qualifying_scope && TYPE_P (qualifying_scope))
  		  {
! 		    ctype = TYPE_MAIN_VARIANT (qualifying_scope);
  		    if (innermost_code != cdk_function
  			&& current_class_type
  			&& !UNIQUELY_DERIVED_FROM_P (ctype,
  						     current_class_type))
  		      {
  			error ("type %qT is not derived from type %qT",
  			       ctype, current_class_type);
! 			ctype = NULL_TREE;
  		      }
- 		    TREE_OPERAND (decl, 0) = ctype;
  		  }
  		else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
  		  in_namespace = qualifying_scope;
- 		decl = TREE_OPERAND (decl, 1);
  	      }
  	    if (TREE_CODE (decl) == BASELINK)
  	      decl = BASELINK_FUNCTIONS (decl);
  	    if (decl == error_mark_node)
  	      return error_mark_node;
--- 6639,6669 ----
  	    }
  	  break;
  
  	case cdk_id:
  	  {
! 	    tree qualifying_scope = id_declarator->u.id.qualifying_scope;
! 	    tree decl = id_declarator->u.id.unqualified_name;
  	    if (!decl)
  	      break;
! 	    if (qualifying_scope)
  	      {
! 		if (TYPE_P (qualifying_scope))
  		  {
! 		    ctype = qualifying_scope;
  		    if (innermost_code != cdk_function
  			&& current_class_type
  			&& !UNIQUELY_DERIVED_FROM_P (ctype,
  						     current_class_type))
  		      {
  			error ("type %qT is not derived from type %qT",
  			       ctype, current_class_type);
! 			return error_mark_node;
  		      }
  		  }
  		else if (TREE_CODE (qualifying_scope) == NAMESPACE_DECL)
  		  in_namespace = qualifying_scope;
  	      }
  	    if (TREE_CODE (decl) == BASELINK)
  	      decl = BASELINK_FUNCTIONS (decl);
  	    if (decl == error_mark_node)
  	      return error_mark_node;
*************** grokdeclarator (const cp_declarator *dec
*** 7123,7135 ****
  
  	      if (declarator)
  		{
  		  /* Avoid trying to get an operand off an identifier node.  */
  		  if (declarator->kind != cdk_id)
! 		    tmp = declarator->declarator->u.id.name;
  		  else
! 		    tmp = declarator->u.id.name;
  		  op = IDENTIFIER_OPNAME_P (tmp);
  		  if (IDENTIFIER_TYPENAME_P (tmp))
  		    {
  		      if (is_typename_at_global_scope (tmp))
  			name = IDENTIFIER_POINTER (tmp);
--- 7123,7135 ----
  
  	      if (declarator)
  		{
  		  /* Avoid trying to get an operand off an identifier node.  */
  		  if (declarator->kind != cdk_id)
! 		    tmp = declarator->declarator->u.id.unqualified_name;
  		  else
! 		    tmp = declarator->u.id.unqualified_name;
  		  op = IDENTIFIER_OPNAME_P (tmp);
  		  if (IDENTIFIER_TYPENAME_P (tmp))
  		    {
  		      if (is_typename_at_global_scope (tmp))
  			name = IDENTIFIER_POINTER (tmp);
*************** grokdeclarator (const cp_declarator *dec
*** 7190,7202 ****
  
    if (!id_declarator)
      unqualified_id = NULL_TREE;
    else
      {
!       unqualified_id = id_declarator->u.id.name;
!       if (TREE_CODE (unqualified_id) == SCOPE_REF)
! 	unqualified_id = TREE_OPERAND (unqualified_id, 1);
        if (TREE_CODE (unqualified_id) == BASELINK)
  	unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
        switch (TREE_CODE (unqualified_id))
  	{
  	case BIT_NOT_EXPR:
--- 7190,7200 ----
  
    if (!id_declarator)
      unqualified_id = NULL_TREE;
    else
      {
!       unqualified_id = id_declarator->u.id.unqualified_name;
        if (TREE_CODE (unqualified_id) == BASELINK)
  	unqualified_id = BASELINK_FUNCTIONS (unqualified_id);
        switch (TREE_CODE (unqualified_id))
  	{
  	case BIT_NOT_EXPR:
*************** grokdeclarator (const cp_declarator *dec
*** 7487,7507 ****
      }
  
    /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
       otherwise, we would not have exited the loop above.  */
    if (declarator
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF
!       /* If the qualifying scope was invalid, it will have been set to
! 	 NULL_TREE above.  */
!       && TREE_OPERAND (declarator->u.id.name, 0)
!       && TYPE_P (TREE_OPERAND (declarator->u.id.name, 0)))
      {
        tree t;
  
!       ctype = TREE_OPERAND (declarator->u.id.name, 0);
!       if (TYPE_P (ctype))
! 	ctype = TYPE_MAIN_VARIANT (ctype);
        t = ctype;
        while (t != NULL_TREE && CLASS_TYPE_P (t))
  	{
  	  /* You're supposed to have one `template <...>' for every
  	     template class, but you don't need one for a full
--- 7485,7501 ----
      }
  
    /* If DECLARATOR is non-NULL, we know it is a cdk_id declarator;
       otherwise, we would not have exited the loop above.  */
    if (declarator
!       && declarator->u.id.qualifying_scope
!       && TYPE_P (declarator->u.id.qualifying_scope))
      {
        tree t;
  
!       ctype = declarator->u.id.qualifying_scope;
!       ctype = TYPE_MAIN_VARIANT (ctype);
        t = ctype;
        while (t != NULL_TREE && CLASS_TYPE_P (t))
  	{
  	  /* You're supposed to have one `template <...>' for every
  	     template class, but you don't need one for a full
*************** grokdeclarator (const cp_declarator *dec
*** 7535,7545 ****
  	    pedwarn ("extra qualification %<%T::%> on member %qs ignored",
  			ctype, name);
  	}
        else if (TREE_CODE (type) == FUNCTION_TYPE)
  	{
! 	  tree sname = TREE_OPERAND (declarator->u.id.name, 1);
  
  	  if (TREE_CODE (sname) == IDENTIFIER_NODE
  	      && NEW_DELETE_OPNAME_P (sname))
  	    /* Overloaded operator new and operator delete
  	       are always static functions.  */
--- 7529,7539 ----
  	    pedwarn ("extra qualification %<%T::%> on member %qs ignored",
  			ctype, name);
  	}
        else if (TREE_CODE (type) == FUNCTION_TYPE)
  	{
! 	  tree sname = declarator->u.id.unqualified_name;
  
  	  if (TREE_CODE (sname) == IDENTIFIER_NODE
  	      && NEW_DELETE_OPNAME_P (sname))
  	    /* Overloaded operator new and operator delete
  	       are always static functions.  */
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.761
diff -c -5 -p -r1.761 decl2.c
*** decl2.c	16 Dec 2004 11:03:28 -0000	1.761
--- decl2.c	30 Dec 2004 23:28:01 -0000
*************** grokfield (const cp_declarator *declarat
*** 828,842 ****
    const char *asmspec = 0;
    int flags = LOOKUP_ONLYCONVERTING;
  
    if (!declspecs->any_specifiers_p
        && declarator->kind == cdk_id
!       && TREE_CODE (declarator->u.id.name) == SCOPE_REF
!       && (TREE_CODE (TREE_OPERAND (declarator->u.id.name, 1)) 
! 	  == IDENTIFIER_NODE))
      /* Access declaration */
!     return do_class_using_decl (declarator->u.id.name);
  
    if (init
        && TREE_CODE (init) == TREE_LIST
        && TREE_VALUE (init) == error_mark_node
        && TREE_CHAIN (init) == NULL_TREE)
--- 828,842 ----
    const char *asmspec = 0;
    int flags = LOOKUP_ONLYCONVERTING;
  
    if (!declspecs->any_specifiers_p
        && declarator->kind == cdk_id
!       && declarator->u.id.qualifying_scope 
!       && TREE_CODE (declarator->u.id.unqualified_name) == IDENTIFIER_NODE)
      /* Access declaration */
!     return do_class_using_decl (declarator->u.id.qualifying_scope,
! 				declarator->u.id.unqualified_name);
  
    if (init
        && TREE_CODE (init) == TREE_LIST
        && TREE_VALUE (init) == error_mark_node
        && TREE_CHAIN (init) == NULL_TREE)
Index: name-lookup.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.c,v
retrieving revision 1.103
diff -c -5 -p -r1.103 name-lookup.c
*** name-lookup.c	22 Dec 2004 02:38:15 -0000	1.103
--- name-lookup.c	30 Dec 2004 23:28:01 -0000
*************** push_class_level_binding (tree name, tre
*** 2684,2721 ****
      }
  
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
  }
  
  tree
! do_class_using_decl (tree decl)
  {
!   tree name, value, scope, type;
    
!   if (TREE_CODE (decl) != SCOPE_REF
!       || !TREE_OPERAND (decl, 0)
!       || !TYPE_P (TREE_OPERAND (decl, 0)))
      {
        error ("using-declaration for non-member at class scope");
        return NULL_TREE;
      }
-   scope = TREE_OPERAND (decl, 0);
-   name = TREE_OPERAND (decl, 1);
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
        error ("using-declaration cannot name destructor");
        return NULL_TREE;
      }
-   if (TREE_CODE (name) == TYPE_DECL)
-     name = DECL_NAME (name);
-   else if (TREE_CODE (name) == TEMPLATE_DECL)
-      name = DECL_NAME (name);
-   else if (BASELINK_P (name))
-     {
-       tree fns = BASELINK_FUNCTIONS (name);
-       name = DECL_NAME (get_first_fn (fns));
-     }
  
    gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
  
    /* Dependent using decls have a NULL type, non-dependent ones have a
       void type.  */
--- 2684,2711 ----
      }
  
    POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
  }
  
+ /* Process "using SCOPE::NAME" in a class scope.  Return the
+    USING_DECL created.  */
+ 
  tree
! do_class_using_decl (tree scope, tree name)
  {
!   tree value, type;
    
!   if (!scope || !TYPE_P (scope))
      {
        error ("using-declaration for non-member at class scope");
        return NULL_TREE;
      }
    if (TREE_CODE (name) == BIT_NOT_EXPR)
      {
        error ("using-declaration cannot name destructor");
        return NULL_TREE;
      }
  
    gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE);
  
    /* Dependent using decls have a NULL type, non-dependent ones have a
       void type.  */
Index: name-lookup.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/name-lookup.h,v
retrieving revision 1.33
diff -c -5 -p -r1.33 name-lookup.h
*** name-lookup.h	26 Nov 2004 17:15:39 -0000	1.33
--- name-lookup.h	30 Dec 2004 23:28:01 -0000
*************** extern tree current_decl_namespace (void
*** 333,343 ****
  extern void push_decl_namespace (tree);
  extern void pop_decl_namespace (void);
  extern void do_namespace_alias (tree, tree);
  extern void do_toplevel_using_decl (tree, tree, tree);
  extern void do_local_using_decl (tree, tree, tree);
! extern tree do_class_using_decl (tree);
  extern void do_using_directive (tree);
  extern tree lookup_arg_dependent (tree, tree, tree);
  extern bool is_associated_namespace (tree, tree);
  extern void parse_using_directive (tree, tree);
  extern tree innermost_non_namespace_value (tree);
--- 333,343 ----
  extern void push_decl_namespace (tree);
  extern void pop_decl_namespace (void);
  extern void do_namespace_alias (tree, tree);
  extern void do_toplevel_using_decl (tree, tree, tree);
  extern void do_local_using_decl (tree, tree, tree);
! extern tree do_class_using_decl (tree, tree);
  extern void do_using_directive (tree);
  extern tree lookup_arg_dependent (tree, tree, tree);
  extern bool is_associated_namespace (tree, tree);
  extern void parse_using_directive (tree, tree);
  extern tree innermost_non_namespace_value (tree);
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.298
diff -c -5 -p -r1.298 parser.c
*** parser.c	23 Dec 2004 22:07:01 -0000	1.298
--- parser.c	30 Dec 2004 23:28:01 -0000
*************** clear_decl_specs (cp_decl_specifier_seq 
*** 745,756 ****
  /* Nothing other than the parser should be creating declarators;
     declarators are a semi-syntactic representation of C++ entities.
     Other parts of the front end that need to create entities (like
     VAR_DECLs or FUNCTION_DECLs) should do that directly.  */
  
- static cp_declarator *make_id_declarator
-   (tree);
  static cp_declarator *make_call_declarator
    (cp_declarator *, cp_parameter_declarator *, cp_cv_quals, tree);
  static cp_declarator *make_array_declarator
    (cp_declarator *, tree);
  static cp_declarator *make_pointer_declarator
--- 745,754 ----
*************** make_declarator (cp_declarator_kind kind
*** 790,808 ****
    declarator->declarator = NULL;
  
    return declarator;
  }
  
! /* Make a declarator for a generalized identifier.  */
  
! cp_declarator *
! make_id_declarator (tree id)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_id);
!   declarator->u.id.name = id;
    declarator->u.id.sfk = sfk_none;
  
    return declarator;
  }
  
--- 788,822 ----
    declarator->declarator = NULL;
  
    return declarator;
  }
  
! /* Make a declarator for a generalized identifier.  If non-NULL, the
!    identifier is QUALIFYING_SCOPE::UNQUALIFIED_NAME; otherwise, it is
!    just UNQUALIFIED_NAME.  */
  
! static cp_declarator *
! make_id_declarator (tree qualifying_scope, tree unqualified_name)
  {
    cp_declarator *declarator;
  
+   /* It is valid to write:
+ 
+        class C { void f(); };
+        typedef C D;
+        void D::f();
+ 
+      The standard is not clear about whether `typedef const C D' is
+      legal; as of 2002-09-15 the committee is considering that
+      question.  EDG 3.0 allows that syntax.  Therefore, we do as
+      well.  */
+   if (qualifying_scope && TYPE_P (qualifying_scope))
+     qualifying_scope = TYPE_MAIN_VARIANT (qualifying_scope);
+ 
    declarator = make_declarator (cdk_id);
!   declarator->u.id.qualifying_scope = qualifying_scope;
!   declarator->u.id.unqualified_name = unqualified_name;
    declarator->u.id.sfk = sfk_none;
  
    return declarator;
  }
  
*************** cp_parser_using_declaration (cp_parser* 
*** 10158,10170 ****
    else
      {
        if (at_class_scope_p ())
  	{
  	  /* Create the USING_DECL.  */
! 	  decl = do_class_using_decl (build_nt (SCOPE_REF,
! 						parser->scope,
! 						identifier));
  	  /* Add it to the list of members in this class.  */
  	  finish_member_declaration (decl);
  	}
        else
  	{
--- 10172,10182 ----
    else
      {
        if (at_class_scope_p ())
  	{
  	  /* Create the USING_DECL.  */
! 	  decl = do_class_using_decl (parser->scope, identifier);
  	  /* Add it to the list of members in this class.  */
  	  finish_member_declaration (decl);
  	}
        else
  	{
*************** cp_parser_direct_declarator (cp_parser* 
*** 11016,11052 ****
  
  	  declarator = make_array_declarator (declarator, bounds);
  	}
        else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
  	{
! 	  tree id;
  
  	  /* Parse a declarator-id */
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    cp_parser_parse_tentatively (parser);
! 	  id = cp_parser_declarator_id (parser);
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    {
  	      if (!cp_parser_parse_definitely (parser))
! 		id = error_mark_node;
! 	      else if (TREE_CODE (id) != IDENTIFIER_NODE)
  		{
  		  cp_parser_error (parser, "expected unqualified-id");
! 		  id = error_mark_node;
  		}
  	    }
  
! 	  if (id == error_mark_node)
  	    {
  	      declarator = cp_error_declarator;
  	      break;
  	    }
  
! 	  if (TREE_CODE (id) == SCOPE_REF && at_namespace_scope_p ())
  	    {
- 	      tree scope = TREE_OPERAND (id, 0);
- 
  	      /* In the declaration of a member of a template class
  	     	 outside of the class itself, the SCOPE will sometimes
  	     	 be a TYPENAME_TYPE.  For example, given:
  
                 	 template <typename T>
--- 11028,11067 ----
  
  	  declarator = make_array_declarator (declarator, bounds);
  	}
        else if (first && dcl_kind != CP_PARSER_DECLARATOR_ABSTRACT)
  	{
! 	  tree qualifying_scope;
! 	  tree unqualified_name;
  
  	  /* Parse a declarator-id */
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    cp_parser_parse_tentatively (parser);
! 	  unqualified_name = cp_parser_declarator_id (parser);
! 	  qualifying_scope = parser->scope;
  	  if (dcl_kind == CP_PARSER_DECLARATOR_EITHER)
  	    {
  	      if (!cp_parser_parse_definitely (parser))
! 		unqualified_name = error_mark_node;
! 	      else if (qualifying_scope
! 		       || (TREE_CODE (unqualified_name) 
! 			   != IDENTIFIER_NODE))
  		{
  		  cp_parser_error (parser, "expected unqualified-id");
! 		  unqualified_name = error_mark_node;
  		}
  	    }
  
! 	  if (unqualified_name == error_mark_node)
  	    {
  	      declarator = cp_error_declarator;
  	      break;
  	    }
  
! 	  if (qualifying_scope && at_namespace_scope_p ()
! 	      && TREE_CODE (qualifying_scope) == TYPENAME_TYPE)
  	    {
  	      /* In the declaration of a member of a template class
  	     	 outside of the class itself, the SCOPE will sometimes
  	     	 be a TYPENAME_TYPE.  For example, given:
  
                 	 template <typename T>
*************** cp_parser_direct_declarator (cp_parser* 
*** 11059,11102 ****
  	     	 The reason we normally avoid resolving TYPENAME_TYPEs
  	     	 is that a specialization of `S' might render
  	     	 `S<T>::R' not a type.  However, if `S' is
  	     	 specialized, then this `i' will not be used, so there
  	     	 is no harm in resolving the types here.  */
! 	      if (TREE_CODE (scope) == TYPENAME_TYPE)
! 		{
! 		  tree type;
! 
! 		  /* Resolve the TYPENAME_TYPE.  */
! 		  type = resolve_typename_type (scope,
! 						 /*only_current_p=*/false);
! 		  /* If that failed, the declarator is invalid.  */
! 		  if (type == error_mark_node)
! 		    error ("%<%T::%D%> is not a type",
! 			   TYPE_CONTEXT (scope),
! 			   TYPE_IDENTIFIER (scope));
! 		  /* Build a new DECLARATOR.  */
! 		  id = build_nt (SCOPE_REF, type, TREE_OPERAND (id, 1));
! 		}
  	    }
  
! 	  declarator = make_id_declarator (id);
! 	  if (id)
  	    {
  	      tree class_type;
- 	      tree unqualified_name;
  
! 	      if (TREE_CODE (id) == SCOPE_REF
! 		  && CLASS_TYPE_P (TREE_OPERAND (id, 0)))
! 		{
! 		  class_type = TREE_OPERAND (id, 0);
! 		  unqualified_name = TREE_OPERAND (id, 1);
! 		}
  	      else
! 		{
! 		  class_type = current_class_type;
! 		  unqualified_name = id;
! 		}
  
  	      if (class_type)
  		{
  		  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
  		    declarator->u.id.sfk = sfk_destructor;
--- 11074,11107 ----
  	     	 The reason we normally avoid resolving TYPENAME_TYPEs
  	     	 is that a specialization of `S' might render
  	     	 `S<T>::R' not a type.  However, if `S' is
  	     	 specialized, then this `i' will not be used, so there
  	     	 is no harm in resolving the types here.  */
! 	      tree type;
! 	      
! 	      /* Resolve the TYPENAME_TYPE.  */
! 	      type = resolve_typename_type (qualifying_scope,
! 					    /*only_current_p=*/false);
! 	      /* If that failed, the declarator is invalid.  */
! 	      if (type == error_mark_node)
! 		error ("%<%T::%D%> is not a type",
! 		       TYPE_CONTEXT (qualifying_scope),
! 		       TYPE_IDENTIFIER (qualifying_scope));
! 	      qualifying_scope = type;
  	    }
  
! 	  declarator = make_id_declarator (qualifying_scope, 
! 					   unqualified_name);
! 	  if (unqualified_name)
  	    {
  	      tree class_type;
  
! 	      if (qualifying_scope
! 		  && CLASS_TYPE_P (qualifying_scope))
! 		class_type = qualifying_scope;
  	      else
! 		class_type = current_class_type;
  
  	      if (class_type)
  		{
  		  if (TREE_CODE (unqualified_name) == BIT_NOT_EXPR)
  		    declarator->u.id.sfk = sfk_destructor;
*************** cp_parser_direct_declarator (cp_parser* 
*** 11109,11119 ****
  					       class_type)))
  		    declarator->u.id.sfk = sfk_constructor;
  
  		  if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
  		    *ctor_dtor_or_conv_p = -1;
! 		  if (TREE_CODE (id) == SCOPE_REF
  		      && TREE_CODE (unqualified_name) == TYPE_DECL
  		      && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
  		    {
  		      error ("invalid use of constructor as a template");
  		      inform ("use %<%T::%D%> instead of %<%T::%T%> to name "
--- 11114,11124 ----
  					       class_type)))
  		    declarator->u.id.sfk = sfk_constructor;
  
  		  if (ctor_dtor_or_conv_p && declarator->u.id.sfk != sfk_none)
  		    *ctor_dtor_or_conv_p = -1;
! 		  if (qualifying_scope
  		      && TREE_CODE (unqualified_name) == TYPE_DECL
  		      && CLASSTYPE_USE_TEMPLATE (TREE_TYPE (unqualified_name)))
  		    {
  		      error ("invalid use of constructor as a template");
  		      inform ("use %<%T::%D%> instead of %<%T::%T%> to name "
*************** cp_parser_cv_qualifier_seq_opt (cp_parse
*** 11331,11342 ****
     unqualified-id.  */
  
  static tree
  cp_parser_declarator_id (cp_parser* parser)
  {
-   tree id_expression;
- 
    /* The expression must be an id-expression.  Assume that qualified
       names are the names of types so that:
  
         template <class T>
         int S<T>::R::i = 3;
--- 11336,11345 ----
*************** cp_parser_declarator_id (cp_parser* pars
*** 11347,11370 ****
  
         template <class T>
         int S<T>::R<T>::i = 3;
  
       will work, too.  */
!   id_expression = cp_parser_id_expression (parser,
! 					   /*template_keyword_p=*/false,
! 					   /*check_dependency_p=*/false,
! 					   /*template_p=*/NULL,
! 					   /*declarator_p=*/true);
!   /* If the name was qualified, create a SCOPE_REF to represent
!      that.  */
!   if (parser->scope)
!     {
!       id_expression = build_nt (SCOPE_REF, parser->scope, id_expression);
!       parser->scope = NULL_TREE;
!     }
! 
!   return id_expression;
  }
  
  /* Parse a type-id.
  
     type-id:
--- 11350,11364 ----
  
         template <class T>
         int S<T>::R<T>::i = 3;
  
       will work, too.  */
!   return cp_parser_id_expression (parser,
! 				  /*template_keyword_p=*/false,
! 				  /*check_dependency_p=*/false,
! 				  /*template_p=*/NULL,
! 				  /*declarator_p=*/true);
  }
  
  /* Parse a type-id.
  
     type-id:
*************** cp_parser_member_declaration (cp_parser*
*** 13062,13072 ****
  	      /* Combine the attributes.  */
  	      attributes = chainon (prefix_attributes, attributes);
  
  	      /* Create the bitfield declaration.  */
  	      decl = grokbitfield (identifier
! 				   ? make_id_declarator (identifier)
  				   : NULL,
  				   &decl_specifiers,
  				   width);
  	      /* Apply the attributes.  */
  	      cplus_decl_attributes (&decl, attributes, /*flags=*/0);
--- 13056,13067 ----
  	      /* Combine the attributes.  */
  	      attributes = chainon (prefix_attributes, attributes);
  
  	      /* Create the bitfield declaration.  */
  	      decl = grokbitfield (identifier
! 				   ? make_id_declarator (NULL_TREE,
! 							 identifier)
  				   : NULL,
  				   &decl_specifiers,
  				   width);
  	      /* Apply the attributes.  */
  	      cplus_decl_attributes (&decl, attributes, /*flags=*/0);
*************** cp_parser_check_declarator_template_para
*** 14381,14397 ****
    num_templates = 0;
  
    switch (declarator->kind)
      {
      case cdk_id:
!       if (TREE_CODE (declarator->u.id.name) == SCOPE_REF)
  	{
  	  tree scope;
  	  tree member;
  
! 	  scope = TREE_OPERAND (declarator->u.id.name, 0);
! 	  member = TREE_OPERAND (declarator->u.id.name, 1);
  
  	  while (scope && CLASS_TYPE_P (scope))
  	    {
  	      /* You're supposed to have one `template <...>'
  		 for every template class, but you don't need one
--- 14376,14392 ----
    num_templates = 0;
  
    switch (declarator->kind)
      {
      case cdk_id:
!       if (declarator->u.id.qualifying_scope)
  	{
  	  tree scope;
  	  tree member;
  
! 	  scope = declarator->u.id.qualifying_scope;
! 	  member = declarator->u.id.unqualified_name;
  
  	  while (scope && CLASS_TYPE_P (scope))
  	    {
  	      /* You're supposed to have one `template <...>'
  		 for every template class, but you don't need one
*************** cp_parser_check_declarator_template_para
*** 14410,14423 ****
  		++num_templates;
  
  	      scope = TYPE_CONTEXT (scope);
  	    }
  	}
! 
!       /* If the DECLARATOR has the form `X<y>' then it uses one
! 	 additional level of template parameters.  */
!       if (TREE_CODE (declarator->u.id.name) == TEMPLATE_ID_EXPR)
  	++num_templates;
  
        return cp_parser_check_template_parameters (parser,
  						  num_templates);
  
--- 14405,14418 ----
  		++num_templates;
  
  	      scope = TYPE_CONTEXT (scope);
  	    }
  	}
!       else if (TREE_CODE (declarator->u.id.unqualified_name) 
! 	       == TEMPLATE_ID_EXPR)
! 	/* If the DECLARATOR has the form `X<y>' then it uses one
! 	   additional level of template parameters.  */
  	++num_templates;
  
        return cp_parser_check_template_parameters (parser,
  						  num_templates);
  


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