30th Cygnus<->FSF merge.
authorMike Stump <mrs@gcc.gnu.org>
Wed, 23 Mar 1994 23:33:53 +0000 (23:33 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Wed, 23 Mar 1994 23:33:53 +0000 (23:33 +0000)
From-SVN: r6859

24 files changed:
gcc/cp/Makefile.in
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/class.h
gcc/cp/cp-tree.h
gcc/cp/cvt.c
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/errfn.c
gcc/cp/error.c
gcc/cp/except.c
gcc/cp/gxxint.texi
gcc/cp/init.c
gcc/cp/input.c
gcc/cp/lex.c
gcc/cp/lex.h
gcc/cp/method.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/spew.c
gcc/cp/tree.c
gcc/cp/typeck.c
gcc/cp/typeck2.c

index 686b5b54635ecc22a5b59a09f26f342ce95d4828..5b2a422836d14cc56c315e1c91c95498be55bcf5 100644 (file)
@@ -44,10 +44,9 @@ X_CPPFLAGS =
 T_CPPFLAGS =
 
 CC = cc
-# CYGNUS LOCAL: we use byacc instead of bison, DO NOT SEND TO RMS
-BISON = `if [ -f ../../byacc/byacc ] ; then echo ../../byacc/byacc ;  else echo byacc ; fi`
+BISON = bison
 BISONFLAGS =
-LEX = `if [ -f ../../flex/flex ] ; then echo ../../flex/flex ;  else echo flex ; fi`
+LEX = flex
 LEXFLAGS=
 AR = ar
 OLDAR_FLAGS = qc
@@ -204,7 +203,7 @@ parse.o : $(srcdir)/parse.c $(CONFIG_H) $(CXX_TREE_H) ../flags.h lex.h
   `echo $(srcdir)/parse.c | sed 's,^\./,,'`
 
 $(srcdir)/parse.c $(srcdir)/parse.h : $(srcdir)/parse.y
-       @echo expect 28 shift/reduce conflicts, 14 reduce/reduce conflicts.
+       @echo expect 24 reduce/reduce conflicts.
        cd $(srcdir); $(BISON) $(BISONFLAGS) -d -o parse.c parse.y
        cd $(srcdir); grep '^#define[   ]*YYEMPTY' parse.c >>parse.h
 
index 02fc964e3aee4956194a79de5f41cb068b1b9192..663b727aa95a926d7911fbccd609308f28bd93d1 100644 (file)
@@ -39,7 +39,7 @@ extern int inhibit_warnings;
 extern int flag_assume_nonnull_objects;
 extern tree ctor_label, dtor_label;
 
-/* From cp-typeck.c:  */
+/* From typeck.c:  */
 extern tree unary_complex_lvalue ();
 
 /* Compute the ease with which a conversion can be performed
@@ -2821,6 +2821,8 @@ build_method_call (instance, name, parms, basetype_path, flags)
          cp_error ("call to destructor for non-type `%D'", name);
          return void_zero_node;
        }
+      if (basetype != TREE_TYPE(instance))
+       basetype = TREE_TYPE(instance);
       if (! TYPE_HAS_DESTRUCTOR (basetype))
        return void_zero_node;
       instance = default_conversion (instance);
@@ -3096,6 +3098,11 @@ build_method_call (instance, name, parms, basetype_path, flags)
          TREE_VALUE (parm) = resolve_offset_ref (TREE_VALUE (parm));
          t = TREE_TYPE (TREE_VALUE (parm));
        }
+      if (TREE_CODE (TREE_VALUE (parm)) == OFFSET_REF
+         && TREE_CODE (t) == METHOD_TYPE)
+       {
+         TREE_VALUE (parm) = build_unary_op (ADDR_EXPR, TREE_VALUE (parm), 0);
+       }
       if (TREE_CODE (t) == ARRAY_TYPE)
        {
          /* Perform the conversion from ARRAY_TYPE to POINTER_TYPE in place.
index e64001051124fb9f6e811662b528fff1c320b94e..0c5cc264408077c5e037418973553a1a1a46ac96 100644 (file)
@@ -83,7 +83,7 @@ tree the_null_vtable_entry;
 
 /* Way of stacking language names.  */
 tree *current_lang_base, *current_lang_stack;
-static int current_lang_stacksize;
+int current_lang_stacksize;
 
 /* Names of languages we recognize.  */
 tree lang_name_c, lang_name_cplusplus;
@@ -94,7 +94,7 @@ tree current_lang_name;
    via this node.  */
 static tree base_layout_decl;
 
-/* Variables shared between cp-class.c and cp-call.c.  */
+/* Variables shared between class.c and call.c.  */
 
 int n_vtables = 0;
 int n_vtable_entries = 0;
@@ -471,7 +471,8 @@ build_vfn_ref (ptr_to_instptr, instance, idx)
        vtbl = build_indirect_ref (build_vfield_ref (instance, basetype),
                                   NULL_PTR);
     }
-  assemble_external (vtbl);
+  if (!flag_vtable_hack)
+    assemble_external (vtbl);
   aref = build_array_ref (vtbl, idx);
 
   /* Save the intermediate result in a SAVE_EXPR so we don't have to
@@ -777,7 +778,8 @@ prepare_fresh_vtable (binfo, base_binfo, for_type)
 
 /* Access the virtual function table entry that logically
    contains BASE_FNDECL.  VIRTUALS is the virtual function table's
-   initializer.  */
+   initializer.  We can run off the end, when dealing with virtual
+   destructors in MI situations, return NULL_TREE in that case.  */
 static tree
 get_vtable_entry (virtuals, base_fndecl)
      tree virtuals, base_fndecl;
@@ -794,7 +796,7 @@ get_vtable_entry (virtuals, base_fndecl)
   n_vtable_searches += i;
 #endif
 
-  while (i > 0)
+  while (i > 0 && virtuals)
     {
       virtuals = TREE_CHAIN (virtuals);
       i -= 1;
@@ -1276,13 +1278,15 @@ modify_vtable_entries (t, fndecl, base_fndecl, pfn)
            prepare_fresh_vtable (binfo, base, t);
        }
 
-      saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl))), 0);
+      saved_pfn = get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl);
+      if (saved_pfn)
+       saved_pfn = TREE_OPERAND (FNADDR_FROM_VTABLE_ENTRY (TREE_VALUE (saved_pfn)), 0);
 #ifdef NOTQUITE
       cp_warning ("in %D", DECL_NAME (BINFO_VTABLE (binfo)));
 #endif
       /* The this_offset can be wrong, if we try and modify an entry
         that had been modified once before. */
-      if (! SAME_FN (saved_pfn, fndecl))
+      if (saved_pfn && ! SAME_FN (saved_pfn, fndecl))
         {
          modify_vtable_entry (get_vtable_entry (BINFO_VIRTUALS (binfo), base_fndecl),
                               build_vtable_entry (this_offset, pfn),
@@ -1738,12 +1742,15 @@ alter_access (t, fdecl, access)
   return 0;
 }
 
-static tree
+/* Return the offset to the main vtable for a given base BINFO.  */
+tree
 get_vfield_offset (binfo)
      tree binfo;
 {
   return size_binop (PLUS_EXPR,
-                    DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
+                    size_binop (FLOOR_DIV_EXPR,
+                                DECL_FIELD_BITPOS (CLASSTYPE_VFIELD (BINFO_TYPE (binfo))),
+                                size_int (BITS_PER_UNIT)),
                     BINFO_OFFSET (binfo));
 }
 
@@ -2148,6 +2155,22 @@ finish_base_struct (t, b, t_binfo)
          b->cant_synth_copy_ctor = 1;
        }
     }
+  {
+    tree v = get_vbase_types (t_binfo);
+
+    for (; v; v = TREE_CHAIN (v))
+      {
+       tree basetype = BINFO_TYPE (v);
+       if (get_base_distance (basetype, t_binfo, 0, (tree*)0) == -2)
+         {
+           if (extra_warnings)
+             cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+                         basetype, t);
+           b->cant_synth_asn_ref = 1;
+           b->cant_synth_copy_ctor = 1;
+         }
+      }
+  }    
 
   {
     tree vfields;
@@ -2726,7 +2749,8 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   enum tree_code code = TREE_CODE (t);
   register tree x, last_x, method_vec;
   int needs_virtual_dtor;
-  tree name = TYPE_NAME (t), fields, fn_fields, tail;
+  tree name = TYPE_NAME (t), fields, fn_fields, *tail;
+  tree *tail_user_methods = &CLASSTYPE_METHODS (t);
   enum access_type access;
   int all_virtual;
   int has_virtual;
@@ -2902,8 +2926,7 @@ finish_struct (t, list_of_fieldlists, warn_anon)
   CLASSTYPE_VFIELDS (t) = vfields;
   CLASSTYPE_VFIELD (t) = vfield;
 
-  fn_fields = NULL_TREE;
-  tail = NULL_TREE;
+  tail = &fn_fields;
   if (last_x && list_of_fieldlists)
     TREE_CHAIN (last_x) = TREE_VALUE (list_of_fieldlists);
 
@@ -2961,11 +2984,11 @@ finish_struct (t, list_of_fieldlists, warn_anon)
 
              if (last_x)
                TREE_CHAIN (last_x) = TREE_CHAIN (x);
-             if (! fn_fields)
-               fn_fields = x;
-             else
-               TREE_CHAIN (tail) = x;
-             tail = x;
+             /* Link x onto end of fn_fields and CLASSTYPE_METHODS. */
+             *tail = x;
+             tail = &TREE_CHAIN (x);
+             *tail_user_methods = x;
+             tail_user_methods = &DECL_NEXT_METHOD (x);
 
 #if 0
              /* ??? What if we have duplicate declarations
@@ -3284,8 +3307,6 @@ finish_struct (t, list_of_fieldlists, warn_anon)
        }
     }
 
-  if (tail) TREE_CHAIN (tail) = NULL_TREE;
-
   /* If this type has any constant members which did not come
      with their own initialization, mark that fact here.  It is
      not an error here, since such types can be saved either by their
@@ -3306,11 +3327,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
        TYPE_NEEDS_DESTRUCTOR (t) = 0;
       else
        {
-         if (! fn_fields)
-           fn_fields = dtor;
-         else
-           TREE_CHAIN (tail) = dtor;
-         tail = dtor;
+         /* Link dtor onto end of fn_fields. */
+         *tail = dtor;
+         tail = &TREE_CHAIN (dtor);
 
          if (DECL_VINDEX (dtor) == NULL_TREE
              && ! CLASSTYPE_DECLARED_EXCEPTION (t)
@@ -3325,6 +3344,9 @@ finish_struct (t, list_of_fieldlists, warn_anon)
        }
     }
 
+  *tail = NULL_TREE;
+  *tail_user_methods = NULL_TREE;
+
   TYPE_NEEDS_DESTRUCTOR (t) |= TYPE_HAS_DESTRUCTOR (t);
 
   /* Synthesize any needed methods.  Note that methods will be synthesized
index fb25a5f56b4fa8b862de8f9432fa827e98833e59..7e138243c011732a779d734c787cc399ff461d5f 100644 (file)
@@ -149,7 +149,7 @@ struct candidate
 };
 int rank_for_overload ();
 
-/* Variables shared between cp-class.c and cp-call.c.  */
+/* Variables shared between class.c and call.c.  */
 
 extern int n_vtables;
 extern int n_vtable_entries;
index b431e160a6b2e220dd1621be8a2365feaf8d0018..e4db0dc8c9721be5502fa51ddf8c32374cc12638 100644 (file)
@@ -259,6 +259,11 @@ extern int flag_signed_bitfields;
 
 extern int write_virtuals;
 
+/* True if we want output of vtables to be controlled by whether
+   we seen the class's first non-inline virtual function.
+   0 is old behavior; 1 is new behavior. */
+extern flag_vtable_hack;
+
 /* INTERFACE_ONLY nonzero means that we are in an "interface"
    section of the compiler.  INTERFACE_UNKNOWN nonzero means
    we cannot trust the value of INTERFACE_ONLY.  If INTERFACE_UNKNOWN
@@ -486,6 +491,8 @@ struct lang_type
 
   union tree_node *dossier;
 
+  union tree_node *methods;
+
   union tree_node *signature;
   union tree_node *signature_pointer_to;
   union tree_node *signature_reference_to;
@@ -604,6 +611,10 @@ struct lang_type
 /* The is the VAR_DECL that contains NODE's dossier.  */
 #define CLASSTYPE_DOSSIER(NODE) (TYPE_LANG_SPECIFIC(NODE)->dossier)
 
+/* List of all explicit methods (chained using DECL_NEXT_METHOD),
+   in order they were parsed. */
+#define CLASSTYPE_METHODS(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
+
 /* Nonzero means that this _CLASSTYPE node overloads operator().  */
 #define TYPE_OVERLOADS_CALL_EXPR(NODE) (TYPE_LANG_SPECIFIC(NODE)->type_flags.has_call_overloaded)
 
@@ -927,7 +938,7 @@ struct lang_decl
   struct template_info *template_info;
   tree main_decl_variant;
   struct pending_inline *pending_inline_info;
-  tree vbase_init_list;
+  tree next_method;
   tree chain;
 };
 
@@ -1007,6 +1018,9 @@ struct lang_decl
 #define DECL_CHAIN(NODE) (TREE_CHAIN (NODE))
 #endif
 
+/* Next method in CLASSTYPE_METHODS list. */
+#define DECL_NEXT_METHOD(NODE) (DECL_LANG_SPECIFIC(NODE)->next_method)
+
 /* Points back to the decl which caused this lang_decl to be allocated.  */
 #define DECL_MAIN_VARIANT(NODE) (DECL_LANG_SPECIFIC(NODE)->main_decl_variant)
 
@@ -1024,11 +1038,6 @@ struct lang_decl
    which this signature member function pointer was created.  */
 #define DECL_MEMFUNC_POINTING_TO(NODE) (DECL_LANG_SPECIFIC(NODE)->decl_flags.memfunc_pointer_to)
 
-/* Holds information about how virtual base classes should be initialized
-   by this constructor *if* this constructor is the one to perform
-   such initialization.  */
-#define DECL_VBASE_INIT_LIST(NODE) (DECL_LANG_SPECIFIC(NODE)->vbase_init_list)
-
 /* For a TEMPLATE_DECL: template-specific information.  */
 #define DECL_TEMPLATE_INFO(NODE) (DECL_LANG_SPECIFIC(NODE)->template_info)
 
@@ -1218,7 +1227,7 @@ struct lang_decl
 #define DECL_TEMPLATE_IS_CLASS(NODE)    (DECL_RESULT(NODE) == NULL_TREE)
 #define DECL_TEMPLATE_PARMS(NODE)       DECL_ARGUMENTS(NODE)
 /* For class templates.  */
-#define DECL_TEMPLATE_MEMBERS(NODE)     DECL_INITIAL(NODE)
+#define DECL_TEMPLATE_MEMBERS(NODE)     DECL_SIZE(NODE)
 /* For function, method, class-data templates.  */
 #define DECL_TEMPLATE_RESULT(NODE)      DECL_RESULT(NODE)
 #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
@@ -1279,7 +1288,7 @@ extern tree truthvalue_conversion               PROTO((tree));
 extern tree type_for_mode                       PROTO((enum machine_mode, int));
 extern tree type_for_size                       PROTO((unsigned, int));
 
-/* in cp-decl{2}.c */
+/* in decl{2}.c */
 extern tree void_list_node;
 extern tree void_zero_node;
 extern tree default_function_type;
@@ -1319,12 +1328,12 @@ extern tree long_long_integer_type_node, long_long_unsigned_type_node;
 /* For building calls to `delete'.  */
 extern tree integer_two_node, integer_three_node;
 
-/* in cp-except.c */
+/* in except.c */
 extern tree current_exception_type;
 extern tree current_exception_decl;
 extern tree current_exception_object;
 
-/* in cp-pt.c  */
+/* in pt.c  */
 /* PARM_VEC is a vector of template parameters, either IDENTIFIER_NODEs or
    PARM_DECLs.  BINDINGS, if non-null, is a vector of bindings for those
    parameters.  */
@@ -1358,7 +1367,7 @@ struct tinst_level
 
 extern struct tinst_level *current_tinst_level;
 
-/* in cp-class.c */
+/* in class.c */
 extern tree current_class_name;
 extern tree current_class_type;
 extern tree previous_class_type;
@@ -1372,7 +1381,7 @@ extern tree original_function_name;
 extern tree current_class_name, current_class_type, current_class_decl, C_C_D;
 extern tree current_vtable_decl;
 
-/* in cp-init.c  */
+/* in init.c  */
 extern tree global_base_init_list;
 extern tree current_base_init_list, current_member_init_list;
 
@@ -1568,7 +1577,7 @@ enum access_type {
   access_private_virtual
 };
 
-/* in cp-lex.c  */
+/* in lex.c  */
 extern tree current_unit_name, current_unit_language;
 
 /* Things for handling inline functions.  */
@@ -1590,7 +1599,7 @@ struct pending_inline
   unsigned int interface : 2;  /* 0=interface 1=unknown 2=implementation */
 };
 
-/* in cp-method.c */
+/* in method.c */
 extern struct pending_inline *pending_inlines;
 
 /* 1 for -fall-virtual: make every member function (except
@@ -1695,7 +1704,7 @@ extern tree current_class_type;   /* _TYPE: the type of the current class */
   (TEMPLATE_CONST_TPARMLIST (NODE) = saved_parmlist, \
    TEMPLATE_CONST_IDX (NODE) = I)
 
-/* in cp-lex.c  */
+/* in lex.c  */
 /* Indexed by TREE_CODE, these tables give C-looking names to
    operators represented by TREE_CODES.  For example,
    opname_tab[(int) MINUS_EXPR] == "-".  */
@@ -1706,7 +1715,7 @@ extern tree convert_and_check                     PROTO((tree, tree));
 extern void overflow_warning                   PROTO((tree));
 extern void unsigned_conversion_warning                PROTO((tree, tree));
 
-/* in cp-call.c */
+/* in call.c */
 extern struct candidate *ansi_c_bullshit;
 
 extern int rank_for_overload                   PROTO((struct candidate *, struct candidate *));
@@ -1721,12 +1730,13 @@ extern tree build_overload_call_real            PROTO((tree, tree, int, struct candidate *
 extern tree build_overload_call                        PROTO((tree, tree, int, struct candidate *));
 extern tree build_overload_call_maybe          PROTO((tree, tree, int, struct candidate *));
 
-/* in cp-class.c */
+/* in class.c */
 extern tree build_vbase_pointer                        PROTO((tree, tree));
 extern tree build_vbase_path                   PROTO((enum tree_code, tree, tree, tree, int));
 extern tree build_vtable_entry                 PROTO((tree, tree));
 extern tree build_vfn_ref                      PROTO((tree *, tree, tree));
 extern void add_method                         PROTO((tree, tree *, tree));
+extern tree get_vfield_offset                  PROTO((tree));
 extern void duplicate_tag_error                        PROTO((tree));
 extern tree finish_struct                      PROTO((tree, tree, int));
 extern int resolves_to_fixed_type_p            PROTO((tree, int *));
@@ -1742,7 +1752,7 @@ extern tree instantiate_type                      PROTO((tree, tree, int));
 extern void print_class_statistics             PROTO((void));
 extern void maybe_push_cache_obstack           PROTO((void));
 
-/* in cp-cvt.c */
+/* in cvt.c */
 extern tree convert_to_reference               PROTO((tree, tree, tree, tree, int, char *, int, int));
 extern tree convert_from_reference             PROTO((tree));
 extern tree convert_to_aggr                    PROTO((tree, tree, char **, int));
@@ -1755,7 +1765,7 @@ extern tree build_type_conversion         PROTO((enum tree_code, tree, tree, int));
 extern int build_default_binary_type_conversion        PROTO((enum tree_code, tree *, tree *));
 extern int build_default_unary_type_conversion PROTO((enum tree_code, tree *));
 
-/* cp-decl.c */
+/* decl.c */
 extern int global_bindings_p                   PROTO((void));
 extern void keep_next_level                    PROTO((void));
 extern int kept_level_p                                PROTO((void));
@@ -1833,7 +1843,7 @@ extern void pop_implicit_try_blocks               PROTO((tree));
 extern void push_exception_cleanup             PROTO((tree));
 extern void revert_static_member_fn            PROTO((tree *, tree *, tree *));
 
-/* in cp-decl2.c */
+/* in decl2.c */
 extern int lang_decode_option                  PROTO((char *));
 extern tree grok_method_quals                  PROTO((tree, tree, tree));
 extern void grokclassfn                                PROTO((tree, tree, tree, enum overload_flags, tree));
@@ -1844,7 +1854,7 @@ extern void check_classfn                 PROTO((tree, tree, tree));
 extern tree grokfield                          PROTO((tree, tree, tree, tree, tree));
 extern tree grokbitfield                       PROTO((tree, tree, tree));
 extern tree groktypefield                      PROTO((tree, tree));
-extern tree grokoptypename                     PROTO((tree, int));
+extern tree grokoptypename                     PROTO((tree, tree));
 extern tree build_push_scope                   PROTO((tree, tree));
 extern tree constructor_name_full              PROTO((tree));
 extern tree constructor_name                   PROTO((tree));
@@ -1862,10 +1872,14 @@ extern void walk_vtables                        PROTO((void (*)(), void (*)()));
 extern void finish_file                                PROTO((void));
 extern void warn_if_unknown_interface          PROTO((void));
 extern tree grok_x_components                  PROTO((tree, tree));
+extern tree reparse_absdcl_as_expr             PROTO((tree, tree));
+extern tree reparse_absdcl_as_casts            PROTO((tree, tree));
+extern tree reparse_decl_as_expr               PROTO((tree, tree));
+extern tree finish_decl_parsing                        PROTO((tree));
 
-/* in cp-edsel.c */
+/* in edsel.c */
 
-/* in cp-except.c */
+/* in except.c */
 extern tree lookup_exception_cname             PROTO((tree, tree, tree));
 extern tree lookup_exception_tname             PROTO((tree));
 extern tree lookup_exception_object            PROTO((tree, tree, int));
@@ -1888,13 +1902,13 @@ extern void setup_exception_throw_decl          PROTO((void));
 extern void init_exception_processing          PROTO((void));
 extern void init_exception_processing_1                PROTO((void));
 
-/* in cp-expr.c */
+/* in expr.c */
 /* skip cplus_expand_expr */
 extern void init_cplus_expand                  PROTO((void));
 extern void fixup_result_decl                  PROTO((tree, struct rtx_def *));
 extern int decl_in_memory_p                    PROTO((tree));
 
-/* in cp-gc.c */
+/* in gc.c */
 extern int type_needs_gc_entry                 PROTO((tree));
 extern int value_safe_from_gc                  PROTO((tree, tree));
 extern void build_static_gc_entry              PROTO((tree, tree));
@@ -1911,7 +1925,7 @@ extern tree build_typeid                  PROTO((tree));
 extern tree get_typeid                         PROTO((tree));
 extern tree build_dynamic_cast                 PROTO((tree, tree));
 
-/* in cp-init.c */
+/* in init.c */
 extern void emit_base_init                     PROTO((tree, int));
 extern void check_base_init                    PROTO((tree));
 extern tree build_virtual_init                 PROTO((tree, tree, tree));
@@ -1941,9 +1955,9 @@ extern tree build_delete                  PROTO((tree, tree, tree, int, int));
 extern tree build_vbase_delete                 PROTO((tree, tree));
 extern tree build_vec_delete                   PROTO((tree, tree, tree, tree, tree, tree));
 
-/* in cp-input.c */
+/* in input.c */
 
-/* in cp-lex.c */
+/* in lex.c */
 extern tree make_pointer_declarator            PROTO((tree, tree));
 extern tree make_reference_declarator          PROTO((tree, tree));
 extern char *operator_name_string              PROTO((tree));
@@ -1986,7 +2000,7 @@ extern void dump_time_statistics          PROTO((void));
 extern void compiler_error_with_decl           PROTO((tree, char *));
 extern void yyerror                            PROTO((char *));
 
-/* in cp-error.c */
+/* in error.c */
 extern void init_error                         PROTO((void));
 extern char *fndecl_as_string                  PROTO((tree, tree, int));
 extern char *type_as_string                    PROTO((tree, int));
@@ -1998,7 +2012,7 @@ extern char *language_as_string                   PROTO((enum languages, int));
 extern char *parm_as_string                    PROTO((int, int));
 extern char *op_as_string                      PROTO((enum tree_code, int));
 
-/* in cp-method.c */
+/* in method.c */
 extern void init_method                                PROTO((void));
 extern tree make_anon_parm_name                        PROTO((void));
 extern void clear_anon_parm_name               PROTO((void));
@@ -2017,11 +2031,11 @@ extern tree build_opfncall                      PROTO((enum tree_code, int, tree, tree, tree));
 extern tree hack_identifier                    PROTO((tree, tree, int));
 extern tree build_component_type_expr          PROTO((tree, tree, tree, int));
 
-/* in cp-pt.c */
+/* in pt.c */
 extern void begin_template_parm_list           PROTO((void));
 extern tree process_template_parm              PROTO((tree, tree));
 extern tree end_template_parm_list             PROTO((tree));
-extern void end_template_decl                  PROTO((tree, tree, tree));
+extern void end_template_decl                  PROTO((tree, tree, tree, int));
 extern tree lookup_template_class              PROTO((tree, tree, tree));
 extern void push_template_decls                        PROTO((tree, tree, int));
 extern void pop_template_decls                 PROTO((tree, tree, int));
@@ -2039,7 +2053,7 @@ extern void do_pending_templates          PROTO((void));
 struct tinst_level *tinst_for_decl             PROTO((void));
 extern void do_function_instantiation          PROTO((tree, tree));
 
-/* in cp-search.c */
+/* in search.c */
 extern tree make_memoized_table_entry          PROTO((tree, tree, int));
 extern void push_memoized_context              PROTO((tree, int));
 extern void pop_memoized_context               PROTO((int));
@@ -2075,7 +2089,7 @@ extern void init_search_processing                PROTO((void));
 extern void reinit_search_statistics           PROTO((void));
 extern tree current_scope                      PROTO((void));
 
-/* in cp-sig.c */
+/* in sig.c */
 extern tree build_signature_pointer_type       PROTO((tree, int, int));
 extern tree build_signature_reference_type     PROTO((tree, int, int));
 extern tree build_signature_pointer_constructor        PROTO((tree, tree));
@@ -2084,12 +2098,12 @@ extern tree build_optr_ref                      PROTO((tree));
 extern tree build_sptr_ref                     PROTO((tree));
 extern tree build_vptr_ref                     PROTO((tree));
 
-/* in cp-spew.c */
+/* in spew.c */
 extern void init_spew                          PROTO((void));
 extern int yylex                               PROTO((void));
 extern tree arbitrate_lookup                   PROTO((tree, tree, tree));
 
-/* in cp-tree.c */
+/* in tree.c */
 extern int lvalue_p                            PROTO((tree));
 extern int lvalue_or_else                      PROTO((tree, char *));
 extern tree build_cplus_new                    PROTO((tree, tree, int));
@@ -2135,7 +2149,7 @@ extern void print_lang_statistics         PROTO((void));
 extern tree array_type_nelts_total             PROTO((tree));
 extern tree array_type_nelts_top               PROTO((tree));
 
-/* in cp-typeck.c */
+/* in typeck.c */
 extern tree target_type                                PROTO((tree));
 extern tree require_complete_type              PROTO((tree));
 extern int type_unknown_p                      PROTO((tree));
@@ -2191,7 +2205,7 @@ extern tree c_expand_start_case                   PROTO((tree));
 extern tree build_component_ref                        PROTO((tree, tree, tree, int));
 extern tree build_ptrmemfunc                   PROTO((tree, tree, int));
 
-/* in cp-type2.c */
+/* in typeck2.c */
 extern tree error_not_base_type                        PROTO((tree, tree));
 extern tree binfo_or_else                      PROTO((tree, tree));
 extern void error_with_aggr_type               (); /* PROTO((tree, char *, HOST_WIDE_INT)); */
@@ -2209,7 +2223,7 @@ extern tree build_functional_cast         PROTO((tree, tree));
 extern char *enum_name_string                  PROTO((tree, tree));
 extern void report_case_error                  PROTO((int, tree, tree, tree));
 
-/* in cp-xref.c */
+/* in xref.c */
 extern void GNU_xref_begin                     PROTO((char *));
 extern void GNU_xref_end                       PROTO((int));
 extern void GNU_xref_file                      PROTO((char *));
index 347a901a821969d9f3fc8aa8b62ca5a8fcd06d03..5e41618a63139019c6b3f354c76bbc118ecd200b 100644 (file)
@@ -581,7 +581,11 @@ build_up_reference (type, arg, flags, checkconst)
   if (TYPE_USES_COMPLEX_INHERITANCE (argtype))
     {
       TREE_TYPE (rval) = TYPE_POINTER_TO (argtype);
-      rval = convert_pointer_to (target_type, rval);
+      if (flags & LOOKUP_PROTECT)
+       rval = convert_pointer_to (target_type, rval);
+      else
+       rval
+         = convert_to_pointer_force (build_pointer_type (target_type), rval);
       TREE_TYPE (rval) = type;
     }
   TREE_CONSTANT (rval) = literal_flag;
@@ -1439,18 +1443,16 @@ convert_force (type, expr)
   if (code == POINTER_TYPE)
     return fold (convert_to_pointer_force (type, e));
 
-  /* From cp-typeck.c convert_for_assignment */
+  /* From typeck.c convert_for_assignment */
   if (((TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE && TREE_CODE (e) == ADDR_EXPR
        && TREE_CODE (TREE_TYPE (e)) == POINTER_TYPE
        && TREE_CODE (TREE_TYPE (TREE_TYPE (e))) == METHOD_TYPE)
-       || integer_zerop (e))
+       || integer_zerop (e)
+       || TYPE_PTRMEMFUNC_P (TREE_TYPE (e)))
       && TYPE_PTRMEMFUNC_P (type))
     {
       /* compatible pointer to member functions. */
-      e = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
-      if (e == 0)
-       return error_mark_node;
-      return digest_init (type, e, (tree *)0);
+      return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), e, 1);
     }
   {
     int old_equiv = flag_int_enum_equivalence;
index f9ee26dca0cc9fc8b7add34ab742fc31fab14728..1ad7849f8f315474b71240622846b0ba917c9339 100644 (file)
@@ -444,7 +444,7 @@ extern int flag_conserve_space;
 
 extern tree *current_lang_base, *current_lang_stack;
 \f
-/* C and C++ flags are in cp-decl2.c.  */
+/* C and C++ flags are in decl2.c.  */
 
 /* Set to 0 at beginning of a constructor, set to 1
    if that function does an allocation before referencing its
@@ -465,7 +465,7 @@ int current_function_obstack_index;
 
 int current_function_obstack_usage;
 
-/* Flag used when debugging cp-spew.c */
+/* Flag used when debugging spew.c */
 
 extern int spew_debug;
 
@@ -1471,6 +1471,9 @@ struct saved_scope {
   tree class_name, class_type, class_decl, function_decl;
   struct binding_level *class_bindings;
   tree previous_class_type;
+  tree *lang_base, *lang_stack, lang_name;
+  int lang_stacksize;
+  tree named_labels;
 };
 static struct saved_scope *current_saved_scope;
 extern tree prev_class_type;
@@ -1478,6 +1481,7 @@ extern tree prev_class_type;
 void
 push_to_top_level ()
 {
+  extern int current_lang_stacksize;
   struct saved_scope *s =
     (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
   struct binding_level *b = current_binding_level;
@@ -1543,10 +1547,21 @@ push_to_top_level ()
   s->function_decl = current_function_decl;
   s->class_bindings = class_binding_level;
   s->previous_class_type = previous_class_type;
+  s->lang_stack = current_lang_stack;
+  s->lang_base = current_lang_base;
+  s->lang_stacksize = current_lang_stacksize;
+  s->lang_name = current_lang_name;
+  s->named_labels = named_labels;
   current_class_name = current_class_type = current_class_decl = NULL_TREE;
   current_function_decl = NULL_TREE;
   class_binding_level = (struct binding_level *)0;
   previous_class_type = NULL_TREE;
+  current_lang_stacksize = 10;
+  current_lang_stack = current_lang_base
+    = (tree *) xmalloc (current_lang_stacksize * sizeof (tree));
+  current_lang_name = lang_name_cplusplus;
+  strict_prototype = strict_prototypes_lang_cplusplus;
+  named_labels = NULL_TREE;
 
   s->prev = current_saved_scope;
   s->old_bindings = old_bindings;
@@ -1556,6 +1571,7 @@ push_to_top_level ()
 void
 pop_from_top_level ()
 {
+  extern int current_lang_stacksize;
   struct saved_scope *s = current_saved_scope;
   tree t;
 
@@ -1584,6 +1600,17 @@ pop_from_top_level ()
   current_function_decl = s->function_decl;
   class_binding_level = s->class_bindings;
   previous_class_type = s->previous_class_type;
+  free (current_lang_base);
+  current_lang_base = s->lang_base;
+  current_lang_stack = s->lang_stack;
+  current_lang_name = s->lang_name;
+  current_lang_stacksize = s->lang_stacksize;
+  if (current_lang_name == lang_name_cplusplus)
+    strict_prototype = strict_prototypes_lang_cplusplus;
+  else if (current_lang_name == lang_name_c)
+    strict_prototype = strict_prototypes_lang_c;
+  named_labels = s->named_labels;
+
   free (s);
 }
 \f
@@ -1661,7 +1688,7 @@ set_nested_typename (decl, classname, name, type)
    incorrect results with `-g' unless they duplicate this code.
 
    This is currently needed mainly for dbxout.c, but we can make
-   use of it in cp-method.c later as well.  */
+   use of it in method.c later as well.  */
 tree
 make_type_decl (name, type)
      tree name, type;
@@ -1958,6 +1985,37 @@ decls_match (newdecl, olddecl)
       else
        types_match = 0;
     }
+  else if (TREE_CODE (newdecl) == TEMPLATE_DECL
+          && TREE_CODE (olddecl) == TEMPLATE_DECL)
+    {
+       tree newargs = DECL_TEMPLATE_PARMS (newdecl);
+       tree oldargs = DECL_TEMPLATE_PARMS (olddecl);
+       int i, len = TREE_VEC_LENGTH (newargs);
+
+       if (TREE_VEC_LENGTH (oldargs) != len)
+         return 0;
+       
+       for (i = 0; i < len; i++)
+         {
+           tree newarg = TREE_VEC_ELT (newargs, i);
+           tree oldarg = TREE_VEC_ELT (oldargs, i);
+           if (TREE_CODE (newarg) != TREE_CODE (oldarg))
+             return 0;
+           else if (TREE_CODE (newarg) == IDENTIFIER_NODE)
+             /* continue */;
+           else if (! comptypes (TREE_TYPE (newarg), TREE_TYPE (oldarg), 1))
+             return 0;
+         }
+
+       if (DECL_TEMPLATE_IS_CLASS (newdecl)
+           != DECL_TEMPLATE_IS_CLASS (olddecl))
+         types_match = 0;
+       else if (DECL_TEMPLATE_IS_CLASS (newdecl))
+         types_match = 1;
+       else
+         types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
+                                    DECL_TEMPLATE_RESULT (newdecl));
+    }
   else
     {
       if (TREE_TYPE (newdecl) == error_mark_node)
@@ -2028,7 +2086,7 @@ warn_extern_redeclared_static (newdecl, olddecl)
    If safely possible, alter OLDDECL to look like NEWDECL, and return 1.
    Otherwise, return 0.  */
 
-static int
+int
 duplicate_decls (newdecl, olddecl)
      register tree newdecl, olddecl;
 {
@@ -2038,8 +2096,7 @@ duplicate_decls (newdecl, olddecl)
   int new_defines_function;
   tree previous_c_decl = NULL_TREE;
 
-  if (TREE_CODE (newdecl) == FUNCTION_DECL
-      && is_overloaded_fn (olddecl))
+  if (TREE_CODE (newdecl) == FUNCTION_DECL && is_overloaded_fn (olddecl))
     {
       olddecl = get_first_fn (olddecl);
 
@@ -2144,6 +2201,8 @@ duplicate_decls (newdecl, olddecl)
       cp_error ("declaration of C function `%#D' conflicts with", newdecl);
       cp_error_at ("previous declaration `%#D' here", previous_c_decl);
     }
+  else if (!types_match && TREE_CODE (newdecl) == TEMPLATE_DECL)
+    return 0;
   else if (!types_match)
     {
       tree oldtype = TREE_TYPE (olddecl);
@@ -2238,7 +2297,7 @@ duplicate_decls (newdecl, olddecl)
       char *errmsg = redeclaration_error_message (newdecl, olddecl);
       if (errmsg)
        {
-         error_with_decl (newdecl, errmsg);
+         cp_error (errmsg, newdecl);
          if (DECL_NAME (olddecl) != NULL_TREE)
            cp_error_at ((DECL_INITIAL (olddecl)
                          && current_binding_level == global_binding_level)
@@ -2295,6 +2354,8 @@ duplicate_decls (newdecl, olddecl)
        DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
       if (DECL_CHAIN (newdecl) == NULL_TREE)
        DECL_CHAIN (newdecl) = DECL_CHAIN (olddecl);
+      if (DECL_NEXT_METHOD (newdecl) == NULL_TREE)
+       DECL_NEXT_METHOD (newdecl) = DECL_NEXT_METHOD (olddecl);
       if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
        DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
     }
@@ -2325,6 +2386,10 @@ duplicate_decls (newdecl, olddecl)
 #endif
     }
 
+  if (TREE_CODE (olddecl) == TEMPLATE_DECL
+      && DECL_TEMPLATE_INFO (olddecl)->length)
+    DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
+  
   /* Special handling ensues if new decl is a function definition.  */
   new_defines_function = (TREE_CODE (newdecl) == FUNCTION_DECL
                          && DECL_INITIAL (newdecl) != NULL_TREE);
@@ -2381,7 +2446,8 @@ duplicate_decls (newdecl, olddecl)
            layout_type (TREE_TYPE (newdecl));
          if (TREE_CODE (newdecl) != FUNCTION_DECL
              && TREE_CODE (newdecl) != TYPE_DECL
-             && TREE_CODE (newdecl) != CONST_DECL)
+             && TREE_CODE (newdecl) != CONST_DECL
+             && TREE_CODE (newdecl) != TEMPLATE_DECL)
            layout_decl (newdecl, 0);
        }
       else
@@ -2630,7 +2696,7 @@ pushdecl (x)
          cp_error_at ("`%#D' used prior to declaration", x);
        }
 
-      if (t != NULL_TREE)
+      else if (t != NULL_TREE)
        {
          if (TREE_CODE (t) == PARM_DECL)
            {
@@ -2639,25 +2705,23 @@ pushdecl (x)
            }
          file = DECL_SOURCE_FILE (t);
          line = DECL_SOURCE_LINE (t);
-       }
 
-      if (t != NULL_TREE
-         && (TREE_CODE (t) != TREE_CODE (x) || is_overloaded_fn (t)))
-       {
-         if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
+         if (TREE_CODE (t) != TREE_CODE (x))
            {
-             /* We do nothing special here, because C++ does such nasty
-                things with TYPE_DECLs.  Instead, just let the TYPE_DECL
-                get shadowed, and know that if we need to find a TYPE_DECL
-                for a given name, we can look in the IDENTIFIER_TYPE_VALUE
-                slot of the identifier.  */
-             ;
+             if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (x) == TYPE_DECL)
+               {
+                 /* We do nothing special here, because C++ does such nasty
+                    things with TYPE_DECLs.  Instead, just let the TYPE_DECL
+                    get shadowed, and know that if we need to find a TYPE_DECL
+                    for a given name, we can look in the IDENTIFIER_TYPE_VALUE
+                    slot of the identifier.  */
+                 ;
+               }
+             else if (duplicate_decls (x, t))
+               return t;
            }
          else if (duplicate_decls (x, t))
-           return t;
-       }
-      else if (t != NULL_TREE && duplicate_decls (x, t))
-       {
+           {
 #if 0
          /* This is turned off until I have time to do it right (bpk).  */
 
@@ -2682,14 +2746,16 @@ pushdecl (x)
            }
 #endif
 
-         /* Due to interference in memory reclamation (X may be
-            obstack-deallocated at this point), we must guard against
-            one really special case.  */
-         if (current_function_decl == x)
-           current_function_decl = t;
-
-         return t;
+             /* Due to interference in memory reclamation (X may be
+                obstack-deallocated at this point), we must guard against
+                one really special case.  */
+             if (current_function_decl == x)
+               current_function_decl = t;
+             
+             return t;
+           }
        }
+      
 
       /* If declaring a type as a typedef, and the type has no known
         typedef name, install this TYPE_DECL as its typedef name.  */
@@ -3272,7 +3338,7 @@ redeclaration_error_message (newdecl, olddecl)
       if (comptypes (newdecl, olddecl, 0))
        return 0;
       else
-       return "redefinition of `%s'";
+       return "redefinition of `%#D'";
     }
   else if (TREE_CODE (newdecl) == FUNCTION_DECL)
     {
@@ -3294,12 +3360,18 @@ redeclaration_error_message (newdecl, olddecl)
               && !(DECL_INLINE (newdecl) && DECL_EXTERNAL (newdecl))))
        {
          if (DECL_NAME (olddecl) == NULL_TREE)
-           return "`%s' not declared in class";
+           return "`%#D' not declared in class";
          else
-           return "redefinition of `%s'";
+           return "redefinition of `%#D'";
        }
       return 0;
     }
+  else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
+    {
+      if (DECL_INITIAL (olddecl) && DECL_INITIAL (newdecl))
+       return "redefinition of `%#D'";
+      return 0;
+    }
   else if (current_binding_level == global_binding_level)
     {
       /* Objects declared at top level:  */
@@ -3309,11 +3381,11 @@ redeclaration_error_message (newdecl, olddecl)
       /* Reject two definitions.  */
       if (DECL_INITIAL (olddecl) != NULL_TREE
          && DECL_INITIAL (newdecl) != NULL_TREE)
-       return "redefinition of `%s'";
+       return "redefinition of `%#D'";
       /* Now we have two tentative defs, or one tentative and one real def.  */
       /* Insist that the linkage match.  */
       if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
-       return "conflicting declarations of `%s'";
+       return "conflicting declarations of `%#D'";
       return 0;
     }
   else
@@ -3322,7 +3394,7 @@ redeclaration_error_message (newdecl, olddecl)
       /* Reject two definitions, and reject a definition
         together with an external reference.  */
       if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
-       return "redeclaration of `%s'";
+       return "redeclaration of `%#D'";
       return 0;
     }
 }
@@ -3780,8 +3852,7 @@ lookup_nested_type (type, context)
    definitions if there are many, or return 0 if it is undefined.
 
    If PREFER_TYPE is > 0, we prefer TYPE_DECLs.
-   If PREFER_TYPE is = 0, we prefer non-TYPE_DECLs.
-   If PREFER_TYPE is < 0, we arbitrate according to lexical context.  */
+   Otherwise we prefer non-TYPE_DECLs.  */
 
 tree
 lookup_name (name, prefer_type)
@@ -3840,9 +3911,8 @@ lookup_name (name, prefer_type)
          if (val == val_as_type || prefer_type > 0
              || looking_for_typename > 0)
            return val_as_type;
-         if (prefer_type == 0)
-           return val;
-         return arbitrate_lookup (name, val, val_as_type);
+
+         return val;
        }
       if (TREE_TYPE (val) == error_mark_node)
        return error_mark_node;
@@ -5233,7 +5303,7 @@ start_decl (declarator, declspecs, initialized, raises)
           my_friendly_abort (13);
         }
       else if (TREE_CODE (result) == FUNCTION_DECL)
-        tem = push_overloaded_decl (tem, 0);
+        /*tem = push_overloaded_decl (tem, 0)*/;
       else if (TREE_CODE (result) == VAR_DECL
               || TREE_CODE (result) == TYPE_DECL)
        {
@@ -6329,9 +6399,17 @@ complete_array_type (type, initial_value, do_default)
 
   if (maxindex)
     {
+      tree itype;
+
       TYPE_DOMAIN (type) = build_index_type (maxindex);
       if (!TREE_TYPE (maxindex))
        TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+      if (initial_value)
+        itype = TREE_TYPE (initial_value);
+      else
+       itype = NULL;
+      if (itype && !TYPE_DOMAIN (itype))
+       TYPE_DOMAIN (itype) = TYPE_DOMAIN (type);
     }
 
   /* Lay out the type now that we can get the real answer.  */
@@ -6947,8 +7025,20 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
 
        case IDENTIFIER_NODE:
          dname = decl;
-         name = IDENTIFIER_POINTER (decl);
          decl = NULL_TREE;
+
+         if (IDENTIFIER_TYPENAME_P (dname))
+           {
+             my_friendly_assert (flags == NO_SPECIAL, 154);
+             flags = TYPENAME_FLAG;
+             ctor_return_type = TREE_TYPE (dname);
+             return_type = return_conversion;
+           }
+
+         if (IDENTIFIER_OPNAME_P (dname))
+           name = operator_name_string (dname);
+         else
+           name = IDENTIFIER_POINTER (dname);
          break;
 
        case RECORD_TYPE:
@@ -6965,15 +7055,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
          decl = NULL_TREE;
          break;
 
-       case TYPE_EXPR:
-         my_friendly_assert (flags == NO_SPECIAL, 154);
-         flags = TYPENAME_FLAG;
-         name = "operator <typename>"; /* We don't know the type yet.  */
-         /* Go to the absdcl.  */
-         decl = TREE_OPERAND (decl, 0);
-         return_type = return_conversion;
-         break;
-
          /* C++ extension */
        case SCOPE_REF:
 /*
@@ -7214,6 +7295,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
        type = void_type_node;
       else if (return_type == return_ctor)
        type = TYPE_POINTER_TO (ctor_return_type);
+      else if (return_type == return_conversion)
+       type = ctor_return_type;
       else if (current_class_type
               && IS_SIGNATURE (current_class_type)
               && (RIDBIT_SETP (RID_TYPEDEF, specbits)
@@ -7247,6 +7330,17 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
       error ("return type specification for constructor invalid");
       type = TYPE_POINTER_TO (ctor_return_type);
     }
+  else if (return_type == return_conversion)
+    {
+      if (comp_target_types (type, ctor_return_type, 1) == 0)
+       cp_error ("operator `%T' declared to return `%T'",
+                 ctor_return_type, type);
+      else
+       cp_pedwarn ("return type specified for `operator %T'",
+                   ctor_return_type);
+
+      type = ctor_return_type;
+    }
 
   ctype = NULL_TREE;
 
@@ -7508,11 +7602,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
            error ("typedef declaration includes an initializer");
   
          /* To process a class-local typedef declaration, we descend down
-            the chain of declspecs looking for the `typedef' spec.  When we
-            find it, we splice it out of the chain of declspecs, and then
-            recursively call `grokdeclarator' with the original declarator
-            and with the newly adjusted declspecs.  This call should return
-            FIELD_DECL node with the TREE_TYPE (and other parts) set
+            the chain of declspecs looking for the `typedef' spec.  When
+            we find it, we replace it with `static', and then recursively
+            call `grokdeclarator' with the original declarator and with
+            the newly adjusted declspecs.  This call should return a
+            FIELD_DECL node with the TREE_TYPE (and other parts) set
             appropriately.  We can then just change the TREE_CODE on that
             from FIELD_DECL to TYPE_DECL and we're done.  */
 
@@ -7523,11 +7617,19 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
              if (TREE_VALUE (scanner) == ridpointers[(int) RID_TYPEDEF])
                break;
            }
-         if (previous_declspec)
-           TREE_CHAIN (previous_declspec) = TREE_CHAIN (scanner);
+
+         if (scanner == IDENTIFIER_AS_LIST (ridpointers [(int) RID_TYPEDEF]))
+           {
+             if (previous_declspec)
+               TREE_CHAIN (previous_declspec)
+                 = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
+             else
+               declspecs
+                 = IDENTIFIER_AS_LIST (ridpointers [(int) RID_STATIC]);
+           }
          else
-           declspecs = TREE_CHAIN (scanner);
-  
+           TREE_VALUE (scanner) = ridpointers[(int) RID_STATIC];
+
          /* In the recursive call to grokdeclarator we need to know
             whether we are working on a signature-local typedef.  */
          if (IS_SIGNATURE (current_class_type))
@@ -7650,7 +7752,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
         qualify the member name.
         an ADDR_EXPR (for &...),
         a BIT_NOT_EXPR (for destructors)
-        a TYPE_EXPR (for operator typenames)
 
         At this point, TYPE is the type of elements of an array,
         or for a function to return, or for a pointer to point to.
@@ -7854,7 +7955,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                && (friendp == 0 || dname == current_class_name))
              ctype = current_class_type;
 
-           if (ctype && flags == TYPENAME_FLAG)
+           if (ctype && return_type == return_conversion)
              TYPE_HAS_CONVERSION (ctype) = 1;
            if (ctype && constructor_name (ctype) == dname)
              {
@@ -7910,17 +8011,12 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                        return void_type_node;
                      }
                    {
-                     int inlinep, staticp;
-                     inlinep = RIDBIT_SETP (RID_INLINE, specbits);
-                     staticp = RIDBIT_SETP (RID_STATIC, specbits);
-                     RIDBIT_RESET (RID_INLINE, specbits);
-                     RIDBIT_RESET (RID_STATIC, specbits);
-                     if (RIDBIT_ANY_SET (specbits))
+                     RID_BIT_TYPE tmp_bits;
+                     bcopy ((void*)&specbits, (void*)&tmp_bits, 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 (inlinep)
-                       RIDBIT_SET (RID_INLINE, specbits);
-                     if (staticp)
-                       RIDBIT_SET (RID_STATIC, specbits);
                    }
                    type = TYPE_POINTER_TO (ctype);
                    if (decl_context == FIELD &&
@@ -7982,9 +8078,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
              /* Say it's a definition only for the CALL_EXPR
                 closest to the identifier.  */
              funcdef_p =
-               (inner_decl &&
-                (TREE_CODE (inner_decl) == IDENTIFIER_NODE
-                 || TREE_CODE (inner_decl) == TYPE_EXPR)) ? funcdef_flag : 0;
+               (inner_decl && TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+                 ? funcdef_flag : 0;
 
              /* FIXME: This is where default args should be fully
                 processed.  */
@@ -8242,12 +8337,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                            return t;
                          }
 
-                       if (flags == TYPENAME_FLAG)
-                         cp_error ("type conversion is not a member of structure `%T'", ctype);
-                       else
-                         cp_error
-                           ("field `%D' is not a member of structure `%T'",
-                            sname, ctype);
+                       cp_error
+                         ("field `%D' is not a member of structure `%T'",
+                          sname, ctype);
                      }
 
                    if (current_class_type)
@@ -8283,28 +8375,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
 
                declarator = sname;
              }
-           else if (TREE_CODE (sname) == TYPE_EXPR)
-             {
-               /* A TYPE_EXPR will change types out from under us.
-                  So do the TYPE_EXPR now, and make this SCOPE_REF
-                  inner to the TYPE_EXPR's CALL_EXPR.
-
-                  This does not work if we don't get a CALL_EXPR back.
-                  I did not think about error recovery, hence the
-                  my_friendly_abort.  */
-
-               /* Get the CALL_EXPR.  */
-               sname = grokoptypename (sname, 0);
-               my_friendly_assert (TREE_CODE (sname) == CALL_EXPR, 157);
-               type = TREE_TYPE (TREE_OPERAND (sname, 0));
-               /* Scope the CALL_EXPR's name.  */
-               TREE_OPERAND (declarator, 1) = TREE_OPERAND (sname, 0);
-               /* Put the SCOPE_EXPR in the CALL_EXPR's innermost position.  */
-               TREE_OPERAND (sname, 0) = declarator;
-               /* Now work from the CALL_EXPR.  */
-               declarator = sname;
-               continue;
-             }
            else if (TREE_CODE (sname) == SCOPE_REF)
              my_friendly_abort (17);
            else
@@ -8329,21 +8399,6 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
          declarator = TREE_OPERAND (declarator, 0);
          break;
 
-       case TYPE_EXPR:
-         declarator = grokoptypename (declarator, 0);
-         if (explicit_int != -1)
-           {
-             tree stype = TREE_TYPE (TREE_OPERAND (declarator, 0));
-             if (comp_target_types (type, stype, 1) == 0)
-               cp_error ("`operator %T' declared to return `%T'", stype,
-                         type);
-             else
-               cp_pedwarn ("return type specified for `operator %T'", type);
-           }
-         dname = declarator;
-         type = TREE_TYPE (TREE_OPERAND (declarator, 0));
-         break;
-
        case RECORD_TYPE:
        case UNION_TYPE:
        case ENUMERAL_TYPE:
@@ -8667,6 +8722,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
                           && ! funcdef_flag
                           && RIDBIT_NOTSETP (RID_STATIC, specbits)
                           && RIDBIT_NOTSETP (RID_INLINE, specbits)));
+           if (TREE_CODE (type) == METHOD_TYPE)
+             publicp 
+               |= (ctype && CLASSTYPE_INTERFACE_KNOWN (ctype))
+                 || (!funcdef_flag && RIDBIT_NOTSETP (RID_INLINE, specbits));
            decl = grokfndecl (ctype, type, declarator,
                               virtualp, flags, quals,
                               raises, friendp ? -1 : 0, publicp);
@@ -8843,8 +8902,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized, raises)
           into some other file, so we don't clear TREE_PUBLIC for them.  */
        publicp
          = ((ctype
-             && CLASSTYPE_INTERFACE_KNOWN (ctype)
-             && ! CLASSTYPE_INTERFACE_ONLY (ctype))
+             && CLASSTYPE_INTERFACE_KNOWN (ctype))
             || !(RIDBIT_SETP (RID_STATIC, specbits)
                  || RIDBIT_SETP (RID_INLINE, specbits)));
 
@@ -10212,7 +10270,7 @@ build_enumerator (name, value)
   if (value)
     STRIP_TYPE_NOPS (value);
 
-  /* Make up for hacks in cp-lex.c.  */
+  /* Make up for hacks in lex.c.  */
   if (value == integer_zero_node)
     value = build_int_2 (0, 0);
   else if (value == integer_one_node)
@@ -10573,7 +10631,9 @@ start_function (declspecs, declarator, raises, pre_parsed_p)
   else if (pre_parsed_p == 0)
     {
       current_function_decl = pushdecl (decl1);
-      if (TREE_CODE (current_function_decl) == TREE_LIST)
+      if (TREE_CODE (current_function_decl) == TREE_LIST
+         || (DECL_ASSEMBLER_NAME (current_function_decl)
+             != DECL_ASSEMBLER_NAME (decl1)))
        {
          /* @@ revert to modified original declaration.  */
          decl1 = DECL_MAIN_VARIANT (decl1);
index db455777115b3253c7f2dde55fb29826d78d193e..c752e2303f827b484411882aa4dd6ac0e4cf8461 100644 (file)
@@ -58,7 +58,7 @@ static int temp_name_counter;
    can have the same name.  */
 static int global_temp_name_counter;
 
-/* Flag used when debugging cp-spew.c */
+/* Flag used when debugging spew.c */
 
 extern int spew_debug;
 \f
@@ -129,6 +129,10 @@ int warn_implicit = 1;
 
 int warn_ctor_dtor_privacy = 1;
 
+/* True if we want output of vtables to be controlled by whether
+   we seen the class's first non-inline virtual function. */
+int flag_vtable_hack = 0;
+
 /* Nonzero means give string constants the type `const char *'
    to get extra warnings from them.  These warnings will be too numerous
    to be useful, except in thoroughly ANSIfied programs.  */
@@ -360,6 +364,7 @@ static struct { char *string; int *variable; int on_value;} lang_f_options[] =
   {"ansi-overloading", &flag_ansi_overloading, 1},
   {"huge-objects", &flag_huge_objects, 1},
   {"conserve-space", &flag_conserve_space, 1},
+  {"vtable-hack", &flag_vtable_hack, 1},
 };
 
 /* Decode the string P as a language-specific option.
@@ -1619,107 +1624,12 @@ groktypefield (declspecs, parmlist)
   return decl;
 }
 
-/* The precedence rules of this grammar (or any other deterministic LALR
-   grammar, for that matter), place the CALL_EXPR somewhere where we
-   may not want it.  The solution is to grab the first CALL_EXPR we see,
-   pretend that that is the one that belongs to the parameter list of
-   the type conversion function, and leave everything else alone.
-   We pull it out in place.
-
-   CALL_REQUIRED is non-zero if we should complain if a CALL_EXPR
-   does not appear in DECL.  */
 tree
-grokoptypename (decl, call_required)
-     tree decl;
-     int call_required;
+grokoptypename (declspecs, declarator)
+     tree declspecs, declarator;
 {
-  tree tmp, last;
-
-  my_friendly_assert (TREE_CODE (decl) == TYPE_EXPR, 195);
-
-  tmp = TREE_OPERAND (decl, 0);
-  last = NULL_TREE;
-
-  while (tmp)
-    {
-      switch (TREE_CODE (tmp))
-       {
-       case CALL_EXPR:
-         {
-           tree parms = TREE_OPERAND (tmp, 1);
-
-           if (last)
-             TREE_OPERAND (last, 0) = TREE_OPERAND (tmp, 0);
-           else
-             TREE_OPERAND (decl, 0) = TREE_OPERAND (tmp, 0);
-
-           last = grokdeclarator (TREE_OPERAND (decl, 0),
-                                  TREE_TYPE (decl),
-                                  TYPENAME, 0, NULL_TREE);
-           TREE_OPERAND (tmp, 0) = build_typename_overload (last);
-           TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
-
-           if (parms
-               && TREE_CODE (TREE_VALUE (parms)) == TREE_LIST)
-             TREE_VALUE (parms)
-               = grokdeclarator (TREE_VALUE (TREE_VALUE (parms)),
-                                 TREE_PURPOSE (TREE_VALUE (parms)),
-                                 TYPENAME, 0, NULL_TREE);
-           if (parms)
-             {
-               if (TREE_VALUE (parms) != void_type_node)
-                 cp_error ("`operator %T' requires empty parameter list",
-                           last);
-               else
-                 /* Canonicalize parameter lists.  */
-                 TREE_OPERAND (tmp, 1) = void_list_node;
-             }
-
-           return tmp;
-         }
-
-       case INDIRECT_REF:
-       case ADDR_EXPR:
-       case ARRAY_REF:
-         break;
-
-       case SCOPE_REF:
-         /* This is legal when declaring a conversion to
-            something of type pointer-to-member.  */
-         if (TREE_CODE (TREE_OPERAND (tmp, 1)) == INDIRECT_REF)
-           {
-             tmp = TREE_OPERAND (tmp, 1);
-           }
-         else
-           {
-#if 0
-             /* We may need to do this if grokdeclarator cannot handle this.  */
-             error ("type `member of class %s' invalid return type",
-                    TYPE_NAME_STRING (TREE_OPERAND (tmp, 0)));
-             TREE_OPERAND (tmp, 1) = build_parse_node (INDIRECT_REF, TREE_OPERAND (tmp, 1));
-#endif
-             tmp = TREE_OPERAND (tmp, 1);
-           }
-         break;
-
-       default:
-         my_friendly_abort (196);
-       }
-      last = tmp;
-      tmp = TREE_OPERAND (tmp, 0);
-    }
-
-  last = grokdeclarator (TREE_OPERAND (decl, 0),
-                        TREE_TYPE (decl),
-                        TYPENAME, 0, NULL_TREE);
-
-  if (call_required)
-    cp_error ("`operator %T' construct requires parameter list", last);
-
-  tmp = build_parse_node (CALL_EXPR, build_typename_overload (last),
-                         void_list_node, NULL_TREE);
-  TREE_TYPE (TREE_OPERAND (tmp, 0)) = last;
-  return tmp;
+  tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL_TREE);
+  return build_typename_overload (t);
 }
 
 /* When a function is declared with an initializer,
@@ -2420,6 +2330,22 @@ static void
 finish_vtable_vardecl (prev, vars)
      tree prev, vars;
 {
+  tree ctype = DECL_CONTEXT (vars);
+  if (flag_vtable_hack && !CLASSTYPE_INTERFACE_KNOWN (ctype))
+    {
+      tree method;
+      for (method = CLASSTYPE_METHODS (ctype); method != NULL_TREE;
+          method = DECL_NEXT_METHOD (method))
+       {
+         if (DECL_VINDEX (method) != NULL_TREE && !DECL_SAVED_INSNS (method))
+           {
+             TREE_PUBLIC (vars) = 1;
+             DECL_EXTERNAL (vars) = DECL_EXTERNAL (method);
+             break;
+           }
+       }
+    }
+
   if (write_virtuals >= 0
       && ! DECL_EXTERNAL (vars) && (TREE_PUBLIC (vars) || TREE_USED (vars)))
     {
@@ -2468,6 +2394,8 @@ finish_vtable_vardecl (prev, vars)
 
       rest_of_decl_compilation (vars, 0, 1, 1);
     }
+  else if (TREE_USED (vars) && flag_vtable_hack)
+    assemble_external (vars);
   /* We know that PREV must be non-zero here.  */
   TREE_CHAIN (prev) = TREE_CHAIN (vars);
 }
@@ -2783,7 +2711,7 @@ finish_file ()
      There are several ways of getting the same effect, from changing the
      way that iterators over the chain treat the elements that pertain to
      virtual function tables, moving the implementation of this code to
-     cp-decl.c (where we can manipulate global_binding_level directly),
+     decl.c (where we can manipulate global_binding_level directly),
      popping the garbage after pushing it and slicing away the vtable
      stuff, or just leaving it alone. */
 
@@ -2821,3 +2749,134 @@ finish_file ()
   if (flag_detailed_statistics)
     dump_time_statistics ();
 }
+
+/* This is something of the form 'A()()()()()+1' that has turned out to be an
+   expr.  Since it was parsed like a type, we need to wade through and fix
+   that.  Unfortunately, since operator() is left-associative, we can't use
+   tail recursion.  In the above example, TYPE is `A', and DECL is
+   `()()()()()'.
+
+   Maybe this shouldn't be recursive, but how often will it actually be
+   used?  (jason) */
+tree
+reparse_absdcl_as_expr (type, decl)
+     tree type, decl;
+{
+  /* do build_functional_cast (type, NULL_TREE) at bottom */
+  if (TREE_OPERAND (decl, 0) == NULL_TREE)
+    return build_functional_cast (type, NULL_TREE);
+
+  /* recurse */
+  decl = reparse_decl_as_expr (type, TREE_OPERAND (decl, 0));
+
+  decl = build_x_function_call (decl, NULL_TREE, current_class_decl);
+
+  if (TREE_CODE (decl) == CALL_EXPR && TREE_TYPE (decl) != void_type_node)
+    decl = require_complete_type (decl);
+
+  return decl;
+}
+
+/* This is something of the form `int ((int)(int)(int)1)' that has turned
+   out to be an expr.  Since it was parsed like a type, we need to wade
+   through and fix that.  Since casts are right-associative, we are
+   reversing the order, so we don't have to recurse.
+
+   In the above example, DECL is the `(int)(int)(int)', and EXPR is the
+   `1'.  */
+tree
+reparse_absdcl_as_casts (decl, expr)
+     tree decl, expr;
+{
+  tree type;
+  
+  if (TREE_CODE (expr) == CONSTRUCTOR)
+    {
+      type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
+      decl = TREE_OPERAND (decl, 0);
+
+      if (IS_SIGNATURE (type))
+       {
+         error ("cast specifies signature type");
+         return error_mark_node;
+       }
+
+      expr = digest_init (type, expr, (tree *) 0);
+      if (TREE_CODE (type) == ARRAY_TYPE && TYPE_SIZE (type) == 0)
+       {
+         int failure = complete_array_type (type, expr, 1);
+         if (failure)
+           my_friendly_abort (78);
+       }
+    }
+
+  while (decl)
+    {
+      type = groktypename (TREE_VALUE (TREE_OPERAND (decl, 1)));
+      decl = TREE_OPERAND (decl, 0);
+      expr = build_c_cast (type, expr);
+    }
+
+  return expr;
+}
+
+/* Recursive helper function for reparse_decl_as_expr.  It may be a good
+   idea to reimplement this using an explicit stack, rather than recursion. */
+static tree
+reparse_decl_as_expr1 (decl)
+     tree decl;
+{
+  switch (TREE_CODE (decl))
+    {
+    case IDENTIFIER_NODE:
+      return do_identifier (decl);
+    case INDIRECT_REF:
+      return build_x_indirect_ref
+       (reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)), "unary *");
+    case ADDR_EXPR:
+      return build_x_unary_op (ADDR_EXPR,
+                              reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+    case BIT_NOT_EXPR:
+      return build_x_unary_op (BIT_NOT_EXPR,
+                              reparse_decl_as_expr1 (TREE_OPERAND (decl, 0)));
+    }
+  my_friendly_abort (5);
+}
+
+/* This is something of the form `int (*a)++' that has turned out to be an
+   expr.  It was only converted into parse nodes, so we need to go through
+   and build up the semantics.  Most of the work is done by
+   reparse_decl_as_expr1, above.
+
+   In the above example, TYPE is `int' and DECL is `*a'.  */
+tree
+reparse_decl_as_expr (type, decl)
+     tree type, decl;
+{
+  decl = build_tree_list (NULL_TREE, reparse_decl_as_expr1 (decl));
+  return build_functional_cast (type, decl);
+}
+
+/* This is something of the form `int (*a)' that has turned out to be a
+   decl.  It was only converted into parse nodes, so we need to do the
+   checking that make_{pointer,reference}_declarator do. */
+
+tree
+finish_decl_parsing (decl)
+     tree decl;
+{
+  switch (TREE_CODE (decl))
+    {
+    case IDENTIFIER_NODE:
+      return decl;
+    case INDIRECT_REF:
+      return make_pointer_declarator
+       (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
+    case ADDR_EXPR:
+      return make_reference_declarator
+       (NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
+    case BIT_NOT_EXPR:
+      TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
+      return decl;
+    }
+}
index 21feb772b47382fe210f65d5e295131634f98375..335a304798aa37df2a4d12140ffdef15ca673df8 100644 (file)
@@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 /* cp_printer is the type of a function which converts an argument into
    a string for digestion by printf.  The cp_printer function should deal
    with all memory management; the functions in this file will not free
-   the char*s returned.  See cp-error.c for an example use of this code.  */
+   the char*s returned.  See error.c for an example use of this code.  */
 
 typedef char* cp_printer PROTO((HOST_WIDE_INT, int));
 extern cp_printer * cp_printers[256];
index 75167fcdf4ed37cd117faf105af950f5e04c755f..3cc3ce8e05e47fc930ec74264ce1b206c5c28121 100644 (file)
@@ -76,6 +76,7 @@ static char *scratch_firstobj;
 # define OB_FINISH() (obstack_1grow (&scratch_obstack, '\0'))
 # define OB_PUTI(CST) do { sprintf (digit_buffer, "%d", (CST)); \
                           OB_PUTCP (digit_buffer); } while (0)
+# define OB_UNPUT(N) obstack_blank (&scratch_obstack, - (N));
 
 # define NEXT_CODE(t) (TREE_CODE (TREE_TYPE (t)))
 
@@ -131,11 +132,11 @@ dump_type (t, v)
   switch (TREE_CODE (t))
     {
     case ERROR_MARK:
-      OB_PUTS ("<error>");
+      OB_PUTS ("{error}");
       break;
 
     case UNKNOWN_TYPE:
-      OB_PUTS ("<unknown type>");
+      OB_PUTS ("{unknown type}");
       break;
 
     case TREE_LIST:
@@ -206,9 +207,7 @@ dump_type (t, v)
       break;
 
     case TEMPLATE_TYPE_PARM:
-      OB_PUTS ("<template type parm ");
       OB_PUTID (TYPE_IDENTIFIER (t));
-      OB_PUTC ('>');
       break;
 
     case UNINSTANTIATED_P_TYPE:
@@ -230,30 +229,35 @@ dump_type (t, v)
       break;
 
     default:
-      my_friendly_abort (68);
-      
+      sorry ("`%s' not supported by dump_type",
+            tree_code_name[(int) TREE_CODE (t)]);
     }
 }
 
-/* Print out a class declaration, in the form `class foo'. */
-static void
-dump_aggr_type (t, v)
+static char *
+aggr_variety (t)
      tree t;
-     int v;                    /* verbose? */
 {
-  tree name;
-  char *variety;
-
   if (TREE_CODE (t) == ENUMERAL_TYPE)
-    variety = "enum";
+    return "enum";
   else if (TREE_CODE (t) == UNION_TYPE)
-    variety = "union";
+    return "union";
   else if (TYPE_LANG_SPECIFIC (t) && CLASSTYPE_DECLARED_CLASS (t))
-    variety = "class";
+    return "class";
   else if (TYPE_LANG_SPECIFIC (t) && IS_SIGNATURE (t))
-    variety = "signature";
+    return "signature";
   else
-    variety = "struct";
+    return "struct";
+}
+
+/* Print out a class declaration, in the form `class foo'. */
+static void
+dump_aggr_type (t, v)
+     tree t;
+     int v;                    /* verbose? */
+{
+  tree name;
+  char *variety = aggr_variety (t);
 
   dump_readonly_or_volatile (t, after);
 
@@ -278,13 +282,13 @@ dump_aggr_type (t, v)
 
   if (ANON_AGGRNAME_P (name))
     {
-      OB_PUTS ("<anonymous");
+      OB_PUTS ("{anonymous");
       if (!v)
        {
          OB_PUTC (' ');
          OB_PUTCP (variety);
        }
-      OB_PUTC ('>');
+      OB_PUTC ('}');
     }
   else
     OB_PUTID (name);
@@ -369,13 +373,12 @@ dump_type_prefix (t, v)
     case OFFSET_TYPE:
     offset_type:
       dump_type_prefix (TREE_TYPE (t), v);
-      if (NEXT_CODE (t) != FUNCTION_TYPE && NEXT_CODE (t) != METHOD_TYPE)
-       OB_PUTC (' ');
-      if (TREE_CODE (t) == OFFSET_TYPE)
-       dump_type (TYPE_OFFSET_BASETYPE (t), 0);
-      else                     /* pointer to member function */
-       dump_type (TYPE_METHOD_BASETYPE (TREE_TYPE (t)), 0);
-      OB_PUTC2 (':', ':');
+      if (TREE_CODE (t) == OFFSET_TYPE)        /* pmfs deal with this in d_t_p */
+       {
+         OB_PUTC (' ');
+         dump_type (TYPE_OFFSET_BASETYPE (t), 0);
+         OB_PUTC2 (':', ':');
+       }
       OB_PUTC ('*');
       dump_readonly_or_volatile (t, none);
       break;
@@ -416,7 +419,8 @@ dump_type_prefix (t, v)
       break;
       
     default:
-      my_friendly_abort (65);
+      sorry ("`%s' not supported by dump_type_prefix",
+            tree_code_name[(int) TREE_CODE (t)]);
     }
 }
 
@@ -483,7 +487,8 @@ dump_type_suffix (t, v)
       break;
 
     default:
-      my_friendly_abort (67);
+      sorry ("`%s' not supported by dump_type_suffix",
+            tree_code_name[(int) TREE_CODE (t)]);
     }
 }
 
@@ -576,7 +581,7 @@ dump_decl (t, v)
       if (DECL_NAME (t))
        dump_decl (DECL_NAME (t), v);
       else
-       OB_PUTS ("<anon>");
+       OB_PUTS ("{anon}");
       if (v > 0) dump_type_suffix (TREE_TYPE (t), v);
       break;
 
@@ -636,16 +641,41 @@ dump_decl (t, v)
       break;
 
     case TEMPLATE_DECL:
-      switch (NEXT_CODE (t))
-       {
-       case METHOD_TYPE:
-       case FUNCTION_TYPE:
-         dump_function_decl (t, v);
-         break;
+      {
+       tree args = DECL_TEMPLATE_PARMS (t);
+       int i, len = TREE_VEC_LENGTH (args);
+       OB_PUTS ("template <");
+       for (i = 0; i < len; i++)
+         {
+           tree arg = TREE_VEC_ELT (args, i);
+           if (TREE_CODE (arg) == IDENTIFIER_NODE)
+             {
+               OB_PUTS ("class ");
+               OB_PUTID (arg);
+             }
+           else
+             dump_decl (arg, 1);
+           OB_PUTC2 (',', ' ');
+         }
+       OB_UNPUT (2);
+       OB_PUTC2 ('>', ' ');
 
-       default:
-         my_friendly_abort (353);
-       }
+       if (DECL_TEMPLATE_IS_CLASS (t))
+         {
+           OB_PUTS ("class ");
+           OB_PUTID (DECL_NAME (t));
+         }
+       else switch (NEXT_CODE (t))
+         {
+         case METHOD_TYPE:
+         case FUNCTION_TYPE:
+           dump_function_decl (t, v);
+           break;
+
+         default:
+           my_friendly_abort (353);
+         }
+      }
       break;
 
     case LABEL_DECL:
@@ -667,7 +697,8 @@ dump_decl (t, v)
       break;
 
     default:
-      my_friendly_abort (70);
+      sorry ("`%s' not supported by dump_decl",
+            tree_code_name[(int) TREE_CODE (t)]);
     }
 }
 
@@ -1157,6 +1188,22 @@ dump_expr (t, nop)
       OB_PUTC ('}');
       break;
 
+    case OFFSET_REF:
+      {
+       tree ob = TREE_OPERAND (t, 0);
+       if (TREE_CODE (ob) == NOP_EXPR
+           && TREE_OPERAND (ob, 0) == error_mark_node
+           && TREE_CODE (TREE_OPERAND (t, 1)) == FUNCTION_DECL)
+           /* A::f */
+         dump_expr (TREE_OPERAND (t, 1), 0);
+       else
+         {
+           sorry ("operand of OFFSET_REF not understood");
+           goto error;
+         }
+       break;
+      }
+
       /*  This list is incomplete, but should suffice for now.
          It is very important that `sorry' does not call
          `report_error_function'.  That could cause an infinite loop.  */
@@ -1167,7 +1214,7 @@ dump_expr (t, nop)
       /* fall through to ERROR_MARK...  */
     case ERROR_MARK:
     error:
-      OB_PUTCP ("/* error */");
+      OB_PUTCP ("{error}");
       break;
     }
 }
@@ -1321,7 +1368,7 @@ op_as_string (p, v)
   static char buf[] = "operator                ";
 
   if (p == 0)
-    return "<unknown>";
+    return "{unknown}";
   
   strcpy (buf + 9, opname_tab [p]);
   return buf;
index 4d956fc73a6c6503ce6d4f91470ce0d33eefeedb..d0fe130add8575070e04e02d4f0b63f21b202244 100644 (file)
@@ -349,7 +349,7 @@ void
 finish_exception_decl (cname, decl)
      tree cname, decl;
 {
-  /* In cp-decl.h.  */
+  /* In decl.h.  */
   extern tree last_function_parms;
 
   /* An exception declaration.  */
index ef491092c5a3d6b8116d406429c6e6863c58ae91..1878c86a5142074430a9663f0d06441955ed0bf8 100644 (file)
@@ -22,6 +22,8 @@ Questions and comments to mrs@@cygnus.com.
 * Templates::                   
 * Access Control::              
 * Error Reporting::             
+* Parser::                      
+* Copying Objects::             
 * Concept Index::               
 @end menu
 
@@ -77,19 +79,19 @@ An example would be:
 
 @example
 extern "C" int printf(const char*, ...);
-struct A { virtual void f() { } };
-struct B : virtual A { int b; B() : b(0) {} void f() { b++; } };
-struct C : B {};
-struct D : B {};
-struct E : C, D {};
+struct A @{ virtual void f() @{ @} @};
+struct B : virtual A @{ int b; B() : b(0) @{@} void f() @{ b++; @} @};
+struct C : B @{@};
+struct D : B @{@};
+struct E : C, D @{@};
 int main()
-{
+@{
   E e;
   C& c = e; D& d = e;
   c.f(); d.f();
   printf ("C::b = %d, D::b = %d\n", e.C::b, e.D::b);
   return 0;
-}
+@}
 @end example
 
 This will print out 2, 0, instead of 1,1.
@@ -984,7 +986,7 @@ TREE_PROTECTED and TREE_PRIVATE are used to record the access levels
 granted by the containing class.  BEWARE: TREE_PUBLIC means something
 completely unrelated to access control!
 
-@node Error Reporting, Concept Index, Access Control, Top
+@node Error Reporting, Parser, Access Control, Top
 @section Error Reporting
 
 The C++ frontend uses a call-back mechanism to allow functions to print
@@ -1022,7 +1024,110 @@ To have the line number on the error message indicate the line of the
 DECL, use @code{cp_error_at} and its ilk; to indicate which argument you want,
 use @code{%+D}, or it will default to the first.
 
-@node Concept Index,  , Error Reporting, Top
+@node Parser, Copying Objects, Error Reporting, Top
+@section Parser
+
+Some comments on the parser:
+
+The @code{after_type_declarator} / @code{notype_declarator} hack is
+necessary in order to allow redeclarations of @code{TYPENAME}s, for
+instance
+
+@example
+typedef int foo;
+class A @{
+  char *foo;
+@};
+@end example
+
+In the above, the first @code{foo} is parsed as a @code{notype_declarator},
+and the second as a @code{after_type_declarator}.
+
+Ambiguities:
+
+There are currently four reduce/reduce ambiguities in the parser.  They are:
+
+1) Between @code{template_parm} and
+@code{named_class_head_sans_basetype}, for the tokens @code{aggr
+identifier}.  This situation occurs in code looking like
+
+@example
+template <class T> class A @{ @};
+@end example
+
+It is ambiguous whether @code{class T} should be parsed as the
+declaration of a template type parameter named @code{T} or an unnamed
+constant parameter of type @code{class T}.  Section 14.6, paragraph 3 of
+the January '94 working paper states that the first interpretation is
+the correct one.  This ambiguity results in four reduce/reduce conflicts.
+
+2) Between @code{primary} and @code{typename} for code like @samp{int()}
+in places where both can be accepted, such as the argument to
+@code{sizeof}.  Section 8.1 of the pre-San Diego working paper specifies
+that these ambiguous constructs will be interpreted as @code{typename}s.
+This ambiguity results in six reduce/reduce conflicts.
+
+3) Between @code{primary}/@code{functional_cast} and
+@code{expr_or_declarator}/@code{complex_direct_notype_declarator}, for
+various token strings.  This situation occurs in code looking like
+
+@example
+int (*a);
+@end example
+
+This code is ambiguous; it could be a declaration of the variable
+@samp{a} as a pointer to @samp{int}, or it could be a functional cast of
+@samp{*a} to @samp{int}.  Section 6.8 specifies that the former
+interpretation is correct.  This ambiguity results in 12 reduce/reduce
+conflicts.  Ack.
+
+4) Between @code{after_type_declarator} and @code{parm}, for the token
+@code{TYPENAME}.  This occurs in (as one example) code like
+
+@example
+typedef int foo, bar;
+class A @{
+  foo (bar);
+@};
+@end example
+
+What is @code{bar} inside the class definition?  We currently interpret
+it as a @code{parm}, as does Cfront, but IBM xlC interprets it as an
+@code{after_type_declarator}.  I suspect that xlC is correct, in light
+of 7.1p2, which says "The longest sequence of @i{decl-specifiers} that
+could possibly be a type name is taken as the @i{decl-specifier-seq} of
+a @i{declaration}."  However, it seems clear that this rule must be
+violated in the case of constructors, so...
+
+Unlike the others, this ambiguity is not recognized by the Working Paper.
+
+@node  Copying Objects, Concept Index, Parser, Top
+@section Copying Objects
+
+The generated copy assignment operator in g++ does not currently do the
+right thing for multiple inheritance involving virtual bases; it just
+calls the copy assignment operators for its direct bases.  What it
+should probably do is:
+
+1) Split up the copy assignment operator for all classes that have
+vbases into "copy my vbases" and "copy everything else" parts.  Or do
+the trickiness that the constructors do to ensure that vbases don't get
+initialized by intermediate bases.
+
+2) Wander through the class lattice, find all vbases for which no
+intermediate base has a user-defined copy assignment operator, and call
+their "copy everything else" routines.  If not all of my vbases satisfy
+this criterion, warn, because this may be surprising behavior.
+
+3) Call the "copy everything else" routine for my direct bases.
+
+If we only have one direct base, we can just foist everything off onto
+them.
+
+This issue is currently under discussion in the core reflector
+(2/28/94).
+
+@node Concept Index,  , Copying Objects, Top
 @section Concept Index
 
 @printindex cp
index 12e0a640703938a26bcc8b1504653c7b4cff636e..eeb5de65a2110da92305bfe482fcccee80133ad7 100644 (file)
@@ -1872,7 +1872,7 @@ get_type_value (name)
 }
   
 \f
-/* This code could just as well go in `cp-class.c', but is placed here for
+/* This code could just as well go in `class.c', but is placed here for
    modularity.  */
 
 /* For an expression of the form CNAME :: NAME (PARMLIST), build
@@ -1992,7 +1992,7 @@ build_member_call (cname, name, parmlist)
    @@ Prints out lousy diagnostics for operator <typename>
    @@ fields.
 
-   @@ This function should be rewritten and placed in cp-search.c.  */
+   @@ This function should be rewritten and placed in search.c.  */
 tree
 build_offset_ref (cname, name)
      tree cname, name;
@@ -2024,12 +2024,8 @@ build_offset_ref (cname, name)
                      name);
          return error_mark_node;
        }
-      if (TREE_CODE (t) == TYPE_DECL)
-       {
-         cp_error ("member `%D' is just a type declaration", t);
-         return error_mark_node;
-       }
-      if (TREE_CODE (t) == VAR_DECL || TREE_CODE (t) == CONST_DECL)
+      if (TREE_CODE (t) == TYPE_DECL || TREE_CODE (t) == VAR_DECL
+         || TREE_CODE (t) == CONST_DECL)
        {
          TREE_USED (t) = 1;
          return t;
@@ -2170,8 +2166,8 @@ build_offset_ref (cname, name)
 
   if (TREE_CODE (t) == TYPE_DECL)
     {
-      cp_error ("member `%D' is just a type declaration", t);
-      return error_mark_node;
+      TREE_USED (t) = 1;
+      return t;
     }
   /* static class members and class-specific enum
      values can be returned without further ado.  */
@@ -3036,6 +3032,13 @@ build_new (placement, decl, init, use_global_new)
          /* probably meant to be a vec new */
          tree this_nelts;
 
+         while (TREE_OPERAND (absdcl, 0)
+                && TREE_CODE (TREE_OPERAND (absdcl, 0)) == ARRAY_REF)
+           {
+             last_absdcl = absdcl;
+             absdcl = TREE_OPERAND (absdcl, 0);
+           }
+
          has_array = 1;
          this_nelts = TREE_OPERAND (absdcl, 1);
          if (this_nelts != error_mark_node)
@@ -3369,6 +3372,12 @@ build_new (placement, decl, init, use_global_new)
        }
     }
  done:
+  if (rval && TREE_TYPE (rval) != build_pointer_type (type))
+    {
+      /* The type of new int [3][3] is not int *, but int [3] * */
+      rval = build_c_cast (build_pointer_type (type), rval);
+    }
+
   if (pending_sizes)
     rval = build_compound_expr (chainon (pending_sizes,
                                         build_tree_list (NULL_TREE, rval)));
index 1252aed187a87d5a8ca9c56e9bf4a42a3cce1a15..1570489fc2a6cbd82f1f4f58ed3b98d848da3e71 100644 (file)
@@ -25,7 +25,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    the GNU library available, so FILE objects just don't cut it.
 
    This file is written as a separate module, but can be included by
-   cp-lex.c for very minor efficiency gains (primarily in function
+   lex.c for very minor efficiency gains (primarily in function
    inlining).  */
 
 #include <stdio.h>
@@ -97,7 +97,7 @@ free_input (inp)
 static int putback_char = -1;
 
 /* Some of these external functions are declared inline in case this file
-   is included in cp-lex.c.  */
+   is included in lex.c.  */
 
 inline
 void
index 233a33b5cc970a62ebbabeac19053ef3101f59aa..8f7c2bea92a10055d66562cc4cbc6af53bd9c622 100644 (file)
@@ -313,7 +313,7 @@ my_get_run_time ()
 \f
 /* Table indexed by tree code giving a string containing a character
    classifying the tree code.  Possibilities are
-   t, d, s, c, r, <, 1 and 2.  See cp-tree.def for details.  */
+   t, d, s, c, r, <, 1 and 2.  See cp/tree.def for details.  */
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
 
@@ -1036,7 +1036,7 @@ extract_interface_info ()
     interface_unknown = TREE_INT_CST_HIGH (fileinfo);
 }
 
-/* Return nonzero if S and T are not considered part of an
+/* Return nonzero if S is not considered part of an
    INTERFACE/IMPLEMENTATION pair.  Otherwise, return 0.  */
 static int
 interface_strcmp (s)
@@ -1046,8 +1046,6 @@ interface_strcmp (s)
   struct impl_files *ifiles;
   char *s1;
 
-  s = FILE_NAME_NONDIRECTORY (s);
-
   for (ifiles = impl_file_chain; ifiles; ifiles = ifiles->next)
     {
       char *t1 = ifiles->filename;
@@ -1087,7 +1085,7 @@ set_typedecl_interface_info (prev, vars)
   tree type = TREE_TYPE (vars);
 
   CLASSTYPE_INTERFACE_ONLY (type) = TREE_INT_CST_LOW (fileinfo)
-    = interface_strcmp (DECL_SOURCE_FILE (vars));
+    = interface_strcmp (FILE_NAME_NONDIRECTORY (DECL_SOURCE_FILE (vars)));
 }
 
 void
@@ -1109,7 +1107,7 @@ set_vardecl_interface_info (prev, vars)
 \f
 /* Called from the top level: if there are any pending inlines to
    do, set up to process them now.  This function sets up the first function
-   to be parsed; after it has been, the rule for fndef in cp-parse.y will
+   to be parsed; after it has been, the rule for fndef in parse.y will
    call process_next_inline to start working on the next one.  */
 void
 do_pending_inlines ()
@@ -2432,19 +2430,39 @@ check_newline ()
                      && getch () == 'e'
                      && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
                    {
-                     int warned_interface = 0;
+                     int warned_already = 0;
+                     char *main_filename = input_filename;
 
-                     /* Read to newline.  */
+                     main_filename = FILE_NAME_NONDIRECTORY (main_filename);
+                     while (c == ' ' || c == '\t')
+                       c = getch ();
+                     if (c != '\n')
+                       {
+                         put_back (c);
+                         token = real_yylex ();
+                         if (token != STRING
+                             || TREE_CODE (yylval.ttype) != STRING_CST)
+                           {
+                             error ("invalid `#pragma interface'");
+                             goto skipline;
+                           }
+                         main_filename = TREE_STRING_POINTER (yylval.ttype);
+                         c = getch();
+                         put_back (c);
+                       }
+
+                     while (c == ' ' || c == '\t')
+                       c = getch ();
 
                      while (c != '\n')
                        {
-                         c = getch ();
-                         if (!warned_interface && extra_warnings
+                         if (!warned_already && extra_warnings
                              && c != ' ' && c != '\t' && c != '\n')
                            {
                              warning ("garbage after `#pragma interface' ignored");
-                             warned_interface = 1;
+                             warned_already = 1;
                            }
+                         c = getch ();
                        }
 
                      write_virtuals = 3;
@@ -2459,6 +2477,7 @@ check_newline ()
                          if (main_input_filename == 0)
                            main_input_filename = input_filename;
 
+#ifdef AUTO_IMPLEMENT
                          filename = FILE_NAME_NONDIRECTORY (main_input_filename);
                          fi = get_time_identifier (filename);
                          fi = IDENTIFIER_CLASS_VALUE (fi);
@@ -2468,9 +2487,10 @@ check_newline ()
                          impl_file_chain = (struct impl_files *)permalloc (sizeof (struct impl_files));
                          impl_file_chain->filename = filename;
                          impl_file_chain->next = 0;
+#endif
                        }
 
-                     interface_only = interface_strcmp (input_filename);
+                     interface_only = interface_strcmp (main_filename);
                      interface_unknown = 0;
                      TREE_INT_CST_LOW (fileinfo) = interface_only;
                      TREE_INT_CST_HIGH (fileinfo) = interface_unknown;
@@ -2490,8 +2510,10 @@ check_newline ()
                           && getch () == 'n'
                           && ((c = getch ()) == ' ' || c == '\t' || c == '\n'))
                    {
+                     int warned_already = 0;
                      char *main_filename = main_input_filename ? main_input_filename : input_filename;
 
+                     main_filename = FILE_NAME_NONDIRECTORY (main_filename);
                      while (c == ' ' || c == '\t')
                        c = getch ();
                      if (c != '\n')
@@ -2505,13 +2527,24 @@ check_newline ()
                              goto skipline;
                            }
                          main_filename = TREE_STRING_POINTER (yylval.ttype);
+                         c = getch();
+                         put_back (c);
                        }
-                     main_filename = FILE_NAME_NONDIRECTORY (main_filename);
 
-                     /* read to newline.  */
-                     while (c != '\n')
+                     while (c == ' ' || c == '\t')
                        c = getch ();
 
+                     while (c != '\n')
+                       {
+                         if (!warned_already && extra_warnings
+                             && c != ' ' && c != '\t' && c != '\n')
+                           {
+                             warning ("garbage after `#pragma implementation' ignored");
+                             warned_already = 1;
+                           }
+                         c = getch ();
+                       }
+
                      if (write_virtuals == 3)
                        {
                          struct impl_files *ifiles = impl_file_chain;
index a212f5c8d6411793fd57f9bf4d8402a59fe54af7..457fa39502ddc5226bbd0ed39b0fbf3c73036437 100644 (file)
@@ -1,4 +1,4 @@
-/* Define constants and variables for communication with cp-parse.y.
+/* Define constants and variables for communication with parse.y.
    Copyright (C) 1987, 1992, 1993 Free Software Foundation, Inc.
    Hacked by Michael Tiemann (tiemann@cygnus.com)
    and by Brendan Kehoe (brendan@cygnus.com).
index 83750436546e4b4b7e2090f3f1aa85811ad9b3ee..03450659777b97fbf5802351f52cec625c1e1996 100644 (file)
@@ -929,6 +929,8 @@ build_typename_overload (type)
   build_overload_name (type, 0, 1);
   id = get_identifier (obstack_base (&scratch_obstack));
   IDENTIFIER_OPNAME_P (id) = 1;
+  IDENTIFIER_GLOBAL_VALUE (id) = TYPE_NAME (type);
+  TREE_TYPE (id) = type;
   return id;
 }
 
index 933cd444005ceb52d0768b67698aed18416e84d3..70026d345f761496fdbaf24b3cbef156ea015044 100644 (file)
@@ -177,7 +177,7 @@ empty_parms ()
 %nonassoc IF
 %nonassoc ELSE
 
-%left IDENTIFIER TYPENAME PTYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS
+%left IDENTIFIER TYPENAME PTYPENAME TYPENAME_COLON SCSPEC TYPESPEC TYPE_QUAL ENUM AGGR ELLIPSIS SCOPED_TYPENAME TYPEOF SIGOF START_DECLARATOR OPERATOR
 
 %left '{' ',' ';'
 
@@ -194,10 +194,11 @@ empty_parms ()
 %left <code> LSHIFT RSHIFT
 %left <code> '+' '-'
 %left <code> '*' '/' '%'
-%right <code> UNARY PLUSPLUS MINUSMINUS
+%left <code> POINTSAT_STAR DOT_STAR
+%right <code> UNARY PLUSPLUS MINUSMINUS '~'
 %left HYPERUNARY
 %left <ttype> PAREN_STAR_PAREN LEFT_RIGHT
-%left <code> POINTSAT POINTSAT_STAR '.' DOT_STAR '(' '['
+%left <code> POINTSAT '.' '(' '['
 
 %right SCOPE                   /* C++ extension */
 %nonassoc NEW DELETE RAISE RAISES RERAISE TRY EXCEPT CATCH THROW
@@ -206,7 +207,7 @@ empty_parms ()
 %type <code> unop
 
 %type <ttype> identifier IDENTIFIER TYPENAME CONSTANT expr nonnull_exprlist
-%type <ttype> optional_identifier paren_expr_or_null
+%type <ttype> optional_identifier paren_expr_or_null nontrivial_exprlist
 %type <ttype> expr_no_commas cast_expr unary_expr primary string STRING
 %type <ttype> typed_declspecs reserved_declspecs
 %type <ttype> typed_typespecs reserved_typespecquals
@@ -216,18 +217,29 @@ empty_parms ()
 %type <ttype> init initlist maybeasm
 %type <ttype> asm_operands nonnull_asm_operands asm_operand asm_clobbers
 %type <ttype> maybe_attribute attribute_list attrib
-%type <ttype> abs_member_declarator after_type_member_declarator
 
 %type <ttype> compstmt except_stmts ansi_except_stmts implicitly_scoped_stmt
 
 %type <ttype> declarator notype_declarator after_type_declarator
+%type <ttype> notype_declarator1 after_type_declarator1
+%type <ttype> direct_notype_declarator direct_after_type_declarator
 
 %type <ttype> structsp opt.component_decl_list component_decl_list
 %type <ttype> component_decl components component_declarator
+%type <ttype> notype_components notype_component_declarator
+%type <ttype> after_type_component_declarator after_type_component_declarator0
+%type <ttype> notype_component_declarator0
 %type <ttype> enumlist enumerator
-%type <ttype> typename absdcl absdcl1 type_quals abs_or_notype_decl
-%type <ttype> xexpr see_typename parmlist parms parm bad_parm
+%type <ttype> type_id absdcl absdcl1 type_quals
+%type <ttype> direct_abstract_declarator conversion_declarator
+%type <ttype> new_type_id new_declarator direct_new_declarator
+%type <ttype> xexpr parmlist parms parm bad_parm
 %type <ttype> identifiers_or_typenames
+%type <ttype> fcast_or_absdcl regcast_or_absdcl sub_cast_expr
+%type <ttype> expr_or_declarator complex_notype_declarator1
+%type <ttype> notype_unqualified_id
+%type <ttype> complex_direct_notype_declarator functional_cast
+%type <ttype> named_parm complex_parmlist typed_declspecs1 parms_comma
 
 /* C++ extensions */
 %type <ttype> typename_scope
@@ -242,11 +254,10 @@ empty_parms ()
 %type <ttype> class_head base_class_list
 %type <itype> base_class_access_list
 %type <ttype> base_class maybe_base_class_list base_class.1
-%type <ttype> after_type_declarator_no_typename
 %type <ttype> maybe_raises raise_identifier raise_identifiers ansi_raise_identifier ansi_raise_identifiers
 %type <ttype> component_declarator0 id_scope scoped_typename scoped_base_class
 %type <ttype> forhead.1 identifier_or_opname operator_name
-%type <ttype> new delete object object_star aggr
+%type <ttype> new delete object aggr
 /* %type <ttype> primary_no_id */
 %type <ttype> nonmomentary_expr
 %type <itype> forhead.2 initdcl0 notype_initdcl0 member_init_list
@@ -267,7 +278,7 @@ empty_parms ()
 
 %type <strtype> .pushlevel
 
-/* cp-spew.c depends on this being the last token.  Define
+/* spew.c depends on this being the last token.  Define
    any new tokens before this one!  */
 %token END_OF_SAVED_INPUT
 \f
@@ -373,8 +384,9 @@ template_parm_list:
 
 template_parm:
        /* The following rules introduce a new reduce/reduce
-          conflict: they are valid prefixes for a `structsp',
-          which means they could match a nameless parameter.
+          conflict on the ',' and '>' input tokens: they are valid
+          prefixes for a `structsp', which means they could match a
+          nameless parameter.  See 14.6, paragraph 3.
           By putting them before the `parm' rule, we get
           their match before considering them nameless parameter
           declarations.  */
@@ -440,19 +452,19 @@ template_def:
                    sorry ("template type defining a signature");
                  /* Maybe pedantic warning for union?
                     How about an enum? :-)  */
-                 end_template_decl ($1, $2, current_aggr);
+                 end_template_decl ($1, $2, current_aggr, 1);
                  reinit_parse_for_template (yychar, $1, $2);
                  yychar = YYEMPTY;
                }
          ';'
        | template_header named_class_head_sans_basetype ';'
                {
-                 end_template_decl ($1, $2, current_aggr);
+                 end_template_decl ($1, $2, current_aggr, 0);
                  /* declare $2 as template name with $1 parm list */
                }
        | template_header named_class_head_sans_basetype_defn ';'
                {
-                 end_template_decl ($1, $2, current_aggr);
+                 end_template_decl ($1, $2, current_aggr, 0);
                  /* declare $2 as template name with $1 parm list */
                }
        | template_header /* notype_initdcl0 ';' */
@@ -461,12 +473,14 @@ template_def:
                {
                  tree d;
                  int momentary;
+                 int def = ($6 != ';');
                  momentary = suspend_momentary ();
-                 d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0, $3);
+                 d = start_decl ($<ttype>2, /*current_declspecs*/NULL_TREE, 0,
+                                 $3);
                  cplus_decl_attributes (d, $5);
                  finish_decl (d, NULL_TREE, $4, 0);
-                 end_template_decl ($1, d, 0);
-                 if ($6 != ';')
+                 end_template_decl ($1, d, 0, def);
+                 if (def)
                    reinit_parse_for_template ((int) $6, $1, d);
                  resume_momentary (momentary);
                }
@@ -476,6 +490,7 @@ template_def:
                {
                  tree d;
                  int momentary;
+                 int def = ($7 != ';');
 
                  current_declspecs = $2;
                  momentary = suspend_momentary ();
@@ -484,8 +499,8 @@ template_def:
                  cplus_decl_attributes (d, $6);
                  finish_decl (d, NULL_TREE, $5, 0);
                  end_exception_decls ();
-                 end_template_decl ($1, d, 0);
-                 if ($7 != ';')
+                 end_template_decl ($1, d, 0, def);
+                 if (def)
                    {
                      reinit_parse_for_template ((int) $7, $1, d);
                      yychar = YYEMPTY;
@@ -493,17 +508,18 @@ template_def:
                  note_list_got_semicolon ($<ttype>2);
                  resume_momentary (momentary);
                }
-       | template_header declmods declarator fn_tmpl_end
+       | template_header declmods notype_declarator fn_tmpl_end
                {
+                 int def = ($4 != ';');
                  tree d = start_decl ($<ttype>3, $<ttype>2, 0, NULL_TREE);
                  finish_decl (d, NULL_TREE, NULL_TREE, 0);
-                 end_template_decl ($1, d, 0);
-                 if ($4 != ';')
+                 end_template_decl ($1, d, 0, def);
+                 if (def)
                    reinit_parse_for_template ((int) $4, $1, d);
                }
        /* Try to recover from syntax errors in templates.  */
-       | template_header error '}'     { end_template_decl ($1, 0, 0); }
-       | template_header error ';'     { end_template_decl ($1, 0, 0); }
+       | template_header error '}'     { end_template_decl ($1, 0, 0, 0); }
+       | template_header error ';'     { end_template_decl ($1, 0, 0, 0); }
        ;
 
 fn_tmpl_end: '{'               { $$ = '{'; }
@@ -521,8 +537,8 @@ datadef:
                    warning ("data definition has no type or storage class"); }
        | declmods notype_initdecls ';'
                {}
-       /* Normal case to make fast: "int i;".  */
-       | declmods declarator ';'
+       /* Normal case to make fast: "const i;".  */
+       | declmods notype_declarator ';'
                { tree d;
                  d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
                  finish_decl (d, NULL_TREE, NULL_TREE, 0);
@@ -660,7 +676,8 @@ fn.def1:
                  reinit_parse_for_function (); }
        ;
 
-/* more C++ complexity */
+/* more C++ complexity.  See component_decl for a comment on the
+   reduce/reduce conflict introduced by these rules.  */
 fn.def2:
          typed_declspecs '(' parmlist ')' type_quals maybe_raises
                {
@@ -705,7 +722,7 @@ fn.def2:
                  if (yychar == YYEMPTY)
                    yychar = YYLEX;
                  reinit_parse_for_method (yychar, $$); }
-       | declmods declarator maybe_raises
+       | declmods notype_declarator maybe_raises
                { $$ = start_method ($$, $2, $3);
                  if (! $$)
                    YYERROR1;
@@ -907,7 +924,7 @@ template_arg_list:
        ;
 
 template_arg:
-         typename
+         type_id
                { $$ = groktypename ($$); }
        | expr_no_commas  %prec UNARY
        ;
@@ -986,9 +1003,8 @@ unop:     '-'
                { $$ = TRUTH_NOT_EXPR; }
        ;
 
-expr:    nonnull_exprlist
+expr:    nontrivial_exprlist
                { $$ = build_x_compound_expr ($$); }
-       /* Ugly, but faster.  */
        | expr_no_commas
        ;
 
@@ -1097,13 +1113,23 @@ already_scoped_stmt:
        | simple_stmt
        ;
 
+nontrivial_exprlist:
+         expr_no_commas ',' expr_no_commas
+               { $$ = tree_cons (NULL_TREE, $$, 
+                                 build_tree_list (NULL_TREE, $3)); }
+       | expr_no_commas ',' error
+               { $$ = tree_cons (NULL_TREE, $$, 
+                                 build_tree_list (NULL_TREE, error_mark_node)); }
+       | nontrivial_exprlist ',' expr_no_commas
+               { chainon ($$, build_tree_list (NULL_TREE, $3)); }
+       | nontrivial_exprlist ',' error
+               { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); }
+       ;
+
 nonnull_exprlist:
          expr_no_commas
                { $$ = build_tree_list (NULL_TREE, $$); }
-       | nonnull_exprlist ',' expr_no_commas
-               { chainon ($$, build_tree_list (NULL_TREE, $3)); }
-       | nonnull_exprlist ',' error
-               { chainon ($$, build_tree_list (NULL_TREE, error_mark_node)); }
+       | nontrivial_exprlist
        ;
 
 unary_expr:
@@ -1123,7 +1149,7 @@ unary_expr:
                { $$ = build_x_indirect_ref ($2, "unary *"); }
        | '&' cast_expr   %prec UNARY
                { $$ = build_x_unary_op (ADDR_EXPR, $2); }
-       | '~' cast_expr   %prec UNARY
+       | '~' cast_expr
                { $$ = build_x_unary_op (BIT_NOT_EXPR, $2); }
        | unop cast_expr  %prec UNARY
                { $$ = build_x_unary_op ((enum tree_code) $$, $2);
@@ -1163,16 +1189,16 @@ unary_expr:
                        pedwarn ("ANSI C++ forbids using sizeof() on a function");
                    }
                  $$ = c_sizeof (TREE_TYPE ($2)); }
-       | SIZEOF '(' typename ')'  %prec HYPERUNARY
+       | SIZEOF '(' type_id ')'  %prec HYPERUNARY
                { $$ = c_sizeof (groktypename ($3)); }
        | ALIGNOF unary_expr  %prec UNARY
                { $$ = grok_alignof ($2); }
-       | ALIGNOF '(' typename ')'  %prec HYPERUNARY
+       | ALIGNOF '(' type_id ')'  %prec HYPERUNARY
                { $$ = c_alignof (groktypename ($3)); }
 
-       | .scope new typename %prec '='
+       | .scope new new_type_id %prec '='
                { $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
-       | .scope new '(' nonnull_exprlist ')' typename %prec '='
+       | .scope new '(' nonnull_exprlist ')' new_type_id %prec '='
                { $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); }
        | .scope new typespec '(' nonnull_exprlist ')'
                { $$ = build_new ($2, $3, $5, $$ != NULL_TREE); }
@@ -1185,37 +1211,24 @@ unary_expr:
                { $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
        | .scope new '(' nonnull_exprlist ')' typespec LEFT_RIGHT
                { $$ = build_new ($4, $6, NULL_TREE, $$ != NULL_TREE); }
-       | .scope new typename '=' init %prec '='
+       | .scope new new_type_id '=' init %prec '='
                { $$ = build_new ($2, $3, $5, $$ != NULL_TREE); }
-       | .scope new '(' nonnull_exprlist ')' typename '=' init %prec '='
+       | .scope new '(' nonnull_exprlist ')' new_type_id '=' init %prec '='
                { $$ = build_new ($4, $6, $8, $$ != NULL_TREE); }
-
-       /* I am not going to add placement syntax to the below complex rules
-          because Ken says the syntax is illegal. (mrs) */
-       /* I'm not sure why this is disallowed.  But since it is, and it
-          doesn't seem difficult to catch it, let's give a message, so
-          the programmer can fix it.  --Ken Raeburn  */
-       | .scope new '(' typed_typespecs absdcl ')' '[' nonmomentary_expr ']'
-               {
+       /* If you don't understand why this is illegal, read 5.3.4. (jason) */
+       | .scope new '(' type_id ')' '[' nonmomentary_expr ']'
+               { 
                  tree absdcl, typename;
 
-               illegal_new_array:
-                 absdcl = build_parse_node (ARRAY_REF, $5, $8);
-                 typename = build_decl_list ($4, absdcl);
+                 absdcl = build_parse_node (ARRAY_REF, TREE_VALUE ($4), $7);
+                 typename = build_decl_list (TREE_PURPOSE ($4), absdcl);
                  pedwarn ("ANSI C++ forbids array dimensions with parenthesized type");
                  $$ = build_new ($2, typename, NULL_TREE, $$ != NULL_TREE);
                }
-       | .scope new '(' nonempty_type_quals absdcl ')' '[' nonmomentary_expr ']'
-               { goto illegal_new_array; }
-
-       | .scope new '(' typed_typespecs absdcl ')'
-               { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$ != NULL_TREE); }
-       | .scope new '(' nonnull_exprlist ')' '(' typed_typespecs absdcl ')'
-               { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$ != NULL_TREE); }
-       | .scope new '(' nonempty_type_quals absdcl ')'
-               { $$ = build_new ($2, build_decl_list ($4, $5), NULL_TREE, $$ != NULL_TREE); }
-       | .scope new '(' nonnull_exprlist ')' '(' nonempty_type_quals absdcl ')'
-               { $$ = build_new ($4, build_decl_list ($7, $8), NULL_TREE, $$ != NULL_TREE); }
+       | .scope new '(' type_id ')'
+               { $$ = build_new ($2, $4, NULL_TREE, $$ != NULL_TREE); }
+       | .scope new '(' nonnull_exprlist ')' '(' type_id ')'
+               { $$ = build_new ($4, $7, NULL_TREE, $$ != NULL_TREE); }
        /* Unswallow a ':' which is probably meant for ?: expression.  */
        | .scope new TYPENAME_COLON
                { yyungetc (':', 1); $$ = build_new ($2, $3, NULL_TREE, $$ != NULL_TREE); }
@@ -1234,37 +1247,38 @@ unary_expr:
                    yychar = YYLEX; }
        ;
 
+/* This is necessary to postpone reduction of `int ((int)(int)(int))'.  */
+regcast_or_absdcl:
+         '(' type_id ')' %prec EMPTY
+               { $2 = tree_cons (NULL_TREE, $2, void_list_node);
+                 TREE_PARMLIST ($2) = 1;
+                 $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, 
+                                        NULL_TREE); }
+       | regcast_or_absdcl '(' type_id ')' %prec EMPTY
+               { $3 = tree_cons (NULL_TREE, $3, void_list_node);
+                 TREE_PARMLIST ($3) = 1;
+                 $$ = build_parse_node (CALL_EXPR, $$, $3, NULL_TREE); }
+       ;
+
 cast_expr:
-         unary_expr
-       | '(' typename ')' expr_no_commas  %prec UNARY
-               { tree type = groktypename ($2);
-                 $$ = build_c_cast (type, $4); }
-       | '(' typename ')' '{' initlist maybecomma '}'  %prec UNARY
-               { tree type = groktypename ($2);
+         sub_cast_expr
+       | regcast_or_absdcl sub_cast_expr  %prec UNARY
+               { $$ = reparse_absdcl_as_casts ($$, $2); }
+       | regcast_or_absdcl '{' initlist maybecomma '}'  %prec UNARY
+               { 
+                 tree init = build_nt (CONSTRUCTOR, NULL_TREE,
+                                       nreverse ($3)); 
+                 if (pedantic)
+                   pedwarn ("ANSI C++ forbids constructor-expressions");
+                 /* Indicate that this was a GNU C constructor expression.  */
+                 TREE_HAS_CONSTRUCTOR (init) = 1;
 
-                 if (IS_SIGNATURE (type))
-                   {
-                     error ("cast specifies signature type");
-                     $$ = error_mark_node;
-                   }
-                 else
-                   {
-                     tree init;
-                     init = build_nt (CONSTRUCTOR, NULL_TREE, nreverse ($5));
-                     if (pedantic)
-                       pedwarn ("ANSI C++ forbids constructor-expressions");
-                     /* Indicate that this was a GNU C constructor expression.  */
-                     TREE_HAS_CONSTRUCTOR (init) = 1;
-                     $$ = digest_init (type, init, (tree *) 0);
-                     if (TREE_CODE (type) == ARRAY_TYPE
-                         && TYPE_SIZE (type) == 0)
-                       {
-                         int failure = complete_array_type (type, $$, 1);
-                         if (failure)
-                           my_friendly_abort (78);
-                       }
-                   }
+                 $$ = reparse_absdcl_as_casts ($$, init);
                }
+       ;
+
+sub_cast_expr:
+         unary_expr
        | HEADOF '(' expr ')'
                { $$ = build_headof ($3); }
        | CLASSOF '(' expr ')'
@@ -1288,6 +1302,11 @@ cast_expr:
 
 expr_no_commas:
          cast_expr
+       /* Handle general members.  */
+       | expr_no_commas POINTSAT_STAR expr_no_commas
+               { $$ = build_x_binary_op (MEMBER_REF, $$, $3); }
+       | expr_no_commas DOT_STAR expr_no_commas
+               { $$ = build_m_component_ref ($$, $3); }
        | expr_no_commas '+' expr_no_commas
                { $$ = build_x_binary_op ($2, $$, $3); }
        | expr_no_commas '-' expr_no_commas
@@ -1333,11 +1352,6 @@ expr_no_commas:
                    $$ = rval;
                  else
                    $$ = build_modify_expr ($$, $2, $3); }
-       | primary DOT_STAR expr_no_commas %prec UNARY
-               { $$ = build_m_component_ref ($$, $3); }
-       /* Handle general members.  */
-       | object_star expr_no_commas   %prec UNARY
-               { $$ = build_x_binary_op (MEMBER_REF, $$, $2); }
 /* These extensions are not defined.  The second arg to build_m_component_ref
    is old, build_m_component_ref now does an implicit
    build_indirect_ref (x, NULL_PTR) on the second argument.
@@ -1345,7 +1359,7 @@ expr_no_commas:
                { $$ = build_m_component_ref ($$, build_x_unary_op (ADDR_EXPR, $3)); }
        | object unop expr_no_commas  %prec UNARY
                { $$ = build_m_component_ref ($$, build_x_unary_op ($2, $3)); }
-       | object '(' typename ')' expr_no_commas  %prec UNARY
+       | object '(' type_id ')' expr_no_commas  %prec UNARY
                { tree type = groktypename ($3);
                  $$ = build_m_component_ref ($$, build_c_cast (type, $5)); }
        | object primary_no_id  %prec UNARY
@@ -1353,16 +1367,44 @@ expr_no_commas:
 */
        ;
 
-primary:
-       IDENTIFIER
-               { $$ = do_identifier ($$); }
+notype_unqualified_id:
+         '~' see_typename TYPENAME
+               {
+               destructor_name:
+                 $$ = build_parse_node (BIT_NOT_EXPR, $3);
+               }
+       | '~' see_typename IDENTIFIER
+                { goto destructor_name; }
+       | '~' see_typename PTYPENAME
+                { goto destructor_name; }
        | operator_name
+       | IDENTIFIER
+       | PTYPENAME %prec EMPTY
+       ;
+
+expr_or_declarator:
+         '*' expr_or_declarator %prec UNARY
+               { $$ = build_parse_node (INDIRECT_REF, $2); }
+       | '&' expr_or_declarator %prec UNARY
+               { $$ = build_parse_node (ADDR_EXPR, $2); }
+       | notype_unqualified_id
+               { see_typename (); }
+       ;
+
+direct_notype_declarator:
+         complex_direct_notype_declarator
+       | notype_unqualified_id
+               { see_typename (); }
+       ;
+
+primary:
+         notype_unqualified_id
                {
-                 tree op = $$;
-                 if (TREE_CODE (op) != IDENTIFIER_NODE)
-                   $$ = op;
-                 else
+                 if (TREE_CODE ($$) == BIT_NOT_EXPR)
+                   $$ = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND ($$, 0));
+                 else if (IDENTIFIER_OPNAME_P ($$))
                    {
+                     tree op = $$;
                      $$ = lookup_name (op, 0);
                      if ($$ == NULL_TREE)
                        {
@@ -1372,7 +1414,9 @@ primary:
                          $$ = error_mark_node;
                        }
                    }
-               }
+                 else
+                   $$ = do_identifier ($$);
+               }               
        | CONSTANT
        | string
                { $$ = combine_strings ($$); }
@@ -1516,17 +1560,14 @@ primary:
                      $$ = build_c_cast (type, build_compound_expr ($3));
                    }
                }
-       | typespec '(' nonnull_exprlist ')'
-               { $$ = build_functional_cast ($$, $3); }
-       | typespec LEFT_RIGHT
-               { $$ = build_functional_cast ($$, NULL_TREE); }
+       | functional_cast
        /* Stroustrup RTTI */
-       | DYNAMIC_CAST '<' typename '>' '(' expr ')'
+       | DYNAMIC_CAST '<' type_id '>' '(' expr ')'
                { tree type = groktypename ($3);
                  $$ = build_dynamic_cast (type, $6); }
        | TYPEID '(' expr ')'
                { $$ = build_typeid ($3); }
-       | TYPEID '(' typename ')'
+       | TYPEID '(' type_id ')'
                { tree type = groktypename ($3);
                  $$ = get_typeid (type); }
        | SCOPE typespec '(' nonnull_exprlist ')'
@@ -1746,28 +1787,40 @@ object:   primary '.'
                }
        ;
 
-object_star: primary POINTSAT_STAR
-       ;
-
 decl:
          typed_declspecs initdecls ';'
                {
                  resume_momentary ($2);
-                 note_list_got_semicolon ($<ttype>$);
+                 note_list_got_semicolon ($1);
+               }
+       | typespec initdecls ';'
+               {
+                 resume_momentary ($2);
+                 if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
+                   note_got_semicolon ($1);
                }
        /* Normal case: make this fast.  */
        | typed_declspecs declarator ';'
-               { tree d;
+               { tree d = $1;
                  int yes = suspend_momentary ();
-                 d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
+                 d = start_decl ($2, d, 0, NULL_TREE);
                  finish_decl (d, NULL_TREE, NULL_TREE, 0);
                  resume_momentary (yes);
-                 note_list_got_semicolon ($<ttype>$);
+                 note_list_got_semicolon ($1);
+               }
+       | typespec declarator ';'
+               { tree d = get_decl_list ($1);
+                 int yes = suspend_momentary ();
+                 d = start_decl ($2, d, 0, NULL_TREE);
+                 finish_decl (d, NULL_TREE, NULL_TREE, 0);
+                 resume_momentary (yes);
+                 if (IS_AGGR_TYPE_CODE (TREE_CODE ($1)))
+                   note_got_semicolon ($1);
                }
        | declmods notype_initdecls ';'
                { resume_momentary ((int) $<itype>2); }
        /* Normal case: make this fast.  */
-       | declmods declarator ';'
+       | declmods notype_declarator ';'
                { tree d;
                  int yes = suspend_momentary ();
                  d = start_decl ($<ttype>2, $<ttype>$, 0, NULL_TREE);
@@ -1787,12 +1840,32 @@ decl:
    after an explicit typespec).  */
 
 declarator:
-         after_type_declarator
-       | notype_declarator
-       | START_DECLARATOR after_type_declarator
-               { $$ = $2; }
-       | START_DECLARATOR notype_declarator
-               { $$ = $2; }
+         after_type_declarator %prec EMPTY
+       | notype_declarator %prec EMPTY
+       ;
+
+/* This is necessary to postpone reduction of `int()()()()'.  */
+fcast_or_absdcl:
+         LEFT_RIGHT %prec EMPTY
+               { $$ = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (),
+                                        NULL_TREE); }
+       | fcast_or_absdcl LEFT_RIGHT %prec EMPTY
+               { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), 
+                                        NULL_TREE); }
+       ;
+
+/* ANSI type-id (8.1) */
+type_id:
+         typed_typespecs absdcl
+               { $$ = build_decl_list ($$, $2); }
+       | nonempty_type_quals absdcl
+               { $$ = build_decl_list ($$, $2); }
+       | typespec absdcl
+               { $$ = build_decl_list (get_decl_list ($$), $2); }
+       | typed_typespecs %prec EMPTY
+               { $$ = build_decl_list ($$, NULL_TREE); }
+       | nonempty_type_quals %prec EMPTY
+               { $$ = build_decl_list ($$, NULL_TREE); }
        ;
 
 /* Declspecs which contain at least one type specifier or typedef name.
@@ -1800,21 +1873,25 @@ declarator:
    A typedef'd name following these is taken as a name to be declared.  */
 
 typed_declspecs:
-         typespec      %prec HYPERUNARY
-               { if ($$) $$ = list_hash_lookup_or_cons ($$); }
-       | declmods typespec
-               { $$ = hash_tree_chain ($2, $$); }
+         typed_typespecs %prec EMPTY
+       | typed_declspecs1
+
+typed_declspecs1:
+         declmods typespec
+               { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
        | typespec reserved_declspecs   %prec HYPERUNARY
-               { $$ = hash_tree_chain ($$, $2); }
+               { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
        | declmods typespec reserved_declspecs
-               { $$ = hash_tree_chain ($2, hash_chainon ($3, $$)); }
+               { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+       | declmods typespec reserved_typespecquals
+               { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
+       | declmods typespec reserved_typespecquals reserved_declspecs
+               { $$ = decl_tree_cons (NULL_TREE, $2, 
+                                      chainon ($3, chainon ($4, $$))); }
        ;
 
-reserved_declspecs:  /* empty
-               { $$ = NULL_TREE; } */
-         typespecqual_reserved
-               { $$ = build_decl_list (NULL_TREE, $$); }
-       | SCSPEC
+reserved_declspecs:
+         SCSPEC
                { if (extra_warnings)
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($$));
@@ -1833,19 +1910,18 @@ reserved_declspecs:  /* empty
    to redeclare a typedef-name.  */
 
 declmods:
-         TYPE_QUAL
-               { $$ = IDENTIFIER_AS_LIST ($$);
-                 TREE_STATIC ($$) = 1; }
+         nonempty_type_quals %prec EMPTY
+               { TREE_STATIC ($$) = 1; }
        | SCSPEC
                { $$ = IDENTIFIER_AS_LIST ($$); }
        | declmods TYPE_QUAL
-               { $$ = hash_tree_chain ($2, $$);
+               { $$ = decl_tree_cons (NULL_TREE, $2, $$);
                  TREE_STATIC ($$) = 1; }
        | declmods SCSPEC
                { if (extra_warnings && TREE_STATIC ($$))
                    warning ("`%s' is not at beginning of declaration",
                             IDENTIFIER_POINTER ($2));
-                 $$ = hash_tree_chain ($2, $$);
+                 $$ = decl_tree_cons (NULL_TREE, $2, $$);
                  TREE_STATIC ($$) = TREE_STATIC ($1); }
        ;
 
@@ -1864,12 +1940,12 @@ typed_typespecs:
        | typespec reserved_typespecquals
                { $$ = decl_tree_cons (NULL_TREE, $$, $2); }
        | nonempty_type_quals typespec reserved_typespecquals
-               { $$ = decl_tree_cons (NULL_TREE, $2, hash_chainon ($3, $$)); }
+               { $$ = decl_tree_cons (NULL_TREE, $2, chainon ($3, $$)); }
        ;
 
 reserved_typespecquals:
          typespecqual_reserved
-               { $$ = get_decl_list ($$); }
+               { $$ = build_decl_list (NULL_TREE, $$); }
        | reserved_typespecquals typespecqual_reserved
                { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
        ;
@@ -1881,12 +1957,26 @@ reserved_typespecquals:
 typespec: structsp
        | TYPESPEC  %prec EMPTY
        | TYPENAME  %prec EMPTY
-       | scoped_typename
+       | scoped_typename %prec EMPTY
+       | SCOPE TYPENAME %prec EMPTY
+               { $$ = IDENTIFIER_GLOBAL_VALUE ($2);
+                  if (!$$)
+                   {
+                      error ("undeclared variable `%s' (first use here)",
+                      IDENTIFIER_POINTER ($2));
+                      $$ = error_mark_node;
+                      IDENTIFIER_GLOBAL_VALUE ($2) = error_mark_node;
+                   }
+                 else 
+                   {
+                     $$ = TREE_TYPE($$);
+                   }
+               }
        | TYPEOF '(' expr ')'
                { $$ = TREE_TYPE ($3);
                  if (pedantic)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
-       | TYPEOF '(' typename ')'
+       | TYPEOF '(' type_id ')'
                { $$ = groktypename ($3);
                  if (pedantic)
                    pedwarn ("ANSI C++ forbids `typeof'"); }
@@ -1904,7 +1994,7 @@ typespec: structsp
                      $$ = error_mark_node;
                    }
                }
-       | SIGOF '(' typename ')'
+       | SIGOF '(' type_id ')'
                { tree type = groktypename ($3);
 
                  if (IS_AGGR_TYPE (type))
@@ -1948,6 +2038,8 @@ maybeasm:
 initdcl0:
          declarator maybe_raises maybeasm maybe_attribute '='
                { current_declspecs = $<ttype>0;
+                 if (TREE_CODE (current_declspecs) != TREE_LIST)
+                   current_declspecs = get_decl_list (current_declspecs);
                  $<itype>5 = suspend_momentary ();
                  $<ttype>$ = start_decl ($<ttype>1, current_declspecs, 1, $2);
                  cplus_decl_attributes ($<ttype>$, $4); }
@@ -1958,6 +2050,8 @@ initdcl0:
        | declarator maybe_raises maybeasm maybe_attribute
                { tree d;
                  current_declspecs = $<ttype>0;
+                 if (TREE_CODE (current_declspecs) != TREE_LIST)
+                   current_declspecs = get_decl_list (current_declspecs);
                  $$ = suspend_momentary ();
                  d = start_decl ($<ttype>1, current_declspecs, 0, $2);
                  cplus_decl_attributes (d, $4);
@@ -2233,15 +2327,18 @@ named_class_head_sans_basetype:
        ;
 
 named_class_head_sans_basetype_defn:
-         aggr identifier_defn
+         aggr identifier_defn %prec EMPTY
                { current_aggr = $$; $$ = $2; }
        ;
 
+do_xref: /* empty */ %prec EMPTY
+       { $<ttype>$ = xref_tag (current_aggr, $<ttype>0, NULL_TREE, 1); }
+
+do_xref_defn: /* empty */ %prec EMPTY
+       { $<ttype>$ = xref_defn_tag (current_aggr, $<ttype>0, NULL_TREE); }
+
 named_class_head:
-         named_class_head_sans_basetype
-               {
-                 $<ttype>$ = xref_tag (current_aggr, $1, NULL_TREE, 1);
-               }
+         named_class_head_sans_basetype do_xref
          maybe_base_class_list %prec EMPTY
                {
                  if ($3)
@@ -2250,10 +2347,7 @@ named_class_head:
                    $$ = $<ttype>2;
                }
        |
-         named_class_head_sans_basetype_defn
-               {
-                 $<ttype>$ = xref_defn_tag (current_aggr, $1, NULL_TREE);
-               }
+         named_class_head_sans_basetype_defn do_xref_defn
          maybe_base_class_list %prec EMPTY
                {
                  if ($3)
@@ -2398,7 +2492,7 @@ base_class.1:
                      $$ = error_mark_node;
                    }
                }
-       | SIGOF '(' typename ')'
+       | SIGOF '(' type_id ')'
                {
                  if (current_aggr == signature_type_node)
                    {
@@ -2540,11 +2634,21 @@ component_decl_list:
        ;
 
 component_decl:
+       /* Do not add a "typed_declspecs declarator ';'" rule here for
+          speed; we need to call grok_x_components for enums, so the
+          speedup would be insignificant.  */
          typed_declspecs components ';'
                {
                  $$ = grok_x_components ($$, $2);
                  end_exception_decls ();
                }
+       /* These rules introduce a reduce/reduce conflict; in
+               typedef int foo, bar;
+               class A {
+                 foo (bar);
+               };
+          should "A::foo" be declared as a function or data member?  
+          In other words, is "bar" an after_type_declarator or a parmlist? */
        | typed_declspecs '(' parmlist ')' ';'
                { $$ = groktypefield ($$, $3); }
        | typed_declspecs '(' parmlist ')' '}'
@@ -2557,16 +2661,16 @@ component_decl:
                { error ("missing ';' before right brace");
                  yyungetc ('}', 0);
                  $$ = groktypefield ($$, empty_parms ()); }
-       | declmods components ';'
+       | declmods notype_components ';'
                { 
                  $$ = grok_x_components ($$, $2);
                  end_exception_decls ();
                }
        /* Normal case: make this fast.  */
-       | declmods declarator ';'
+       | declmods notype_declarator ';'
                { $$ = grokfield ($<ttype>2, $<ttype>$,
                                  NULL_TREE, NULL_TREE, NULL_TREE); }
-       | declmods components '}'
+       | declmods notype_components '}'
                { error ("missing ';' before right brace");
                  yyungetc ('}', 0);
                  $$ = grok_x_components ($$, $2);
@@ -2607,6 +2711,7 @@ component_decl:
                  $$ = grokfield ($$, NULL_TREE, $2, NULL_TREE, NULL_TREE); }
        ;
 
+/* The case of exactly one component is handled directly by component_decl. */
 components:
          /* empty: possibly anonymous */
                { $$ = NULL_TREE; }
@@ -2622,20 +2727,56 @@ components:
                }
        ;
 
+notype_components:
+         /* empty: possibly anonymous */
+               { $$ = NULL_TREE; }
+       | notype_component_declarator0
+       | notype_components ',' notype_component_declarator
+               {
+                 /* In this context, void_type_node encodes
+                    friends.  They have been recorded elsewhere.  */
+                 if ($$ == void_type_node)
+                   $$ = $3;
+                 else
+                   $$ = chainon ($$, $3);
+               }
+       ;
+
 component_declarator0:
-         declarator maybe_raises maybeasm maybe_attribute
+         after_type_component_declarator0
+       | notype_component_declarator0
+       ;
+
+component_declarator:
+         after_type_component_declarator
+       | notype_component_declarator
+       ;
+
+after_type_component_declarator0:
+         after_type_declarator maybe_raises maybeasm maybe_attribute
                { current_declspecs = $<ttype>0;
                  $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3);
                  cplus_decl_attributes ($$, $4); }
-       | declarator maybe_raises maybeasm maybe_attribute '=' init
+       | after_type_declarator maybe_raises maybeasm maybe_attribute '=' init
                { current_declspecs = $<ttype>0;
                  $$ = grokfield ($$, current_declspecs, $2, $6, $3);
                  cplus_decl_attributes ($$, $4); }
-       | IDENTIFIER ':' expr_no_commas maybe_attribute
+       | TYPENAME ':' expr_no_commas maybe_attribute
                { current_declspecs = $<ttype>0;
                  $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4); }
-       | TYPENAME ':' expr_no_commas maybe_attribute
+       ;
+
+notype_component_declarator0:
+         notype_declarator maybe_raises maybeasm maybe_attribute
+               { current_declspecs = $<ttype>0;
+                 $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3);
+                 cplus_decl_attributes ($$, $4); }
+       | notype_declarator maybe_raises maybeasm maybe_attribute '=' init
+               { current_declspecs = $<ttype>0;
+                 $$ = grokfield ($$, current_declspecs, $2, $6, $3);
+                 cplus_decl_attributes ($$, $4); }
+       | IDENTIFIER ':' expr_no_commas maybe_attribute
                { current_declspecs = $<ttype>0;
                  $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4); }
@@ -2645,17 +2786,26 @@ component_declarator0:
                  cplus_decl_attributes ($$, $3); }
        ;
 
-component_declarator:
-         declarator maybe_raises maybeasm maybe_attribute
+after_type_component_declarator:
+         after_type_declarator maybe_raises maybeasm maybe_attribute
                { $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3);
                  cplus_decl_attributes ($$, $4); }
-       | declarator maybe_raises maybeasm maybe_attribute '=' init
+       | after_type_declarator maybe_raises maybeasm maybe_attribute '=' init
                { $$ = grokfield ($$, current_declspecs, $2, $6, $3);
                  cplus_decl_attributes ($$, $4); }
-       | IDENTIFIER ':' expr_no_commas maybe_attribute
+       | TYPENAME ':' expr_no_commas maybe_attribute
                { $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4); }
-       | TYPENAME ':' expr_no_commas maybe_attribute
+       ;
+
+notype_component_declarator:
+         notype_declarator maybe_raises maybeasm maybe_attribute
+               { $$ = grokfield ($$, current_declspecs, $2, NULL_TREE, $3);
+                 cplus_decl_attributes ($$, $4); }
+       | notype_declarator maybe_raises maybeasm maybe_attribute '=' init
+               { $$ = grokfield ($$, current_declspecs, $2, $6, $3);
+                 cplus_decl_attributes ($$, $4); }
+       | IDENTIFIER ':' expr_no_commas maybe_attribute
                { $$ = grokbitfield ($$, current_declspecs, $3);
                  cplus_decl_attributes ($$, $4); }
        | ':' expr_no_commas maybe_attribute
@@ -2680,23 +2830,32 @@ enumerator:
                { $$ = build_enumerator ($$, $3); }
        ;
 
-/* ANSI type-id (8.1) */
-typename:
-         typed_typespecs absdcl
+/* ANSI new-type-id (5.3.4) */
+new_type_id:
+         typed_typespecs new_declarator
                { $$ = build_decl_list ($$, $2); }
-       | nonempty_type_quals absdcl
+       | nonempty_type_quals new_declarator
                { $$ = build_decl_list ($$, $2); }
+       | typed_typespecs %prec EMPTY
+               { $$ = build_decl_list ($$, NULL_TREE); }
+       | nonempty_type_quals %prec EMPTY
+               { $$ = build_decl_list ($$, NULL_TREE); }
        ;
 
 /* ANSI abstract-declarator (8.1) */
-absdcl:   /* an abstract declarator */
-       /* empty */ %prec EMPTY
-               { $$ = NULL_TREE; }
-       | absdcl1  %prec EMPTY
+absdcl:
+         absdcl1  %prec EMPTY
        | START_DECLARATOR absdcl1  %prec EMPTY
                { $$ = $2; }
        ;
 
+type_quals:
+         /* empty */ %prec EMPTY
+               { $$ = NULL_TREE; }
+       | type_quals TYPE_QUAL
+               { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
+       ;
+
 nonempty_type_quals:
          TYPE_QUAL
                { $$ = IDENTIFIER_AS_LIST ($$); }
@@ -2704,13 +2863,6 @@ nonempty_type_quals:
                { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
        ;
 
-type_quals:
-         /* empty */
-               { $$ = NULL_TREE; }
-       | type_quals TYPE_QUAL
-               { $$ = decl_tree_cons (NULL_TREE, $2, $$); }
-       ;
-
 /* These rules must follow the rules for function declarations
    and component declarations.  That way, longer rules are preferred.  */
 
@@ -2718,102 +2870,126 @@ type_quals:
 nonmomentary_expr:
        { $<itype>$ = suspend_momentary (); } expr
        { resume_momentary ((int) $<itype>1); $$ = $2; }
+       ;
 
 /* A declarator that is allowed only after an explicit typespec.  */
 /* may all be followed by prec '.' */
 after_type_declarator:
-         after_type_declarator '(' nonnull_exprlist ')' type_quals  %prec '.'
-               { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | after_type_declarator '(' parmlist ')' type_quals  %prec '.'
-               { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | after_type_declarator LEFT_RIGHT type_quals  %prec '.'
-               { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); }
-       | after_type_declarator '(' error ')' type_quals  %prec '.'
-               { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); }
-       | after_type_declarator '[' nonmomentary_expr ']'
-               { $$ = build_parse_node (ARRAY_REF, $$, $3); }
-       | after_type_declarator '[' ']'
-               { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
-       | '(' after_type_declarator_no_typename ')'
+         after_type_declarator1
+       | START_DECLARATOR after_type_declarator1
                { $$ = $2; }
-       | '(' '*' type_quals after_type_declarator ')'
-               { $$ = make_pointer_declarator ($3, $4); }
-       | PAREN_STAR_PAREN
-               { see_typename (); }
-       | after_type_member_declarator
-       | '(' '&' type_quals after_type_declarator ')'
-               { $$ = make_reference_declarator ($3, $4); }
-       | '*' type_quals after_type_declarator  %prec UNARY
+       ;
+
+after_type_declarator1:
+         '*' nonempty_type_quals after_type_declarator1  %prec UNARY
                { $$ = make_pointer_declarator ($2, $3); }
-       | '&' type_quals after_type_declarator  %prec UNARY
+       | '&' nonempty_type_quals after_type_declarator1  %prec UNARY
                { $$ = make_reference_declarator ($2, $3); }
-       | TYPENAME %prec EMPTY
+       | '*' after_type_declarator1  %prec UNARY
+               { $$ = make_pointer_declarator (NULL_TREE, $2); }
+       | '&' after_type_declarator1  %prec UNARY
+               { $$ = make_reference_declarator (NULL_TREE, $2); }
+       | id_scope '*' type_quals after_type_declarator1
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | direct_after_type_declarator
        ;
 
-after_type_declarator_no_typename:
-         after_type_declarator_no_typename '(' nonnull_exprlist ')' type_quals  %prec '.'
+direct_after_type_declarator:
+         direct_after_type_declarator '(' nonnull_exprlist ')' type_quals %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | after_type_declarator_no_typename '(' parmlist ')' type_quals  %prec '.'
+       | direct_after_type_declarator '(' parmlist ')' type_quals %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | after_type_declarator_no_typename LEFT_RIGHT type_quals  %prec '.'
+       | direct_after_type_declarator LEFT_RIGHT type_quals %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); }
-       | after_type_declarator_no_typename '(' error ')' type_quals  %prec '.'
+       | direct_after_type_declarator '(' error ')' type_quals %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); }
-       | after_type_declarator_no_typename '[' nonmomentary_expr ']'
+       | direct_after_type_declarator '[' nonmomentary_expr ']'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
-       | after_type_declarator_no_typename '[' ']'
+       | direct_after_type_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
-       | '(' after_type_declarator_no_typename ')'
+       | '(' after_type_declarator1 ')'
                { $$ = $2; }
-       | PAREN_STAR_PAREN
-               { see_typename (); }
-       | after_type_member_declarator
-       | '*' type_quals after_type_declarator  %prec UNARY
-               { $$ = make_pointer_declarator ($2, $3); }
-       | '&' type_quals after_type_declarator  %prec UNARY
-               { $$ = make_reference_declarator ($2, $3); }
+       | TYPENAME %prec EMPTY
        ;
 
 /* A declarator allowed whether or not there has been
    an explicit typespec.  These cannot redeclare a typedef-name.  */
 
 notype_declarator:
-         notype_declarator '(' nonnull_exprlist ')' type_quals  %prec '.'
+          notype_declarator1
+        | START_DECLARATOR notype_declarator1
+               { $$ = $2; }
+       ;
+
+notype_declarator1:
+         '*' nonempty_type_quals notype_declarator1  %prec UNARY
+               { $$ = make_pointer_declarator ($2, $3); }
+       | '&' nonempty_type_quals notype_declarator1  %prec UNARY
+               { $$ = make_reference_declarator ($2, $3); }
+       | '*' notype_declarator1  %prec UNARY
+               { $$ = make_pointer_declarator (NULL_TREE, $2); }
+       | '&' notype_declarator1  %prec UNARY
+               { $$ = make_reference_declarator (NULL_TREE, $2); }
+       | id_scope '*' type_quals notype_declarator1
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | direct_notype_declarator
+       ;
+
+complex_notype_declarator1:
+         '*' nonempty_type_quals notype_declarator1  %prec UNARY
+               { $$ = make_pointer_declarator ($2, $3); }
+       | '&' nonempty_type_quals notype_declarator1  %prec UNARY
+               { $$ = make_reference_declarator ($2, $3); }
+       | '*' complex_notype_declarator1  %prec UNARY
+               { $$ = make_pointer_declarator (NULL_TREE, $2); }
+       | '&' complex_notype_declarator1  %prec UNARY
+               { $$ = make_reference_declarator (NULL_TREE, $2); }
+       | id_scope '*' type_quals notype_declarator1
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | complex_direct_notype_declarator
+       ;
+
+complex_direct_notype_declarator:
+         direct_notype_declarator '(' nonnull_exprlist ')' type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | notype_declarator '(' parmlist ')' type_quals  %prec '.'
+       | direct_notype_declarator '(' parmlist ')' type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | notype_declarator LEFT_RIGHT type_quals  %prec '.'
+       | direct_notype_declarator LEFT_RIGHT type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); }
-       | notype_declarator '(' error ')' type_quals  %prec '.'
+       | direct_notype_declarator '(' error ')' type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, NULL_TREE, NULL_TREE); }
-       | '(' notype_declarator ')'
+       | '(' expr_or_declarator ')'
+               { $$ = finish_decl_parsing ($2); }
+       | '(' complex_notype_declarator1 ')'
                { $$ = $2; }
-       | '*' type_quals notype_declarator  %prec UNARY
-               { $$ = make_pointer_declarator ($2, $3); }
-       | '&' type_quals notype_declarator  %prec UNARY
-               { $$ = make_reference_declarator ($2, $3); }
-       | notype_declarator '[' nonmomentary_expr ']'
+       | direct_notype_declarator '[' nonmomentary_expr ']'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
-       | notype_declarator '[' ']'
+       | direct_notype_declarator '[' ']'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
-       | IDENTIFIER
-               { see_typename (); }
 
        /* C++ extensions.  */
-       | operator_name
-               { see_typename (); }
-
-       | '~' TYPENAME
-               {
-               destructor_name:
-                 see_typename ();
-                 $$ = build_parse_node (BIT_NOT_EXPR, $2);
-               }
-       | '~' IDENTIFIER
-               { goto destructor_name; }
-        | '~' PTYPENAME
-                { goto destructor_name; }
-       | id_scope see_typename notype_declarator  %prec '('
+       | id_scope see_typename notype_unqualified_id
                { see_typename ();
                  if (TREE_CODE ($$) != SCOPE_REF)
                    $$ = build_push_scope ($$, $3);
@@ -2822,34 +2998,35 @@ notype_declarator:
                  else
                    $$ = build_parse_node (SCOPE_REF, $$, $3);
                }
-       | id_scope see_typename TYPENAME  %prec '('
-               { $$ = build_push_scope ($$, $3); }
-       | id_scope see_typename TYPENAME '(' nonnull_exprlist ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); }
-       | id_scope see_typename TYPENAME '(' parmlist ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); }
-       | id_scope see_typename TYPENAME LEFT_RIGHT type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, empty_parms (), $5)); }
-       | id_scope see_typename TYPENAME '(' error ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, NULL_TREE, NULL_TREE)); }
-       /* For constructor templates.  */
-       | id_scope see_typename PTYPENAME  %prec '('
+       | id_scope see_typename TYPENAME
                { $$ = build_push_scope ($$, $3); }
-       | id_scope see_typename PTYPENAME '(' nonnull_exprlist ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); }
-       | id_scope see_typename PTYPENAME '(' parmlist ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, $5, $7)); }
-       | id_scope see_typename PTYPENAME LEFT_RIGHT type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, empty_parms (), $5)); }
-       | id_scope see_typename PTYPENAME '(' error ')' type_quals  %prec '.'
-               { $$ = build_push_scope ($$, build_parse_node (CALL_EXPR, $3, NULL_TREE, NULL_TREE)); }
-       | SCOPE see_typename notype_declarator
+       | SCOPE see_typename direct_notype_declarator
                { $$ = build_parse_node (SCOPE_REF, NULL_TREE, $3); }
        | template_type SCOPED_NAME 
-               { $$ = $2; }
+               { tree t;
+                 extern int current_class_depth;
+
+                 t = TREE_TYPE(TREE_OPERAND($2, 0));
+                 if (t != current_class_type &&
+                     TREE_CODE(t) != TEMPLATE_TYPE_PARM)
+                   {
+                     push_nested_class(t, 3);
+                     TREE_COMPLEXITY ($2) = current_class_depth;
+                   }
+                 $$ = $2; 
+               }
+       ;
+
+functional_cast:
+         typespec '(' nonnull_exprlist ')'
+               { $$ = build_functional_cast ($$, $3); }
+       | typespec '(' expr_or_declarator ')'
+               { $$ = reparse_decl_as_expr ($$, $3); }
+       | typespec fcast_or_absdcl %prec EMPTY
+               { $$ = reparse_absdcl_as_expr ($$, $2); }
        ;
 
-id_scope:      typename_scope
+id_scope: typename_scope
                { tree t;
                   do_id_scope:
 
@@ -2906,97 +3083,108 @@ scoped_typename: SCOPED_TYPENAME
                } */
        ;
 
-absdcl1:  /* a nonempty abstract declarator */
-         '(' absdcl1 ')'
-               { see_typename ();
-                 $$ = $2; }
-         /* `(typedef)1' is `int'.  */
-       | '*' type_quals absdcl1  %prec EMPTY
+/* ANSI new-declarator (5.3.4) */
+new_declarator:
+         '*' type_quals new_declarator
                { $$ = make_pointer_declarator ($2, $3); }
        | '*' type_quals  %prec EMPTY
                { $$ = make_pointer_declarator ($2, NULL_TREE); }
-/*
-       | id_scope '*' type_quals absdcl1 %prec EMPTY
-               { $3 = make_pointer_declarator ($3, $4);
-                 $$ = build_parse_node (SCOPE_REF, $$, $3); }
+       | '&' type_quals new_declarator %prec EMPTY
+               { $$ = make_reference_declarator ($2, $3); }
+       | '&' type_quals %prec EMPTY
+               { $$ = make_reference_declarator ($2, NULL_TREE); }
        | id_scope '*' type_quals %prec EMPTY
-               { $3 = make_pointer_declarator ($3, NULL_TREE);
-                 $$ = build_parse_node (SCOPE_REF, $$, $3); }
-*/
-       | PAREN_STAR_PAREN
-               { see_typename (); }
-       | '(' abs_member_declarator ')'
-               { $$ = $2; }
-       | '&' type_quals absdcl1 %prec EMPTY
+               { tree arg = make_pointer_declarator ($3, NULL_TREE);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | id_scope '*' type_quals new_declarator
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | direct_new_declarator %prec EMPTY
+       ;
+
+/* ANSI direct-new-declarator (5.3.4) */
+direct_new_declarator:
+         '[' expr ']'
+               { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
+       | direct_new_declarator '[' nonmomentary_expr ']'
+               { $$ = build_parse_node (ARRAY_REF, $$, $3); }
+       ;
+
+/* ANSI abstract-declarator (8.1) */
+absdcl1:
+         '*' nonempty_type_quals absdcl1
+               { $$ = make_pointer_declarator ($2, $3); }
+       | '*' absdcl1
+               { $$ = make_pointer_declarator (NULL_TREE, $2); }
+       | '*' type_quals  %prec EMPTY
+               { $$ = make_pointer_declarator ($2, NULL_TREE); }
+       | '&' nonempty_type_quals absdcl1
                { $$ = make_reference_declarator ($2, $3); }
+       | '&' absdcl1
+               { $$ = make_reference_declarator (NULL_TREE, $2); }
        | '&' type_quals %prec EMPTY
                { $$ = make_reference_declarator ($2, NULL_TREE); }
-       | absdcl1 '(' parmlist ')' type_quals  %prec '.'
+       | id_scope '*' type_quals %prec EMPTY
+               { tree arg = make_pointer_declarator ($3, NULL_TREE);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | id_scope '*' type_quals absdcl1
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       | direct_abstract_declarator %prec EMPTY
+       ;
+
+/* ANSI direct-abstract-declarator (8.1) */
+direct_abstract_declarator:
+         '(' absdcl1 ')'
+               { see_typename ();
+                 $$ = $2; }
+         /* `(typedef)1' is `int'.  */
+       | PAREN_STAR_PAREN
+               { see_typename (); }
+       | direct_abstract_declarator '(' parmlist ')' type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, $3, $5); }
-       | absdcl1 LEFT_RIGHT type_quals  %prec '.'
+       | direct_abstract_declarator LEFT_RIGHT type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, $$, empty_parms (), $3); }
-       | absdcl1 '[' nonmomentary_expr ']'  %prec '.'
+       | direct_abstract_declarator '[' nonmomentary_expr ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, $$, $3); }
-       | absdcl1 '[' ']'  %prec '.'
+       | direct_abstract_declarator '[' ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, $$, NULL_TREE); }
-       | '(' parmlist ')' type_quals  %prec '.'
+       | '(' complex_parmlist ')' type_quals  %prec '.'
                { $$ = build_parse_node (CALL_EXPR, NULL_TREE, $2, $4); }
-       | LEFT_RIGHT type_quals  %prec '.'
-               { $$ = build_parse_node (CALL_EXPR, NULL_TREE, empty_parms (), $2); }
+       | regcast_or_absdcl type_quals %prec '.'
+               { TREE_OPERAND ($$, 2) = $2; }
+       | fcast_or_absdcl type_quals %prec '.'
+               { TREE_OPERAND ($$, 2) = $2; }
        | '[' nonmomentary_expr ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, NULL_TREE, $2); }
        | '[' ']'  %prec '.'
                { $$ = build_parse_node (ARRAY_REF, NULL_TREE, NULL_TREE); }
        ;
 
-abs_member_declarator:
-         id_scope see_typename '*' type_quals
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, 0);
-               }
-       | id_scope see_typename '*' type_quals absdcl1
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, $5);
-               }
-       | id_scope see_typename '&' type_quals
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, 0);
-               }
-       | id_scope see_typename '&' type_quals absdcl1
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, $5);
-               }
-       ;
-
-after_type_member_declarator:
-         id_scope see_typename '*' type_quals after_type_declarator
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (INDIRECT_REF, $5);
-               }
-       | id_scope see_typename '&' type_quals after_type_declarator
-               { tree t;
-                 t = $$;
-                 while (TREE_OPERAND (t, 1))
-                   t = TREE_OPERAND (t, 1);
-                 TREE_OPERAND (t, 1) = build_parse_node (ADDR_EXPR, $5);
-               }
-       ;
-
 /* For C++, decls and stmts can be intermixed, so we don't need to
    have a special rule that won't start parsing the stmt section
    until we have a stmt that parses without errors.  */
@@ -3734,7 +3922,7 @@ optional_identifier:
 ansi_except_stmts:
          /* empty */
                { $$ = NULL_TREE; }
-       | ansi_except_stmts CATCH '(' typename optional_identifier ')'
+       | ansi_except_stmts CATCH '(' type_id optional_identifier ')'
                {
                  tree type = groktypename ($4);
                  if (IS_SIGNATURE (type))
@@ -3842,6 +4030,7 @@ asm_clobbers:
 
    In C++, declaring a function with no parameters
    means that that function takes *no* parameters.  */
+
 parmlist:  /* empty */
                {
                  if (strict_prototype)
@@ -3849,12 +4038,21 @@ parmlist:  /* empty */
                  else
                    $$ = NULL_TREE;
                }
-       | parms
+       | complex_parmlist
+       | type_id
+               { $$ = tree_cons (NULL_TREE, $$, void_list_node);
+                 TREE_PARMLIST ($$) = 1; }
+       ;
+
+/* This nonterminal does not include the common sequence '(' type_id ')',
+   as it is ambiguous and must be disambiguated elsewhere.  */
+complex_parmlist:
+         parms
                {
                  $$ = chainon ($$, void_list_node);
                  TREE_PARMLIST ($$) = 1;
                }
-       | parms ',' ELLIPSIS
+       | parms_comma ELLIPSIS
                {
                  TREE_PARMLIST ($$) = 1;
                }
@@ -3863,6 +4061,11 @@ parmlist:  /* empty */
                {
                  TREE_PARMLIST ($$) = 1;
                }
+       | type_id ELLIPSIS
+               {
+                 $$ = build_tree_list (NULL_TREE, $$); 
+                 TREE_PARMLIST ($$) = 1;
+               }
        | ELLIPSIS
                {
                  /* ARM $8.2.5 has this as a boxed-off comment.  */
@@ -3878,6 +4081,11 @@ parmlist:  /* empty */
                {
                  TREE_PARMLIST ($$) = 1;
                }
+       | type_id TYPENAME_ELLIPSIS
+               {
+                 $$ = build_tree_list (NULL_TREE, $$);
+                 TREE_PARMLIST ($$) = 1;
+               }
        | parms ':'
                {
                  /* This helps us recover from really nasty
@@ -3889,29 +4097,46 @@ parmlist:  /* empty */
                  yyungetc (':', 0);
                  yychar = ')';
                }
+       | type_id ':'
+               {
+                 /* This helps us recover from really nasty
+                    parse errors, for example, a missing right
+                    parenthesis.  */
+                 yyerror ("possibly missing ')'");
+                 $$ = tree_cons (NULL_TREE, $$, void_list_node);
+                 TREE_PARMLIST ($$) = 1;
+                 yyungetc (':', 0);
+                 yychar = ')';
+               }
        ;
 
 /* A nonempty list of parameter declarations or type names.  */
 parms:
-         parm
+         named_parm
                { $$ = build_tree_list (NULL_TREE, $$); }
        | parm '=' init
                { $$ = build_tree_list ($3, $$); }
-       | parms ',' parm
-               { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); }
-       | parms ',' parm '=' init
-               { $$ = chainon ($$, build_tree_list ($5, $3)); }
-       | parms ',' bad_parm
-               { $$ = chainon ($$, build_tree_list (NULL_TREE, $3)); }
-       | parms ',' bad_parm '=' init
-               { $$ = chainon ($$, build_tree_list ($5, $3)); }
+       | parms_comma parm
+               { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
+       | parms_comma parm '=' init
+               { $$ = chainon ($$, build_tree_list ($4, $2)); }
+       | parms_comma bad_parm
+               { $$ = chainon ($$, build_tree_list (NULL_TREE, $2)); }
+       | parms_comma bad_parm '=' init
+               { $$ = chainon ($$, build_tree_list ($4, $2)); }
+       ;
+
+parms_comma:
+         parms ','
+       | type_id ','
+               { $$ = build_tree_list (NULL_TREE, $$); }
        ;
 
 /* A single parameter declaration or parameter type name,
    as found in a parmlist.  The first four cases make up for 10%
    of the time spent parsing C++.  We cannot use them because
    of `int id[]' which won't get parsed properly.  */
-parm:
+named_parm:
 /*
          typed_declspecs dont_see_typename '*' IDENTIFIER
                { $$ = build_tree_list ($$, build_parse_node (INDIRECT_REF, $4));
@@ -3920,33 +4145,46 @@ parm:
                { $$ = build_tree_list ($$, build_parse_node (ADDR_EXPR, $4));
                  see_typename (); }
        | TYPENAME IDENTIFIER
-               { $$ = build_tree_list (list_hash_lookup_or_cons ($$), $2);  }
+               { $$ = build_tree_list (get_decl_list ($$), $2);  }
        | TYPESPEC IDENTIFIER
-               { $$ = build_tree_list (list_hash_lookup_or_cons ($$), $2); }
+               { $$ = build_tree_list (get_decl_list ($$), $2); }
        | */
-         typed_declspecs dont_see_typename abs_or_notype_decl
-               { $$ = build_tree_list ($$, $3);
+       /* Here we expand typed_declspecs inline to avoid mis-parsing of
+          TYPESPEC IDENTIFIER.  */
+         typed_declspecs1 declarator
+               { $$ = build_tree_list ($$, $2);
+                 see_typename (); }
+       | typed_typespecs declarator
+               { $$ = build_tree_list ($$, $2);
+                 see_typename (); }
+       | typespec declarator
+               { $$ = build_tree_list (get_decl_list ($$), $2);
+                 see_typename (); }
+       | typed_declspecs1 absdcl
+               { $$ = build_tree_list ($$, $2);
+                 see_typename (); }
+       | typed_declspecs1 %prec EMPTY
+               { $$ = build_tree_list ($$, NULL_TREE);
                  see_typename (); }
-       | declmods dont_see_typename abs_or_notype_decl
-               { $$ = build_tree_list ($$, $3);
+       | declmods notype_declarator
+               { $$ = build_tree_list ($$, $2);
                  see_typename (); }
        ;
 
-abs_or_notype_decl: absdcl
-       | notype_declarator
-       | START_DECLARATOR notype_declarator
-               { $$ = $2; }
+parm:
+       named_parm
+       | type_id
        ;
 
-see_typename: type_quals
+see_typename: %prec EMPTY
        { see_typename (); }
        ;
 
-dont_see_typename: %prec EMPTY /* empty */
+/* 
+dont_see_typename: %prec EMPTY
        { dont_see_typename (); }
-       ;
+       ; 
 
-/*
 try_for_typename:
         {
          if ($<ttype>-1 == error_mark_node)
@@ -3961,7 +4199,12 @@ try_for_typename:
 */
 
 bad_parm:
-         abs_or_notype_decl
+         /* empty */ %prec EMPTY
+               {
+                 warning ("type specifier omitted for parameter");
+                 $$ = build_tree_list (TREE_PURPOSE (TREE_VALUE ($<ttype>-1)), NULL_TREE);
+               }
+       | notype_declarator
                {
                  warning ("type specifier omitted for parameter");
                  $$ = build_tree_list (TREE_PURPOSE (TREE_VALUE ($<ttype>-1)), $$);
@@ -3994,7 +4237,7 @@ raise_identifier:
        ;
 
 ansi_raise_identifier:
-         typename
+         type_id
                { $$ = build_decl_list (NULL_TREE, $$); }
        ;
 
@@ -4016,6 +4259,24 @@ ansi_raise_identifiers:
                }
        ;
 
+conversion_declarator:
+         /* empty */ %prec EMPTY
+               { $$ = NULL_TREE; }
+       | '*' type_quals conversion_declarator
+               { $$ = make_pointer_declarator ($2, $3); }
+       | '&' type_quals conversion_declarator
+               { $$ = make_reference_declarator ($2, $3); }
+       | id_scope '*' type_quals conversion_declarator
+               { tree arg = make_pointer_declarator ($3, $4);
+                 if (TREE_CODE ($$) != SCOPE_REF)
+                   $$ = build_push_scope ($$, arg);
+                 else if (TREE_OPERAND ($$, 1) == NULL_TREE)
+                   TREE_OPERAND ($$, 1) = arg;
+                 else
+                   $$ = build_parse_node (SCOPE_REF, $$, arg);
+               }
+       ;
+
 operator_name:
          OPERATOR '*'
                { $$ = ansi_opname[MULT_EXPR]; }
@@ -4077,21 +4338,14 @@ operator_name:
                { $$ = ansi_opname[ARRAY_REF]; }
        | OPERATOR NEW
                { $$ = ansi_opname[NEW_EXPR]; }
-/*
-       | OPERATOR NEW '[' ']'
-               { $$ = ansi_opname[VEC_NEW_EXPR]; }
-*/
        | OPERATOR DELETE
                { $$ = ansi_opname[DELETE_EXPR]; }
-/*
+/*     | OPERATOR NEW '[' ']'
+               { $$ = ansi_opname[VEC_NEW_EXPR]; }
        | OPERATOR DELETE '[' ']'
-               { $$ = ansi_opname[VEC_DELETE_EXPR]; }
-*/
-
-       /* These should do `groktypename' and set up TREE_HAS_X_CONVERSION
-          here, rather than doing it in class.c .  */
-       | OPERATOR typed_typespecs absdcl
-               { $$ = build1 (TYPE_EXPR, $2, $3); }
+               { $$ = ansi_opname[VEC_DELETE_EXPR]; }  */
+       | OPERATOR typed_typespecs conversion_declarator
+               { $$ = grokoptypename ($2, $3); }
        | OPERATOR error
                { $$ = ansi_opname[ERROR_MARK]; }
        ;
index 0727e9a00661413fefc80d9ff5b8f76aa8399422..90fe017112ff2d9c1ad9afacd1253f68bdc3afe2 100644 (file)
@@ -169,8 +169,9 @@ end_template_parm_list (parms)
    D1 is template header; D2 is class_head_sans_basetype or a
    TEMPLATE_DECL with its DECL_RESULT field set.  */
 void
-end_template_decl (d1, d2, is_class)
+end_template_decl (d1, d2, is_class, defn)
      tree d1, d2, is_class;
+     int defn;
 {
   tree decl;
   struct template_info *tmpl;
@@ -254,37 +255,47 @@ end_template_decl (d1, d2, is_class)
     }
   DECL_TEMPLATE_INFO (decl) = tmpl;
   DECL_TEMPLATE_PARMS (decl) = d1;
-lose:
-  if (decl)
+
+  /* So that duplicate_decls can do the right thing.  */
+  if (defn)
+    DECL_INITIAL (decl) = error_mark_node;
+  
+  /* If context of decl is non-null (i.e., method template), add it
+     to the appropriate class template, and pop the binding levels.  */
+  if (! DECL_TEMPLATE_IS_CLASS (decl)
+      && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
     {
-      /* If context of decl is non-null (i.e., method template), add it
-        to the appropriate class template, and pop the binding levels.  */
-      if (! DECL_TEMPLATE_IS_CLASS (decl)
-         && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE)
+      tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
+      tree tmpl;
+      my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
+      tmpl = UPT_TEMPLATE (ctx);
+      DECL_TEMPLATE_MEMBERS (tmpl) =
+       perm_tree_cons (DECL_NAME (decl), decl,
+                       DECL_TEMPLATE_MEMBERS (tmpl));
+      poplevel (0, 0, 0);
+      poplevel (0, 0, 0);
+    }
+  /* Otherwise, go back to top level first, and push the template decl
+     again there.  */
+  else
+    {
+      poplevel (0, 0, 0);
+      poplevel (0, 0, 0);
+      if (TREE_TYPE (decl))
        {
-         tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl));
-         tree tmpl;
-         my_friendly_assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE, 266);
-         tmpl = UPT_TEMPLATE (ctx);
-         DECL_TEMPLATE_MEMBERS (tmpl) =
-           perm_tree_cons (DECL_NAME (decl), decl,
-                           DECL_TEMPLATE_MEMBERS (tmpl));
-         poplevel (0, 0, 0);
-         poplevel (0, 0, 0);
+         /* Function template */
+         tree t = IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl));
+         if (t && is_overloaded_fn (t))
+           for (t = get_first_fn (t); t; t = DECL_CHAIN (t))
+             if (TREE_CODE (t) == TEMPLATE_DECL
+                 && duplicate_decls (decl, t))
+               decl = t;
+         push_overloaded_decl (decl, 0);
        }
-      /* Otherwise, go back to top level first, and push the template decl
-        again there.  */
       else
-       {
-         poplevel (0, 0, 0);
-         poplevel (0, 0, 0);
-         if (TREE_TYPE (decl)
-             && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl)) != NULL_TREE)
-           push_overloaded_decl (decl, 0);
-         else
-           pushdecl (decl);
-       }
+       pushdecl (decl);
     }
+ lose:
 #if 0 /* It happens sometimes, with syntactic or semantic errors.
 
         One specific case:
@@ -671,7 +682,7 @@ pop_template_decls (parmlist, arglist, class_level)
     poplevel (0, 0, 0);
 }
 \f
-/* Should be defined in cp-parse.h.  */
+/* Should be defined in parse.h.  */
 extern int yychar;
 
 int
@@ -1842,8 +1853,7 @@ end_template_instantiation (name)
   extract_interface_info ();
 }
 \f
-/* Store away the text of an inline template function. No rtl is
-   generated for this function until it is actually needed.  */
+/* Store away the text of an template.  */
 
 void
 reinit_parse_for_template (yychar, d1, d2)
@@ -1851,7 +1861,7 @@ reinit_parse_for_template (yychar, d1, d2)
      tree d1, d2;
 {
   struct template_info *template_info;
-  extern struct obstack inline_text_obstack; /* see comment in cp-lex.c */
+  extern struct obstack inline_text_obstack; /* see comment in lex.c */
 
   if (d2 == NULL_TREE || d2 == error_mark_node)
     {
@@ -1912,7 +1922,7 @@ type_unification (tparms, targs, parms, args, nsubsts, subr)
 
   my_friendly_assert (TREE_CODE (tparms) == TREE_VEC, 289);
   my_friendly_assert (TREE_CODE (parms) == TREE_LIST, 290);
-  /* ARGS could be NULL (via a call from cp-parse.y to
+  /* ARGS could be NULL (via a call from parse.y to
      build_x_function_call).  */
   if (args)
     my_friendly_assert (TREE_CODE (args) == TREE_LIST, 291);
index 3619663cc672ab7c250ab06e24b309c911a462b0..048e0a4000e3c11004192225eb555bdc0354516b 100644 (file)
@@ -435,6 +435,8 @@ get_binfo (parent, binfo, protect)
     type = BINFO_TYPE (binfo);
   else if (TREE_CODE (binfo) == RECORD_TYPE)
     type = binfo;
+  else if (TREE_CODE (binfo) == UNION_TYPE)
+    return NULL_TREE;
   else
     my_friendly_abort (90);
   
@@ -479,9 +481,10 @@ get_base_distance_recursive (binfo, depth, is_private, basetype_path, rval,
        }
       else
        {
-         int same_object = tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
-                                               BINFO_OFFSET (binfo));
-
+         int same_object = (tree_int_cst_equal (BINFO_OFFSET (*new_binfo_ptr),
+                                                BINFO_OFFSET (binfo))
+                            && *via_virtual_ptr && via_virtual);
+                            
          if (*via_virtual_ptr && via_virtual==0)
            {
              *rval_private_ptr = is_private;
@@ -2535,7 +2538,8 @@ build_vbase_vtables_init (main_binfo, binfo, true_exp, decl_ptr,
              tree addr;
              tree vtbl = BINFO_VTABLE (vbases);
              tree init = build_unary_op (ADDR_EXPR, vtbl, 0);
-             assemble_external (vtbl);
+             if (!flag_vtable_hack)
+               assemble_external (vtbl);
              TREE_USED (vtbl) = 1;
 
              if (use_computed_offsets)
@@ -2580,112 +2584,42 @@ static void
 dfs_get_vbase_types (binfo)
      tree binfo;
 {
-  tree binfos = BINFO_BASETYPES (binfo);
-  tree type = BINFO_TYPE (binfo);
-  tree these_vbase_types = CLASSTYPE_VBASECLASSES (type);
-  int i, n_baselinks = binfos ? TREE_VEC_LENGTH (binfos) : 0;
-
-  if (these_vbase_types)
-    {
-      while (these_vbase_types)
-       {
-         tree this_type = BINFO_TYPE (these_vbase_types);
-
-         /* We really need to start from a fresh copy of this
-            virtual basetype!  CLASSTYPE_MARKED2 is the shortcut
-            for BINFO_VBASE_MARKED.  */
-         if (! CLASSTYPE_MARKED2 (this_type))
-           {
-             vbase_types = make_binfo (integer_zero_node,
-                                       this_type,
-                                       TYPE_BINFO_VTABLE (this_type),
-                                       TYPE_BINFO_VIRTUALS (this_type),
-                                       vbase_types);
-             TREE_VIA_VIRTUAL (vbase_types) = 1;
-             SET_CLASSTYPE_MARKED2 (this_type);
-           }
-         these_vbase_types = TREE_CHAIN (these_vbase_types);
-       }
-    }
-  else for (i = 0; i < n_baselinks; i++)
+  if (TREE_VIA_VIRTUAL (binfo) && ! BINFO_VBASE_MARKED (binfo))
     {
-      tree base_binfo = TREE_VEC_ELT (binfos, i);
-      if (TREE_VIA_VIRTUAL (base_binfo) && ! BINFO_VBASE_MARKED (base_binfo))
-       {
-         vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (base_binfo),
-                                   BINFO_VTABLE (base_binfo),
-                                   BINFO_VIRTUALS (base_binfo), vbase_types);
-         TREE_VIA_VIRTUAL (vbase_types) = 1;
-         SET_BINFO_VBASE_MARKED (base_binfo);
-       }
+      vbase_types = make_binfo (integer_zero_node, BINFO_TYPE (binfo),
+                               BINFO_VTABLE (binfo),
+                               BINFO_VIRTUALS (binfo), vbase_types);
+      TREE_VIA_VIRTUAL (vbase_types) = 1;
+      SET_BINFO_VBASE_MARKED (binfo);
     }
   SET_BINFO_MARKED (binfo);
 }
 
-/* Some virtual baseclasses might be virtual baseclasses for
-   other virtual baseclasses.  We sort the virtual baseclasses
-   topologically: in the list returned, the first virtual base
-   classes have no virtual baseclasses themselves, and any entry
-   on the list has no dependency on virtual base classes later in the
-   list.  */
+/* get a list of virtual base classes in dfs order.  */
 tree
 get_vbase_types (type)
      tree type;
 {
-  tree ordered_vbase_types = NULL_TREE, prev, next;
   tree vbases;
+  tree binfo;
+
+  if (TREE_CODE (type) == TREE_VEC)
+    binfo = type;
+  else
+    binfo = TYPE_BINFO (type);
 
   vbase_types = NULL_TREE;
-  dfs_walk (TYPE_BINFO (type), dfs_get_vbase_types, unmarkedp);
-  dfs_walk (TYPE_BINFO (type), dfs_unmark, markedp);
+  dfs_walk (binfo, dfs_get_vbase_types, unmarkedp);
+  dfs_walk (binfo, dfs_unmark, markedp);
   /* Rely upon the reverse dfs ordering from dfs_get_vbase_types, and now
      reverse it so that we get normal dfs ordering.  */
   vbase_types = nreverse (vbase_types);
 
-  /* Almost all of the below is not needed now.  We should be able to just
-     return vbase_types directly... (mrs) */
-  while (vbase_types)
-    {
-      /* Now sort these types.  This is essentially a bubble merge.  */
-
-      /* Farm out virtual baseclasses which have no marked ancestors.  */
-      for (vbases = vbase_types, prev = NULL_TREE;
-          vbases; vbases = next)
-       {
-         next = TREE_CHAIN (vbases);
-         /* If VBASES does not have any vbases itself, or it's
-            topologically safe, it goes into the sorted list.  */
-         if (1 /* ANSI C++ specifies dfs ordering now. */
-             || ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases))
-             || BINFO_VBASE_MARKED (vbases) == 0)
-           {
-             if (prev)
-               TREE_CHAIN (prev) = TREE_CHAIN (vbases);
-             else
-               vbase_types = TREE_CHAIN (vbases);
-             TREE_CHAIN (vbases) = NULL_TREE;
-             ordered_vbase_types = chainon (ordered_vbase_types, vbases);
-             CLEAR_BINFO_VBASE_MARKED (vbases);
-           }
-         else
-           prev = vbases;
-       }
-
-      /* Now unmark types all of whose ancestors are now on the
-        `ordered_vbase_types' list.  */
-      for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
-       {
-         /* If all our virtual baseclasses are unmarked, ok.  */
-         tree t = CLASSTYPE_VBASECLASSES (BINFO_TYPE (vbases));
-         while (t && (BINFO_VBASE_MARKED (t) == 0
-                      || ! CLASSTYPE_VBASECLASSES (BINFO_TYPE (t))))
-           t = TREE_CHAIN (t);
-         if (t == NULL_TREE)
-           CLEAR_BINFO_VBASE_MARKED (vbases);
-       }
-    }
+  /* unmark marked vbases */
+  for (vbases = vbase_types; vbases; vbases = TREE_CHAIN (vbases))
+    CLEAR_BINFO_VBASE_MARKED (vbases);
 
-  return ordered_vbase_types;
+  return vbase_types;
 }
 \f
 static void
index 211876e9e576271613ecfd8bf7ed2400c9819a9e..fd0cafae40ad141f6792b3304c8098bdefdc9b95 100644 (file)
@@ -20,7 +20,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
 
 /* This file is the type analyzer for GNU C++.  To debug it, define SPEW_DEBUG
-   when compiling cp-parse.c and cp-spew.c.  */
+   when compiling parse.c and spew.c.  */
 
 #include "config.h"
 #include <stdio.h>
@@ -50,7 +50,7 @@ static struct token hack_scope ();
 static tree hack_ptype ();
 static tree hack_more_ids ();
 
-/* From cp-lex.c: */
+/* From lex.c: */
 /* the declaration found for the last IDENTIFIER token read in.
    yylex must look this up to detect typedefs, which get token type TYPENAME,
    so it is left around in case the identifier is not a typedef but is
@@ -74,7 +74,7 @@ static char follows_typename[END_OF_SAVED_INPUT+1];
 static char follows_identifier[END_OF_SAVED_INPUT+1];
 
 /* This is a hack!!! TEMPLATE_TYPE_SEEN_BEFORE_SCOPE consists of the name
- * of the last template_type parsed in cp-parse.y if it is followed by a
+ * of the last template_type parsed in parse.y if it is followed by a
  * scope operator.  It will be reset inside the next invocation of yylex().
  * This is used for recognizing nested types inside templates.
  * - niklas@appli.se */
@@ -271,7 +271,7 @@ probe_obstack (h, obj, nlevels)
   return nlevels != 0 && lp != 0;
 }
 
-/* from cp-lex.c: */
+/* from lex.c: */
 /* Value is 1 if we should try to make the next identifier look like a
    typename (when it may be a local variable or a class variable).
    Value is 0 if we treat this name in a default fashion.
@@ -306,7 +306,7 @@ yylex()
        {
          /* Sync back again, leaving SCOPE on the token stream, because we
           * failed to substitute the original SCOPE token with a
-          * SCOPED_TYPENAME.  See rule "template_type" in cp-parse.y */
+          * SCOPED_TYPENAME.  See rule "template_type" in parse.y */
          consume_token ();
        }
       else
@@ -364,7 +364,6 @@ yylex()
       goto retry;
 
     case IDENTIFIER:
-      /* Note: this calls arbitrate_lookup.  */
       trrr = lookup_name (tmp_token.yylval.ttype, -2);
       if (trrr)
        {
@@ -436,6 +435,7 @@ yylex()
     case TYPESPEC:
       consume_token ();
     finish_typename_processing:
+#if 0
       /* Now see if we should insert a START_DECLARATOR token.
          Here are the cases caught:
 
@@ -487,6 +487,7 @@ yylex()
              nth_token (0)->yychar = START_DECLARATOR;
            }
        }
+#endif
       break;
 
 #if 0
@@ -708,6 +709,7 @@ frob_identifier ()
   return rt;
 }
 
+#if 0
 /* When this function is called, nth_token(0) is the current
    token we are scanning.  This means that the next token we'll
    scan is nth_token (1).  Usually the next token we'll scan
@@ -874,6 +876,7 @@ arbitrate_lookup (name, exp_decl, type_decl)
       return t;
     }
 }
+#endif
 
 /* now returns decl_node */
 
@@ -1125,7 +1128,7 @@ static int
 debug_yychar (yy)
      int yy;
 {
-  /* In cp-parse.y: */
+  /* In parse.y: */
   extern char *debug_yytranslate ();
   
   int i;
index 4edcabcaa344a28af4abef1fe1bc193257cfbbc3..785033cf86dde3a66d433f0b108b99c3860362ca 100644 (file)
@@ -83,13 +83,8 @@ lvalue_p (ref)
       case OFFSET_REF:
        if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
          return 1;
-       if (TREE_CODE (TREE_OPERAND (ref, 1)) == VAR_DECL)
-         if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
-             && DECL_LANG_SPECIFIC (ref)
-             && DECL_IN_AGGR_P (ref))
-           return 0;
-         else
-           return 1;
+       return lvalue_p (TREE_OPERAND (ref, 0))
+         && lvalue_p (TREE_OPERAND (ref, 1));
        break;
 
       case ADDR_EXPR:
@@ -940,42 +935,52 @@ hash_chainon (list1, list2)
                          hash_chainon (TREE_CHAIN (list1), list2));
 }
 
-tree
-get_decl_list (value)
+static tree
+get_identifier_list (value)
      tree value;
 {
-  tree list = NULL_TREE;
-
-  if (TREE_CODE (value) == IDENTIFIER_NODE)
+  tree list = IDENTIFIER_AS_LIST (value);
+  if (list != NULL_TREE
+      && (TREE_CODE (list) != TREE_LIST
+         || TREE_VALUE (list) != value))
+    list = NULL_TREE;
+  else if (IDENTIFIER_HAS_TYPE_VALUE (value)
+          && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
     {
-      list = IDENTIFIER_AS_LIST (value);
-      if (list != NULL_TREE
-         && (TREE_CODE (list) != TREE_LIST
-             || TREE_VALUE (list) != value))
+      tree type = IDENTIFIER_TYPE_VALUE (value);
+
+      if (TYPE_PTRMEMFUNC_P (type))
        list = NULL_TREE;
-      else if (IDENTIFIER_HAS_TYPE_VALUE (value)
-              && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
+      else if (type == current_class_type)
+       /* Don't mess up the constructor name.  */
+       list = tree_cons (NULL_TREE, value, NULL_TREE);
+      else
        {
          register tree id;
-         tree type = IDENTIFIER_TYPE_VALUE (value);
-
-         if (TYPE_PTRMEMFUNC_P (type))
-           list = NULL_TREE;
+         /* This will return the correct thing for regular types,
+            nested types, and templates.  Yay! */
+         if (TYPE_NESTED_NAME (type))
+           id = TYPE_NESTED_NAME (type);
          else
-           {
-             /* This will return the correct thing for regular types,
-                nested types, and templates.  Yay! */
-             if (DECL_NESTED_TYPENAME (TYPE_NAME (type)))
-               value = DECL_NESTED_TYPENAME (TYPE_NAME (type));
-             id = value;
-
-             if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
-               CLASSTYPE_ID_AS_LIST (type) = perm_tree_cons (NULL_TREE,
-                                                             id, NULL_TREE);
-             list = CLASSTYPE_ID_AS_LIST (type);
-           }
+           id = TYPE_IDENTIFIER (type);
+
+         if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
+           CLASSTYPE_ID_AS_LIST (type)
+             = perm_tree_cons (NULL_TREE, id, NULL_TREE);
+         list = CLASSTYPE_ID_AS_LIST (type);
        }
     }
+  return list;
+}
+
+tree
+get_decl_list (value)
+     tree value;
+{
+  tree list = NULL_TREE;
+
+  if (TREE_CODE (value) == IDENTIFIER_NODE)
+    list = get_identifier_list (value);
   else if (TREE_CODE (value) == RECORD_TYPE
           && TYPE_LANG_SPECIFIC (value))
     list = CLASSTYPE_AS_LIST (value);
@@ -1003,39 +1008,7 @@ list_hash_lookup_or_cons (value)
   tree list = NULL_TREE;
 
   if (TREE_CODE (value) == IDENTIFIER_NODE)
-    {
-      list = IDENTIFIER_AS_LIST (value);
-      if (list != NULL_TREE
-         && (TREE_CODE (list) != TREE_LIST
-             || TREE_VALUE (list) != value))
-       list = NULL_TREE;
-      else if (IDENTIFIER_HAS_TYPE_VALUE (value)
-              && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE)
-       {
-         /* If the type name and constructor name are different, don't
-            write constructor name into type.  */
-         if (identifier_typedecl_value (value)
-             && identifier_typedecl_value (value) != constructor_name (value))
-           list = tree_cons (NULL_TREE, value, NULL_TREE);
-         else
-           {
-             tree type = IDENTIFIER_TYPE_VALUE (value);
-             if (TYPE_PTRMEMFUNC_P (type))
-               list = NULL_TREE;
-             else
-               {
-                 if (CLASSTYPE_ID_AS_LIST (type) == NULL_TREE)
-                   {
-                     /* Not just `value', which could be a template parm.  */
-                     tree id = DECL_NAME (TYPE_NAME (type));
-                     CLASSTYPE_ID_AS_LIST (type) =
-                       perm_tree_cons (NULL_TREE, id, NULL_TREE);
-                   }
-                 list = CLASSTYPE_ID_AS_LIST (type);
-               }
-           }
-       }
-    }
+    list = get_identifier_list (value);
   else if (TREE_CODE (value) == TYPE_DECL
           && TREE_CODE (TREE_TYPE (value)) == RECORD_TYPE
           && TYPE_LANG_SPECIFIC (TREE_TYPE (value)))
index e68893736d5f74b9ea82cc76c7e4439371abe9b6..f7f1505cce13ee28024f63c107083616be82d449 100644 (file)
@@ -541,10 +541,10 @@ comptypes (type1, type2, strict)
        t1 = type_for_size (TYPE_PRECISION (t1), 1);
       if (TREE_CODE (t2) == ENUMERAL_TYPE)
        t2 = type_for_size (TYPE_PRECISION (t2), 1);
-    }
 
-  if (t1 == t2)
-    return 1;
+      if (t1 == t2)
+       return 1;
+    }
 
   /* Different classes of types can't be compatible.  */
 
@@ -643,6 +643,8 @@ comptypes (type1, type2, strict)
       /* Target types must match incl. qualifiers.  */
       return comp_array_types (comptypes, t1, t2, strict);
 
+    case TEMPLATE_TYPE_PARM:
+      return 1;
     }
   return 0;
 }
@@ -2109,8 +2111,15 @@ get_member_function_from_ptrfunc (instance_ptrptr, instance, function)
       tree e2;
       tree e3;
       tree aref, vtbl;
+      tree aux_delta;
 
-      vtbl = build1 (ADDR_EXPR, ptr_type_node, instance);
+      /* convert down to the right base, before using the instance. */
+      instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)),
+                                         build_unary_op (ADDR_EXPR, instance, 0));
+      if (instance == error_mark_node)
+       return instance;
+
+      vtbl = convert_pointer_to (ptr_type_node, instance);
       vtbl = build (PLUS_EXPR,
                    build_pointer_type (build_pointer_type (vtable_entry_type)),
                    vtbl, convert (sizetype, delta2));
@@ -2398,6 +2407,12 @@ convert_arguments (return_loc, typelist, values, fndecl, flags)
              val = integer_zero_node;
            }
        }
+      else if (TREE_CODE (val) == OFFSET_REF
+           && TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
+       {
+         /* This is unclean.  Should be handled elsewhere. */
+         val = build_unary_op (ADDR_EXPR, val, 0);
+       }
       else if (TREE_CODE (val) == OFFSET_REF)
        val = resolve_offset_ref (val);
 
@@ -3075,7 +3090,11 @@ build_binary_op_nodefault (code, op0, op1, error_code)
            }
          else
            index1 = integer_neg_one_node;
-         op1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), op1);
+         {
+           tree nop1 = build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type0), op1);
+           TREE_CONSTANT (nop1) = TREE_CONSTANT (op1);
+           op1 = nop1;
+         }
          e1 = build_binary_op (EQ_EXPR, index0, index1, 1);
          e2 = build_binary_op (NE_EXPR, index1, integer_neg_one_node, 1);
          e2 = build_binary_op (TRUTH_ANDIF_EXPR, e2, build_binary_op (EQ_EXPR, delta20, delta21, 1), 1);
@@ -3577,11 +3596,14 @@ build_component_addr (arg, argtype, msg)
 
   if (TREE_CODE (field) == FIELD_DECL
       && TYPE_USES_COMPLEX_INHERITANCE (basetype))
-    /* Can't convert directly to ARGTYPE, since that
-       may have the same pointer type as one of our
-       baseclasses.  */
-    rval = build1 (NOP_EXPR, argtype,
-                  convert_pointer_to (basetype, rval));
+    {
+      /* Can't convert directly to ARGTYPE, since that
+        may have the same pointer type as one of our
+        baseclasses.  */
+      rval = build1 (NOP_EXPR, argtype,
+                    convert_pointer_to (basetype, rval));
+      TREE_CONSTANT (rval) == TREE_CONSTANT (TREE_OPERAND (rval, 0));
+    }
   else
     /* This conversion is harmless.  */
     rval = convert (argtype, rval);
@@ -4787,20 +4809,6 @@ build_c_cast (type, expr)
        }
     }
 
-  /* When converting into a reference type, just convert into a pointer to
-     the new type and deference it.  While this is not exactly what ARM 5.4
-     calls for [why not? -jason], it is pretty close for now.
-     (int &)ri ---> *(int*)&ri  */
-  if (TREE_CODE (type) == REFERENCE_TYPE)
-    {
-      value = build_unary_op (ADDR_EXPR, value, 0);
-      if (value != error_mark_node)
-       value = convert (build_pointer_type (TREE_TYPE (type)), value);
-      if (value != error_mark_node)
-       value = build_indirect_ref (value, "reference conversion");
-      return value;
-    }
-
   if (IS_SIGNATURE (type))
     {
       error ("cast specifies signature type");
@@ -5819,6 +5827,59 @@ language_lvalue_valid (exp)
   return 1;
 }
 \f
+/* Get differnce in deltas for different pointer to member function
+   types.  Return inetger_zero_node, if FROM cannot be converted to a
+   TO type.  If FORCE is true, then allow reverse conversions as well.  */
+static tree
+get_delta_difference (from, to, force)
+     tree from, to;
+{
+  tree delta = integer_zero_node;
+  tree binfo;
+  
+  if (to == from)
+    return delta;
+
+  binfo = get_binfo (from, to, 1);
+  if (binfo == error_mark_node)
+    {
+      error ("   in pointer to member function conversion");
+      return delta;
+    }
+  if (binfo == 0)
+    {
+      if (!force)
+       {
+         error_not_base_type (from, to);
+         error ("   in pointer to member function conversion");
+         return delta;
+       }
+      binfo = get_binfo (to, from, 1);
+      if (binfo == error_mark_node)
+       {
+         error ("   in pointer to member function conversion");
+         return delta;
+       }
+      if (binfo == 0)
+       {
+         error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to);
+         return delta;
+       }
+      if (TREE_VIA_VIRTUAL (binfo))
+       {
+         warning ("pointer to member conversion from virtual base class will only work if your very careful");
+       }
+      return fold (size_binop (MINUS_EXPR,
+                              integer_zero_node,
+                              BINFO_OFFSET (binfo)));
+    }
+  if (TREE_VIA_VIRTUAL (binfo))
+    {
+      warning ("pointer to member conversion from virtual base class will only work if your very careful");
+    }
+  return BINFO_OFFSET (binfo);
+}
+
 /* Build a constructor for a pointer to member function.  It can be
    used to initialize global variables, local variable, or used
    as a value in expressions.  TYPE is the POINTER to METHOD_TYPE we
@@ -5826,62 +5887,104 @@ language_lvalue_valid (exp)
 
    If FORCE is non-zero, then force this conversion, even if
    we would rather not do it.  Usually set when using an explicit
-   cast.  */
+   cast.
+
+   Return error_mark_node, if something goes wrong.  */
 
 tree
 build_ptrmemfunc (type, pfn, force)
      tree type, pfn;
      int force;
 {
-  tree index;
+  tree index = integer_zero_node;
   tree delta = integer_zero_node;
   tree delta2 = integer_zero_node;
   tree vfield_offset;
   tree npfn;
   tree u;
 
-  /* Handle null pointer to member function conversions. */
-  if (integer_zerop (pfn))
-    {
-      pfn = build_c_cast (type, integer_zero_node);
-      u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
-      return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
-                                                 tree_cons (NULL_TREE, integer_zero_node,
-                                                            tree_cons (NULL_TREE, u, NULL_TREE))));
-    }
-
-  /* Allow pointer to member conversions here. */
-  if (type != TREE_TYPE (pfn))
+  /* Handle multiple conversions of pointer to member fucntions. */
+  if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn)))
     {
-      tree binfo
-       = get_binfo (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
-                    TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
-                    1);
-      if (binfo == error_mark_node)
-       {
-         error ("   in pointer to member function conversion");
-         return NULL_TREE;
-       }
-      if (binfo == 0)
+      tree ndelta, ndelta2, nindex;
+      /* Is is already the right type? */
+#if 0
+      /* Sorry, can't do this, the backend is too stupid. */
+      if (TYPE_METHOD_BASETYPE (TREE_TYPE (type))
+         == TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))))
        {
-         if (!force)
+         if (type != TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
            {
-             error_not_base_type (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
-                                  TYPE_METHOD_BASETYPE (TREE_TYPE (type)));
-             error ("   in pointer to member function conversion");
-             return NULL_TREE;
+             npfn = build1 (NOP_EXPR, TYPE_GET_PTRMEMFUNC_TYPE (type), pfn);
+             TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
            }
-         /* Just something handy with an offset of zero. */
-         binfo = TYPE_BINFO (TYPE_METHOD_BASETYPE (TREE_TYPE (type)));
+         return pfn;
        }
-      if (TREE_VIA_VIRTUAL (binfo))
+#else
+      if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))
+       return pfn;
+#endif
+
+      if (TREE_CODE (pfn) != CONSTRUCTOR)
        {
-         sorry ("pointer to member conversion from virtual base class");
+         tree e1, e2, e3;
+         ndelta = convert (sizetype, build_component_ref (pfn, delta_identifier, 0, 0));
+         ndelta2 = convert (sizetype, DELTA2_FROM_PTRMEMFUNC (pfn));
+         index = build_component_ref (pfn, index_identifier, 0, 0);
+         delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))),
+                                       TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+                                       force);
+         delta = fold (size_binop (PLUS_EXPR, delta, ndelta));
+         delta2 = fold (size_binop (PLUS_EXPR, ndelta2, delta2));
+         e1 = fold (build (GT_EXPR, integer_type_node, index, integer_zero_node));
+         
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
+                                                  tree_cons (NULL_TREE, index,
+                                                             tree_cons (NULL_TREE, u, NULL_TREE))));
+         e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+
+         pfn = PFN_FROM_PTRMEMFUNC (pfn);
+         npfn = build1 (NOP_EXPR, type, pfn);
+         TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
+         u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
+                                                  tree_cons (NULL_TREE, index,
+                                                             tree_cons (NULL_TREE, u, NULL_TREE))));
+         e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+         return build_conditional_expr (e1, e2, e3);
+       }
+
+      ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn));
+      nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)));
+      npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))));
+      npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn));
+      if (integer_zerop (nindex))
+       pfn = integer_zero_node;
+      else
+       {
+         sorry ("value casting of varible nonnull pointer to member functions not supported");
+         return error_mark_node;
        }
-      delta = BINFO_OFFSET (binfo);
-      delta2 = size_binop (PLUS_EXPR, delta2, delta);
     }
-  
+
+  /* Handle null pointer to member function conversions. */
+  if (integer_zerop (pfn))
+    {
+      pfn = build_c_cast (type, integer_zero_node);
+      u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE));
+      u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node,
+                                              tree_cons (NULL_TREE, integer_zero_node,
+                                                         tree_cons (NULL_TREE, u, NULL_TREE))));
+      return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
+    }
+
+  /* Allow pointer to member conversions here. */
+  delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))),
+                               TYPE_METHOD_BASETYPE (TREE_TYPE (type)),
+                               force);
+  delta2 = fold (size_binop (PLUS_EXPR, delta2, delta));
 
   if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL)
     warning ("assuming pointer to member function is non-virtual");
@@ -5890,10 +5993,10 @@ build_ptrmemfunc (type, pfn, force)
       && DECL_VINDEX (TREE_OPERAND (pfn, 0)))
     {
       /* Find the offset to the vfield pointer in the object. */
-      vfield_offset = TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn)));
-      vfield_offset = CLASSTYPE_VFIELD (vfield_offset);
-      vfield_offset = DECL_FIELD_BITPOS (vfield_offset);
-      vfield_offset = size_binop (FLOOR_DIV_EXPR, vfield_offset, size_int (BITS_PER_UNIT));
+      vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)),
+                                DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)),
+                                0);
+      vfield_offset = get_vfield_offset (vfield_offset);
       delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2);
 
       /* Map everything down one to make room for the null pointer to member.  */
@@ -5901,22 +6004,21 @@ build_ptrmemfunc (type, pfn, force)
                          DECL_VINDEX (TREE_OPERAND (pfn, 0)),
                          integer_one_node);
       u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE));
-
-      return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
-                                                 tree_cons (NULL_TREE, index,
-                                                            tree_cons (NULL_TREE, u, NULL_TREE))));
     }
   else
-    index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node);
+    {
+      index = fold (size_binop (MINUS_EXPR, integer_zero_node, integer_one_node));
 
-  npfn = build1 (NOP_EXPR, type, pfn);
-  TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
+      npfn = build1 (NOP_EXPR, type, pfn);
+      TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn);
 
-  u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
+      u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE));
+    }
 
-  return build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
-                                             tree_cons (NULL_TREE, index,
-                                                        tree_cons (NULL_TREE, u, NULL_TREE))));
+  u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta,
+                                          tree_cons (NULL_TREE, index,
+                                                     tree_cons (NULL_TREE, u, NULL_TREE))));
+  return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0);
 }
 
 /* Convert value RHS to type TYPE as preparation for an assignment
@@ -6125,21 +6227,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
            else
              pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
                       errtype);
-         else if (pedantic
-             && ((TYPE_MAIN_VARIANT (ttl) == void_type_node
-                  && (TREE_CODE (ttr) == FUNCTION_TYPE
-                      || TREE_CODE (ttr) == METHOD_TYPE))
-                 ||
-                 (TYPE_MAIN_VARIANT (ttr) == void_type_node
-                  && (TREE_CODE (ttl) == FUNCTION_TYPE
-                      || TREE_CODE (ttl) == METHOD_TYPE))))
-           {
-             if (fndecl)
-               cp_pedwarn ("passing `%T' as argument %P of `%D'",
-                           rhstype, parmnum, fndecl);
-             else
-               cp_pedwarn ("%s to `void *' from `%T'", errtype, rhstype);
-           }
          /* Const and volatile mean something different for function types,
             so the usual warnings are not appropriate.  */
          else if ((TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE)
@@ -6334,14 +6421,12 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
   else if (((coder == POINTER_TYPE && TREE_CODE (rhs) == ADDR_EXPR
             && TREE_CODE (rhstype) == POINTER_TYPE
             && TREE_CODE (TREE_TYPE (rhstype)) == METHOD_TYPE)
-           || integer_zerop (rhs))
+           || integer_zerop (rhs)
+           || TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
           && TYPE_PTRMEMFUNC_P (type))
     {
       /* compatible pointer to member functions. */
-      rhs = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0);
-      if (rhs == 0)
-       return error_mark_node;
-      return digest_init (type, rhs, (tree *)0);
+      return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), rhs, 0);
     }
   else if (codel == ERROR_MARK || coder == ERROR_MARK)
     return error_mark_node;
@@ -6353,7 +6438,11 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
     /* Force an abort.  */
     my_friendly_assert (codel != REFERENCE_TYPE, 317);
   else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))
-    return build1 (NOP_EXPR, type, rhs);
+    {
+      tree nrhs = build1 (NOP_EXPR, type, rhs);
+      TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
+      return nrhs;
+    }
   else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
     return convert (type, rhs);
 
@@ -6512,7 +6601,11 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
          if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
            rhs = convert_from_reference (rhs);
          if (type != rhstype)
-           return build1 (NOP_EXPR, type, rhs);
+           {
+             tree nrhs = build1 (NOP_EXPR, type, rhs);
+             TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
+             rhs = nrhs;
+           }
          return rhs;
        }
 
index 8106e58fee0d7f5954564018beff7561a1be9253..f9f9be7f9b9ca1dc8cbabfd948e6118bd3b3099d 100644 (file)
@@ -329,7 +329,7 @@ ack (s, v, v2)
    silly.  So instead, we just do the equivalent of a call to fatal in the
    same situation (call exit).  */
 
-/* First used: 0 (reserved), Last used: 355.  Free: 5.  */
+/* First used: 0 (reserved), Last used: 355.  */
 
 static int abortcount = 0;
 
@@ -641,13 +641,17 @@ digest_init (type, init, tail)
   if (TREE_CODE (init) == NON_LVALUE_EXPR)
     init = TREE_OPERAND (init, 0);
 
+  if (init && TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (type))
+    init = default_conversion (init);
+
   if (init && TYPE_PTRMEMFUNC_P (type)
       && ((TREE_CODE (init) == ADDR_EXPR
           && TREE_CODE (TREE_TYPE (init)) == POINTER_TYPE
           && TREE_CODE (TREE_TYPE (TREE_TYPE (init))) == METHOD_TYPE)
-         || integer_zerop (init)))
+         || integer_zerop (init)
+         || (TREE_TYPE (init) && TYPE_PTRMEMFUNC_P (TREE_TYPE (init)))))
     {
-      init = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), init, 0);
+      return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), init, 0);
     }
 
   raw_constructor = TREE_CODE (init) == CONSTRUCTOR && TREE_TYPE (init) == 0;
@@ -999,19 +1003,8 @@ process_init_constructor (type, init, elts)
            {
              tree tail1 = tail;
 
-             if (TYPE_PTRMEMFUNC_P (TREE_TYPE (field)))
-               {
-                 tree t
-                   = build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (field)),
-                                       default_conversion (TREE_VALUE (tail)),
-                                       0);
-                 if (t == NULL_TREE)
-                   return error_mark_node;
-                 next1 = digest_init (TREE_TYPE (field), t, &tail1);
-               }
-             else
-               next1 = digest_init (TREE_TYPE (field),
-                                    TREE_VALUE (tail), &tail1);
+             next1 = digest_init (TREE_TYPE (field),
+                                  TREE_VALUE (tail), &tail1);
              my_friendly_assert (tail1 == 0
                                  || TREE_CODE (tail1) == TREE_LIST, 320);
              tail = tail1;
@@ -1377,22 +1370,22 @@ build_m_component_ref (datum, component)
   if (datum == error_mark_node || component == error_mark_node)
     return error_mark_node;
 
-  if (! IS_AGGR_TYPE (objtype))
-    {
-      cp_error ("cannot apply member pointer `%D' to `%E'", component, datum);
-      cp_error ("which is of non-aggregate type `%T'", objtype);
-      return error_mark_node;
-    }
-  
   if (TREE_CODE (type) != OFFSET_TYPE && TREE_CODE (type) != METHOD_TYPE)
     {
-      error ("non-member type composed with object");
+      cp_error ("`%E' cannot be used as a member pointer, since it is of type `%T'", component, type);
       return error_mark_node;
     }
 
   if (TREE_CODE (objtype) == REFERENCE_TYPE)
     objtype = TREE_TYPE (objtype);
 
+  if (! IS_AGGR_TYPE (objtype))
+    {
+      cp_error ("cannot apply member pointer `%E' to `%E'", component, datum);
+      cp_error ("which is of non-aggregate type `%T'", objtype);
+      return error_mark_node;
+    }
+  
   if (! comptypes (TYPE_METHOD_BASETYPE (type), objtype, 0))
     {
       cp_error ("member type `%T::' incompatible with object type `%T'",