* Make-lang.in (cp/lex.o): Do not depend on cp/lex.h.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Jun 2004 06:48:44 +0000 (06:48 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 24 Jun 2004 06:48:44 +0000 (06:48 +0000)
(cp/decl.o): Likewise.
(cp/decl2.o): Likewise.
(cp/pt.o): Likewise.
(cp/semantics.o): Likewise.
* config-lang.in (gtfiles): Do not reference cp/lex.h.
* class.c: Do not include lex.h.
(add_implicitly_declared_members): Do not use
adding_implicit_members.
(check_bases_and_members): Do not talk about grok_x_components.
* cp/cp-tree.h (adding_implicit_members): Remove.
(cp_storage_class): New type.
(cp_decl_spec): Likewise.
(cp_decl_specifier_seq): Likewise.
(cp_parameter_declarator): Use it for the decl_specifiers field.
(check_tag_decl): Adjust prototype.
(shadow_tag): Likewise.
(groktypename): Likewise.
(start_decl): Likewise.
(start_function): Likewise.
(start_method): Likewise.
(grok_x_components): Remove.
(grokfield): Adjust prototype.
(grokbitfield): Likewise.
(finish_member_class_template): Remove.
* decl.c: Do not include lex.h.
(adding_implicit_members): Do not define.
(check_tag_decl): Do not use trees to represent decl-specifiers.
(shadow_tag): Likewise.
(groktypename): Likewise.
(start_decl): Likewise.
(grokvardecl): Likewise.
(grokdeclarator): Likewise.
(grokparms): Likewise.
(start_function): Likewise.
(start_method): Likewise.
* decl.h (grokdeclarator): Adjust prototype.
* decl2.c: Do not include lex.h.
(grok_x_components): Remove.
(grokfield): Do not use trees to represent decl-specifiers.
(grokbitfield): Likewise.
* lex.c: Do not include lex.h.
* lex.h: Remove.
* parser.c: Include target.h.
(clear_decl_specs): New function.
(cp_parser_translation_unit): Do not use trees to represent
decl-specifiers.
(cp_parser_postfix_expression): Likewise.
(cp_parser_new_type_id): Likewise.
(cp_parser_condition): Likewise.
(cp_parser_simple_declaration): Likewise.
(cp_parser_decl_specifier_seq): Likewise.
(cp_parser_function_specifier_opt): Likewise.
(cp_parser_conversion_type_id): Likewise.
(cp_parser_template_parameter): Likewise.
(cp_parser_explicit_instantiation): Likewise.
(cp_parser_type_specifier): Likewise.
(cp_parser_simple_type_specifier): Likewise.
(cp_parser_init_declarator): Likewise.
(cp_parser_type_id): Likewise.
(cp_parser_type_specifier_seq): Likewise.
(cp_parser_parameter_declaration): Likewise.
(cp_parser_member_declaration): Likewise.
(cp_parser_exception_declaration): Likewise.
(cp_parser_function_definition_from_specifiers_and_declarator):
Likewise.
(cp_parser_single_declaration): Likewise.
(cp_parser_save_member_function_body): Likewise.
(cp_parser_friend_p): Likewise.
(cp_parser_set_storage_class): New function.
(cp_parser_set_decl_spec_type): Likewise.
* pt.c: Do not include lex.h.
* semantics.c: Likewise.
(finish_member_class_template): Remove.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@83584 138bc75d-0d04-0410-961f-82ee72b054a4

13 files changed:
gcc/cp/ChangeLog
gcc/cp/Make-lang.in
gcc/cp/class.c
gcc/cp/config-lang.in
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl.h
gcc/cp/decl2.c
gcc/cp/lex.c
gcc/cp/lex.h [deleted file]
gcc/cp/parser.c
gcc/cp/pt.c
gcc/cp/semantics.c

index 531df51..5a18b46 100644 (file)
@@ -1,3 +1,80 @@
+2004-06-23  Mark Mitchell  <mark@codesourcery.com>
+
+       * Make-lang.in (cp/lex.o): Do not depend on cp/lex.h.
+       (cp/decl.o): Likewise.
+       (cp/decl2.o): Likewise.
+       (cp/pt.o): Likewise.
+       (cp/semantics.o): Likewise.
+       * config-lang.in (gtfiles): Do not reference cp/lex.h.
+       * class.c: Do not include lex.h.
+       (add_implicitly_declared_members): Do not use
+       adding_implicit_members.
+       (check_bases_and_members): Do not talk about grok_x_components.
+       * cp/cp-tree.h (adding_implicit_members): Remove.
+       (cp_storage_class): New type.
+       (cp_decl_spec): Likewise.
+       (cp_decl_specifier_seq): Likewise.
+       (cp_parameter_declarator): Use it for the decl_specifiers field.
+       (check_tag_decl): Adjust prototype.
+       (shadow_tag): Likewise.
+       (groktypename): Likewise.
+       (start_decl): Likewise.
+       (start_function): Likewise.
+       (start_method): Likewise.
+       (grok_x_components): Remove.
+       (grokfield): Adjust prototype.
+       (grokbitfield): Likewise.
+       (finish_member_class_template): Remove.
+       * decl.c: Do not include lex.h.
+       (adding_implicit_members): Do not define.
+       (check_tag_decl): Do not use trees to represent decl-specifiers.
+       (shadow_tag): Likewise.
+       (groktypename): Likewise.
+       (start_decl): Likewise.
+       (grokvardecl): Likewise.
+       (grokdeclarator): Likewise.
+       (grokparms): Likewise.
+       (start_function): Likewise.
+       (start_method): Likewise.
+       * decl.h (grokdeclarator): Adjust prototype.
+       * decl2.c: Do not include lex.h.
+       (grok_x_components): Remove.
+       (grokfield): Do not use trees to represent decl-specifiers.
+       (grokbitfield): Likewise.
+       * lex.c: Do not include lex.h.
+       * lex.h: Remove.
+       * parser.c: Include target.h.
+       (clear_decl_specs): New function.
+       (cp_parser_translation_unit): Do not use trees to represent
+       decl-specifiers.
+       (cp_parser_postfix_expression): Likewise.
+       (cp_parser_new_type_id): Likewise.
+       (cp_parser_condition): Likewise.
+       (cp_parser_simple_declaration): Likewise.
+       (cp_parser_decl_specifier_seq): Likewise.
+       (cp_parser_function_specifier_opt): Likewise.
+       (cp_parser_conversion_type_id): Likewise.
+       (cp_parser_template_parameter): Likewise.
+       (cp_parser_explicit_instantiation): Likewise.
+       (cp_parser_type_specifier): Likewise.
+       (cp_parser_simple_type_specifier): Likewise.
+       (cp_parser_init_declarator): Likewise.
+       (cp_parser_type_id): Likewise.
+       (cp_parser_type_specifier_seq): Likewise.
+       (cp_parser_parameter_declaration): Likewise.
+       (cp_parser_member_declaration): Likewise.
+       (cp_parser_exception_declaration): Likewise.
+       (cp_parser_function_definition_from_specifiers_and_declarator):
+       Likewise.
+       (cp_parser_single_declaration): Likewise.
+       (cp_parser_save_member_function_body): Likewise.
+       (cp_parser_friend_p): Likewise.
+       (cp_parser_set_storage_class): New function.
+       (cp_parser_set_decl_spec_type): Likewise.
+       * pt.c: Do not include lex.h.
+       * semantics.c: Likewise.
+       (finish_member_class_template): Remove. 
+       
 2004-06-23  Roger Sayle  <roger@eyesopen.com>
 
        * call.c (build_cxx_call): Don't call expand_tree_builtin.  No
index a928c38..997b8aa 100644 (file)
@@ -216,15 +216,15 @@ CXX_TREE_H = $(TREE_H) cp/name-lookup.h cp/cp-tree.h c-common.h \
 
 CXX_PRETTY_PRINT_H = cp/cxx-pretty-print.h $(C_PRETTY_PRINT_H)
 
-cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h \
+cp/lex.o: cp/lex.c $(CXX_TREE_H) $(TM_H) flags.h \
   c-pragma.h toplev.h output.h input.h cp/operators.def $(TM_P_H)
 cp/cp-lang.o: cp/cp-lang.c $(CXX_TREE_H) $(TM_H) toplev.h langhooks.h \
   $(LANGHOOKS_DEF_H) c-common.h $(CXX_PRETTY_PRINT_H) $(DIAGNOSTIC_H)
-cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h stack.h \
+cp/decl.o: cp/decl.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h stack.h \
   output.h $(EXPR_H) except.h toplev.h $(HASHTAB_H) $(RTL_H) \
   cp/operators.def $(TM_P_H) tree-inline.h diagnostic.h c-pragma.h \
   debug.h gt-cp-decl.h gtype-cp.h timevar.h $(TREE_FLOW_H)
-cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/lex.h cp/decl.h $(EXPR_H) \
+cp/decl2.o: cp/decl2.c $(CXX_TREE_H) $(TM_H) flags.h cp/decl.h $(EXPR_H) \
   output.h except.h toplev.h $(RTL_H) c-common.h gt-cp-decl2.h cgraph.h
 cp/typeck2.o: cp/typeck2.c $(CXX_TREE_H) $(TM_H) flags.h toplev.h output.h $(TM_P_H) \
    diagnostic.h
@@ -248,13 +248,13 @@ cp/except.o: cp/except.c $(CXX_TREE_H) $(TM_H) flags.h $(RTL_H) except.h toplev.
   cp/cfns.h $(EXPR_H) libfuncs.h tree-inline.h
 cp/expr.o: cp/expr.c $(CXX_TREE_H) $(TM_H) $(RTL_H) flags.h $(EXPR_H) toplev.h \
   except.h $(TM_P_H)
-cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h cp/lex.h \
+cp/pt.o: cp/pt.c $(CXX_TREE_H) $(TM_H) cp/decl.h \
   toplev.h $(RTL_H) except.h tree-inline.h gt-cp-pt.h
 cp/error.o: cp/error.c $(CXX_TREE_H) $(TM_H) toplev.h $(DIAGNOSTIC_H) \
   flags.h real.h $(LANGHOOKS_DEF_H) $(CXX_PRETTY_PRINT_H)
 cp/repo.o: cp/repo.c $(CXX_TREE_H) $(TM_H) toplev.h diagnostic.h \
   gt-cp-repo.h
-cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) cp/lex.h except.h toplev.h \
+cp/semantics.o: cp/semantics.c $(CXX_TREE_H) $(TM_H) except.h toplev.h \
   flags.h debug.h output.h $(RTL_H) $(TIMEVAR_H) $(EXPR_H) \
   tree-inline.h cgraph.h
 cp/dump.o: cp/dump.c $(CXX_TREE_H) $(TM_H) tree-dump.h
index d58577f..c2d6541 100644 (file)
@@ -33,7 +33,6 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "output.h"
 #include "toplev.h"
-#include "lex.h"
 #include "target.h"
 #include "convert.h"
 
@@ -2624,8 +2623,6 @@ add_implicitly_declared_members (tree t,
   tree virtual_dtor = NULL_TREE;
   tree *f;
 
-  ++adding_implicit_members;
-
   /* Destructor.  */
   if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) && !TYPE_HAS_DESTRUCTOR (t))
     {
@@ -2700,8 +2697,6 @@ add_implicitly_declared_members (tree t,
       *f = TYPE_METHODS (t);
       TYPE_METHODS (t) = implicit_fns;
     }
-
-  --adding_implicit_members;
 }
 
 /* Subroutine of finish_struct_1.  Recursively count the number of fields
@@ -4206,8 +4201,7 @@ check_bases_and_members (tree t)
   TYPE_HAS_COMPLEX_ASSIGN_REF (t)
     |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
 
-  /* Synthesize any needed methods.  Note that methods will be synthesized
-     for anonymous unions; grok_x_components undoes that.  */
+  /* Synthesize any needed methods.   */
   add_implicitly_declared_members (t, cant_have_default_ctor,
                                   cant_have_const_ctor,
                                   no_const_asn_ref);
index f3037dc..0d0c38f 100644 (file)
@@ -34,4 +34,4 @@ stagestuff="g++\$(exeext) g++-cross\$(exeext) cc1plus\$(exeext)"
 
 target_libs="target-libstdc++-v3 target-gperf"
 
-gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/lex.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
+gtfiles="\$(srcdir)/cp/mangle.c \$(srcdir)/cp/name-lookup.h \$(srcdir)/cp/name-lookup.c \$(srcdir)/cp/cp-tree.h \$(srcdir)/cp/decl.h \$(srcdir)/cp/call.c \$(srcdir)/cp/decl.c \$(srcdir)/cp/decl2.c \$(srcdir)/cp/pt.c \$(srcdir)/cp/repo.c \$(srcdir)/cp/semantics.c \$(srcdir)/cp/tree.c \$(srcdir)/cp/parser.c \$(srcdir)/cp/method.c \$(srcdir)/c-common.c \$(srcdir)/c-common.h \$(srcdir)/c-lex.c \$(srcdir)/c-pragma.c"
index 9638c2d..ecd9b18 100644 (file)
@@ -3082,11 +3082,6 @@ typedef enum base_kind {
                             binfo.  */
 } base_kind;
 
-/* Set by add_implicitly_declared_members() to keep those members from
-   being flagged as deprecated or reported as using deprecated
-   types.  */
-extern int adding_implicit_members;
-
 /* in decl{2}.c */
 /* A node that is a list (length 1) of error_mark_nodes.  */
 extern GTY(()) tree error_mark_list;
@@ -3508,6 +3503,74 @@ extern GTY(()) operator_name_info_t operator_name_info
 extern GTY(()) operator_name_info_t assignment_operator_name_info
   [(int) LAST_CPLUS_TREE_CODE];
 
+/* 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.  */
+  sc_none = 0,
+  sc_auto,
+  sc_register,
+  sc_static,
+  sc_extern,
+  sc_mutable,
+} cp_storage_class;
+
+/* An individual decl-specifier.  */
+
+typedef enum cp_decl_spec {
+  ds_first,
+  ds_signed = ds_first,
+  ds_unsigned,
+  ds_short,
+  ds_long,
+  ds_const,
+  ds_volatile,
+  ds_restrict,
+  ds_inline,
+  ds_virtual,
+  ds_explicit,
+  ds_friend,
+  ds_typedef,
+  ds_complex,
+  ds_thread,
+  ds_last
+} cp_decl_spec;
+
+/* A decl-specifier-seq.  */
+
+typedef struct cp_decl_specifier_seq {
+  /* The number of times each of the keywords has been seen.  */
+  unsigned specs[(int) ds_last];
+  /* The primary type, if any, given by the decl-specifier-seq.
+     Modifiers, like "short", "const", and "unsigned" are not
+     reflected here.  This field will be a TYPE, unless a typedef-name
+     was used, in which case it will be a TYPE_DECL.  */
+  tree type;
+  /* The attributes, if any, provided with the specifier sequence.  */
+  tree attributes;
+  /* If non-NULL, a built-in type that the user attempted to redefine
+     to some other type.  */
+  tree redefined_builtin_type;
+  /* The storage class specified -- or sc_none if no storage class was
+     explicitly specified.  */
+  cp_storage_class storage_class;
+  /* True iff TYPE_SPEC indicates a user-defined type.  */
+  BOOL_BITFIELD user_defined_type_p : 1;
+  /* True iff multiple types were (erroneously) specified for this
+     decl-specifier-seq.  */
+  BOOL_BITFIELD multiple_types_p : 1;
+  /* True iff multiple storage classes were (erroneously) specified
+     for this decl-specifier-seq.  */
+  BOOL_BITFIELD multiple_storage_classes_p : 1;
+  /* True iff at least one decl-specifier was found.  */
+  BOOL_BITFIELD any_specifiers_p : 1;
+  /* True iff "int" was explicitly provided.  */
+  BOOL_BITFIELD explicit_int_p : 1;
+  /* True iff "char" was explicitly provided.  */
+  BOOL_BITFIELD explicit_char_p : 1;
+} cp_decl_specifier_seq;
+
 /* The various kinds of declarators.  */
 
 typedef enum cp_declarator_kind {
@@ -3531,7 +3594,7 @@ struct cp_parameter_declarator {
   /* The next parameter, or NULL_TREE if none.  */
   cp_parameter_declarator *next;
   /* The decl-specifiers-seq for the parameter.  */
-  tree decl_specifiers;
+  cp_decl_specifier_seq decl_specifiers;
   /* The declarator for the parameter.  */
   cp_declarator *declarator;
   /* The default-argument expression, or NULL_TREE, if none.  */
@@ -3735,10 +3798,10 @@ extern tree push_library_fn                     (tree, tree);
 extern tree push_void_library_fn               (tree, tree);
 extern tree push_throw_library_fn              (tree, tree);
 extern int init_type_desc                      (void);
-extern tree check_tag_decl                     (tree);
-extern tree shadow_tag                         (tree);
-extern tree groktypename                       (tree, const cp_declarator *);
-extern tree start_decl                         (const cp_declarator *, tree, int, tree, tree);
+extern tree check_tag_decl                     (cp_decl_specifier_seq *);
+extern tree shadow_tag                         (cp_decl_specifier_seq *);
+extern tree groktypename                       (cp_decl_specifier_seq *, const cp_declarator *);
+extern tree start_decl                         (const cp_declarator *, cp_decl_specifier_seq *, int, tree, tree);
 extern void start_decl_1                       (tree);
 extern void cp_finish_decl                     (tree, tree, tree, int);
 extern void finish_decl                                (tree, tree, tree);
@@ -3759,11 +3822,11 @@ extern tree start_enum                          (tree);
 extern void finish_enum                                (tree);
 extern void build_enumerator                   (tree, tree, tree);
 extern void start_preparsed_function            (tree, tree, int);
-extern int start_function                      (tree, const cp_declarator *, tree);
+extern int start_function                      (cp_decl_specifier_seq *, const cp_declarator *, tree);
 extern tree begin_function_body                        (void);
 extern void finish_function_body               (tree);
 extern tree finish_function                    (int);
-extern tree start_method                       (tree, const cp_declarator *, tree);
+extern tree start_method                       (cp_decl_specifier_seq *, const cp_declarator *, tree);
 extern tree finish_method                      (tree);
 extern void maybe_register_incomplete_var       (tree);
 extern void complete_vars                      (tree);
@@ -3804,7 +3867,6 @@ extern bool have_extern_spec;
 /* in decl2.c */
 extern bool check_java_method (tree);
 extern int grok_method_quals (tree, tree, tree);
-extern void grok_x_components (tree);
 extern void maybe_retrofit_in_chrg (tree);
 extern void maybe_make_one_only        (tree);
 extern void grokclassfn        (tree, tree, enum overload_flags, tree);
@@ -3812,8 +3874,8 @@ 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 *, tree, tree, tree, tree);
-extern tree grokbitfield (const cp_declarator *, tree, tree);
+extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, tree, tree, tree);
+extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, tree);
 extern tree groktypefield                      (tree, tree);
 extern void cplus_decl_attributes (tree *, tree, int);
 extern void finish_anon_union (tree);
@@ -4157,7 +4219,6 @@ extern tree finish_template_type_parm           (tree, tree);
 extern tree finish_template_template_parm       (tree, tree);
 extern tree begin_class_definition              (tree);
 extern void finish_default_args                 (void);
-extern tree finish_member_class_template        (tree);
 extern void finish_template_decl                (tree);
 extern tree finish_template_type                (tree, tree, int);
 extern tree finish_base_specifier               (tree, tree, bool);
index 66f6b36..e986cb7 100644 (file)
@@ -39,7 +39,6 @@ Boston, MA 02111-1307, USA.  */
 #include "cp-tree.h"
 #include "tree-inline.h"
 #include "decl.h"
-#include "lex.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
@@ -53,7 +52,7 @@ Boston, MA 02111-1307, USA.  */
 #include "timevar.h"
 #include "tree-flow.h"
 
-static tree grokparms (const cp_parameter_declarator *, tree *);
+static tree grokparms (cp_parameter_declarator *, tree *);
 static const char *redeclaration_error_message (tree, tree);
 
 static int decl_jump_unsafe (tree);
@@ -65,7 +64,7 @@ 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, RID_BIT_TYPE *, 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 *,
@@ -242,11 +241,6 @@ enum deprecated_states {
 
 static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
 
-/* Set by add_implicitly_declared_members() to keep those members from
-   being flagged as deprecated or reported as using deprecated
-   types.  */
-int adding_implicit_members = 0;
-
 /* True if a declaration with an `extern' linkage specifier is being
    processed.  */
 bool have_extern_spec;
@@ -3410,13 +3404,10 @@ fixup_anonymous_aggr (tree t)
    Returns the type declared; or NULL_TREE if none.  */
 
 tree
-check_tag_decl (tree declspecs)
+check_tag_decl (cp_decl_specifier_seq *declspecs)
 {
-  int found_type = 0;
-  int saw_friend = 0;
-  int saw_typedef = 0;
-  tree ob_modifier = NULL_TREE;
-  tree link;
+  int saw_friend = declspecs->specs[(int)ds_friend] != 0;
+  int saw_typedef = declspecs->specs[(int)ds_typedef] != 0;
   /* If a class, struct, or enum type is declared by the DECLSPECS
      (i.e, if a class-specifier, enum-specifier, or non-typename
      elaborated-type-specifier appears in the DECLSPECS),
@@ -3424,59 +3415,23 @@ check_tag_decl (tree declspecs)
   tree declared_type = NULL_TREE;
   bool error_p = false;
 
-  for (link = declspecs; link; link = TREE_CHAIN (link))
-    {
-      tree value = TREE_VALUE (link);
-
-      if (TYPE_P (value) || TREE_CODE (value) == TYPE_DECL
-         || (TREE_CODE (value) == IDENTIFIER_NODE
-             && is_typename_at_global_scope (value)))
-       {
-         ++found_type;
-
-         if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
-           {
-             if (! in_system_header)
-               pedwarn ("redeclaration of C++ built-in type `%T'", value);
-             return NULL_TREE;
-           }
-
-         if (TYPE_P (value)
-             && ((TREE_CODE (value) != TYPENAME_TYPE && IS_AGGR_TYPE (value))
-                 || TREE_CODE (value) == ENUMERAL_TYPE))
-           {
-             my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
-             declared_type = value;
-           }
-       }
-      else if (value == ridpointers[(int) RID_TYPEDEF])
-        saw_typedef = 1;
-      else if (value == ridpointers[(int) RID_FRIEND])
-       {
-         if (current_class_type == NULL_TREE
-             || current_scope () != current_class_type)
-           ob_modifier = value;
-         else
-           saw_friend = 1;
-       }
-      else if (value == ridpointers[(int) RID_STATIC]
-              || value == ridpointers[(int) RID_EXTERN]
-              || value == ridpointers[(int) RID_AUTO]
-              || value == ridpointers[(int) RID_REGISTER]
-              || value == ridpointers[(int) RID_INLINE]
-              || value == ridpointers[(int) RID_VIRTUAL]
-              || value == ridpointers[(int) RID_CONST]
-              || value == ridpointers[(int) RID_VOLATILE]
-              || value == ridpointers[(int) RID_EXPLICIT]
-              || value == ridpointers[(int) RID_THREAD])
-       ob_modifier = value;
-      else if (value == error_mark_node)
-       error_p = true;
-    }
-
-  if (found_type > 1)
+  if (declspecs->multiple_types_p)
     error ("multiple types in one declaration");
+  else if (declspecs->redefined_builtin_type)
+    {
+      if (!in_system_header)
+       pedwarn ("redeclaration of C++ built-in type",
+                declspecs->redefined_builtin_type);
+      return NULL_TREE;
+    }
 
+  if (TYPE_P (declspecs->type)
+      && ((TREE_CODE (declspecs->type) != TYPENAME_TYPE 
+          && IS_AGGR_TYPE (declspecs->type))
+         || TREE_CODE (declspecs->type) == ENUMERAL_TYPE))
+    declared_type = declspecs->type;
+  else if (declspecs->type == error_mark_node)
+    error_p = true;
   if (declared_type == NULL_TREE && ! saw_friend && !error_p)
     pedwarn ("declaration does not declare anything");
   /* Check for an anonymous union.  */
@@ -3512,19 +3467,28 @@ check_tag_decl (tree declspecs)
        pedwarn ("ISO C++ prohibits anonymous structs");
     }
 
-  else if (ob_modifier)
+  else
     {
-      if (ob_modifier == ridpointers[(int) RID_INLINE]
-         || ob_modifier == ridpointers[(int) RID_VIRTUAL])
-       error ("`%D' can only be specified for functions", ob_modifier);
-      else if (ob_modifier == ridpointers[(int) RID_FRIEND])
-       error ("`%D' can only be specified inside a class", ob_modifier);
-      else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
-       error ("`%D' can only be specified for constructors",
-                 ob_modifier);
-      else
-       error ("`%D' can only be specified for objects and functions",
-                 ob_modifier);
+      if (declspecs->specs[(int)ds_inline]
+         || declspecs->specs[(int)ds_virtual])
+       error ("`%s' can only be specified for functions", 
+              declspecs->specs[(int)ds_inline] 
+              ? "inline" : "virtual");
+      else if (saw_friend
+              && (!current_class_type 
+                  || current_scope () != current_class_type))
+       error ("`friend' can only be specified inside a class");
+      else if (declspecs->specs[(int)ds_explicit])
+       error ("`explicit' can only be specified for constructors");
+      else if (declspecs->storage_class)
+       error ("a storage class can only be specified for objects "
+              "and functions");
+      else if (declspecs->specs[(int)ds_const]
+              || declspecs->specs[(int)ds_volatile]
+              || declspecs->specs[(int)ds_restrict]
+              || declspecs->specs[(int)ds_thread])
+       error ("qualifiers can only be specified for objects "
+              "and functions");
     }
 
   return declared_type;
@@ -3544,7 +3508,7 @@ check_tag_decl (tree declspecs)
    Returns the TYPE declared -- or NULL_TREE if none.  */
 
 tree
-shadow_tag (tree declspecs)
+shadow_tag (cp_decl_specifier_seq *declspecs)
 {
   tree t = check_tag_decl (declspecs);
 
@@ -3576,12 +3540,14 @@ shadow_tag (tree declspecs)
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
-groktypename (tree type_specifiers, const cp_declarator *declarator)
+groktypename (cp_decl_specifier_seq *type_specifiers, 
+             const cp_declarator *declarator)
 {
-  tree specs, attrs;
+  tree attrs;
   tree type;
-  split_specs_attrs (type_specifiers, &specs, &attrs);
-  type = grokdeclarator (declarator, specs, TYPENAME, 0, &attrs);
+  attrs = type_specifiers->attributes;
+  type_specifiers->attributes = NULL_TREE;
+  type = grokdeclarator (declarator, type_specifiers, TYPENAME, 0, &attrs);
   if (attrs)
     cplus_decl_attributes (&type, attrs, 0);
   return type;
@@ -3604,7 +3570,7 @@ groktypename (tree type_specifiers, const cp_declarator *declarator)
 
 tree
 start_decl (const cp_declarator *declarator, 
-            tree declspecs, 
+           cp_decl_specifier_seq *declspecs,
             int initialized, 
             tree attributes, 
             tree prefix_attributes)
@@ -3616,8 +3582,7 @@ start_decl (const cp_declarator *declarator,
   /* This should only be done once on the top most decl.  */
   if (have_extern_spec)
     {
-      declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
-                            declspecs);
+      declspecs->storage_class = sc_extern;
       have_extern_spec = false;
     }
 
@@ -5758,25 +5723,22 @@ grokfndecl (tree ctype,
 static tree
 grokvardecl (tree type,
              tree name,
-             RID_BIT_TYPE * specbits_in,
+            cp_decl_specifier_seq *declspecs,
              int initialized,
              int constp,
              tree scope)
 {
   tree decl;
-  RID_BIT_TYPE specbits;
 
   my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE, 
                      20020808);
 
-  specbits = *specbits_in;
-
   /* Compute the scope in which to place the variable.  */
   if (!scope)
     {
       /* An explicit "extern" specifier indicates a namespace-scope
         variable.  */
-      if (RIDBIT_SETP (RID_EXTERN, specbits))
+      if (declspecs->storage_class == sc_extern)
        scope = current_namespace;
       else if (!at_function_scope_p ())
        {
@@ -5805,7 +5767,7 @@ grokvardecl (tree type,
   else
     DECL_CONTEXT (decl) = scope;
 
-  if (RIDBIT_SETP (RID_EXTERN, specbits))
+  if (declspecs->storage_class == sc_extern)
     {
       DECL_THIS_EXTERN (decl) = 1;
       DECL_EXTERNAL (decl) = !initialized;
@@ -5823,18 +5785,18 @@ grokvardecl (tree type,
      (perhaps tentative), and absence of `static' makes it public.  */
   else if (toplevel_bindings_p ())
     {
-      TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits)
+      TREE_PUBLIC (decl) = (declspecs->storage_class != sc_static
                            && (DECL_THIS_EXTERN (decl) || ! constp));
       TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
     }
   /* Not at top level, only `static' makes a static definition.  */
   else
     {
-      TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
+      TREE_STATIC (decl) = declspecs->storage_class == sc_static;
       TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
     }
 
-  if (RIDBIT_SETP (RID_THREAD, specbits))
+  if (declspecs->specs[(int)ds_thread])
     {
       if (targetm.have_tls)
        DECL_THREAD_LOCAL (decl) = 1;
@@ -6292,14 +6254,11 @@ check_special_function_return_type (special_function_kind sfk,
 
 tree
 grokdeclarator (const cp_declarator *declarator,
-                tree declspecs,
+               cp_decl_specifier_seq *declspecs,
                 enum decl_context decl_context,
                 int initialized,
                 tree* attrlist)
 {
-  RID_BIT_TYPE specbits;
-  int nclasses = 0;
-  tree spec;
   tree type = NULL_TREE;
   int longlong = 0;
   int type_quals;
@@ -6307,7 +6266,6 @@ grokdeclarator (const cp_declarator *declarator,
   int explicit_int = 0;
   int explicit_char = 0;
   int defaulted_int = 0;
-  int extern_langp = 0;
   tree dependant_name = NULL_TREE;
   
   tree typedef_decl = NULL_TREE;
@@ -6348,8 +6306,8 @@ grokdeclarator (const cp_declarator *declarator,
      this value will be NULL_TREE, even if the entity is located at
      namespace scope.  */ 
   tree in_namespace = NULL_TREE;
+  cp_decl_spec ds;
 
-  RIDBIT_RESET_ALL (specbits);
   if (decl_context == FUNCDEF)
     funcdef_flag = 1, decl_context = NORMAL;
   else if (decl_context == MEMFUNCDEF)
@@ -6503,7 +6461,7 @@ grokdeclarator (const cp_declarator *declarator,
 
   if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
       && innermost_code != cdk_function
-      && ! (ctype && declspecs == NULL_TREE))
+      && ! (ctype && !declspecs->any_specifiers_p))
     {
       error ("declaration of `%D' as non-function", dname);
       return void_type_node;
@@ -6535,143 +6493,59 @@ grokdeclarator (const cp_declarator *declarator,
   if (name == NULL)
     name = decl_context == PARM ? "parameter" : "type name";
 
-  /* Look through the decl specs and record which ones appear.
-     Some typespecs are defined as built-in typenames.
-     Others, the ones that are modifiers of other types,
-     are represented by bits in SPECBITS: set the bits for
-     the modifiers that appear.  Storage class keywords are also in SPECBITS.
-
-     If there is a typedef name or a type, store the type in TYPE.
-     This includes builtin typedefs such as `int'.
-
-     Set EXPLICIT_INT if the type is `int' or `char' and did not
-     come from a user typedef.
-
-     Set LONGLONG if `long' is mentioned twice.
-
-     For C++, constructors and destructors have their own fast treatment.  */
-
-  for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+  /* If there were multiple types specified in the decl-specifier-seq,
+     issue an error message.  */
+  if (declspecs->multiple_types_p)
+    error ("two or more data types in declaration of `%s'", name);
+  /* Extract the basic type from the decl-specifier-seq.  */
+  type = declspecs->type;
+  if (type == error_mark_node)
+    type = NULL_TREE;
+  /* If the entire declaration is itself tagged as deprecated then
+     suppress reports of deprecated items.  */
+  if (type && TREE_DEPRECATED (type)
+      && deprecated_state != DEPRECATED_SUPPRESS)
+    warn_deprecated_use (type);
+  if (type && TREE_CODE (type) == TYPE_DECL)
     {
-      int i;
-      tree id;
-
-      /* Certain parse errors slip through.  For example,
-        `int class;' is not caught by the parser. Try
-        weakly to recover here.  */
-      if (TREE_CODE (spec) != TREE_LIST)
-       return 0;
-
-      id = TREE_VALUE (spec);
-
-      /* If the entire declaration is itself tagged as deprecated then
-         suppress reports of deprecated items.  */
-      if (!adding_implicit_members && id && TREE_DEPRECATED (id))
-        {
-         if (deprecated_state != DEPRECATED_SUPPRESS)
-           warn_deprecated_use (id);
-        }
-
-      if (TREE_CODE (id) == IDENTIFIER_NODE)
-       {
-         if (id == ridpointers[(int) RID_INT]
-             || id == ridpointers[(int) RID_CHAR]
-             || id == ridpointers[(int) RID_BOOL]
-             || id == ridpointers[(int) RID_WCHAR])
-           {
-             if (type)
-               {
-                 if (id == ridpointers[(int) RID_BOOL])
-                   error ("`bool' is now a keyword");
-                 else
-                   error ("extraneous `%T' ignored", id);
-               }
-             else
-               {
-                 if (id == ridpointers[(int) RID_INT])
-                   explicit_int = 1;
-                 else if (id == ridpointers[(int) RID_CHAR])
-                   explicit_char = 1;
-                 type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
-               }
-             goto found;
-           }
-         /* C++ aggregate types.  */
-         if (IDENTIFIER_HAS_TYPE_VALUE (id))
-           {
-             if (type)
-               error ("multiple declarations `%T' and `%T'", type, id);
-             else
-               type = IDENTIFIER_TYPE_VALUE (id);
-             goto found;
-           }
-
-         for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
-           {
-             if (ridpointers[i] == id)
-               {
-                 if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
-                   {
-                     if (pedantic && ! in_system_header && warn_long_long)
-                       pedwarn ("ISO C++ does not support `long long'");
-                     if (longlong)
-                       error ("`long long long' is too long for GCC");
-                     else
-                       longlong = 1;
-                   }
-                 else if (RIDBIT_SETP (i, specbits))
-                   pedwarn ("duplicate `%E'", id);
-
-                 /* Diagnose "__thread extern" or "__thread static".  */
-                 if (RIDBIT_SETP (RID_THREAD, specbits))
-                   {
-                     if (i == (int)RID_EXTERN)
-                       error ("`__thread' before `extern'");
-                     else if (i == (int)RID_STATIC)
-                       error ("`__thread' before `static'");
-                   }
-
-                 if (i == (int)RID_EXTERN
-                     && TREE_PURPOSE (spec) == error_mark_node)
-                   /* This extern was part of a language linkage.  */
-                   extern_langp = 1;
+      typedef_decl = type;
+      type = TREE_TYPE (typedef_decl);
+    }
+  /* No type at all: default to `int', and set DEFAULTED_INT
+     because it was not a user-defined typedef.  */
+  if (type == NULL_TREE
+      && (declspecs->specs[(int)ds_signed]
+         || declspecs->specs[(int)ds_unsigned]
+         || declspecs->specs[(int)ds_long]
+         || declspecs->specs[(int)ds_short]))
+    {
+      /* These imply 'int'.  */
+      type = integer_type_node;
+      defaulted_int = 1;
+    }
+  /* Gather flags.  */
+  explicit_int = declspecs->explicit_int_p;
+  explicit_char = declspecs->explicit_char_p;
 
-                 RIDBIT_SET (i, specbits);
-                 goto found;
-               }
-           }
-       }
-      else if (TREE_CODE (id) == TYPE_DECL)
-       {
-         if (type)
-           error ("multiple declarations `%T' and `%T'", type,
-                     TREE_TYPE (id));
-         else
-           {
-             type = TREE_TYPE (id);
-             TREE_VALUE (spec) = type;
-             typedef_decl = id;
-           }
-         goto found;
-       }
-      if (type)
-       error ("two or more data types in declaration of `%s'", name);
-      else if (TREE_CODE (id) == IDENTIFIER_NODE)
+  /* Check for repeated decl-specifiers.  */
+  for (ds = ds_first; ds != ds_last; ++ds) 
+    {
+      unsigned count = declspecs->specs[(int)ds];
+      if (count < 2)
+       continue;
+      /* The "long" specifier is a special case because of 
+        "long long".  */
+      if (ds == ds_long)
        {
-         tree t = lookup_name (id, 1);
-         if (!t || TREE_CODE (t) != TYPE_DECL)
-           error ("`%E' fails to be a typedef or built in type", id);
+         if (count > 2)
+           error ("`long long long' is too long for GCC");
+         else if (pedantic && !in_system_header && warn_long_long)
+           pedwarn ("ISO C++ does not support `long long'");
          else
-           {
-             type = TREE_TYPE (t);
-             typedef_decl = t;
-           }
-       }
-      else if (id != error_mark_node)
-       /* Can't change CLASS nodes into RECORD nodes here!  */
-       type = id;
-
-    found: ;
+           longlong = 1;
+       } 
+      else if (declspecs->specs[(int)ds] > 1)
+       error ("duplicate decl-specifier");
     }
 
 #if 0
@@ -6681,19 +6555,6 @@ grokdeclarator (const cp_declarator *declarator,
 #endif
   typedef_type = type;
 
-  /* No type at all: default to `int', and set DEFAULTED_INT
-     because it was not a user-defined typedef.  */
-
-  if (type == NULL_TREE
-      && (RIDBIT_SETP (RID_SIGNED, specbits)
-         || RIDBIT_SETP (RID_UNSIGNED, specbits)
-         || RIDBIT_SETP (RID_LONG, specbits)
-         || RIDBIT_SETP (RID_SHORT, specbits)))
-    {
-      /* These imply 'int'.  */
-      type = integer_type_node;
-      defaulted_int = 1;
-    }
 
   if (sfk != sfk_none)
     type = check_special_function_return_type (sfk, type,
@@ -6731,21 +6592,20 @@ grokdeclarator (const cp_declarator *declarator,
      and check for invalid combinations.  */
 
   /* Long double is a special combination.  */
-
-  if (RIDBIT_SETP (RID_LONG, specbits)
+  if (declspecs->specs[(int)ds_long]
       && TYPE_MAIN_VARIANT (type) == double_type_node)
     {
-      RIDBIT_RESET (RID_LONG, specbits);
+      declspecs->specs[(int)ds_long] = 0;
       type = build_qualified_type (long_double_type_node,
                                   cp_type_quals (type));
     }
 
   /* Check all other uses of type modifiers.  */
 
-  if (RIDBIT_SETP (RID_UNSIGNED, specbits)
-      || RIDBIT_SETP (RID_SIGNED, specbits)
-      || RIDBIT_SETP (RID_LONG, specbits)
-      || RIDBIT_SETP (RID_SHORT, specbits))
+  if (declspecs->specs[(int)ds_unsigned]
+      || declspecs->specs[(int)ds_signed]
+      || declspecs->specs[(int)ds_long]
+      || declspecs->specs[(int)ds_short])
     {
       int ok = 0;
 
@@ -6753,19 +6613,19 @@ grokdeclarator (const cp_declarator *declarator,
        error ("short, signed or unsigned invalid for `%s'", name);
       else if (TREE_CODE (type) != INTEGER_TYPE)
        error ("long, short, signed or unsigned invalid for `%s'", name);
-      else if (RIDBIT_SETP (RID_LONG, specbits)
-              && RIDBIT_SETP (RID_SHORT, specbits))
+      else if (declspecs->specs[(int)ds_long]
+              && declspecs->specs[(int)ds_short])
        error ("long and short specified together for `%s'", name);
-      else if ((RIDBIT_SETP (RID_LONG, specbits)
-               || RIDBIT_SETP (RID_SHORT, specbits))
+      else if ((declspecs->specs[(int)ds_long]
+               || declspecs->specs[(int)ds_short])
               && explicit_char)
        error ("long or short specified with char for `%s'", name);
-      else if ((RIDBIT_SETP (RID_LONG, specbits)
-               || RIDBIT_SETP (RID_SHORT, specbits))
+      else if ((declspecs->specs[(int)ds_long]
+               || declspecs->specs[(int)ds_short])
               && TREE_CODE (type) == REAL_TYPE)
        error ("long or short specified with floating type for `%s'", name);
-      else if (RIDBIT_SETP (RID_SIGNED, specbits)
-              && RIDBIT_SETP (RID_UNSIGNED, specbits))
+      else if (declspecs->specs[(int)ds_signed]
+              && declspecs->specs[(int)ds_unsigned])
        error ("signed and unsigned given together for `%s'", name);
       else
        {
@@ -6782,24 +6642,24 @@ grokdeclarator (const cp_declarator *declarator,
       /* Discard the type modifiers if they are invalid.  */
       if (! ok)
        {
-         RIDBIT_RESET (RID_UNSIGNED, specbits);
-         RIDBIT_RESET (RID_SIGNED, specbits);
-         RIDBIT_RESET (RID_LONG, specbits);
-         RIDBIT_RESET (RID_SHORT, specbits);
+         declspecs->specs[(int)ds_unsigned] = 0;
+         declspecs->specs[(int)ds_signed] = 0;
+         declspecs->specs[(int)ds_long] = 0;
+         declspecs->specs[(int)ds_short] = 0;
          longlong = 0;
        }
     }
 
-  if (RIDBIT_SETP (RID_COMPLEX, specbits)
+  if (declspecs->specs[(int)ds_complex]
       && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
     {
       error ("complex invalid for `%s'", name);
-      RIDBIT_RESET (RID_COMPLEX, specbits);
+      declspecs->specs[(int)ds_complex] = 0;
     }
 
   /* Decide whether an integer type is signed or not.
      Optionally treat bitfields as signed by default.  */
-  if (RIDBIT_SETP (RID_UNSIGNED, specbits)
+  if (declspecs->specs[(int)ds_unsigned]
       /* [class.bit]
 
         It is implementation-defined whether a plain (neither
@@ -6809,7 +6669,7 @@ grokdeclarator (const cp_declarator *declarator,
         Naturally, we extend this to long long as well.  Note that
         this does not include wchar_t.  */
       || (bitfield && !flag_signed_bitfields
-         && RIDBIT_NOTSETP (RID_SIGNED, specbits)
+         && !declspecs->specs[(int)ds_signed]
          /* A typedef for plain `int' without `signed' can be
             controlled just like plain `int', but a typedef for
             `signed int' cannot be so controlled.  */
@@ -6821,9 +6681,9 @@ grokdeclarator (const cp_declarator *declarator,
     {
       if (longlong)
        type = long_long_unsigned_type_node;
-      else if (RIDBIT_SETP (RID_LONG, specbits))
+      else if (declspecs->specs[(int)ds_long])
        type = long_unsigned_type_node;
-      else if (RIDBIT_SETP (RID_SHORT, specbits))
+      else if (declspecs->specs[(int)ds_short])
        type = short_unsigned_type_node;
       else if (type == char_type_node)
        type = unsigned_char_type_node;
@@ -6832,17 +6692,17 @@ grokdeclarator (const cp_declarator *declarator,
       else
        type = unsigned_type_node;
     }
-  else if (RIDBIT_SETP (RID_SIGNED, specbits)
+  else if (declspecs->specs[(int)ds_signed]
           && type == char_type_node)
     type = signed_char_type_node;
   else if (longlong)
     type = long_long_integer_type_node;
-  else if (RIDBIT_SETP (RID_LONG, specbits))
+  else if (declspecs->specs[(int)ds_long])
     type = long_integer_type_node;
-  else if (RIDBIT_SETP (RID_SHORT, specbits))
+  else if (declspecs->specs[(int)ds_short])
     type = short_integer_type_node;
 
-  if (RIDBIT_SETP (RID_COMPLEX, specbits))
+  if (declspecs->specs[(int)ds_complex])
     {
       /* If we just have "complex", it is equivalent to
         "complex double", but if any modifiers at all are specified it is
@@ -6850,10 +6710,10 @@ grokdeclarator (const cp_declarator *declarator,
         "complex short int".  */
 
       if (defaulted_int && ! longlong
-         && ! (RIDBIT_SETP (RID_LONG, specbits)
-               || RIDBIT_SETP (RID_SHORT, specbits)
-               || RIDBIT_SETP (RID_SIGNED, specbits)
-               || RIDBIT_SETP (RID_UNSIGNED, specbits)))
+         && ! (declspecs->specs[(int)ds_long]
+               || declspecs->specs[(int)ds_short]
+               || declspecs->specs[(int)ds_signed]
+               || declspecs->specs[(int)ds_unsigned]))
        type = complex_double_type_node;
       else if (type == integer_type_node)
        type = complex_integer_type_node;
@@ -6868,11 +6728,11 @@ grokdeclarator (const cp_declarator *declarator,
     }
 
   type_quals = TYPE_UNQUALIFIED;
-  if (RIDBIT_SETP (RID_CONST, specbits))
+  if (declspecs->specs[(int)ds_const])
     type_quals |= TYPE_QUAL_CONST;
-  if (RIDBIT_SETP (RID_VOLATILE, specbits))
+  if (declspecs->specs[(int)ds_volatile])
     type_quals |= TYPE_QUAL_VOLATILE;
-  if (RIDBIT_SETP (RID_RESTRICT, specbits))
+  if (declspecs->specs[(int)ds_restrict])
     type_quals |= TYPE_QUAL_RESTRICT;
   if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
     error ("qualifiers are not allowed on declaration of `operator %T'",
@@ -6886,13 +6746,11 @@ grokdeclarator (const cp_declarator *declarator,
   type_quals = cp_type_quals (type);
   
   staticp = 0;
-  inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
-  virtualp = !! RIDBIT_SETP (RID_VIRTUAL, specbits);
-  RIDBIT_RESET (RID_VIRTUAL, specbits);
-  explicitp = !! RIDBIT_SETP (RID_EXPLICIT, specbits);
-  RIDBIT_RESET (RID_EXPLICIT, specbits);
+  inlinep = !! declspecs->specs[(int)ds_inline];
+  virtualp = !! declspecs->specs[(int)ds_virtual];
+  explicitp = !! declspecs->specs[(int)ds_explicit];
 
-  if (RIDBIT_SETP (RID_STATIC, specbits))
+  if (declspecs->storage_class == sc_static)
     staticp = 1 + (decl_context == FIELD);
 
   if (virtualp && staticp == 2)
@@ -6901,34 +6759,23 @@ grokdeclarator (const cp_declarator *declarator,
                dname);
       staticp = 0;
     }
-  friendp = !! RIDBIT_SETP (RID_FRIEND, specbits);
-  RIDBIT_RESET (RID_FRIEND, specbits);
+  friendp = !! declspecs->specs[(int)ds_friend];
 
   if (dependant_name && !friendp)
     {
       error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
       return void_type_node;
     }
-  
-  /* Warn if two storage classes are given. Default to `auto'.  */
 
-  if (RIDBIT_ANY_SET (specbits))
+  /* Issue errors about use of storage classes for parameters.  */
+  if (decl_context == PARM)
     {
-      if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
-      if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
-      if (RIDBIT_SETP (RID_THREAD, specbits)) nclasses++;
-      if (decl_context == PARM && nclasses > 0)
+      if (declspecs->specs[(int)ds_typedef])
+       error ("typedef declaration invalid in parameter declaration");
+      else if (declspecs->storage_class == sc_static
+              || declspecs->storage_class == sc_extern
+              || declspecs->specs[(int)ds_thread])
        error ("storage class specifiers invalid in parameter declarations");
-      if (RIDBIT_SETP (RID_TYPEDEF, specbits))
-       {
-         if (decl_context == PARM)
-           error ("typedef declaration invalid in parameter declaration");
-         nclasses++;
-       }
-      if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++;
-      if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++;
-      if (!nclasses && !friendp && extern_langp)
-       nclasses++;
     }
 
   /* Give error if `virtual' is used outside of class declaration.  */
@@ -6941,33 +6788,27 @@ grokdeclarator (const cp_declarator *declarator,
 
   /* Static anonymous unions are dealt with here.  */
   if (staticp && decl_context == TYPENAME
-      && TREE_CODE (declspecs) == TREE_LIST
-      && ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
+      && declspecs->type
+      && ANON_AGGR_TYPE_P (declspecs->type))
     decl_context = FIELD;
 
   /* Warn about storage classes that are invalid for certain
      kinds of declarations (parameters, typenames, etc.).  */
-
-  /* "static __thread" and "extern __thread" are allowed.  */
-  if (nclasses == 2
-      && RIDBIT_SETP (RID_THREAD, specbits)
-      && (RIDBIT_SETP (RID_EXTERN, specbits)
-         || RIDBIT_SETP (RID_STATIC, specbits)))
-    nclasses = 1;
-    
-  if (nclasses > 1)
+  if (declspecs->multiple_storage_classes_p)
     error ("multiple storage classes in declaration of `%s'", name);
-  else if (decl_context != NORMAL && nclasses > 0)
+  else if (decl_context != NORMAL 
+          && declspecs->storage_class != sc_none
+          && declspecs->storage_class != sc_mutable)
     {
       if ((decl_context == PARM || decl_context == CATCHPARM)
-         && (RIDBIT_SETP (RID_REGISTER, specbits)
-             || RIDBIT_SETP (RID_AUTO, specbits)))
+         && (declspecs->storage_class == sc_register
+             || declspecs->storage_class == sc_auto))
        ;
-      else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
+      else if (declspecs->specs[(int)ds_typedef])
        ;
       else if (decl_context == FIELD
               /* C++ allows static class elements.  */
-              && RIDBIT_SETP (RID_STATIC, specbits))
+              && declspecs->storage_class == sc_static)
        /* C++ also allows inlines and signed and unsigned elements,
           but in those cases we don't come in here.  */
        ;
@@ -7005,13 +6846,15 @@ grokdeclarator (const cp_declarator *declarator,
              else
                error ("storage class specified for typename");
            }
-         RIDBIT_RESET (RID_REGISTER, specbits);
-         RIDBIT_RESET (RID_AUTO, specbits);
-         RIDBIT_RESET (RID_EXTERN, specbits);
-         RIDBIT_RESET (RID_THREAD, specbits);
+         if (declspecs->storage_class == sc_register
+             || declspecs->storage_class == sc_auto
+             || declspecs->storage_class == sc_extern
+             || declspecs->specs[(int)ds_thread])
+           declspecs->storage_class = sc_none;
        }
     }
-  else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
+  else if (declspecs->storage_class == sc_extern && initialized 
+          && !funcdef_flag)
     {
       if (toplevel_bindings_p ())
        {
@@ -7023,24 +6866,24 @@ grokdeclarator (const cp_declarator *declarator,
       else
        error ("`%s' has both `extern' and initializer", name);
     }
-  else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag
+  else if (declspecs->storage_class == sc_extern && funcdef_flag
           && ! toplevel_bindings_p ())
     error ("nested function `%s' declared `extern'", name);
   else if (toplevel_bindings_p ())
     {
-      if (RIDBIT_SETP (RID_AUTO, specbits))
+      if (declspecs->storage_class == sc_auto)
        error ("top-level declaration of `%s' specifies `auto'", name);
     }
-  else if (RIDBIT_SETP (RID_THREAD, specbits)
-          && !RIDBIT_SETP (RID_EXTERN, specbits)
-          && !RIDBIT_SETP (RID_STATIC, specbits))
+  else if (declspecs->specs[(int)ds_thread]
+          && declspecs->storage_class != sc_extern
+          && declspecs->storage_class != sc_static)
     {
       error ("function-scope `%s' implicitly auto and declared `__thread'",
             name);
-      RIDBIT_RESET (RID_THREAD, specbits);
+      declspecs->specs[(int)ds_thread] = 0;
     }
 
-  if (nclasses > 0 && friendp)
+  if (declspecs->storage_class && friendp)
     error ("storage class specifiers invalid in friend function declarations");
 
   if (!id_declarator)
@@ -7211,14 +7054,6 @@ grokdeclarator (const cp_declarator *declarator,
                                TREE_VALUE (quals));
                        quals = NULL_TREE;
                      }
-                   {
-                     RID_BIT_TYPE tmp_bits;
-                     memcpy (&tmp_bits, &specbits, sizeof (RID_BIT_TYPE));
-                     RIDBIT_RESET (RID_INLINE, tmp_bits);
-                     RIDBIT_RESET (RID_STATIC, tmp_bits);
-                     if (RIDBIT_ANY_SET (tmp_bits))
-                       error ("return value type specifier for constructor ignored");
-                   }
                    if (decl_context == FIELD)
                      {
                        if (! member_function_or_else (ctype,
@@ -7241,7 +7076,6 @@ grokdeclarator (const cp_declarator *declarator,
                  {
                    /* Cannot be both friend and virtual.  */
                    error ("virtual functions cannot be friends");
-                   RIDBIT_RESET (RID_FRIEND, specbits);
                    friendp = 0;
                  }
                if (decl_context == NORMAL)
@@ -7453,7 +7287,7 @@ grokdeclarator (const cp_declarator *declarator,
              return error_mark_node;
            }
        }
-      else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
+      else if (declspecs->specs[(int)ds_typedef]
               || COMPLETE_TYPE_P (complete_type (ctype)))
        {
          /* Have to move this code elsewhere in this function.
@@ -7516,38 +7350,38 @@ grokdeclarator (const cp_declarator *declarator,
       explicitp = 0;
     }
 
-  if (RIDBIT_SETP (RID_MUTABLE, specbits))
+  if (declspecs->storage_class == sc_mutable)
     {
       if (decl_context != FIELD || friendp)
         {
          error ("non-member `%s' cannot be declared `mutable'", name);
-          RIDBIT_RESET (RID_MUTABLE, specbits);
+         declspecs->storage_class = sc_none;
         }
-      else if (decl_context == TYPENAME || RIDBIT_SETP (RID_TYPEDEF, specbits))
+      else if (decl_context == TYPENAME || declspecs->specs[(int)ds_typedef])
        {
          error ("non-object member `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
+         declspecs->storage_class = sc_none;
        }
       else if (TREE_CODE (type) == FUNCTION_TYPE
                || TREE_CODE (type) == METHOD_TYPE)
         {
          error ("function `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
+         declspecs->storage_class = sc_none;
         }
       else if (staticp)
        {
          error ("static `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
+         declspecs->storage_class = sc_none;
        }
       else if (type_quals & TYPE_QUAL_CONST)
        {
          error ("const `%s' cannot be declared `mutable'", name);
-         RIDBIT_RESET (RID_MUTABLE, specbits);
+         declspecs->storage_class = sc_none;
        }
     }
 
   /* If this is declaring a typedef name, return a TYPE_DECL.  */
-  if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
+  if (declspecs->specs[(int)ds_typedef] && decl_context != TYPENAME)
     {
       tree decl;
 
@@ -7622,7 +7456,7 @@ grokdeclarator (const cp_declarator *declarator,
            grok_method_quals (ctype, decl, quals);
        }
 
-      if (RIDBIT_SETP (RID_SIGNED, specbits)
+      if (declspecs->specs[(int)ds_signed]
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
 
@@ -7944,8 +7778,8 @@ grokdeclarator (const cp_declarator *declarator,
            if (current_class_type
                && TYPE_NAME (current_class_type)
                && IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
-               && declspecs && TREE_VALUE (declspecs)
-               && TREE_TYPE (TREE_VALUE (declspecs)) == type)
+               && declspecs->type
+               && declspecs->type == type)
              error ("  in instantiation of template `%T'",
                        current_class_type);
 
@@ -8039,10 +7873,10 @@ grokdeclarator (const cp_declarator *declarator,
              {
                decl = build_decl (FIELD_DECL, unqualified_id, type);
                DECL_NONADDRESSABLE_P (decl) = bitfield;
-               if (RIDBIT_SETP (RID_MUTABLE, specbits))
+               if (declspecs->storage_class == sc_mutable)
                  {
                    DECL_MUTABLE_P (decl) = 1;
-                   RIDBIT_RESET (RID_MUTABLE, specbits);
+                   declspecs->storage_class = sc_none;
                  }
              }
 
@@ -8064,25 +7898,25 @@ grokdeclarator (const cp_declarator *declarator,
        else
          original_name = unqualified_id;
 
-       if (RIDBIT_SETP (RID_AUTO, specbits))
+       if (declspecs->storage_class == sc_auto)
          error ("storage class `auto' invalid for function `%s'", name);
-       else if (RIDBIT_SETP (RID_REGISTER, specbits))
+       else if (declspecs->storage_class == sc_register)
          error ("storage class `register' invalid for function `%s'", name);
-       else if (RIDBIT_SETP (RID_THREAD, specbits))
+       else if (declspecs->specs[(int)ds_thread])
          error ("storage class `__thread' invalid for function `%s'", name);
 
        /* Function declaration not at top level.
           Storage classes other than `extern' are not allowed
           and `extern' makes no difference.  */
        if (! toplevel_bindings_p ()
-           && (RIDBIT_SETP (RID_STATIC, specbits)
-               || RIDBIT_SETP (RID_INLINE, specbits))
+           && (declspecs->storage_class == sc_static
+               || declspecs->specs[(int)ds_inline])
            && pedantic)
          {
-           if (RIDBIT_SETP (RID_STATIC, specbits))
-             pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
+           if (declspecs->storage_class == sc_static)
+             pedwarn ("`static' specified invalid for function `%s' declared out of global scope", name);
            else
-             pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
+             pedwarn ("`inline' specifier invalid for function `%s' declared out of global scope", name);
          }
 
        if (ctype == NULL_TREE)
@@ -8101,8 +7935,8 @@ grokdeclarator (const cp_declarator *declarator,
 
        /* Record presence of `static'.  */
        publicp = (ctype != NULL_TREE
-                  || RIDBIT_SETP (RID_EXTERN, specbits)
-                  || !RIDBIT_SETP (RID_STATIC, specbits));
+                  || declspecs->storage_class == sc_extern
+                  || declspecs->storage_class != sc_static);
 
        decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
                           virtualp, flags, quals, raises,
@@ -8133,7 +7967,7 @@ grokdeclarator (const cp_declarator *declarator,
            if (invalid_static)
              {
                staticp = 0;
-               RIDBIT_RESET (RID_STATIC, specbits);
+               declspecs->storage_class = sc_none;
              }
          }
       }
@@ -8142,7 +7976,8 @@ grokdeclarator (const cp_declarator *declarator,
        /* It's a variable.  */
 
        /* An uninitialized decl with `extern' is a reference.  */
-       decl = grokvardecl (type, unqualified_id, &specbits,
+       decl = grokvardecl (type, unqualified_id, 
+                           declspecs,
                            initialized,
                            (type_quals & TYPE_QUAL_CONST) != 0,
                            ctype ? ctype : in_namespace);
@@ -8156,34 +7991,30 @@ grokdeclarator (const cp_declarator *declarator,
              {
                 pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
                staticp = 0;
-               RIDBIT_RESET (RID_STATIC, specbits);
+               declspecs->storage_class = sc_none;
              }
-           if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
+           if (declspecs->storage_class == sc_register && TREE_STATIC (decl))
              {
                error ("static member `%D' declared `register'", decl);
-               RIDBIT_RESET (RID_REGISTER, specbits);
+               declspecs->storage_class = sc_none;
              }
-           if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
+           if (declspecs->storage_class == sc_extern && pedantic)
              {
                pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
                            decl);
-               RIDBIT_RESET (RID_EXTERN, specbits);
+               declspecs->storage_class = sc_none;
              }
          }
       }
 
-    my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
-
     /* Record `register' declaration for warnings on &
        and in case doing stupid register allocation.  */
 
-    if (RIDBIT_SETP (RID_REGISTER, specbits))
+    if (declspecs->storage_class == sc_register)
       DECL_REGISTER (decl) = 1;
-
-    if (RIDBIT_SETP (RID_EXTERN, specbits))
+    else if (declspecs->storage_class == sc_extern)
       DECL_THIS_EXTERN (decl) = 1;
-
-    if (RIDBIT_SETP (RID_STATIC, specbits))
+    else if (declspecs->storage_class == sc_static)
       DECL_THIS_STATIC (decl) = 1;
 
     /* Record constancy and volatility.  There's no need to do this
@@ -8348,27 +8179,27 @@ check_default_argument (tree decl, tree arg)
    *PARMS is set to the chain of PARM_DECLs created.  */
 
 static tree
-grokparms (const cp_parameter_declarator *first_parm, tree *parms)
+grokparms (cp_parameter_declarator *first_parm, tree *parms)
 {
   tree result = NULL_TREE;
   tree decls = NULL_TREE;
   int ellipsis = !first_parm || first_parm->ellipsis_p;
-  const cp_parameter_declarator *parm;
+  cp_parameter_declarator *parm;
   int any_error = 0;
 
   for (parm = first_parm; parm != NULL; parm = parm->next)
     {
       tree type = NULL_TREE;
-      tree decl_specifiers = parm->decl_specifiers;
       tree init = parm->default_argument;
-      tree specs, attrs;
+      tree attrs;
       tree decl;
 
       if (parm == no_parameters)
         break;
 
-      split_specs_attrs (decl_specifiers, &specs, &attrs);
-      decl = grokdeclarator (parm->declarator, specs,
+      attrs = parm->decl_specifiers.attributes;
+      parm->decl_specifiers.attributes = NULL_TREE;
+      decl = grokdeclarator (parm->declarator, &parm->decl_specifiers,
                             PARM, init != NULL_TREE, &attrs);
       if (! decl || TREE_TYPE (decl) == error_mark_node)
         continue;
@@ -10070,15 +9901,15 @@ start_preparsed_function (tree decl1, tree attrs, int flags)
    yyparse to report a parse error.  */
 
 int
-start_function (tree declspecs, const cp_declarator *declarator,
+start_function (cp_decl_specifier_seq *declspecs, 
+               const cp_declarator *declarator,
                tree attrs)
 {
   tree decl1;
 
   if (have_extern_spec)
     {
-      declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), 
-                            declspecs);
+      declspecs->storage_class = sc_extern;
       /* This should only be done once on the outermost decl.  */
       have_extern_spec = false;
     }
@@ -10598,7 +10429,8 @@ finish_function (int flags)
    CHANGES TO CODE IN `grokfield'.  */
 
 tree
-start_method (tree declspecs, const cp_declarator *declarator, tree attrlist)
+start_method (cp_decl_specifier_seq *declspecs, 
+              const cp_declarator *declarator, tree attrlist)
 {
   tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
                                &attrlist);
index 871d568..fae386e 100644 (file)
@@ -31,7 +31,9 @@ enum decl_context
 };
 
 /* We need this in here to get the decl_context definition.  */
-extern tree grokdeclarator (const cp_declarator *, tree, enum decl_context, int, tree*);
+extern tree grokdeclarator (const cp_declarator *, 
+                           cp_decl_specifier_seq *, 
+                           enum decl_context, int, tree*);
 
 #ifdef DEBUG_CP_BINDING_LEVELS
 /* Purely for debugging purposes.  */
index 80e56ec..10384b3 100644 (file)
@@ -38,7 +38,6 @@ Boston, MA 02111-1307, USA.  */
 #include "flags.h"
 #include "cp-tree.h"
 #include "decl.h"
-#include "lex.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
@@ -157,27 +156,6 @@ grok_method_quals (tree ctype, tree function, tree quals)
   return this_quals;
 }
 
-/* A subroutine of the parser, to handle a component list.  */
-
-void
-grok_x_components (tree specs)
-{
-  tree t;
-
-  specs = strip_attrs (specs);
-
-  check_tag_decl (specs);
-  t = groktypename (specs, /*declarator=*/NULL);
-
-  /* The only case where we need to do anything additional here is an
-     anonymous union field, e.g.: `struct S { union { int i; }; };'.  */
-  if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
-    return;
-
-  fixup_anonymous_aggr (t);
-  finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t)); 
-}
-
 /* Build a PARM_DECL with NAME and TYPE, and set DECL_ARG_TYPE
    appropriately.  */
 
@@ -840,7 +818,8 @@ finish_static_data_member_decl (tree decl, tree init, tree asmspec_tree,
    CHANGES TO CODE IN `start_method'.  */
 
 tree
-grokfield (const cp_declarator *declarator, tree declspecs, 
+grokfield (const cp_declarator *declarator, 
+          cp_decl_specifier_seq *declspecs, 
           tree init, tree asmspec_tree,
            tree attrlist)
 {
@@ -848,7 +827,7 @@ grokfield (const cp_declarator *declarator, tree declspecs,
   const char *asmspec = 0;
   int flags = LOOKUP_ONLYCONVERTING;
 
-  if (declspecs == NULL_TREE
+  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)) 
@@ -1023,7 +1002,8 @@ grokfield (const cp_declarator *declarator, tree declspecs,
    WIDTH is non-NULL for bit fields only, and is an INTEGER_CST node.  */
 
 tree
-grokbitfield (const cp_declarator *declarator, tree declspecs, tree width)
+grokbitfield (const cp_declarator *declarator, 
+             cp_decl_specifier_seq *declspecs, tree width)
 {
   tree value = grokdeclarator (declarator, declspecs, BITFIELD, 0, NULL);
 
index 7152e69..c942269 100644 (file)
@@ -31,7 +31,6 @@ Boston, MA 02111-1307, USA.  */
 #include "tree.h"
 #include "cp-tree.h"
 #include "cpplib.h"
-#include "lex.h"
 #include "flags.h"
 #include "c-pragma.h"
 #include "toplev.h"
diff --git a/gcc/cp/lex.h b/gcc/cp/lex.h
deleted file mode 100644 (file)
index 35c3503..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* Define constants and variables for communication with the parser.
-   Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   2000, 2001, 2002, 2003 Free Software Foundation, Inc.
-   Hacked by Michael Tiemann (tiemann@cygnus.com)
-   and by Brendan Kehoe (brendan@cygnus.com).
-
-   This file is part of GCC.
-
-   GCC is free software; you can redistribute it and/or modify it
-   under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
-   any later version.
-
-   GCC is distributed in the hope that it will be useful, but
-   WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   General Public License for more details.
-
-   You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
-
-
-#ifndef GCC_CP_LEX_H
-#define GCC_CP_LEX_H
-
-#if 0
-/* Formerly, the RID_* values used as mask bits did not fit into a
-   single 32-bit word.  Now they do, but let's preserve the old logic
-   in case they ever stop fitting again.  -zw, 8 Aug 2000 */
-
-/* The type that can represent all values of RIDBIT.  */
-/* We assume that we can stick in at least 32 bits into this.  */
-typedef struct { unsigned long idata[2]; }
-     RID_BIT_TYPE;
-
-/* Be careful, all these modify N twice.  */
-#define RIDBIT_SETP(N, V) (((unsigned long)1 << (int) ((N)%32))                      \
-                           & (V).idata[(N)/32])
-#define RIDBIT_NOTSETP(NN, VV) (! RIDBIT_SETP (NN, VV))
-#define RIDBIT_SET(N, V) do {                                                \
-                               (V).idata[(N)/32]                             \
-                                 |= ((unsigned long)1 << (int) ((N)%32));    \
-                             } while (0)
-#define RIDBIT_RESET(N, V) do {                                                      \
-                                 (V).idata[(N)/32]                           \
-                                   &= ~((unsigned long)1 << (int) ((N)%32)); \
-                               } while (0)
-#define RIDBIT_RESET_ALL(V) do {                                             \
-                                  (V).idata[0] = 0;                          \
-                                  (V).idata[1] = 0;                          \
-                                } while (0)
-#define RIDBIT_ANY_SET(V) ((V).idata[0] || (V).idata[1])
-#else
-typedef unsigned long RID_BIT_TYPE;    /* assumed at least 32 bits */
-#define RIDBIT_OF(R) ((unsigned long)1 << (int) (R))
-
-#define RIDBIT_SETP(N, V) ((V) & RIDBIT_OF (N))
-#define RIDBIT_NOTSETP(N, V) (! ((V) & RIDBIT_OF (N)))
-#define RIDBIT_ANY_SET(V) (V)
-
-#define RIDBIT_SET(N, V) do { (V) |= RIDBIT_OF (N); } while (0)
-#define RIDBIT_RESET(N, V) do { (V) &= ~RIDBIT_OF (N); } while (0)
-#define RIDBIT_RESET_ALL(V) do { (V) = 0; } while (0)
-#endif
-
-#endif /* ! GCC_CP_LEX_H */
index d86f203..ffaf0c8 100644 (file)
@@ -34,6 +34,7 @@
 #include "diagnostic.h"
 #include "toplev.h"
 #include "output.h"
+#include "target.h"
 
 \f
 /* The lexer.  */
@@ -995,6 +996,19 @@ cp_lexer_stop_debugging (cp_lexer* lexer)
 }
 
 \f
+/* Decl-specifiers.  */
+
+static void clear_decl_specs
+  (cp_decl_specifier_seq *);
+
+/* Set *DECL_SPECS to represent an empty decl-specifier-seq.  */
+
+static void
+clear_decl_specs (cp_decl_specifier_seq *decl_specs)
+{
+  memset (decl_specs, 0, sizeof (cp_decl_specifier_seq));
+}
+
 /* Declarators.  */
 
 /* Nothing other than the parser should be creating declarators;
@@ -1013,7 +1027,7 @@ static cp_declarator *make_pointer_declarator
 static cp_declarator *make_reference_declarator        
   (tree, cp_declarator *);
 static cp_parameter_declarator *make_parameter_declarator 
-  (tree, cp_declarator *, tree);
+  (cp_decl_specifier_seq *, cp_declarator *, tree);
 static cp_declarator *make_ptrmem_declarator   
   (tree, tree, cp_declarator *);
 
@@ -1153,7 +1167,7 @@ cp_parameter_declarator *no_parameters;
    DECLARATOR and DEFAULT_ARGUMENT.  */
 
 cp_parameter_declarator *
-make_parameter_declarator (tree decl_specifiers, 
+make_parameter_declarator (cp_decl_specifier_seq *decl_specifiers, 
                           cp_declarator *declarator,
                           tree default_argument)
 {
@@ -1162,7 +1176,10 @@ make_parameter_declarator (tree decl_specifiers,
   parameter = ((cp_parameter_declarator *) 
               alloc_declarator (sizeof (cp_parameter_declarator)));
   parameter->next = NULL;
-  parameter->decl_specifiers = decl_specifiers;
+  if (decl_specifiers)
+    parameter->decl_specifiers = *decl_specifiers;
+  else
+    clear_decl_specs (&parameter->decl_specifiers);
   parameter->declarator = declarator;
   parameter->default_argument = default_argument;
   parameter->ellipsis_p = false;
@@ -1627,16 +1644,17 @@ static void cp_parser_block_declaration
   (cp_parser *, bool);
 static void cp_parser_simple_declaration
   (cp_parser *, bool);
-static tree cp_parser_decl_specifier_seq
-  (cp_parser *, cp_parser_flags, tree *, int *);
+static void cp_parser_decl_specifier_seq
+  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, int *);
 static tree cp_parser_storage_class_specifier_opt
   (cp_parser *);
 static tree cp_parser_function_specifier_opt
-  (cp_parser *);
+  (cp_parser *, cp_decl_specifier_seq *);
 static tree cp_parser_type_specifier
-  (cp_parser *, cp_parser_flags, bool, bool, int *, bool *);
+  (cp_parser *, cp_parser_flags, cp_decl_specifier_seq *, bool, 
+   int *, bool *);
 static tree cp_parser_simple_type_specifier
-  (cp_parser *, cp_parser_flags, bool);
+  (cp_parser *, cp_decl_specifier_seq *, cp_parser_flags);
 static tree cp_parser_type_name
   (cp_parser *);
 static tree cp_parser_elaborated_type_specifier
@@ -1669,7 +1687,7 @@ static void cp_parser_linkage_specification
 /* Declarators [gram.dcl.decl] */
 
 static tree cp_parser_init_declarator
-  (cp_parser *, tree, tree, bool, bool, int, bool *);
+  (cp_parser *, cp_decl_specifier_seq *, bool, bool, int, bool *);
 static cp_declarator *cp_parser_declarator
   (cp_parser *, cp_parser_declarator_kind, int *, bool *);
 static cp_declarator *cp_parser_direct_declarator
@@ -1684,8 +1702,8 @@ static tree cp_parser_declarator_id
   (cp_parser *);
 static tree cp_parser_type_id
   (cp_parser *);
-static tree cp_parser_type_specifier_seq
-  (cp_parser *);
+static void cp_parser_type_specifier_seq
+  (cp_parser *, cp_decl_specifier_seq *);
 static cp_parameter_declarator *cp_parser_parameter_declaration_clause
   (cp_parser *);
 static cp_parameter_declarator *cp_parser_parameter_declaration_list
@@ -1834,7 +1852,7 @@ static tree cp_parser_global_scope_opt
 static bool cp_parser_constructor_declarator_p
   (cp_parser *, bool);
 static tree cp_parser_function_definition_from_specifiers_and_declarator
-  (cp_parser *, tree, tree, const cp_declarator *);
+  (cp_parser *, cp_decl_specifier_seq *, tree, const cp_declarator *);
 static tree cp_parser_function_definition_after_declarator
   (cp_parser *, bool);
 static void cp_parser_template_declaration_after_export
@@ -1844,7 +1862,7 @@ static tree cp_parser_single_declaration
 static tree cp_parser_functional_cast
   (cp_parser *, tree);
 static tree cp_parser_save_member_function_body
-  (cp_parser *, tree, cp_declarator *, tree);
+  (cp_parser *, cp_decl_specifier_seq *, cp_declarator *, tree);
 static tree cp_parser_enclosed_template_argument_list
   (cp_parser *);
 static void cp_parser_save_default_args
@@ -1857,8 +1875,12 @@ static tree cp_parser_sizeof_operand
   (cp_parser *, enum rid);
 static bool cp_parser_declares_only_class_p
   (cp_parser *);
+static void cp_parser_set_storage_class
+  (cp_decl_specifier_seq *, cp_storage_class);
+static void cp_parser_set_decl_spec_type 
+  (cp_decl_specifier_seq *, tree, bool);
 static bool cp_parser_friend_p
-  (tree);
+  (const cp_decl_specifier_seq *);
 static cp_token *cp_parser_require
   (cp_parser *, enum cpp_ttype, const char *);
 static cp_token *cp_parser_require_keyword
@@ -2612,7 +2634,7 @@ cp_parser_translation_unit (cp_parser* parser)
       /* Create the error declarator.  */
       cp_error_declarator = make_declarator (cdk_error);
       /* Create the empty parameter list.  */
-      no_parameters = make_parameter_declarator (NULL_TREE, NULL, NULL_TREE);
+      no_parameters = make_parameter_declarator (NULL, NULL, NULL_TREE);
       /* Remember where the base of the declarator obstack lies.  */
       declarator_obstack_base = obstack_next_free (&declarator_obstack);
     }
@@ -3880,8 +3902,8 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
        cp_parser_parse_tentatively (parser);
        /* Look for the simple-type-specifier.  */
        type = cp_parser_simple_type_specifier (parser,
-                                               CP_PARSER_FLAGS_NONE,
-                                               /*identifier_p=*/false);
+                                               /*decl_specs=*/NULL,
+                                               CP_PARSER_FLAGS_NONE);
        /* Parse the cast itself.  */
        if (!cp_parser_error_occurred (parser))
          postfix_expression
@@ -4850,7 +4872,7 @@ cp_parser_new_placement (cp_parser* parser)
 static tree
 cp_parser_new_type_id (cp_parser* parser, tree *nelts)
 {
-  tree type_specifier_seq;
+  cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *new_declarator;
   cp_declarator *declarator;
   cp_declarator *outer_declarator;
@@ -4865,7 +4887,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
   parser->type_definition_forbidden_message
     = "types may not be defined in a new-type-id";
   /* Parse the type-specifier-seq.  */
-  type_specifier_seq = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
   /* Restore the old message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* Parse the new-declarator.  */
@@ -4912,7 +4934,7 @@ cp_parser_new_type_id (cp_parser* parser, tree *nelts)
        new_declarator = NULL;
     }
 
-  type = groktypename (type_specifier_seq, new_declarator);
+  type = groktypename (&type_specifier_seq, new_declarator);
   if (TREE_CODE (type) == ARRAY_TYPE && *nelts == NULL_TREE)
     {
       *nelts = array_type_nelts_top (type);
@@ -6257,7 +6279,7 @@ cp_parser_selection_statement (cp_parser* parser)
 static tree
 cp_parser_condition (cp_parser* parser)
 {
-  tree type_specifiers;
+  cp_decl_specifier_seq type_specifiers;
   const char *saved_message;
 
   /* Try the declaration first.  */
@@ -6268,7 +6290,7 @@ cp_parser_condition (cp_parser* parser)
   parser->type_definition_forbidden_message
     = "types may not be defined in conditions";
   /* Parse the type-specifier-seq.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
   /* If all is well, we might be looking at a declaration.  */
@@ -6301,7 +6323,7 @@ cp_parser_condition (cp_parser* parser)
       if (cp_parser_parse_definitely (parser))
        {
          /* Create the declaration.  */
-         decl = start_decl (declarator, type_specifiers,
+         decl = start_decl (declarator, &type_specifiers,
                             /*initialized_p=*/true,
                             attributes, /*prefix_attributes=*/NULL_TREE);
          /* Parse the assignment-expression.  */
@@ -6911,8 +6933,7 @@ static void
 cp_parser_simple_declaration (cp_parser* parser,
                               bool function_definition_allowed_p)
 {
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   int declares_class_or_enum;
   bool saw_declarator;
 
@@ -6932,18 +6953,18 @@ cp_parser_simple_declaration (cp_parser* parser,
      omitted only when declaring a class or enumeration, that is when
      the decl-specifier-seq contains either a class-specifier, an
      elaborated-type-specifier, or an enum-specifier.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* We no longer need to defer access checks.  */
   stop_deferring_access_checks ();
 
   /* In a block scope, a valid declaration must always have a
      decl-specifier-seq.  By not trying to parse declarators, we can
      resolve the declaration/expression ambiguity more quickly.  */
-  if (!function_definition_allowed_p && !decl_specifiers)
+  if (!function_definition_allowed_p 
+      && !decl_specifiers.any_specifiers_p)
     {
       cp_parser_error (parser, "expected declaration");
       goto done;
@@ -6976,7 +6997,7 @@ cp_parser_simple_declaration (cp_parser* parser,
 
       saw_declarator = true;
       /* Parse the init-declarator.  */
-      decl = cp_parser_init_declarator (parser, decl_specifiers, attributes,
+      decl = cp_parser_init_declarator (parser, &decl_specifiers,
                                        function_definition_allowed_p,
                                        /*member_p=*/false,
                                        declares_class_or_enum,
@@ -7039,7 +7060,7 @@ cp_parser_simple_declaration (cp_parser* parser,
   if (!saw_declarator)
     {
       if (cp_parser_declares_only_class_p (parser))
-       shadow_tag (decl_specifiers);
+       shadow_tag (&decl_specifiers);
       /* Perform any deferred access checks.  */
       perform_deferred_access_checks ();
     }
@@ -7068,14 +7089,7 @@ cp_parser_simple_declaration (cp_parser* parser,
    decl-specifier:
      attributes
 
-   Returns a TREE_LIST, giving the decl-specifiers in the order they
-   appear in the source code.  The TREE_VALUE of each node is the
-   decl-specifier.  For a keyword (such as `auto' or `friend'), the
-   TREE_VALUE is simply the corresponding TREE_IDENTIFIER.  For the
-   representation of a type-specifier, see cp_parser_type_specifier.
-
-   If there are attributes, they will be stored in *ATTRIBUTES,
-   represented as described above cp_parser_attributes.
+   Set *DECL_SPECS to a representation of the decl-specifier-seq.
 
    If FRIEND_IS_NOT_CLASS_P is non-NULL, and the `friend' specifier
    appears, and the entity that will be a friend is not going to be a
@@ -7090,30 +7104,28 @@ cp_parser_simple_declaration (cp_parser* parser,
         (i.e., a type declaration)
      2: one of the decl-specifiers is an enum-specifier or a
         class-specifier (i.e., a type definition)
-
+   
    */
 
-static tree
+static void
 cp_parser_decl_specifier_seq (cp_parser* parser,
-                              cp_parser_flags flags,
-                              tree* attributes,
+                             cp_parser_flags flags,
+                             cp_decl_specifier_seq *decl_specs,
                              int* declares_class_or_enum)
 {
-  tree decl_specs = NULL_TREE;
-  bool friend_p = false;
   bool constructor_possible_p = !parser->in_declarator_p;
 
+  /* Clear DECL_SPECS.  */
+  clear_decl_specs (decl_specs);
+
   /* Assume no class or enumeration type is declared.  */
   *declares_class_or_enum = 0;
 
-  /* Assume there are no attributes.  */
-  *attributes = NULL_TREE;
-
   /* Keep reading specifiers until there are no more to read.  */
   while (true)
     {
-      tree decl_spec = NULL_TREE;
       bool constructor_p;
+      bool found_decl_spec;
       cp_token *token;
 
       /* Peek at the next token.  */
@@ -7122,25 +7134,22 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
       if (token->keyword == RID_ATTRIBUTE)
        {
          /* Parse the attributes.  */
-         decl_spec = cp_parser_attributes_opt (parser);
-         /* Add them to the list.  */
-         *attributes = chainon (*attributes, decl_spec);
+         decl_specs->attributes 
+           = chainon (decl_specs->attributes,
+                      cp_parser_attributes_opt (parser));
          continue;
        }
+      /* Assume we will find a decl-specifier keyword.  */
+      found_decl_spec = true;
       /* If the next token is an appropriate keyword, we can simply
         add it to the list.  */
       switch (token->keyword)
        {
-       case RID_FRIEND:
          /* decl-specifier:
               friend  */
-         if (friend_p)
+       case RID_FRIEND:
+         if (decl_specs->specs[(int) ds_friend]++)
            error ("duplicate `friend'");
-         else
-           friend_p = true;
-         /* The representation of the specifier is simply the
-            appropriate TREE_IDENTIFIER node.  */
-         decl_spec = token->value;
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          break;
@@ -7152,15 +7161,13 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
        case RID_INLINE:
        case RID_VIRTUAL:
        case RID_EXPLICIT:
-         decl_spec = cp_parser_function_specifier_opt (parser);
+         cp_parser_function_specifier_opt (parser, decl_specs);
          break;
 
          /* decl-specifier:
               typedef  */
        case RID_TYPEDEF:
-         /* The representation of the specifier is simply the
-            appropriate TREE_IDENTIFIER node.  */
-         decl_spec = token->value;
+         ++decl_specs->specs[(int) ds_typedef];
          /* Consume the token.  */
          cp_lexer_consume_token (parser->lexer);
          /* A constructor declarator cannot appear in a typedef.  */
@@ -7180,35 +7187,67 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
              GNU Extension:
               thread  */
        case RID_AUTO:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_auto);
+         break;
        case RID_REGISTER:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_register);
+         break;
        case RID_STATIC:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         if (decl_specs->specs[(int) ds_thread])
+           error ("`__thread' before `static'");
+         else
+           cp_parser_set_storage_class (decl_specs, sc_static);
+         break;
        case RID_EXTERN:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         if (decl_specs->specs[(int) ds_thread])
+           error ("`__thread' before `extern'");
+         else
+           cp_parser_set_storage_class (decl_specs, sc_extern);
+         break;
        case RID_MUTABLE:
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         cp_parser_set_storage_class (decl_specs, sc_mutable);
+         break;
        case RID_THREAD:
-         decl_spec = cp_parser_storage_class_specifier_opt (parser);
+         /* Consume the token.  */
+         cp_lexer_consume_token (parser->lexer);
+         ++decl_specs->specs[(int) ds_thread];
          break;
 
        default:
+         /* We did not yet find a decl-specifier yet.  */
+         found_decl_spec = false;
          break;
        }
 
       /* Constructors are a special case.  The `S' in `S()' is not a
         decl-specifier; it is the beginning of the declarator.  */
-      constructor_p = (!decl_spec
-                      && constructor_possible_p
-                      && cp_parser_constructor_declarator_p (parser,
-                                                             friend_p));
+      constructor_p 
+       = (!found_decl_spec
+          && constructor_possible_p
+          && (cp_parser_constructor_declarator_p 
+              (parser, decl_specs->specs[(int) ds_friend] != 0)));
 
       /* If we don't have a DECL_SPEC yet, then we must be looking at
         a type-specifier.  */
-      if (!decl_spec && !constructor_p)
+      if (!found_decl_spec && !constructor_p)
        {
          int decl_spec_declares_class_or_enum;
          bool is_cv_qualifier;
+         tree type_spec;
 
-         decl_spec
+         type_spec
            = cp_parser_type_specifier (parser, flags,
-                                       friend_p,
+                                       decl_specs,
                                        /*is_declaration=*/true,
                                        &decl_spec_declares_class_or_enum,
                                        &is_cv_qualifier);
@@ -7251,44 +7290,31 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
             user-defined types.  We *do* still allow things like `int
             int' to be considered a decl-specifier-seq, and issue the
             error message later.  */
-         if (decl_spec && !is_cv_qualifier)
+         if (type_spec && !is_cv_qualifier)
            flags |= CP_PARSER_FLAGS_NO_USER_DEFINED_TYPES;
          /* A constructor declarator cannot follow a type-specifier.  */
-         if (decl_spec)
-           constructor_possible_p = false;
-       }
-
-      /* If we still do not have a DECL_SPEC, then there are no more
-        decl-specifiers.  */
-      if (!decl_spec)
-       {
-         /* Issue an error message, unless the entire construct was
-             optional.  */
-         if (!(flags & CP_PARSER_FLAGS_OPTIONAL))
+         if (type_spec)
            {
-             cp_parser_error (parser, "expected decl specifier");
-             return error_mark_node;
+             constructor_possible_p = false;
+             found_decl_spec = true;
            }
-
-         break;
        }
 
-      /* Add the DECL_SPEC to the list of specifiers.  */
-      if (decl_specs == NULL || TREE_VALUE (decl_specs) != error_mark_node)
-       decl_specs = tree_cons (NULL_TREE, decl_spec, decl_specs);
+      /* If we still do not have a DECL_SPEC, then there are no more
+        decl-specifiers.  */
+      if (!found_decl_spec)
+       break;
 
+      decl_specs->any_specifiers_p = true;
       /* After we see one decl-specifier, further decl-specifiers are
         always optional.  */
       flags |= CP_PARSER_FLAGS_OPTIONAL;
     }
 
   /* Don't allow a friend specifier with a class definition.  */
-  if (friend_p && (*declares_class_or_enum & 2))
+  if (decl_specs->specs[(int) ds_friend] != 0
+      && (*declares_class_or_enum & 2))
     error ("class definition may not be declared a friend");
-
-  /* We have built up the DECL_SPECS in reverse order.  Return them in
-     the correct order.  */
-  return nreverse (decl_specs);
 }
 
 /* Parse an (optional) storage-class-specifier.
@@ -7333,22 +7359,36 @@ cp_parser_storage_class_specifier_opt (cp_parser* parser)
      virtual
      explicit
 
-   Returns an IDENTIFIER_NODE corresponding to the keyword used.  */
+   Returns an IDENTIFIER_NODE corresponding to the keyword used.
+   Updates DECL_SPECS, if it is non-NULL.  */
 
 static tree
-cp_parser_function_specifier_opt (cp_parser* parser)
+cp_parser_function_specifier_opt (cp_parser* parser,
+                                 cp_decl_specifier_seq *decl_specs)
 {
   switch (cp_lexer_peek_token (parser->lexer)->keyword)
     {
     case RID_INLINE:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_inline];
+      break;
+
     case RID_VIRTUAL:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_virtual];
+      break;
+
     case RID_EXPLICIT:
-      /* Consume the token.  */
-      return cp_lexer_consume_token (parser->lexer)->value;
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_explicit];
+      break;
 
     default:
       return NULL_TREE;
     }
+
+  /* Consume the token.  */
+  return cp_lexer_consume_token (parser->lexer)->value;
 }
 
 /* Parse a linkage-specification.
@@ -7497,20 +7537,20 @@ static tree
 cp_parser_conversion_type_id (cp_parser* parser)
 {
   tree attributes;
-  tree type_specifiers;
+  cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
 
   /* Parse the attributes.  */
   attributes = cp_parser_attributes_opt (parser);
   /* Parse the type-specifiers.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* If that didn't work, stop.  */
-  if (type_specifiers == error_mark_node)
+  if (type_specifiers.type == error_mark_node)
     return error_mark_node;
   /* Parse the conversion-declarator.  */
   declarator = cp_parser_conversion_declarator_opt (parser);
 
-  return grokdeclarator (declarator, type_specifiers, TYPENAME,
+  return grokdeclarator (declarator, &type_specifiers, TYPENAME,
                         /*initialized=*/0, &attributes);
 }
 
@@ -8114,7 +8154,7 @@ static tree
 cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
 {
   cp_token *token;
-  const cp_parameter_declarator *parameter_declarator;
+  cp_parameter_declarator *parameter_declarator;
 
   /* Assume it is a type parameter or a template parameter.  */
   *is_non_type = false;
@@ -8166,7 +8206,7 @@ cp_parser_template_parameter (cp_parser* parser, bool *is_non_type)
   return (build_tree_list 
          (parameter_declarator->default_argument,
           grokdeclarator (parameter_declarator->declarator,
-                          parameter_declarator->decl_specifiers,
+                          &parameter_declarator->decl_specifiers,
                           PARM, /*initialized=*/0, 
                           /*attrlist=*/NULL)));
 }
@@ -9005,8 +9045,7 @@ static void
 cp_parser_explicit_instantiation (cp_parser* parser)
 {
   int declares_class_or_enum;
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   tree extension_specifier = NULL_TREE;
 
   /* Look for an (optional) storage-class-specifier or
@@ -9016,7 +9055,9 @@ cp_parser_explicit_instantiation (cp_parser* parser)
       extension_specifier
        = cp_parser_storage_class_specifier_opt (parser);
       if (!extension_specifier)
-       extension_specifier = cp_parser_function_specifier_opt (parser);
+       extension_specifier 
+         = cp_parser_function_specifier_opt (parser,
+                                             /*decl_specs=*/NULL);
     }
 
   /* Look for the `template' keyword.  */
@@ -9028,11 +9069,10 @@ cp_parser_explicit_instantiation (cp_parser* parser)
      control while processing explicit instantiation directives.  */
   push_deferring_access_checks (dk_no_check);
   /* Parse a decl-specifier-seq.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* If there was exactly one decl-specifier, and it declared a class,
      and there's no declarator, then we have an explicit type
      instantiation.  */
@@ -9040,7 +9080,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
     {
       tree type;
 
-      type = check_tag_decl (decl_specifiers);
+      type = check_tag_decl (&decl_specifiers);
       /* Turn access control back on for names used during
         template instantiation.  */
       pop_deferring_access_checks ();
@@ -9061,7 +9101,7 @@ cp_parser_explicit_instantiation (cp_parser* parser)
                                                     declares_class_or_enum);
       if (declarator != cp_error_declarator)
        {
-         decl = grokdeclarator (declarator, decl_specifiers,
+         decl = grokdeclarator (declarator, &decl_specifiers,
                                 NORMAL, 0, NULL);
          /* Turn access control back on for names used during
             template instantiation.  */
@@ -9146,11 +9186,9 @@ cp_parser_explicit_specialization (cp_parser* parser)
    type-specifier:
      __complex__
 
-   Returns a representation of the type-specifier.  If the
-   type-specifier is a keyword (like `int' or `const', or
-   `__complex__') then the corresponding IDENTIFIER_NODE is returned.
-   For a class-specifier, enum-specifier, or elaborated-type-specifier
-   a TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
+   Returns a representation of the type-specifier.  For a
+   class-specifier, enum-specifier, or elaborated-type-specifier, a
+   TREE_TYPE is returned; otherwise, a TYPE_DECL is returned.
 
    If IS_FRIEND is TRUE then this type-specifier is being declared a
    `friend'.  If IS_DECLARATION is TRUE, then this type-specifier is
@@ -9169,7 +9207,7 @@ cp_parser_explicit_specialization (cp_parser* parser)
 static tree
 cp_parser_type_specifier (cp_parser* parser,
                          cp_parser_flags flags,
-                         bool is_friend,
+                         cp_decl_specifier_seq *decl_specs,
                          bool is_declaration,
                          int* declares_class_or_enum,
                          bool* is_cv_qualifier)
@@ -9177,6 +9215,7 @@ cp_parser_type_specifier (cp_parser* parser,
   tree type_spec = NULL_TREE;
   cp_token *token;
   enum rid keyword;
+  cp_decl_spec ds = ds_last;
 
   /* Assume this type-specifier does not declare a new type.  */
   if (declares_class_or_enum)
@@ -9212,6 +9251,10 @@ cp_parser_type_specifier (cp_parser* parser,
        {
          if (declares_class_or_enum)
            *declares_class_or_enum = 2;
+         if (decl_specs)
+           cp_parser_set_decl_spec_type (decl_specs,
+                                         type_spec,
+                                         /*user_defined_p=*/true);
          return type_spec;
        }
 
@@ -9219,40 +9262,64 @@ cp_parser_type_specifier (cp_parser* parser,
 
     case RID_TYPENAME:
       /* Look for an elaborated-type-specifier.  */
-      type_spec = cp_parser_elaborated_type_specifier (parser,
-                                                      is_friend,
-                                                      is_declaration);
+      type_spec 
+       = (cp_parser_elaborated_type_specifier 
+          (parser,
+           decl_specs && decl_specs->specs[(int) ds_friend],
+           is_declaration));
       /* We're declaring a class or enum -- unless we're using
         `typename'.  */
       if (declares_class_or_enum && keyword != RID_TYPENAME)
        *declares_class_or_enum = 1;
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs,
+                                     type_spec,
+                                     /*user_defined_p=*/true);
       return type_spec;
 
     case RID_CONST:
+      ds = ds_const;
+      if (is_cv_qualifier)
+       *is_cv_qualifier = true;
+      break;
+      
     case RID_VOLATILE:
-    case RID_RESTRICT:
-      type_spec = cp_parser_cv_qualifier_opt (parser);
-      /* Even though we call a routine that looks for an optional
-        qualifier, we know that there should be one.  */
-      my_friendly_assert (type_spec != NULL, 20000328);
-      /* This type-specifier was a cv-qualified.  */
+      ds = ds_volatile;
       if (is_cv_qualifier)
        *is_cv_qualifier = true;
+      break;
 
-      return type_spec;
+    case RID_RESTRICT:
+      ds = ds_restrict;
+      if (is_cv_qualifier)
+       *is_cv_qualifier = true;
+      break;
 
     case RID_COMPLEX:
       /* The `__complex__' keyword is a GNU extension.  */
-      return cp_lexer_consume_token (parser->lexer)->value;
+      ds = ds_complex;
+      break;
 
     default:
       break;
     }
 
+  /* Handle simple keywords.  */
+  if (ds != ds_last)
+    {
+      if (decl_specs)
+       {
+         ++decl_specs->specs[(int)ds];
+         decl_specs->any_specifiers_p = true;
+       }
+      return cp_lexer_consume_token (parser->lexer)->value;
+    }
+
   /* If we do not already have a type-specifier, assume we are looking
      at a simple-type-specifier.  */
-  type_spec = cp_parser_simple_type_specifier (parser, flags,
-                                              /*identifier_p=*/true);
+  type_spec = cp_parser_simple_type_specifier (parser, 
+                                              decl_specs,
+                                              flags);
 
   /* If we didn't find a type-specifier, and a type-specifier was not
      optional in this context, issue an error message.  */
@@ -9288,14 +9355,13 @@ cp_parser_type_specifier (cp_parser* parser,
      __typeof__ unary-expression
      __typeof__ ( type-id )
 
-   For the various keywords, the value returned is simply the
-   TREE_IDENTIFIER representing the keyword if IDENTIFIER_P is true.
-   For the first two productions, and if IDENTIFIER_P is false, the
-   value returned is the indicated TYPE_DECL.  */
+   Returns the indicated TYPE_DECL.  If DECL_SPECS is not NULL, it is
+   appropriately updated.  */
 
 static tree
-cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
-                                bool identifier_p)
+cp_parser_simple_type_specifier (cp_parser* parser, 
+                                cp_decl_specifier_seq *decl_specs,
+                                cp_parser_flags flags)
 {
   tree type = NULL_TREE;
   cp_token *token;
@@ -9307,6 +9373,8 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
   switch (token->keyword)
     {
     case RID_CHAR:
+      if (decl_specs)
+       decl_specs->explicit_char_p = true;
       type = char_type_node;
       break;
     case RID_WCHAR:
@@ -9316,18 +9384,28 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       type = boolean_type_node;
       break;
     case RID_SHORT:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_short];
       type = short_integer_type_node;
       break;
     case RID_INT:
+      if (decl_specs)
+       decl_specs->explicit_int_p = true;
       type = integer_type_node;
       break;
     case RID_LONG:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_long];
       type = long_integer_type_node;
       break;
     case RID_SIGNED:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_signed];
       type = integer_type_node;
       break;
     case RID_UNSIGNED:
+      if (decl_specs)
+       ++decl_specs->specs[(int) ds_unsigned];
       type = unsigned_type_node;
       break;
     case RID_FLOAT:
@@ -9341,19 +9419,19 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       break;
 
     case RID_TYPEOF:
-      {
-       tree operand;
-
-       /* Consume the `typeof' token.  */
-       cp_lexer_consume_token (parser->lexer);
-       /* Parse the operand to `typeof'.  */
-       operand = cp_parser_sizeof_operand (parser, RID_TYPEOF);
-       /* If it is not already a TYPE, take its type.  */
-       if (!TYPE_P (operand))
-         operand = finish_typeof (operand);
-
-       return operand;
-      }
+      /* Consume the `typeof' token.  */
+      cp_lexer_consume_token (parser->lexer);
+      /* Parse the operand to `typeof'.  */
+      type = cp_parser_sizeof_operand (parser, RID_TYPEOF);
+      /* If it is not already a TYPE, take its type.  */
+      if (!TYPE_P (type))
+       type = finish_typeof (type);
+
+      if (decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     /*user_defined_p=*/true);
+       
+      return type;
 
     default:
       break;
@@ -9364,6 +9442,18 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
     {
       tree id;
 
+      /* Record the type.  */
+      if (decl_specs
+         && (token->keyword != RID_SIGNED
+             && token->keyword != RID_UNSIGNED
+             && token->keyword != RID_SHORT
+             && token->keyword != RID_LONG))
+       cp_parser_set_decl_spec_type (decl_specs, 
+                                     type,
+                                     /*user_defined=*/false);
+      if (decl_specs)
+       decl_specs->any_specifiers_p = true;
+
       /* Consume the token.  */
       id = cp_lexer_consume_token (parser->lexer)->value;
 
@@ -9372,7 +9462,7 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
         that the type was a template.  */
       cp_parser_check_for_invalid_template_id (parser, type);
 
-      return identifier_p ? id : TYPE_NAME (type);
+      return TYPE_NAME (type);
     }
 
   /* The type-specifier must be a user-defined type.  */
@@ -9427,6 +9517,9 @@ cp_parser_simple_type_specifier (cp_parser* parser, cp_parser_flags flags,
       if ((flags & CP_PARSER_FLAGS_OPTIONAL)
          && !cp_parser_parse_definitely (parser))
        type = NULL_TREE;
+      if (type && decl_specs)
+       cp_parser_set_decl_spec_type (decl_specs, type,
+                                     /*user_defined=*/true);
     }
 
   /* If we didn't get a type-name, issue an error message.  */
@@ -10370,8 +10463,7 @@ cp_parser_asm_definition (cp_parser* parser)
 
 static tree
 cp_parser_init_declarator (cp_parser* parser,
-                          tree decl_specifiers,
-                          tree prefix_attributes,
+                          cp_decl_specifier_seq *decl_specifiers,
                           bool function_definition_allowed_p,
                           bool member_p,
                           int declares_class_or_enum,
@@ -10379,6 +10471,7 @@ cp_parser_init_declarator (cp_parser* parser,
 {
   cp_token *token;
   cp_declarator *declarator;
+  tree prefix_attributes;
   tree attributes;
   tree asm_specification;
   tree initializer;
@@ -10391,6 +10484,11 @@ cp_parser_init_declarator (cp_parser* parser,
   bool friend_p;
   bool pop_p = false;
 
+  /* Gather the attributes that were provided with the
+     decl-specifiers.  */
+  prefix_attributes = decl_specifiers->attributes;
+  decl_specifiers->attributes = NULL_TREE;
+
   /* Assume that this is not the declarator for a function
      definition.  */
   if (function_definition_p)
@@ -10485,7 +10583,7 @@ cp_parser_init_declarator (cp_parser* parser,
      We explicitly postpone this check past the point where we handle
      function-definitions because we tolerate function-definitions
      that are missing their return types in some modes.  */
-  if (!decl_specifiers && ctor_dtor_or_conv_p <= 0)
+  if (!decl_specifiers->any_specifiers_p && ctor_dtor_or_conv_p <= 0)
     {
       cp_parser_error (parser,
                       "expected constructor, destructor, or type conversion");
@@ -10514,11 +10612,11 @@ cp_parser_init_declarator (cp_parser* parser,
      sure this was intended to be a declarator.  Then continue
      declaring the variable(s), as int, to try to cut down on further
      errors.  */
-  if (decl_specifiers != NULL
-      && TREE_VALUE (decl_specifiers) == error_mark_node)
+  if (decl_specifiers->any_specifiers_p
+      && decl_specifiers->type == error_mark_node)
     {
       cp_parser_error (parser, "invalid type in declaration");
-      TREE_VALUE (decl_specifiers) = integer_type_node;
+      decl_specifiers->type = integer_type_node;
     }
 
   /* Check to see whether or not this declaration is a friend.  */
@@ -10535,9 +10633,7 @@ cp_parser_init_declarator (cp_parser* parser,
     {
       if (parser->in_unbraced_linkage_specification_p)
        {
-         decl_specifiers = tree_cons (error_mark_node,
-                                      get_identifier ("extern"),
-                                      decl_specifiers);
+         decl_specifiers->storage_class = sc_extern;
          have_extern_spec = false;
        }
       decl = start_decl (declarator, decl_specifiers,
@@ -11331,13 +11427,12 @@ cp_parser_declarator_id (cp_parser* parser)
 static tree
 cp_parser_type_id (cp_parser* parser)
 {
-  tree type_specifier_seq;
+  cp_decl_specifier_seq type_specifier_seq;
   cp_declarator *abstract_declarator;
 
   /* Parse the type-specifier-seq.  */
-  type_specifier_seq
-    = cp_parser_type_specifier_seq (parser);
-  if (type_specifier_seq == error_mark_node)
+  cp_parser_type_specifier_seq (parser, &type_specifier_seq);
+  if (type_specifier_seq.type == error_mark_node)
     return error_mark_node;
 
   /* There might or might not be an abstract declarator.  */
@@ -11350,7 +11445,7 @@ cp_parser_type_id (cp_parser* parser)
   if (!cp_parser_parse_definitely (parser))
     abstract_declarator = NULL;
 
-  return groktypename (type_specifier_seq, abstract_declarator);
+  return groktypename (&type_specifier_seq, abstract_declarator);
 }
 
 /* Parse a type-specifier-seq.
@@ -11363,14 +11458,16 @@ cp_parser_type_id (cp_parser* parser)
    type-specifier-seq:
      attributes type-specifier-seq [opt]
 
-   Returns a TREE_LIST.  Either the TREE_VALUE of each node is a
-   type-specifier, or the TREE_PURPOSE is a list of attributes.  */
+   Sets *TYPE_SPECIFIER_SEQ to represent the sequence.  */
 
-static tree
-cp_parser_type_specifier_seq (cp_parser* parser)
+static void
+cp_parser_type_specifier_seq (cp_parser* parser,
+                             cp_decl_specifier_seq *type_specifier_seq)
 {
   bool seen_type_specifier = false;
-  tree type_specifier_seq = NULL_TREE;
+
+  /* Clear the TYPE_SPECIFIER_SEQ.  */
+  clear_decl_specs (type_specifier_seq);
 
   /* Parse the type-specifiers and attributes.  */
   while (true)
@@ -11380,39 +11477,36 @@ cp_parser_type_specifier_seq (cp_parser* parser)
       /* Check for attributes first.  */
       if (cp_lexer_next_token_is_keyword (parser->lexer, RID_ATTRIBUTE))
        {
-         type_specifier_seq = tree_cons (cp_parser_attributes_opt (parser),
-                                         NULL_TREE,
-                                         type_specifier_seq);
+         type_specifier_seq->attributes = 
+           chainon (type_specifier_seq->attributes,
+                    cp_parser_attributes_opt (parser));
          continue;
        }
 
-      /* After the first type-specifier, others are optional.  */
-      if (seen_type_specifier)
-       cp_parser_parse_tentatively (parser);
       /* Look for the type-specifier.  */
       type_specifier = cp_parser_type_specifier (parser,
-                                                CP_PARSER_FLAGS_NONE,
-                                                /*is_friend=*/false,
+                                                CP_PARSER_FLAGS_OPTIONAL,
+                                                type_specifier_seq,
                                                 /*is_declaration=*/false,
                                                 NULL,
                                                 NULL);
       /* If the first type-specifier could not be found, this is not a
         type-specifier-seq at all.  */
-      if (!seen_type_specifier && type_specifier == error_mark_node)
-       return error_mark_node;
+      if (!seen_type_specifier && !type_specifier)
+       {
+         cp_parser_error (parser, "expected type-specifier");
+         type_specifier_seq->type = error_mark_node;
+         return;
+       }
       /* If subsequent type-specifiers could not be found, the
         type-specifier-seq is complete.  */
-      else if (seen_type_specifier && !cp_parser_parse_definitely (parser))
+      else if (seen_type_specifier && !type_specifier)
        break;
 
-      /* Add the new type-specifier to the list.  */
-      type_specifier_seq
-       = tree_cons (NULL_TREE, type_specifier, type_specifier_seq);
       seen_type_specifier = true;
     }
 
-  /* We built up the list in reverse order.  */
-  return nreverse (type_specifier_seq);
+  return;
 }
 
 /* Parse a parameter-declaration-clause.
@@ -11625,8 +11719,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
 {
   int declares_class_or_enum;
   bool greater_than_is_operator_p;
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   cp_declarator *declarator;
   tree default_argument;
   cp_token *token;
@@ -11648,11 +11741,10 @@ cp_parser_parameter_declaration (cp_parser *parser,
     = "types may not be defined in parameter types";
 
   /* Parse the declaration-specifiers.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_NONE,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_NONE,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   /* If an error occurred, there's no reason to attempt to parse the
      rest of the declaration.  */
   if (cp_parser_error_occurred (parser))
@@ -11705,7 +11797,9 @@ cp_parser_parameter_declaration (cp_parser *parser,
                                         parenthesized_p);
       parser->default_arg_ok_p = saved_default_arg_ok_p;
       /* After the declarator, allow more attributes.  */
-      attributes = chainon (attributes, cp_parser_attributes_opt (parser));
+      decl_specifiers.attributes
+       = chainon (decl_specifiers.attributes, 
+                  cp_parser_attributes_opt (parser));
     }
 
   /* The restriction on defining new types applies only to the type
@@ -11846,11 +11940,7 @@ cp_parser_parameter_declaration (cp_parser *parser,
   else
     default_argument = NULL_TREE;
 
-  /* Create the representation of the parameter.  */
-  if (attributes)
-    decl_specifiers = tree_cons (attributes, NULL_TREE, decl_specifiers);
-
-  return make_parameter_declarator (decl_specifiers,
+  return make_parameter_declarator (&decl_specifiers,
                                    declarator,
                                    default_argument);
 }
@@ -12809,7 +12899,7 @@ cp_parser_member_specification_opt (cp_parser* parser)
 static void
 cp_parser_member_declaration (cp_parser* parser)
 {
-  tree decl_specifiers;
+  cp_decl_specifier_seq decl_specifiers;
   tree prefix_attributes;
   tree decl;
   int declares_class_or_enum;
@@ -12847,11 +12937,12 @@ cp_parser_member_declaration (cp_parser* parser)
     }
 
   /* Parse the decl-specifier-seq.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &prefix_attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
+  prefix_attributes = decl_specifiers.attributes;
+  decl_specifiers.attributes = NULL_TREE;
   /* Check for an invalid type-name.  */
   if (cp_parser_parse_and_diagnose_invalid_type_name (parser))
     return;
@@ -12868,7 +12959,7 @@ cp_parser_member_declaration (cp_parser* parser)
 
         Each member-declaration shall declare at least one member
         name of the class.  */
-      if (!decl_specifiers)
+      if (!decl_specifiers.any_specifiers_p)
        {
          if (pedantic)
            pedwarn ("extra semicolon");
@@ -12878,10 +12969,10 @@ cp_parser_member_declaration (cp_parser* parser)
          tree type;
 
          /* See if this declaration is a friend.  */
-         friend_p = cp_parser_friend_p (decl_specifiers);
+         friend_p = cp_parser_friend_p (&decl_specifiers);
          /* If there were decl-specifiers, check to see if there was
             a class-declaration.  */
-         type = check_tag_decl (decl_specifiers);
+         type = check_tag_decl (&decl_specifiers);
          /* Nested classes have already been added to the class, but
             a `friend' needs to be explicitly registered.  */
          if (friend_p)
@@ -12898,27 +12989,10 @@ cp_parser_member_declaration (cp_parser* parser)
 
                  A<T>::B will be represented by a TYPENAME_TYPE, and
                  therefore not recognized by check_tag_decl.  */
-              if (!type)
-                {
-                  tree specifier;
-
-                  for (specifier = decl_specifiers;
-                       specifier;
-                       specifier = TREE_CHAIN (specifier))
-                    {
-                      tree s = TREE_VALUE (specifier);
-
-                      if (TREE_CODE (s) == IDENTIFIER_NODE)
-                         get_global_value_if_present (s, &type);
-                      if (TREE_CODE (s) == TYPE_DECL)
-                        s = TREE_TYPE (s);
-                      if (TYPE_P (s))
-                        {
-                          type = s;
-                          break;
-                        }
-                    }
-                }
+              if (!type 
+                  && decl_specifiers.type
+                  && TYPE_P (decl_specifiers.type))
+                type = decl_specifiers.type;
               if (!type || !TYPE_P (type))
                 error ("friend declaration does not name a class or "
                        "function");
@@ -12928,7 +13002,7 @@ cp_parser_member_declaration (cp_parser* parser)
            }
          /* If there is no TYPE, an error message will already have
             been issued.  */
-         else if (!type)
+         else if (!type || type == error_mark_node)
            ;
          /* An anonymous aggregate has to be handled specially; such
             a declaration really declares a data member (with a
@@ -12950,7 +13024,7 @@ cp_parser_member_declaration (cp_parser* parser)
   else
     {
       /* See if these declarations will be friends.  */
-      friend_p = cp_parser_friend_p (decl_specifiers);
+      friend_p = cp_parser_friend_p (&decl_specifiers);
 
       /* Keep going until we hit the `;' at the end of the
         declaration.  */
@@ -12999,7 +13073,7 @@ cp_parser_member_declaration (cp_parser* parser)
              decl = grokbitfield (identifier 
                                   ? make_id_declarator (identifier)
                                   : NULL,
-                                  decl_specifiers,
+                                  &decl_specifiers,
                                   width);
              /* Apply the attributes.  */
              cplus_decl_attributes (&decl, attributes, /*flags=*/0);
@@ -13095,7 +13169,7 @@ cp_parser_member_declaration (cp_parser* parser)
                  if (initializer)
                    error ("pure-specifier on function-definition");
                  decl = cp_parser_save_member_function_body (parser,
-                                                             decl_specifiers,
+                                                             &decl_specifiers,
                                                              declarator,
                                                              attributes);
                  /* If the member was not a friend, declare it here.  */
@@ -13111,7 +13185,7 @@ cp_parser_member_declaration (cp_parser* parser)
              else
                {
                  /* Create the declaration.  */
-                 decl = grokfield (declarator, decl_specifiers,
+                 decl = grokfield (declarator, &decl_specifiers,
                                    initializer, asm_specification,
                                    attributes);
                  /* Any initialization must have been from a
@@ -13607,7 +13681,7 @@ static tree
 cp_parser_exception_declaration (cp_parser* parser)
 {
   tree decl;
-  tree type_specifiers;
+  cp_decl_specifier_seq type_specifiers;
   cp_declarator *declarator;
   const char *saved_message;
 
@@ -13625,7 +13699,7 @@ cp_parser_exception_declaration (cp_parser* parser)
     = "types may not be defined in exception-declarations";
 
   /* Parse the type-specifier-seq.  */
-  type_specifiers = cp_parser_type_specifier_seq (parser);
+  cp_parser_type_specifier_seq (parser, &type_specifiers);
   /* If it's a `)', then there is no declarator.  */
   if (cp_lexer_next_token_is (parser->lexer, CPP_CLOSE_PAREN))
     declarator = NULL;
@@ -13637,9 +13711,9 @@ cp_parser_exception_declaration (cp_parser* parser)
   /* Restore the saved message.  */
   parser->type_definition_forbidden_message = saved_message;
 
-  if (type_specifiers)
+  if (type_specifiers.any_specifiers_p)
     {
-      decl = grokdeclarator (declarator, type_specifiers, CATCHPARM, 1, NULL);
+      decl = grokdeclarator (declarator, &type_specifiers, CATCHPARM, 1, NULL);
       if (decl == NULL_TREE)
        error ("invalid catch parameter");
     }
@@ -14628,7 +14702,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
          /* Look for the type-specifier.  */
          cp_parser_type_specifier (parser,
                                    CP_PARSER_FLAGS_NONE,
-                                   /*is_friend=*/false,
+                                   /*decl_specs=*/NULL,
                                    /*is_declarator=*/true,
                                    /*declares_class_or_enum=*/NULL,
                                    /*is_cv_qualifier=*/NULL);
@@ -14660,7 +14734,7 @@ cp_parser_constructor_declarator_p (cp_parser *parser, bool friend_p)
 static tree
 cp_parser_function_definition_from_specifiers_and_declarator
   (cp_parser* parser,
-   tree decl_specifiers,
+   cp_decl_specifier_seq *decl_specifiers,
    tree attributes,
    const cp_declarator *declarator)
 {
@@ -14859,8 +14933,7 @@ cp_parser_single_declaration (cp_parser* parser,
 {
   int declares_class_or_enum;
   tree decl = NULL_TREE;
-  tree decl_specifiers;
-  tree attributes;
+  cp_decl_specifier_seq decl_specifiers;
   bool function_definition_p = false;
 
   /* Defer access checks until we know what is being declared.  */
@@ -14868,13 +14941,12 @@ cp_parser_single_declaration (cp_parser* parser,
 
   /* Try the `decl-specifier-seq [opt] init-declarator [opt]'
      alternative.  */
-  decl_specifiers
-    = cp_parser_decl_specifier_seq (parser,
-                                   CP_PARSER_FLAGS_OPTIONAL,
-                                   &attributes,
-                                   &declares_class_or_enum);
+  cp_parser_decl_specifier_seq (parser,
+                               CP_PARSER_FLAGS_OPTIONAL,
+                               &decl_specifiers,
+                               &declares_class_or_enum);
   if (friend_p)
-    *friend_p = cp_parser_friend_p (decl_specifiers);
+    *friend_p = cp_parser_friend_p (&decl_specifiers);
   /* Gather up the access checks that occurred the
      decl-specifier-seq.  */
   stop_deferring_access_checks ();
@@ -14884,8 +14956,8 @@ cp_parser_single_declaration (cp_parser* parser,
     {
       if (cp_parser_declares_only_class_p (parser))
        {
-         decl = shadow_tag (decl_specifiers);
-         if (decl)
+         decl = shadow_tag (&decl_specifiers);
+         if (decl && decl != error_mark_node)
            decl = TYPE_NAME (decl);
          else
            decl = error_mark_node;
@@ -14900,10 +14972,9 @@ cp_parser_single_declaration (cp_parser* parser,
      In that case, there's no need to warn about a missing declarator.  */
   if (!decl
       && (cp_lexer_next_token_is_not (parser->lexer, CPP_SEMICOLON)
-         || !value_member (error_mark_node, decl_specifiers)))
+         || decl_specifiers.type != error_mark_node))
     decl = cp_parser_init_declarator (parser,
-                                     decl_specifiers,
-                                     attributes,
+                                     &decl_specifiers,
                                      /*function_definition_allowed_p=*/true,
                                      member_p,
                                      declares_class_or_enum,
@@ -14966,7 +15037,7 @@ cp_parser_functional_cast (cp_parser* parser, tree type)
 
 static tree
 cp_parser_save_member_function_body (cp_parser* parser,
-                                    tree decl_specifiers,
+                                    cp_decl_specifier_seq *decl_specifiers,
                                     cp_declarator *declarator,
                                     tree attributes)
 {
@@ -15304,14 +15375,15 @@ cp_parser_sizeof_operand (cp_parser* parser, enum rid keyword)
       /* If all went well, then we're done.  */
       if (cp_parser_parse_definitely (parser))
        {
-         /* Build a list of decl-specifiers; right now, we have only
-            a single type-specifier.  */
-         type = build_tree_list (NULL_TREE,
-                                 type);
+         cp_decl_specifier_seq decl_specs;
+
+         /* Build a trivial decl-specifier-seq.  */
+         clear_decl_specs (&decl_specs);
+         decl_specs.type = type;
 
          /* Call grokdeclarator to figure out what type this is.  */
          expr = grokdeclarator (NULL,
-                                type,
+                                &decl_specs,
                                 TYPENAME,
                                 /*initialized=*/0,
                                 /*attrlist=*/NULL);
@@ -15345,24 +15417,49 @@ cp_parser_declares_only_class_p (cp_parser *parser)
          || cp_lexer_next_token_is (parser->lexer, CPP_COMMA));
 }
 
-/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
-   Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
+/* Update the DECL_SPECS to reflect the STORAGE_CLASS.  */
 
-static bool
-cp_parser_friend_p (tree decl_specifiers)
+static void
+cp_parser_set_storage_class (cp_decl_specifier_seq *decl_specs,
+                            cp_storage_class storage_class)
 {
-  while (decl_specifiers)
-    {
-      /* See if this decl-specifier is `friend'.  */
-      if (TREE_CODE (TREE_VALUE (decl_specifiers)) == IDENTIFIER_NODE
-         && C_RID_CODE (TREE_VALUE (decl_specifiers)) == RID_FRIEND)
-       return true;
+  if (decl_specs->storage_class != sc_none)
+    decl_specs->multiple_storage_classes_p = true;
+  else
+    decl_specs->storage_class = storage_class;
+}
+
+/* Update the DECL_SPECS to reflect the TYPE_SPEC.  If USER_DEFINED_P
+   is true, the type is a user-defined type; otherwise it is a
+   built-in type specified by a keyword.  */
 
-      /* Go on to the next decl-specifier.  */
-      decl_specifiers = TREE_CHAIN (decl_specifiers);
+static void
+cp_parser_set_decl_spec_type (cp_decl_specifier_seq *decl_specs,
+                             tree type_spec,
+                             bool user_defined_p)
+{
+  decl_specs->any_specifiers_p = true;
+  if (decl_specs->type)
+    {
+      if (decl_specs->specs[(int)ds_typedef] && !user_defined_p)
+       decl_specs->redefined_builtin_type = type_spec;
+      else
+       decl_specs->multiple_types_p = true;
+    }
+  else
+    {
+      decl_specs->type = type_spec;
+      decl_specs->user_defined_type_p = user_defined_p;
     }
+}
 
-  return false;
+/* DECL_SPECIFIERS is the representation of a decl-specifier-seq.
+   Returns TRUE iff `friend' appears among the DECL_SPECIFIERS.  */
+
+static bool
+cp_parser_friend_p (const cp_decl_specifier_seq *decl_specifiers)
+{
+  return decl_specifiers->specs[(int) ds_friend] != 0;
 }
 
 /* If the next token is of the indicated TYPE, consume it.  Otherwise,
index e451a29..da2b306 100644 (file)
@@ -36,7 +36,6 @@ Boston, MA 02111-1307, USA.  */
 #include "cp-tree.h"
 #include "tree-inline.h"
 #include "decl.h"
-#include "lex.h"
 #include "output.h"
 #include "except.h"
 #include "toplev.h"
index 0d4f4a7..c9f66d9 100644 (file)
@@ -34,7 +34,6 @@
 #include "tree-inline.h"
 #include "tree-mudflap.h"
 #include "except.h"
-#include "lex.h"
 #include "toplev.h"
 #include "flags.h"
 #include "rtl.h"
@@ -2147,36 +2146,6 @@ finish_member_declaration (tree decl)
     }
 }
 
-/* Finish processing the declaration of a member class template
-   TYPES whose template parameters are given by PARMS.  */
-
-tree
-finish_member_class_template (tree types)
-{
-  tree t;
-
-  /* If there are declared, but undefined, partial specializations
-     mixed in with the typespecs they will not yet have passed through
-     maybe_process_partial_specialization, so we do that here.  */
-  for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
-    if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
-      maybe_process_partial_specialization (TREE_VALUE (t));
-
-  grok_x_components (types);
-  if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
-    /* The component was in fact a friend declaration.  We avoid
-       finish_member_template_decl performing certain checks by
-       unsetting TYPES.  */
-    types = NULL_TREE;
-  
-  finish_member_template_decl (types);
-
-  /* As with other component type declarations, we do
-     not store the new DECL on the list of
-     component_decls.  */
-  return NULL_TREE;
-}
-
 /* Finish processing a complete template declaration.  The PARMS are
    the template parameters.  */