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: Do not build TREE_LISTs of cv-qualifiers


Here's another little memory-saving patch.  We were building a
TREE_LIST node for every cv-qualifier appearing in the input program,
which is totally pointless.  We could have at least reused the same
TREE_LISTs (there are only a few combinations of "const", "volatile",
and "restrict") but even better is just to use a bitmask.  Not a
terribly big win, but I could do it while I was tired, and the code
becomes a bit simpler to boot. :-)

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

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

2004-06-26  Mark Mitchell  <mark@codesourcery.com>

	* cp-tree.h (cp_cv_quals): New type.
	(cp_declarator): Use it instead of "tree" as appropriate.
	(grok_method_quals): Adjust prototype.
	(grokclassfn): Likewise.
	(do_friend): Likewise.
	* decl.c (grokfndecl): Use cp_cv_quals, not tree.
	(grokdeclarator): Likewise.
	* decl2.c (grok_method_quals): Likewise.
	(grokclassfn): Likewise.
	* friend.c (do_friend): Likewise.
	* method.c (implicitly_declare_fn): Adjust call to grokclassfn.
	* parser.c (make_call_declarator): Use cp_cv_quals, not tree.
	(make_pointer_declarator): Likewise.
	(make_reference_declarator): Likewise.
	(make_ptrmem_declarator): Likewise.
	(cp_parser_ptr_operator): Likewise.
	(cp_parser_cv_qualifier_seq_opt): Likewise.
	(cp_parser_cv_qualifier_opt): Remove.
	(cp_parser_new_declarator_opt): Adjust call to
	cp_parser_ptr_operator.
	(cp_parser_conversion_declaration_opt): Likewise.
	(cp_parser_declarator): Use cp_cv_quals, not tree.
	(cp_parser_direct_declarator): Likewise.

Index: cp-tree.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/cp-tree.h,v
retrieving revision 1.989
diff -c -5 -p -r1.989 cp-tree.h
*** cp-tree.h	26 Jun 2004 21:11:17 -0000	1.989
--- cp-tree.h	27 Jun 2004 02:10:42 -0000
*************** extern GTY(()) operator_name_info_t oper
*** 3501,3510 ****
--- 3501,3515 ----
    [(int) LAST_CPLUS_TREE_CODE];
  /* Similar, but for assignment operators.  */
  extern GTY(()) operator_name_info_t assignment_operator_name_info
    [(int) LAST_CPLUS_TREE_CODE];
  
+ /* A type-qualifier, or bitmask therefore, using the TYPE_QUAL
+    constants.  */
+ 
+ typedef int cp_cv_quals;
+ 
  /* A storage class.  */
  
  typedef enum cp_storage_class {
    /* sc_none must be zero so that zeroing a cp_decl_specifier_seq
       sets the storage_class field to sc_none.  */
*************** struct cp_declarator {
*** 3626,3636 ****
      /* For functions.  */
      struct {
        /* The parameters to the function.  */
        cp_parameter_declarator *parameters;
        /* The cv-qualifiers for the function.  */
!       tree qualifiers;
        /* The exception-specification for the function.  */
        tree exception_specification;
      } function;
      /* For arrays.  */
      struct {
--- 3631,3641 ----
      /* For functions.  */
      struct {
        /* The parameters to the function.  */
        cp_parameter_declarator *parameters;
        /* The cv-qualifiers for the function.  */
!       cp_cv_quals qualifiers;
        /* The exception-specification for the function.  */
        tree exception_specification;
      } function;
      /* For arrays.  */
      struct {
*************** struct cp_declarator {
*** 3638,3648 ****
        tree bounds;
      } array;
      /* For cdk_pointer, cdk_reference, and cdk_ptrmem.  */
      struct {
        /* The cv-qualifiers for the pointer.  */
!       tree qualifiers;
        /* For cdk_ptrmem, the class type containing the member.  */
        tree class_type;
      } pointer;
    } u;
  };
--- 3643,3653 ----
        tree bounds;
      } array;
      /* For cdk_pointer, cdk_reference, and cdk_ptrmem.  */
      struct {
        /* The cv-qualifiers for the pointer.  */
!       cp_cv_quals qualifiers;
        /* For cdk_ptrmem, the class type containing the member.  */
        tree class_type;
      } pointer;
    } u;
  };
*************** extern bool cp_missing_noreturn_ok_p		(t
*** 3864,3877 ****
  
  extern bool have_extern_spec;
  
  /* in decl2.c */
  extern bool check_java_method (tree);
! extern int grok_method_quals (tree, tree, tree);
  extern void maybe_retrofit_in_chrg (tree);
  extern void maybe_make_one_only	(tree);
! extern void grokclassfn	(tree, tree, enum overload_flags, tree);
  extern tree grok_array_decl (tree, tree);
  extern tree delete_sanity (tree, tree, bool, int);
  extern tree check_classfn (tree, tree, tree);
  extern void check_member_template (tree);
  extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree);
--- 3869,3882 ----
  
  extern bool have_extern_spec;
  
  /* in decl2.c */
  extern bool check_java_method (tree);
! extern cp_cv_quals grok_method_quals (tree, tree, cp_cv_quals);
  extern void maybe_retrofit_in_chrg (tree);
  extern void maybe_make_one_only	(tree);
! extern void grokclassfn	(tree, tree, enum overload_flags, cp_cv_quals);
  extern tree grok_array_decl (tree, tree);
  extern tree delete_sanity (tree, tree, bool, int);
  extern tree check_classfn (tree, tree, tree);
  extern void check_member_template (tree);
  extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree);
*************** extern tree cplus_expand_constant       
*** 3939,3949 ****
  
  /* friend.c */
  extern int is_friend				(tree, tree);
  extern void make_friend_class			(tree, tree, bool);
  extern void add_friend                          (tree, tree, bool);
! extern tree do_friend				(tree, tree, tree, tree, enum overload_flags, tree, int);
  
  /* in init.c */
  extern tree expand_member_init			(tree);
  extern void emit_mem_initializers		(tree);
  extern tree build_aggr_init			(tree, tree, int);
--- 3944,3954 ----
  
  /* friend.c */
  extern int is_friend				(tree, tree);
  extern void make_friend_class			(tree, tree, bool);
  extern void add_friend                          (tree, tree, bool);
! extern tree do_friend				(tree, tree, tree, tree, enum overload_flags, cp_cv_quals, int);
  
  /* in init.c */
  extern tree expand_member_init			(tree);
  extern void emit_mem_initializers		(tree);
  extern tree build_aggr_init			(tree, tree, int);
Index: decl.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl.c,v
retrieving revision 1.1228
diff -c -5 -p -r1.1228 decl.c
*** decl.c	26 Jun 2004 21:11:17 -0000	1.1228
--- decl.c	27 Jun 2004 02:10:42 -0000
*************** static void require_complete_types_for_p
*** 60,70 ****
  static int ambi_op_p (enum tree_code);
  static int unary_op_p (enum tree_code);
  static void push_local_name (tree);
  static tree grok_reference_init (tree, tree, tree, tree *);
  static tree grokfndecl (tree, tree, tree, tree, tree, int,
! 			enum overload_flags, tree,
  			tree, int, int, int, int, int, int, tree);
  static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree);
  static void record_unknown_type (tree, const char *);
  static tree builtin_function_1 (const char *, tree, tree, int,
                                  enum built_in_class, const char *,
--- 60,70 ----
  static int ambi_op_p (enum tree_code);
  static int unary_op_p (enum tree_code);
  static void push_local_name (tree);
  static tree grok_reference_init (tree, tree, tree, tree *);
  static tree grokfndecl (tree, tree, tree, tree, tree, int,
! 			enum overload_flags, cp_cv_quals,
  			tree, int, int, int, int, int, int, tree);
  static tree grokvardecl (tree, tree, cp_decl_specifier_seq *, int, int, tree);
  static void record_unknown_type (tree, const char *);
  static tree builtin_function_1 (const char *, tree, tree, int,
                                  enum built_in_class, const char *,
*************** grokfndecl (tree ctype, 
*** 5422,5432 ****
              tree declarator,
  	    tree parms,
              tree orig_declarator,
              int virtualp,
              enum overload_flags flags,
!             tree quals, 
              tree raises,
              int check, 
              int friendp, 
              int publicp, 
              int inlinep, 
--- 5422,5432 ----
              tree declarator,
  	    tree parms,
              tree orig_declarator,
              int virtualp,
              enum overload_flags flags,
! 	    cp_cv_quals quals,
              tree raises,
              int check, 
              int friendp, 
              int publicp, 
              int inlinep, 
*************** grokfndecl (tree ctype, 
*** 5542,5556 ****
    if (DECL_DECLARED_INLINE_P (decl)
        || (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
      DECL_INLINE (decl) = 1;
  
    DECL_EXTERNAL (decl) = 1;
!   if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
      {
!       error ("%smember function `%D' cannot have `%T' method qualifier",
! 		(ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
!       quals = NULL_TREE;
      }
  
    if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
      grok_op_properties (decl, friendp, /*complain=*/true);
  
--- 5542,5556 ----
    if (DECL_DECLARED_INLINE_P (decl)
        || (flag_inline_trees == 2 && !DECL_INLINE (decl) && funcdef_flag))
      DECL_INLINE (decl) = 1;
  
    DECL_EXTERNAL (decl) = 1;
!   if (quals && TREE_CODE (type) == FUNCTION_TYPE)
      {
!       error ("%smember function `%D' cannot have cv-qualifier",
! 	     (ctype ? "static " : "non-"), decl);
!       quals = TYPE_UNQUALIFIED;
      }
  
    if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
      grok_op_properties (decl, friendp, /*complain=*/true);
  
*************** grokdeclarator (const cp_declarator *dec
*** 6285,6295 ****
    special_function_kind sfk = sfk_none;
  
    tree dname = NULL_TREE;
    tree ctor_return_type = NULL_TREE;
    enum overload_flags flags = NO_SPECIAL;
!   tree quals = NULL_TREE;
    tree raises = NULL_TREE;
    int template_count = 0;
    tree returned_attrs = NULL_TREE;
    tree parms = NULL_TREE;
    const cp_declarator *id_declarator;
--- 6285,6295 ----
    special_function_kind sfk = sfk_none;
  
    tree dname = NULL_TREE;
    tree ctor_return_type = NULL_TREE;
    enum overload_flags flags = NO_SPECIAL;
!   cp_cv_quals quals = TYPE_UNQUALIFIED;
    tree raises = NULL_TREE;
    int template_count = 0;
    tree returned_attrs = NULL_TREE;
    tree parms = NULL_TREE;
    const cp_declarator *id_declarator;
*************** grokdeclarator (const cp_declarator *dec
*** 7047,7059 ****
  		       not be static.  */
  		    if (staticp == 2)
  		      error ("destructor cannot be static member function");
  		    if (quals)
  		      {
! 			error ("destructors may not be `%E'",
! 				  TREE_VALUE (quals));
! 			quals = NULL_TREE;
  		      }
  		    if (decl_context == FIELD)
  		      {
  			if (! member_function_or_else (ctype,
  						       current_class_type,
--- 7047,7058 ----
  		       not be static.  */
  		    if (staticp == 2)
  		      error ("destructor cannot be static member function");
  		    if (quals)
  		      {
! 			error ("destructors may not be cv-qualified");
! 			quals = TYPE_UNQUALIFIED;
  		      }
  		    if (decl_context == FIELD)
  		      {
  			if (! member_function_or_else (ctype,
  						       current_class_type,
*************** grokdeclarator (const cp_declarator *dec
*** 7076,7088 ****
  			pedwarn ("constructors cannot be declared virtual");
  			virtualp = 0;
  		      }
  		    if (quals)
  		      {
! 			error ("constructors may not be `%E'",
!                                TREE_VALUE (quals));
! 			quals = NULL_TREE;
  		      }
  		    if (decl_context == FIELD)
  		      {
  			if (! member_function_or_else (ctype,
  						       current_class_type,
--- 7075,7086 ----
  			pedwarn ("constructors cannot be declared virtual");
  			virtualp = 0;
  		      }
  		    if (quals)
  		      {
! 			error ("constructors may not be cv-qualified");
! 			quals = TYPE_UNQUALIFIED;
  		      }
  		    if (decl_context == FIELD)
  		      {
  			if (! member_function_or_else (ctype,
  						       current_class_type,
*************** grokdeclarator (const cp_declarator *dec
*** 7161,7171 ****
  	    {
  	      tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
  	      grok_method_quals (declarator->u.pointer.class_type, 
  				 dummy, quals);
  	      type = TREE_TYPE (dummy);
! 	      quals = NULL_TREE;
  	    }
  
  	  if (declarator->kind == cdk_reference)
  	    {
  	      if (!VOID_TYPE_P (type))
--- 7159,7169 ----
  	    {
  	      tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
  	      grok_method_quals (declarator->u.pointer.class_type, 
  				 dummy, quals);
  	      type = TREE_TYPE (dummy);
! 	      quals = TYPE_UNQUALIFIED;
  	    }
  
  	  if (declarator->kind == cdk_reference)
  	    {
  	      if (!VOID_TYPE_P (type))
*************** grokdeclarator (const cp_declarator *dec
*** 7182,7230 ****
  	  /* Process a list of type modifier keywords (such as
  	     const or volatile) that were given inside the `*' or `&'.  */
  
  	  if (declarator->u.pointer.qualifiers)
  	    {
! 	      tree typemodlist;
! 	      int erred = 0;
! 	      int constp = 0;
! 	      int volatilep = 0;
! 	      int restrictp = 0;
! 	      
! 	      for (typemodlist = declarator->u.pointer.qualifiers; typemodlist;
! 		   typemodlist = TREE_CHAIN (typemodlist))
! 		{
! 		  tree qualifier = TREE_VALUE (typemodlist);
! 
! 		  if (qualifier == ridpointers[(int) RID_CONST])
! 		    {
! 		      constp++;
! 		      type_quals |= TYPE_QUAL_CONST;
! 		    }
! 		  else if (qualifier == ridpointers[(int) RID_VOLATILE])
! 		    {
! 		      volatilep++;
! 		      type_quals |= TYPE_QUAL_VOLATILE;
! 		    }
! 		  else if (qualifier == ridpointers[(int) RID_RESTRICT])
! 		    {
! 		      restrictp++;
! 		      type_quals |= TYPE_QUAL_RESTRICT;
! 		    }
! 		  else if (!erred)
! 		    {
! 		      erred = 1;
! 		      error ("invalid type modifier within pointer declarator");
! 		    }
! 		}
! 	      if (constp > 1)
! 		pedwarn ("duplicate `const'");
! 	      if (volatilep > 1)
! 		pedwarn ("duplicate `volatile'");
! 	      if (restrictp > 1)
! 		pedwarn ("duplicate `restrict'");
! 	      type = cp_build_qualified_type (type, type_quals);
  	      type_quals = cp_type_quals (type);
  	    }
  	  ctype = NULL_TREE;
  	  break;
  
--- 7180,7192 ----
  	  /* Process a list of type modifier keywords (such as
  	     const or volatile) that were given inside the `*' or `&'.  */
  
  	  if (declarator->u.pointer.qualifiers)
  	    {
! 	      type 
! 		= cp_build_qualified_type (type, 
! 					   declarator->u.pointer.qualifiers);
  	      type_quals = cp_type_quals (type);
  	    }
  	  ctype = NULL_TREE;
  	  break;
  
*************** grokdeclarator (const cp_declarator *dec
*** 7486,7496 ****
  
        if (declspecs->specs[(int)ds_signed]
  	  || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
  	C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
  
!       bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
  		      inlinep, friendp, raises != NULL_TREE);
  
        return decl;
      }
  
--- 7448,7458 ----
  
        if (declspecs->specs[(int)ds_signed]
  	  || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
  	C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
  
!       bad_specifiers (decl, "type", virtualp, quals != TYPE_UNQUALIFIED, 
  		      inlinep, friendp, raises != NULL_TREE);
  
        return decl;
      }
  
*************** grokdeclarator (const cp_declarator *dec
*** 7652,7662 ****
  
      if (decl_context == PARM)
        {
  	decl = cp_build_parm_decl (unqualified_id, type);
  
! 	bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
        }
      else if (decl_context == FIELD)
        {
  	/* The C99 flexible array extension.  */
--- 7614,7624 ----
  
      if (decl_context == PARM)
        {
  	decl = cp_build_parm_decl (unqualified_id, type);
  
! 	bad_specifiers (decl, "parameter", virtualp, quals != TYPE_UNQUALIFIED,
  			inlinep, friendp, raises != NULL_TREE);
        }
      else if (decl_context == FIELD)
        {
  	/* The C99 flexible array extension.  */
*************** grokdeclarator (const cp_declarator *dec
*** 7906,7916 ****
  		    DECL_MUTABLE_P (decl) = 1;
  		    declspecs->storage_class = sc_none;
  		  }
  	      }
  
! 	    bad_specifiers (decl, "field", virtualp, quals != NULL_TREE,
  			    inlinep, friendp, raises != NULL_TREE);
  	  }
        }
      else if (TREE_CODE (type) == FUNCTION_TYPE
  	     || TREE_CODE (type) == METHOD_TYPE)
--- 7868,7878 ----
  		    DECL_MUTABLE_P (decl) = 1;
  		    declspecs->storage_class = sc_none;
  		  }
  	      }
  
! 	    bad_specifiers (decl, "field", virtualp, quals != TYPE_UNQUALIFIED,
  			    inlinep, friendp, raises != NULL_TREE);
  	  }
        }
      else if (TREE_CODE (type) == FUNCTION_TYPE
  	     || TREE_CODE (type) == METHOD_TYPE)
*************** grokdeclarator (const cp_declarator *dec
*** 8007,8017 ****
  	decl = grokvardecl (type, unqualified_id, 
  			    declspecs,
  			    initialized,
  			    (type_quals & TYPE_QUAL_CONST) != 0,
  			    ctype ? ctype : in_namespace);
! 	bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
  			inlinep, friendp, raises != NULL_TREE);
  
  	if (ctype)
  	  {
  	    DECL_CONTEXT (decl) = ctype;
--- 7969,7979 ----
  	decl = grokvardecl (type, unqualified_id, 
  			    declspecs,
  			    initialized,
  			    (type_quals & TYPE_QUAL_CONST) != 0,
  			    ctype ? ctype : in_namespace);
! 	bad_specifiers (decl, "variable", virtualp, quals != TYPE_UNQUALIFIED,
  			inlinep, friendp, raises != NULL_TREE);
  
  	if (ctype)
  	  {
  	    DECL_CONTEXT (decl) = ctype;
Index: decl2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/decl2.c,v
retrieving revision 1.722
diff -c -5 -p -r1.722 decl2.c
*** decl2.c	26 Jun 2004 21:11:18 -0000	1.722
--- decl2.c	27 Jun 2004 02:10:42 -0000
*************** tree static_dtors;
*** 116,150 ****
     QUALS is a list of qualifiers.  Returns any explicit
     top-level qualifiers of the method's this pointer, anything other than
     TYPE_UNQUALIFIED will be an extension.  */
  
  int
! grok_method_quals (tree ctype, tree function, tree quals)
  {
    tree fntype = TREE_TYPE (function);
    tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
    int type_quals = TYPE_UNQUALIFIED;
-   int dup_quals = TYPE_UNQUALIFIED;
    int this_quals = TYPE_UNQUALIFIED;
  
!   while (quals)
!     {
!       int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
!       
!       if ((type_quals | this_quals) & tq)
! 	dup_quals |= tq;
!       else if (tq & TYPE_QUAL_RESTRICT)
!         this_quals |= tq;
!       else
! 	type_quals |= tq;
!       quals = TREE_CHAIN (quals);
!     } 
! 
!   if (dup_quals != TYPE_UNQUALIFIED)
!     error ("duplicate type qualifiers in %s declaration",
! 	      TREE_CODE (function) == FUNCTION_DECL 
! 	      ? "member function" : "type");
  
    ctype = cp_build_qualified_type (ctype, type_quals);
    fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
  				       (TREE_CODE (fntype) == METHOD_TYPE
  					? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
--- 116,134 ----
     QUALS is a list of qualifiers.  Returns any explicit
     top-level qualifiers of the method's this pointer, anything other than
     TYPE_UNQUALIFIED will be an extension.  */
  
  int
! grok_method_quals (tree ctype, tree function, cp_cv_quals quals)
  {
    tree fntype = TREE_TYPE (function);
    tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
    int type_quals = TYPE_UNQUALIFIED;
    int this_quals = TYPE_UNQUALIFIED;
  
!   type_quals = quals & ~TYPE_QUAL_RESTRICT;
!   this_quals = quals & TYPE_QUAL_RESTRICT;
  
    ctype = cp_build_qualified_type (ctype, type_quals);
    fntype = build_method_type_directly (ctype, TREE_TYPE (fntype),
  				       (TREE_CODE (fntype) == METHOD_TYPE
  					? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
*************** maybe_retrofit_in_chrg (tree fn)
*** 279,292 ****
     way the rest of the arguments were declared.
  
     QUALS are the qualifiers for the this pointer.  */
  
  void
! grokclassfn (tree ctype, tree function, enum overload_flags flags, tree quals)
  {
    tree fn_name = DECL_NAME (function);
!   int this_quals = TYPE_UNQUALIFIED;
  
    /* Even within an `extern "C"' block, members get C++ linkage.  See
       [dcl.link] for details.  */
    SET_DECL_LANGUAGE (function, lang_cplusplus);
  
--- 263,277 ----
     way the rest of the arguments were declared.
  
     QUALS are the qualifiers for the this pointer.  */
  
  void
! grokclassfn (tree ctype, tree function, enum overload_flags flags, 
! 	     cp_cv_quals quals)
  {
    tree fn_name = DECL_NAME (function);
!   cp_cv_quals this_quals = TYPE_UNQUALIFIED;
  
    /* Even within an `extern "C"' block, members get C++ linkage.  See
       [dcl.link] for details.  */
    SET_DECL_LANGUAGE (function, lang_cplusplus);
  
Index: friend.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/friend.c,v
retrieving revision 1.97
diff -c -5 -p -r1.97 friend.c
*** friend.c	31 May 2004 22:47:56 -0000	1.97
--- friend.c	27 Jun 2004 02:10:42 -0000
*************** make_friend_class (tree type, tree frien
*** 323,333 ****
     QUALS say what special qualifies should apply to the object
     pointed to by `this'.  */
  
  tree
  do_friend (tree ctype, tree declarator, tree decl,
! 	   tree attrlist, enum overload_flags flags, tree quals,
  	   int funcdef_flag)
  {
    /* Every decl that gets here is a friend of something.  */
    DECL_FRIEND_P (decl) = 1;
  
--- 323,334 ----
     QUALS say what special qualifies should apply to the object
     pointed to by `this'.  */
  
  tree
  do_friend (tree ctype, tree declarator, tree decl,
! 	   tree attrlist, enum overload_flags flags, 
! 	   cp_cv_quals quals,
  	   int funcdef_flag)
  {
    /* Every decl that gets here is a friend of something.  */
    DECL_FRIEND_P (decl) = 1;
  
Index: method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.288
diff -c -5 -p -r1.288 method.c
*** method.c	22 Jun 2004 07:18:36 -0000	1.288
--- method.c	27 Jun 2004 02:10:42 -0000
*************** implicitly_declare_fn (special_function_
*** 1018,1028 ****
        DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
        TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
      }
  
    grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
! 	       /*quals=*/NULL_TREE);
    grok_special_member_properties (fn);
    cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
  		  /*flags=*/LOOKUP_ONLYCONVERTING);
    DECL_IN_AGGR_P (fn) = 1;
    DECL_ARTIFICIAL (fn) = 1;
--- 1018,1028 ----
        DECL_ARGUMENTS (fn) = cp_build_parm_decl (NULL_TREE, rhs_parm_type);
        TREE_READONLY (DECL_ARGUMENTS (fn)) = 1;
      }
  
    grokclassfn (type, fn, kind == sfk_destructor ? DTOR_FLAG : NO_SPECIAL,
! 	       TYPE_UNQUALIFIED);
    grok_special_member_properties (fn);
    cp_finish_decl (fn, /*init=*/NULL_TREE, /*asmspec_tree=*/NULL_TREE,
  		  /*flags=*/LOOKUP_ONLYCONVERTING);
    DECL_IN_AGGR_P (fn) = 1;
    DECL_ARTIFICIAL (fn) = 1;
Index: parser.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/parser.c,v
retrieving revision 1.217
diff -c -5 -p -r1.217 parser.c
*** parser.c	26 Jun 2004 21:11:19 -0000	1.217
--- parser.c	27 Jun 2004 02:10:43 -0000
*************** clear_decl_specs (cp_decl_specifier_seq 
*** 1017,1037 ****
     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 *, tree, tree);
  static cp_declarator *make_array_declarator	
    (cp_declarator *, tree);
  static cp_declarator *make_pointer_declarator	
!   (tree, cp_declarator *);
  static cp_declarator *make_reference_declarator	
!   (tree, cp_declarator *);
  static cp_parameter_declarator *make_parameter_declarator 
    (cp_decl_specifier_seq *, cp_declarator *, tree);
  static cp_declarator *make_ptrmem_declarator	
!   (tree, tree, cp_declarator *);
  
  cp_declarator *cp_error_declarator;
  
  /* The obstack on which declarators and related data structures are
     allocated.  */
--- 1017,1037 ----
     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	
!   (cp_cv_quals, cp_declarator *);
  static cp_declarator *make_reference_declarator	
!   (cp_cv_quals, cp_declarator *);
  static cp_parameter_declarator *make_parameter_declarator 
    (cp_decl_specifier_seq *, cp_declarator *, tree);
  static cp_declarator *make_ptrmem_declarator	
!   (cp_cv_quals, tree, cp_declarator *);
  
  cp_declarator *cp_error_declarator;
  
  /* The obstack on which declarators and related data structures are
     allocated.  */
*************** make_id_declarator (tree id)
*** 1078,1088 ****
  /* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
     of modifiers such as const or volatile to apply to the pointer
     type, represented as identifiers.  */
  
  cp_declarator *
! make_pointer_declarator (tree cv_qualifiers, cp_declarator *target)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_pointer);
    declarator->declarator = target;
--- 1078,1088 ----
  /* Make a declarator for a pointer to TARGET.  CV_QUALIFIERS is a list
     of modifiers such as const or volatile to apply to the pointer
     type, represented as identifiers.  */
  
  cp_declarator *
! make_pointer_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_pointer);
    declarator->declarator = target;
*************** make_pointer_declarator (tree cv_qualifi
*** 1093,1103 ****
  }
  
  /* Like make_pointer_declarator -- but for references.  */
  
  cp_declarator *
! make_reference_declarator (tree cv_qualifiers, cp_declarator *target)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_reference);
    declarator->declarator = target;
--- 1093,1103 ----
  }
  
  /* Like make_pointer_declarator -- but for references.  */
  
  cp_declarator *
! make_reference_declarator (cp_cv_quals cv_qualifiers, cp_declarator *target)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_reference);
    declarator->declarator = target;
*************** make_reference_declarator (tree cv_quali
*** 1109,1119 ****
  
  /* Like make_pointer_declarator -- but for a pointer to a non-static
     member of CLASS_TYPE.  */
  
  cp_declarator *
! make_ptrmem_declarator (tree cv_qualifiers, tree class_type,
  			cp_declarator *pointee)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_ptrmem);
--- 1109,1119 ----
  
  /* Like make_pointer_declarator -- but for a pointer to a non-static
     member of CLASS_TYPE.  */
  
  cp_declarator *
! make_ptrmem_declarator (cp_cv_quals cv_qualifiers, tree class_type,
  			cp_declarator *pointee)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_ptrmem);
*************** make_ptrmem_declarator (tree cv_qualifie
*** 1130,1140 ****
     indicates what exceptions can be thrown.  */
  
  cp_declarator *
  make_call_declarator (cp_declarator *target, 
  		      cp_parameter_declarator *parms,
! 		      tree cv_qualifiers, 
                        tree exception_specification)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_function);
--- 1130,1140 ----
     indicates what exceptions can be thrown.  */
  
  cp_declarator *
  make_call_declarator (cp_declarator *target, 
  		      cp_parameter_declarator *parms,
! 		      cp_cv_quals cv_qualifiers,
                        tree exception_specification)
  {
    cp_declarator *declarator;
  
    declarator = make_declarator (cdk_function);
*************** static tree cp_parser_init_declarator
*** 1691,1704 ****
  static cp_declarator *cp_parser_declarator
    (cp_parser *, cp_parser_declarator_kind, int *, bool *);
  static cp_declarator *cp_parser_direct_declarator
    (cp_parser *, cp_parser_declarator_kind, int *);
  static enum tree_code cp_parser_ptr_operator
!   (cp_parser *, tree *, tree *);
! static tree cp_parser_cv_qualifier_seq_opt
!   (cp_parser *);
! static tree cp_parser_cv_qualifier_opt
    (cp_parser *);
  static tree cp_parser_declarator_id
    (cp_parser *);
  static tree cp_parser_type_id
    (cp_parser *);
--- 1691,1702 ----
  static cp_declarator *cp_parser_declarator
    (cp_parser *, cp_parser_declarator_kind, int *, bool *);
  static cp_declarator *cp_parser_direct_declarator
    (cp_parser *, cp_parser_declarator_kind, int *);
  static enum tree_code cp_parser_ptr_operator
!   (cp_parser *, tree *, cp_cv_quals *);
! static cp_cv_quals cp_parser_cv_qualifier_seq_opt
    (cp_parser *);
  static tree cp_parser_declarator_id
    (cp_parser *);
  static tree cp_parser_type_id
    (cp_parser *);
*************** cp_parser_new_type_id (cp_parser* parser
*** 4954,4988 ****
  static cp_declarator *
  cp_parser_new_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree type;
!   tree cv_qualifier_seq;
  
    /* We don't know if there's a ptr-operator next, or not.  */
    cp_parser_parse_tentatively (parser);
    /* Look for a ptr-operator.  */
!   code = cp_parser_ptr_operator (parser, &type, &cv_qualifier_seq);
    /* If that worked, look for more new-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
        cp_declarator *declarator;
  
        /* Parse another optional declarator.  */
        declarator = cp_parser_new_declarator_opt (parser);
  
        /* Create the representation of the declarator.  */
        if (type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
! 					     type,
! 					     declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_qualifier_seq,
! 					      declarator);
        else
! 	declarator = make_reference_declarator (cv_qualifier_seq,
! 						declarator);
  
        return declarator;
      }
  
    /* If the next token is a `[', there is a direct-new-declarator.  */
--- 4952,4982 ----
  static cp_declarator *
  cp_parser_new_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree type;
!   cp_cv_quals cv_quals;
  
    /* We don't know if there's a ptr-operator next, or not.  */
    cp_parser_parse_tentatively (parser);
    /* Look for a ptr-operator.  */
!   code = cp_parser_ptr_operator (parser, &type, &cv_quals);
    /* If that worked, look for more new-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
        cp_declarator *declarator;
  
        /* Parse another optional declarator.  */
        declarator = cp_parser_new_declarator_opt (parser);
  
        /* Create the representation of the declarator.  */
        if (type)
! 	declarator = make_ptrmem_declarator (cv_quals, type, declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_quals, declarator);
        else
! 	declarator = make_reference_declarator (cv_quals, declarator);
  
        return declarator;
      }
  
    /* If the next token is a `[', there is a direct-new-declarator.  */
*************** cp_parser_conversion_type_id (cp_parser*
*** 7568,7603 ****
  static cp_declarator *
  cp_parser_conversion_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree class_type;
!   tree cv_qualifier_seq;
  
    /* We don't know if there's a ptr-operator next, or not.  */
    cp_parser_parse_tentatively (parser);
    /* Try the ptr-operator.  */
!   code = cp_parser_ptr_operator (parser, &class_type,
! 				 &cv_qualifier_seq);
    /* If it worked, look for more conversion-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
        cp_declarator *declarator;
        
        /* Parse another optional declarator.  */
        declarator = cp_parser_conversion_declarator_opt (parser);
        
        /* Create the representation of the declarator.  */
        if (class_type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
! 					     class_type,
  					     declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_qualifier_seq,
! 					      declarator);
        else
! 	declarator = make_reference_declarator (cv_qualifier_seq,
! 						declarator);
        
        return declarator;
     }
  
    return NULL;
--- 7562,7593 ----
  static cp_declarator *
  cp_parser_conversion_declarator_opt (cp_parser* parser)
  {
    enum tree_code code;
    tree class_type;
!   cp_cv_quals cv_quals;
  
    /* We don't know if there's a ptr-operator next, or not.  */
    cp_parser_parse_tentatively (parser);
    /* Try the ptr-operator.  */
!   code = cp_parser_ptr_operator (parser, &class_type, &cv_quals);
    /* If it worked, look for more conversion-declarators.  */
    if (cp_parser_parse_definitely (parser))
      {
        cp_declarator *declarator;
        
        /* Parse another optional declarator.  */
        declarator = cp_parser_conversion_declarator_opt (parser);
        
        /* Create the representation of the declarator.  */
        if (class_type)
! 	declarator = make_ptrmem_declarator (cv_quals, class_type,
  					     declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_quals, declarator);
        else
! 	declarator = make_reference_declarator (cv_quals, declarator);
        
        return declarator;
     }
  
    return NULL;
*************** cp_parser_declarator (cp_parser* parser,
*** 10777,10787 ****
  		      bool* parenthesized_p)
  {
    cp_token *token;
    cp_declarator *declarator;
    enum tree_code code;
!   tree cv_qualifier_seq;
    tree class_type;
    tree attributes = NULL_TREE;
  
    /* Assume this is not a constructor, destructor, or type-conversion
       operator.  */
--- 10767,10777 ----
  		      bool* parenthesized_p)
  {
    cp_token *token;
    cp_declarator *declarator;
    enum tree_code code;
!   cp_cv_quals cv_quals;
    tree class_type;
    tree attributes = NULL_TREE;
  
    /* Assume this is not a constructor, destructor, or type-conversion
       operator.  */
*************** cp_parser_declarator (cp_parser* parser,
*** 10797,10807 ****
    /* Check for the ptr-operator production.  */
    cp_parser_parse_tentatively (parser);
    /* Parse the ptr-operator.  */
    code = cp_parser_ptr_operator (parser,
  				 &class_type,
! 				 &cv_qualifier_seq);
    /* If that worked, then we have a ptr-operator.  */
    if (cp_parser_parse_definitely (parser))
      {
        /* If a ptr-operator was found, then this declarator was not
  	 parenthesized.  */
--- 10787,10797 ----
    /* Check for the ptr-operator production.  */
    cp_parser_parse_tentatively (parser);
    /* Parse the ptr-operator.  */
    code = cp_parser_ptr_operator (parser,
  				 &class_type,
! 				 &cv_quals);
    /* If that worked, then we have a ptr-operator.  */
    if (cp_parser_parse_definitely (parser))
      {
        /* If a ptr-operator was found, then this declarator was not
  	 parenthesized.  */
*************** cp_parser_declarator (cp_parser* parser,
*** 10823,10841 ****
  	  && !cp_parser_parse_definitely (parser))
  	declarator = NULL;
  
        /* Build the representation of the ptr-operator.  */
        if (class_type)
! 	declarator = make_ptrmem_declarator (cv_qualifier_seq,
  					     class_type,
  					     declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_qualifier_seq,
! 					      declarator);
        else
! 	declarator = make_reference_declarator (cv_qualifier_seq,
! 						declarator);
      }
    /* Everything else is a direct-declarator.  */
    else
      {
        if (parenthesized_p)
--- 10813,10829 ----
  	  && !cp_parser_parse_definitely (parser))
  	declarator = NULL;
  
        /* Build the representation of the ptr-operator.  */
        if (class_type)
! 	declarator = make_ptrmem_declarator (cv_quals,
  					     class_type,
  					     declarator);
        else if (code == INDIRECT_REF)
! 	declarator = make_pointer_declarator (cv_quals, declarator);
        else
! 	declarator = make_reference_declarator (cv_quals, declarator);
      }
    /* Everything else is a direct-declarator.  */
    else
      {
        if (parenthesized_p)
*************** cp_parser_direct_declarator (cp_parser* 
*** 10966,10994 ****
  
  	      /* If all went well, parse the cv-qualifier-seq and the
  	     	 exception-specification.  */
  	      if (cp_parser_parse_definitely (parser))
  		{
! 		  tree cv_qualifiers;
  		  tree exception_specification;
  
  		  if (ctor_dtor_or_conv_p)
  		    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
  		  first = false;
  		  /* Consume the `)'.  */
  		  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  		  /* Parse the cv-qualifier-seq.  */
! 		  cv_qualifiers = cp_parser_cv_qualifier_seq_opt (parser);
  		  /* And the exception-specification.  */
  		  exception_specification
  		    = cp_parser_exception_specification_opt (parser);
  
  		  /* Create the function-declarator.  */
  		  declarator = make_call_declarator (declarator,
  						     params,
! 						     cv_qualifiers,
  						     exception_specification);
  		  /* Any subsequent parameter lists are to do with
  	 	     return type, so are not those of the declared
  	 	     function.  */
  		  parser->default_arg_ok_p = false;
--- 10954,10982 ----
  
  	      /* If all went well, parse the cv-qualifier-seq and the
  	     	 exception-specification.  */
  	      if (cp_parser_parse_definitely (parser))
  		{
! 		  cp_cv_quals cv_quals;
  		  tree exception_specification;
  
  		  if (ctor_dtor_or_conv_p)
  		    *ctor_dtor_or_conv_p = *ctor_dtor_or_conv_p < 0;
  		  first = false;
  		  /* Consume the `)'.  */
  		  cp_parser_require (parser, CPP_CLOSE_PAREN, "`)'");
  
  		  /* Parse the cv-qualifier-seq.  */
! 		  cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
  		  /* And the exception-specification.  */
  		  exception_specification
  		    = cp_parser_exception_specification_opt (parser);
  
  		  /* Create the function-declarator.  */
  		  declarator = make_call_declarator (declarator,
  						     params,
! 						     cv_quals,
  						     exception_specification);
  		  /* Any subsequent parameter lists are to do with
  	 	     return type, so are not those of the declared
  	 	     function.  */
  		  parser->default_arg_ok_p = false;
*************** cp_parser_direct_declarator (cp_parser* 
*** 11224,11252 ****
     GNU Extension:
  
     ptr-operator:
       & cv-qualifier-seq [opt]
  
!    Returns INDIRECT_REF if a pointer, or pointer-to-member, was
!    used.  Returns ADDR_EXPR if a reference was used.  In the
!    case of a pointer-to-member, *TYPE is filled in with the
!    TYPE containing the member.  *CV_QUALIFIER_SEQ is filled in
!    with the cv-qualifier-seq, or NULL_TREE, if there are no
!    cv-qualifiers.  Returns ERROR_MARK if an error occurred.  */
  
  static enum tree_code
  cp_parser_ptr_operator (cp_parser* parser,
                          tree* type,
!                         tree* cv_qualifier_seq)
  {
    enum tree_code code = ERROR_MARK;
    cp_token *token;
  
    /* Assume that it's not a pointer-to-member.  */
    *type = NULL_TREE;
    /* And that there are no cv-qualifiers.  */
!   *cv_qualifier_seq = NULL_TREE;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it's a `*' or `&' we have a pointer or reference.  */
    if (token->type == CPP_MULT || token->type == CPP_AND)
--- 11212,11240 ----
     GNU Extension:
  
     ptr-operator:
       & cv-qualifier-seq [opt]
  
!    Returns INDIRECT_REF if a pointer, or pointer-to-member, was used.
!    Returns ADDR_EXPR if a reference was used.  In the case of a
!    pointer-to-member, *TYPE is filled in with the TYPE containing the
!    member.  *CV_QUALS is filled in with the cv-qualifier-seq, or
!    TYPE_UNQUALIFIED, if there are no cv-qualifiers.  Returns
!    ERROR_MARK if an error occurred.  */
  
  static enum tree_code
  cp_parser_ptr_operator (cp_parser* parser,
                          tree* type,
! 			cp_cv_quals *cv_quals)
  {
    enum tree_code code = ERROR_MARK;
    cp_token *token;
  
    /* Assume that it's not a pointer-to-member.  */
    *type = NULL_TREE;
    /* And that there are no cv-qualifiers.  */
!   *cv_quals = TYPE_UNQUALIFIED;
  
    /* Peek at the next token.  */
    token = cp_lexer_peek_token (parser->lexer);
    /* If it's a `*' or `&' we have a pointer or reference.  */
    if (token->type == CPP_MULT || token->type == CPP_AND)
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11261,11271 ****
  	 `&', if we are allowing GNU extensions.  (The only qualifier
  	 that can legally appear after `&' is `restrict', but that is
  	 enforced during semantic analysis.  */
        if (code == INDIRECT_REF
  	  || cp_parser_allow_gnu_extensions_p (parser))
! 	*cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
      }
    else
      {
        /* Try the pointer-to-member case.  */
        cp_parser_parse_tentatively (parser);
--- 11249,11259 ----
  	 `&', if we are allowing GNU extensions.  (The only qualifier
  	 that can legally appear after `&' is `restrict', but that is
  	 enforced during semantic analysis.  */
        if (code == INDIRECT_REF
  	  || cp_parser_allow_gnu_extensions_p (parser))
! 	*cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
      }
    else
      {
        /* Try the pointer-to-member case.  */
        cp_parser_parse_tentatively (parser);
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11291,11301 ****
  	  parser->qualifying_scope = NULL_TREE;
  	  parser->object_scope = NULL_TREE;
  	  /* Indicate that the `*' operator was used.  */
  	  code = INDIRECT_REF;
  	  /* Look for the optional cv-qualifier-seq.  */
! 	  *cv_qualifier_seq = cp_parser_cv_qualifier_seq_opt (parser);
  	}
        /* If that didn't work we don't have a ptr-operator.  */
        if (!cp_parser_parse_definitely (parser))
  	cp_parser_error (parser, "expected ptr-operator");
      }
--- 11279,11289 ----
  	  parser->qualifying_scope = NULL_TREE;
  	  parser->object_scope = NULL_TREE;
  	  /* Indicate that the `*' operator was used.  */
  	  code = INDIRECT_REF;
  	  /* Look for the optional cv-qualifier-seq.  */
! 	  *cv_quals = cp_parser_cv_qualifier_seq_opt (parser);
  	}
        /* If that didn't work we don't have a ptr-operator.  */
        if (!cp_parser_parse_definitely (parser))
  	cp_parser_error (parser, "expected ptr-operator");
      }
*************** cp_parser_ptr_operator (cp_parser* parse
*** 11306,11378 ****
  /* Parse an (optional) cv-qualifier-seq.
  
     cv-qualifier-seq:
       cv-qualifier cv-qualifier-seq [opt]
  
-    Returns a TREE_LIST.  The TREE_VALUE of each node is the
-    representation of a cv-qualifier.  */
- 
- static tree
- cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
- {
-   tree cv_qualifiers = NULL_TREE;
- 
-   while (true)
-     {
-       tree cv_qualifier;
- 
-       /* Look for the next cv-qualifier.  */
-       cv_qualifier = cp_parser_cv_qualifier_opt (parser);
-       /* If we didn't find one, we're done.  */
-       if (!cv_qualifier)
- 	break;
- 
-       /* Add this cv-qualifier to the list.  */
-       cv_qualifiers
- 	= tree_cons (NULL_TREE, cv_qualifier, cv_qualifiers);
-     }
- 
-   /* We built up the list in reverse order.  */
-   return nreverse (cv_qualifiers);
- }
- 
- /* Parse an (optional) cv-qualifier.
- 
     cv-qualifier:
       const
       volatile
  
     GNU Extension:
  
     cv-qualifier:
!      __restrict__ */
  
! static tree
! cp_parser_cv_qualifier_opt (cp_parser* parser)
  {
!   cp_token *token;
!   tree cv_qualifier = NULL_TREE;
  
!   /* Peek at the next token.  */
!   token = cp_lexer_peek_token (parser->lexer);
!   /* See if it's a cv-qualifier.  */
!   switch (token->keyword)
      {
!     case RID_CONST:
!     case RID_VOLATILE:
!     case RID_RESTRICT:
!       /* Save the value of the token.  */
!       cv_qualifier = token->value;
!       /* Consume the token.  */
!       cp_lexer_consume_token (parser->lexer);
!       break;
  
!     default:
!       break;
      }
  
!   return cv_qualifier;
  }
  
  /* Parse a declarator-id.
  
     declarator-id:
--- 11294,11362 ----
  /* Parse an (optional) cv-qualifier-seq.
  
     cv-qualifier-seq:
       cv-qualifier cv-qualifier-seq [opt]
  
     cv-qualifier:
       const
       volatile
  
     GNU Extension:
  
     cv-qualifier:
!      __restrict__ 
  
!    Returns a bitmask representing the cv-qualifiers.  */
! 
! static cp_cv_quals
! cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
  {
!   cp_cv_quals cv_quals = TYPE_UNQUALIFIED;
  
!   while (true)
      {
!       cp_token *token;
!       cp_cv_quals cv_qualifier;
!       
!       /* Peek at the next token.  */
!       token = cp_lexer_peek_token (parser->lexer);
!       /* See if it's a cv-qualifier.  */
!       switch (token->keyword)
! 	{
! 	case RID_CONST:
! 	  cv_qualifier = TYPE_QUAL_CONST;
! 	  break;
! 	  
! 	case RID_VOLATILE:
! 	  cv_qualifier = TYPE_QUAL_VOLATILE;
! 	  break;
! 	  
! 	case RID_RESTRICT:
! 	  cv_qualifier = TYPE_QUAL_RESTRICT;
! 	  break;
! 	  
! 	default:
! 	  cv_qualifier = TYPE_UNQUALIFIED;
! 	  break;
! 	}
!       
!       if (!cv_qualifier)
! 	break;
  
!       if (cv_quals & cv_qualifier)
! 	{
! 	  error ("duplicate cv-qualifier");
! 	  cp_lexer_purge_token (parser->lexer);
! 	}
!       else
! 	{
! 	  cp_lexer_consume_token (parser->lexer);
! 	  cv_quals |= cv_qualifier;
! 	}
      }
  
!   return cv_quals;
  }
  
  /* Parse a declarator-id.
  
     declarator-id:


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