OSDN Git Service

(fixup_var_refs_1, case ZERO_EXTRACT): Don't call fixup_memory_subreg
[pf3gnuchains/gcc-fork.git] / gcc / dwarfout.c
index e25fff4..1d29394 100644 (file)
@@ -1,8 +1,6 @@
-/* This file contains code written by Ron Guilmette (rfg@ncd.com) for
-   Network Computing Devices, August, September, October, November 1990.
-
-   Output Dwarf format symbol table information from the GNU C compiler.
-   Copyright (C) 1992 Free Software Foundation, Inc.
+/* Output Dwarf format symbol table information from the GNU C compiler.
+   Copyright (C) 1992, 1993, 1995, 1996 Free Software Foundation, Inc.
+   Contributed by Ron Guilmette (rfg@monkeys.com) of Network Computing Devices.
 
 This file is part of GNU CC.
 
@@ -18,7 +16,8 @@ GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
 
 #include "config.h"
 
@@ -28,17 +27,14 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "tree.h"
 #include "flags.h"
 #include "rtl.h"
+#include "hard-reg-set.h"
 #include "insn-config.h"
 #include "reload.h"
 #include "output.h"
 #include "defaults.h"
 
-#ifndef DWARF_VERSION
-#define DWARF_VERSION 1
-#endif
-
 /* #define NDEBUG 1 */
-#include <assert.h>
+#include "assert.h"
 
 #if defined(DWARF_TIMESTAMPS)
 #if defined(POSIX)
@@ -69,10 +65,8 @@ extern char *rindex ();
 /* Note that the implementation of C++ support herein is (as yet) unfinished.
    If you want to try to complete it, more power to you.  */
 
-#if defined(__GNUC__) && (NDEBUG == 1)
-#define inline static inline
-#else
-#define inline static
+#if !defined(__GNUC__) || (NDEBUG != 1)
+#define inline
 #endif
 
 /* How to start an assembler comment.  */
@@ -80,12 +74,11 @@ extern char *rindex ();
 #define ASM_COMMENT_START ";#"
 #endif
 
-/* Define a macro which, when given a pointer to some BLOCK node, returns
-   a pointer to the FUNCTION_DECL node from which the given BLOCK node
-   was instantiated (as an inline expansion).  This macro needs to be
-   defined properly in tree.h, however for the moment, we just fake it.  */
-
-#define BLOCK_INLINE_FUNCTION(block) 0
+/* How to print out a register name.  */
+#ifndef PRINT_REG
+#define PRINT_REG(RTX, CODE, FILE) \
+  fprintf ((FILE), "%s", reg_names[REGNO (RTX)])
+#endif
 
 /* Define a macro which returns non-zero for any tagged type which is
    used (directly or indirectly) in the specification of either some
@@ -104,6 +97,21 @@ extern char *rindex ();
 
 #define TYPE_USED_FOR_FUNCTION(tagged_type) (TYPE_SIZE (tagged_type) == 0)
 
+/* Define a macro which returns non-zero for a TYPE_DECL which was
+   implicitly generated for a tagged type.
+
+   Note that unlike the gcc front end (which generates a NULL named
+   TYPE_DECL node for each complete tagged type, each array type, and
+   each function type node created) the g++ front end generates a
+   _named_ TYPE_DECL node for each tagged type node created.
+   These TYPE_DECLs have DECL_ARTIFICIAL set, so we know not to
+   generate a DW_TAG_typedef DIE for them.  */
+#define TYPE_DECL_IS_STUB(decl)                                \
+  (DECL_NAME (decl) == NULL                            \
+   || (DECL_ARTIFICIAL (decl)                          \
+       && is_tagged_type (TREE_TYPE (decl))            \
+       && decl == TYPE_STUB_DECL (TREE_TYPE (decl))))
+
 extern int flag_traditional;
 extern char *version_string;
 extern char *language_string;
@@ -166,7 +174,7 @@ struct filename_entry {
 
 typedef struct filename_entry filename_entry;
 
-/* Pointer to an array of elements, each one having the structure above. */
+/* Pointer to an array of elements, each one having the structure above.  */
 
 static filename_entry *filename_table;
 
@@ -205,7 +213,7 @@ static char *last_filename;
 
 static unsigned next_block_number = 2;
 
-/* Counter to generate unique names for DIEs. */
+/* Counter to generate unique names for DIEs.  */
 
 static unsigned next_unused_dienum = 1;
 
@@ -284,13 +292,133 @@ static tree fake_containing_scope;
 
 static unsigned current_funcdef_number = 1;
 
+/* A pointer to the ..._DECL node which we have most recently been working
+   on.  We keep this around just in case something about it looks screwy
+   and we want to tell the user what the source coordinates for the actual
+   declaration are.  */
+
+static tree dwarf_last_decl;
+
+/* A flag indicating that we are emitting the member declarations of a
+   class, so member functions and variables should not be entirely emitted.
+   This is a kludge to avoid passing a second argument to output_*_die.  */
+
+static int in_class;
+
 /* Forward declarations for functions defined in this file.  */
 
-static void output_type ();
-static void type_attribute ();
-static void output_decls_for_scope ();
-static void output_decl ();
-static unsigned lookup_filename ();
+static char *dwarf_tag_name            PROTO((unsigned));
+static char *dwarf_attr_name           PROTO((unsigned));
+static char *dwarf_stack_op_name       PROTO((unsigned));
+static char *dwarf_typemod_name                PROTO((unsigned));
+static char *dwarf_fmt_byte_name       PROTO((unsigned));
+static char *dwarf_fund_type_name      PROTO((unsigned));
+static tree decl_ultimate_origin       PROTO((tree));
+static tree block_ultimate_origin      PROTO((tree));
+static void output_unsigned_leb128     PROTO((unsigned long));
+static void output_signed_leb128       PROTO((long));
+static inline int is_body_block                PROTO((tree));
+static int fundamental_type_code       PROTO((tree));
+static tree root_type                  PROTO((tree));
+static void write_modifier_bytes       PROTO((tree, int, int));
+static inline int type_is_fundamental  PROTO((tree));
+static void equate_decl_number_to_die_number PROTO((tree));
+static inline void equate_type_number_to_die_number PROTO((tree));
+static void output_reg_number          PROTO((rtx));
+static void output_mem_loc_descriptor  PROTO((rtx));
+static void output_loc_descriptor      PROTO((rtx));
+static void output_bound_representation        PROTO((tree, unsigned, int));
+static void output_enumeral_list       PROTO((tree));
+static inline unsigned ceiling         PROTO((unsigned, unsigned));
+static inline tree field_type          PROTO((tree));
+static inline unsigned simple_type_align_in_bits PROTO((tree));
+static inline unsigned simple_type_size_in_bits  PROTO((tree));
+static unsigned field_byte_offset      PROTO((tree));
+static inline void sibling_attribute   PROTO((void));
+static void location_attribute         PROTO((rtx));
+static void data_member_location_attribute PROTO((tree));
+static void const_value_attribute      PROTO((rtx));
+static void location_or_const_value_attribute PROTO((tree));
+static inline void name_attribute      PROTO((char *));
+static inline void fund_type_attribute PROTO((unsigned));
+static void mod_fund_type_attribute    PROTO((tree, int, int));
+static inline void user_def_type_attribute PROTO((tree));
+static void mod_u_d_type_attribute     PROTO((tree, int, int));
+static inline void ordering_attribute  PROTO((unsigned));
+static void subscript_data_attribute   PROTO((tree));
+static void byte_size_attribute                PROTO((tree));
+static inline void bit_offset_attribute        PROTO((tree));
+static inline void bit_size_attribute  PROTO((tree));
+static inline void element_list_attribute PROTO((tree));
+static inline void stmt_list_attribute PROTO((char *));
+static inline void low_pc_attribute    PROTO((char *));
+static inline void high_pc_attribute   PROTO((char *));
+static inline void body_begin_attribute        PROTO((char *));
+static inline void body_end_attribute  PROTO((char *));
+static inline void langauge_attribute  PROTO((unsigned));
+static inline void member_attribute    PROTO((tree));
+static inline void string_length_attribute PROTO((tree));
+static inline void comp_dir_attribute  PROTO((char *));
+static inline void sf_names_attribute  PROTO((char *));
+static inline void src_info_attribute  PROTO((char *));
+static inline void mac_info_attribute  PROTO((char *));
+static inline void prototyped_attribute        PROTO((tree));
+static inline void producer_attribute  PROTO((char *));
+static inline void inline_attribute    PROTO((tree));
+static inline void containing_type_attribute PROTO((tree));
+static inline void abstract_origin_attribute PROTO((tree));
+static inline void src_coords_attribute PROTO((unsigned, unsigned));
+static inline void pure_or_virtual_attribute PROTO((tree));
+static void name_and_src_coords_attributes PROTO((tree));
+static void type_attribute             PROTO((tree, int, int));
+static char *type_tag                  PROTO((tree));
+static inline void dienum_push         PROTO((void));
+static inline void dienum_pop          PROTO((void));
+static inline tree member_declared_type PROTO((tree));
+static char *function_start_label      PROTO((tree));
+static void output_array_type_die      PROTO((void *));
+static void output_set_type_die                PROTO((void *));
+static void output_entry_point_die     PROTO((void *));
+static void output_inlined_enumeration_type_die PROTO((void *));
+static void output_inlined_structure_type_die PROTO((void *));
+static void output_inlined_union_type_die PROTO((void *));
+static void output_enumeration_type_die        PROTO((void *));
+static void output_formal_parameter_die        PROTO((void *));
+static void output_global_subroutine_die PROTO((void *));
+static void output_global_variable_die PROTO((void *));
+static void output_label_die           PROTO((void *));
+static void output_lexical_block_die   PROTO((void *));
+static void output_inlined_subroutine_die PROTO((void *));
+static void output_local_variable_die  PROTO((void *));
+static void output_member_die          PROTO((void *));
+static void output_pointer_type_die    PROTO((void *));
+static void output_reference_type_die  PROTO((void *));
+static void output_ptr_to_mbr_type_die PROTO((void *));
+static void output_compile_unit_die    PROTO((void *));
+static void output_string_type_die     PROTO((void *));
+static void output_structure_type_die  PROTO((void *));
+static void output_local_subroutine_die PROTO((void *));
+static void output_subroutine_type_die PROTO((void *));
+static void output_typedef_die         PROTO((void *));
+static void output_union_type_die      PROTO((void *));
+static void output_unspecified_parameters_die PROTO((void *));
+static void output_padded_null_die     PROTO((void *));
+static void output_die                 PROTO((void (*) (), void *));
+static void end_sibling_chain          PROTO((void));
+static void output_formal_types                PROTO((tree));
+static void pend_type                  PROTO((tree));
+static inline int type_of_for_scope    PROTO((tree, tree));
+static void output_pending_types_for_scope PROTO((tree));
+static void output_type                        PROTO((tree, tree));
+static void output_tagged_type_instantiation PROTO((tree));
+static void output_block               PROTO((tree, int));
+static void output_decls_for_scope     PROTO((tree, int));
+static void output_decl                        PROTO((tree, tree));
+static void shuffle_filename_entry     PROTO((filename_entry *));
+static void geneate_new_sfname_entry   PROTO((void));
+static unsigned lookup_filename                PROTO((char *));
+static void generate_srcinfo_entry     PROTO((unsigned, unsigned));
+static void generate_macinfo_entry     PROTO((char *, char *));
 \f
 /* Definitions of defaults for assembler-dependent names of various
    pseudo-ops and section names.
@@ -339,7 +467,7 @@ static unsigned lookup_filename ();
    section name must be enclosed in double quotes.  (See sparcv4.h.)  */
 
 #ifndef PUSHSECTION_FORMAT
-#define PUSHSECTION_FORMAT     "%s\t%s\n"
+#define PUSHSECTION_FORMAT     "\t%s\t%s\n"
 #endif
 
 #ifndef DEBUG_SECTION
@@ -525,6 +653,12 @@ static unsigned lookup_filename ();
 #ifndef SL_END_LABEL_FMT
 #define SL_END_LABEL_FMT       ".L_sl%u_e"
 #endif
+#ifndef BODY_BEGIN_LABEL_FMT
+#define BODY_BEGIN_LABEL_FMT   ".L_b%u"
+#endif
+#ifndef BODY_END_LABEL_FMT
+#define BODY_END_LABEL_FMT     ".L_b%u_e"
+#endif
 #ifndef FUNC_END_LABEL_FMT
 #define FUNC_END_LABEL_FMT     ".L_f%u_e"
 #endif
@@ -548,10 +682,7 @@ static unsigned lookup_filename ();
    output operations.
 
    If necessary, these may be overridden from within your tm.h file,
-   but typically, you shouldn't need to override these.  One known
-   exception is ASM_OUTPUT_DEF which has to be different for stock
-   sparc/svr4 assemblers.
-*/
+   but typically, you shouldn't need to override these.  */
 
 #ifndef ASM_OUTPUT_PUSH_SECTION
 #define ASM_OUTPUT_PUSH_SECTION(FILE, SECTION) \
@@ -565,16 +696,9 @@ static unsigned lookup_filename ();
 
 #ifndef ASM_OUTPUT_SOURCE_FILENAME
 #define ASM_OUTPUT_SOURCE_FILENAME(FILE,NAME) \
-  fprintf ((FILE), "\t%s\t\"%s\"\n", FILE_ASM_OP, NAME)
-#endif
-
-#ifndef ASM_OUTPUT_DEF
-#define ASM_OUTPUT_DEF(FILE,LABEL1,LABEL2)                             \
- do {  fprintf ((FILE), "\t%s\t", SET_ASM_OP);                         \
-       assemble_name (FILE, LABEL1);                                   \
-       fprintf (FILE, ",");                                            \
-       assemble_name (FILE, LABEL2);                                   \
-       fprintf (FILE, "\n");                                           \
+  do { fprintf (FILE, "\t%s\t", FILE_ASM_OP);                          \
+       output_quoted_string (FILE, NAME);                              \
+       fputc ('\n', FILE);                                             \
   } while (0)
 #endif
 
@@ -603,7 +727,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) TAG);           \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_tag_name (TAG));        \
     fputc ('\n', (FILE));                                              \
@@ -615,7 +739,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) ATTR);          \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_attr_name (ATTR));      \
     fputc ('\n', (FILE));                                              \
@@ -626,7 +750,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_STACK_OP(FILE,OP)                             \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) OP);                \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_stack_op_name (OP));    \
     fputc ('\n', (FILE));                                              \
@@ -638,7 +762,7 @@ static unsigned lookup_filename ();
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x",                                     \
                     UNALIGNED_SHORT_ASM_OP, (unsigned) FT);            \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_fund_type_name (FT));   \
     fputc ('\n', (FILE));                                              \
@@ -649,7 +773,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_FMT_BYTE(FILE,FMT)                            \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) FMT);       \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_fmt_byte_name (FMT));   \
     fputc ('\n', (FILE));                                              \
@@ -660,7 +784,7 @@ static unsigned lookup_filename ();
 #define ASM_OUTPUT_DWARF_TYPE_MODIFIER(FILE,MOD)                       \
   do {                                                                 \
     fprintf ((FILE), "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) MOD);       \
-    if (flag_verbose_asm)                                              \
+    if (flag_debug_asm)                                                        \
       fprintf ((FILE), "\t%s %s",                                      \
                       ASM_COMMENT_START, dwarf_typemod_name (MOD));    \
     fputc ('\n', (FILE));                                              \
@@ -730,16 +854,6 @@ static unsigned lookup_filename ();
 \f
 /************************ general utility functions **************************/
 
-inline char *
-xstrdup (s)
-     register char *s;
-{
-  register char *p = (char *) xmalloc (strlen (s) + 1);
-
-  strcpy (p, s);
-  return p;
-}
-
 inline int
 is_pseudo_reg (rtl)
      register rtx rtl;
@@ -749,6 +863,38 @@ is_pseudo_reg (rtl)
              && (REGNO (XEXP (rtl, 0)) >= FIRST_PSEUDO_REGISTER)));
 }
 
+inline tree
+type_main_variant (type)
+     register tree type;
+{
+  type = TYPE_MAIN_VARIANT (type);
+
+  /* There really should be only one main variant among any group of variants
+     of a given type (and all of the MAIN_VARIANT values for all members of
+     the group should point to that one type) but sometimes the C front-end
+     messes this up for array types, so we work around that bug here.  */
+
+  if (TREE_CODE (type) == ARRAY_TYPE)
+    {
+      while (type != TYPE_MAIN_VARIANT (type))
+        type = TYPE_MAIN_VARIANT (type);
+    }
+
+  return type;
+}
+
+/* Return non-zero if the given type node represents a tagged type.  */
+
+inline int
+is_tagged_type (type)
+     register tree type;
+{
+  register enum tree_code code = TREE_CODE (type);
+
+  return (code == RECORD_TYPE || code == UNION_TYPE
+         || code == QUAL_UNION_TYPE || code == ENUMERAL_TYPE);
+}
+
 static char *
 dwarf_tag_name (tag)
      register unsigned tag;
@@ -870,6 +1016,8 @@ dwarf_attr_name (attr)
     case AT_src_info:                  return "AT_src_info";
     case AT_mac_info:                  return "AT_mac_info";
     case AT_src_coords:                        return "AT_src_coords";
+    case AT_body_begin:                        return "AT_body_begin";
+    case AT_body_end:                  return "AT_body_end";
 
     default:                           return "AT_<unknown>";
     }
@@ -924,6 +1072,7 @@ dwarf_fmt_byte_name (fmt)
     default:           return "FMT_<unknown>";
     }
 }
+
 static char *
 dwarf_fund_type_name (ft)
      register unsigned ft;
@@ -970,7 +1119,7 @@ dwarf_fund_type_name (ft)
     case FT_unsigned_int32:    return "FT_unsigned_int32";
     case FT_int64:             return "FT_int64";
     case FT_signed_int64:      return "FT_signed_int64";
-    case FT_unsigned_int64:    return "FT_signed_int64";
+    case FT_unsigned_int64:    return "FT_unsigned_int64";
 
     case FT_real32:            return "FT_real32";
     case FT_real64:            return "FT_real64";
@@ -1010,6 +1159,58 @@ decl_ultimate_origin (decl)
     }
 }
 
+/* Determine the "ultimate origin" of a block.  The block may be an
+   inlined instance of an inlined instance of a block which is local
+   to an inline function, so we have to trace all of the way back
+   through the origin chain to find out what sort of node actually
+   served as the original seed for the given block.  */
+
+static tree
+block_ultimate_origin (block)
+     register tree block;
+{
+  register tree immediate_origin = BLOCK_ABSTRACT_ORIGIN (block);
+
+  if (immediate_origin == NULL)
+    return NULL;
+  else
+    {
+      register tree ret_val;
+      register tree lookahead = immediate_origin;
+
+      do
+       {
+         ret_val = lookahead;
+         lookahead = (TREE_CODE (ret_val) == BLOCK)
+                      ? BLOCK_ABSTRACT_ORIGIN (ret_val)
+                      : NULL;
+       }
+      while (lookahead != NULL && lookahead != ret_val);
+      return ret_val;
+    }
+}
+
+/* Get the class to which DECL belongs, if any.  In g++, the DECL_CONTEXT
+   of a virtual function may refer to a base class, so we check the 'this'
+   parameter.  */
+
+static tree
+decl_class_context (decl)
+     tree decl;
+{
+  tree context = NULL_TREE;
+  if (TREE_CODE (decl) != FUNCTION_DECL || ! DECL_VINDEX (decl))
+    context = DECL_CONTEXT (decl);
+  else
+    context = TYPE_MAIN_VARIANT
+      (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (decl)))));
+
+  if (context && TREE_CODE_CLASS (TREE_CODE (context)) != 't')
+    context = NULL_TREE;
+
+  return context;
+}
+
 static void
 output_unsigned_leb128 (value)
      register unsigned long value;
@@ -1024,7 +1225,7 @@ output_unsigned_leb128 (value)
       if (value != 0)  /* more bytes to follow */
        byte |= 0x80;
       fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
-      if (flag_verbose_asm && value == 0)
+      if (flag_debug_asm && value == 0)
        fprintf (asm_out_file, "\t%s ULEB128 number - value = %u",
                 ASM_COMMENT_START, orig_value);
       fputc ('\n', asm_out_file);
@@ -1056,7 +1257,7 @@ output_signed_leb128 (value)
          more = 1;
        }
       fprintf (asm_out_file, "\t%s\t0x%x", ASM_BYTE_OP, (unsigned) byte);
-      if (flag_verbose_asm && more == 0)
+      if (flag_debug_asm && more == 0)
        fprintf (asm_out_file, "\t%s SLEB128 number - value = %d",
                 ASM_COMMENT_START, orig_value);
       fputc ('\n', asm_out_file);
@@ -1067,23 +1268,34 @@ output_signed_leb128 (value)
 /**************** utility functions for attribute functions ******************/
 
 /* Given a pointer to a BLOCK node return non-zero if (and only if) the
-   node in question represents the outermost block (i.e. the "body block")
-   of a function or method.
-
-   For any BLOCK node representing a "body block", the BLOCK_SUPERCONTEXT
-   of the node will point to another BLOCK node which represents the outer-
-   most (function) scope for the function or method.  The BLOCK_SUPERCONTEXT
-   of that node in turn will point to the relevant FUNCTION_DECL node.
+   node in question represents the outermost pair of curly braces (i.e.
+   the "body block") of a function or method.
+
+   For any BLOCK node representing a "body block" of a function or method,
+   the BLOCK_SUPERCONTEXT of the node will point to another BLOCK node
+   which represents the outermost (function) scope for the function or
+   method (i.e. the one which includes the formal parameters).  The
+   BLOCK_SUPERCONTEXT of *that* node in turn will point to the relevant
+   FUNCTION_DECL node.
 */
 
-inline int
+static inline int
 is_body_block (stmt)
      register tree stmt;
 {
-  register enum tree_code code
-    = TREE_CODE (BLOCK_SUPERCONTEXT (BLOCK_SUPERCONTEXT (stmt)));
+  if (TREE_CODE (stmt) == BLOCK)
+    {
+      register tree parent = BLOCK_SUPERCONTEXT (stmt);
 
-  return (code == FUNCTION_DECL);
+      if (TREE_CODE (parent) == BLOCK)
+       {
+         register tree grandparent = BLOCK_SUPERCONTEXT (parent);
+
+         if (TREE_CODE (grandparent) == FUNCTION_DECL)
+           return 1;
+       }
+    }
+  return 0;
 }
 
 /* Given a pointer to a tree node for some type, return a Dwarf fundamental
@@ -1248,10 +1460,10 @@ root_type (type)
 
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-       return TYPE_MAIN_VARIANT (root_type (TREE_TYPE (type)));
+       return type_main_variant (root_type (TREE_TYPE (type)));
 
       default:
-       return TYPE_MAIN_VARIANT (type);
+       return type_main_variant (type);
     }
 }
 
@@ -1292,7 +1504,7 @@ write_modifier_bytes (type, decl_const, decl_volatile)
 /* Given a pointer to an arbitrary ..._TYPE tree node, return non-zero if the
    given input type is a Dwarf "fundamental" type.  Otherwise return zero.  */
 
-inline int
+static inline int
 type_is_fundamental (type)
      register tree type;
 {
@@ -1311,12 +1523,12 @@ type_is_fundamental (type)
       case ARRAY_TYPE:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
       case ENUMERAL_TYPE:
       case FUNCTION_TYPE:
       case METHOD_TYPE:
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-      case STRING_TYPE:
       case FILE_TYPE:
       case OFFSET_TYPE:
       case LANG_TYPE:
@@ -1373,7 +1585,7 @@ equate_decl_number_to_die_number (decl)
    simply by re-generating the alternative name from the ..._TYPE node's
    UID number. */
 
-inline void
+static inline void
 equate_type_number_to_die_number (type)
      register tree type;
 {
@@ -1385,13 +1597,35 @@ equate_type_number_to_die_number (type)
      to get the equate to come out right, we need to get the main variant
      itself here.  */
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = type_main_variant (type);
 
   sprintf (type_label, TYPE_NAME_FMT, TYPE_UID (type));
   sprintf (die_label, DIE_BEGIN_LABEL_FMT, current_dienum);
   ASM_OUTPUT_DEF (asm_out_file, type_label, die_label);
 }
 
+static void
+output_reg_number (rtl)
+     register rtx rtl;
+{
+  register unsigned regno = REGNO (rtl);
+
+  if (regno >= FIRST_PSEUDO_REGISTER)
+    {
+      warning_with_decl (dwarf_last_decl, "internal regno botch: regno = %d\n",
+                        regno);
+      regno = 0;
+    }
+  fprintf (asm_out_file, "\t%s\t0x%x",
+          UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
+  if (flag_debug_asm)
+    {
+      fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
+      PRINT_REG (rtl, 0, asm_out_file);
+    }
+  fputc ('\n', asm_out_file);
+}
+
 /* The following routine is a nice and simple transducer.  It converts the
    RTL for a variable or parameter (resident in memory) into an equivalent
    Dwarf representation of a mechanism for getting the address of that same
@@ -1428,15 +1662,25 @@ output_mem_loc_descriptor (rtl)
 
        /* Whenever a register number forms a part of the description of
           the method for calculating the (dynamic) address of a memory
-          resident object, Dwarf rules require the register number to
+          resident object, DWARF rules require the register number to
           be referred to as a "base register".  This distinction is not
           based in any way upon what category of register the hardware
           believes the given register belongs to.  This is strictly
-          Dwarf terminology we're dealing with here.  */
+          DWARF terminology we're dealing with here.
+
+          Note that in cases where the location of a memory-resident data
+          object could be expressed as:
+
+                   OP_ADD (OP_BASEREG (basereg), OP_CONST (0))
+
+          the actual DWARF location descriptor that we generate may just
+          be OP_BASEREG (basereg).  This may look deceptively like the
+          object in question was allocated to a register (rather than
+          in memory) so DWARF consumers need to be aware of the subtle
+          distinction between OP_REG and OP_BASEREG.  */
 
        ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_BASEREG);
-        ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               DBX_REGISTER_NUMBER (REGNO (rtl)));
+       output_reg_number (rtl);
        break;
 
       case MEM:
@@ -1461,6 +1705,15 @@ output_mem_loc_descriptor (rtl)
        ASM_OUTPUT_DWARF_DATA4 (asm_out_file, INTVAL (rtl));
        break;
 
+      case MULT:
+       /* If a pseudo-reg is optimized away, it is possible for it to
+          be replaced with a MEM containing a multiply.  Use a GNU extension
+          to describe it.  */
+       output_mem_loc_descriptor (XEXP (rtl, 0));
+       output_mem_loc_descriptor (XEXP (rtl, 1));
+       ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_MULT);
+       break;
+
       default:
        abort ();
     }
@@ -1491,8 +1744,7 @@ output_loc_descriptor (rtl)
 
     case REG:
        ASM_OUTPUT_DWARF_STACK_OP (asm_out_file, OP_REG);
-        ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               DBX_REGISTER_NUMBER (REGNO (rtl)));
+       output_reg_number (rtl);
        break;
 
     case MEM:
@@ -1516,79 +1768,73 @@ output_bound_representation (bound, dim_num, u_or_l)
   switch (TREE_CODE (bound))
     {
 
-      case ERROR_MARK:
-       return;
+    case ERROR_MARK:
+      return;
 
       /* All fixed-bounds are represented by INTEGER_CST nodes.         */
 
-      case INTEGER_CST:
-       ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
-                               (unsigned) TREE_INT_CST_LOW (bound));
-       break;
-
-      /* Dynamic bounds may be represented by NOP_EXPR nodes containing
-        SAVE_EXPR nodes.  */
-
-      case NOP_EXPR:
-       bound = TREE_OPERAND (bound, 0);
-       /* ... fall thru... */
-
-      case SAVE_EXPR:
-       {
-         char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
-         char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-         sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
-                               current_dienum, dim_num, u_or_l);
-
-         sprintf (end_label,   BOUND_END_LABEL_FMT,
-                               current_dienum, dim_num, u_or_l);
-
-         ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
-         ASM_OUTPUT_LABEL (asm_out_file, begin_label);
-
-         /* If we are working on a bound for a dynamic dimension in C,
-            the dynamic dimension in question had better have a static
-            (zero) lower bound and a dynamic *upper* bound.  */
+    case INTEGER_CST:
+      ASM_OUTPUT_DWARF_DATA4 (asm_out_file,
+                             (unsigned) TREE_INT_CST_LOW (bound));
+      break;
 
-         if (u_or_l != 'u')
-           abort ();
+    default:
 
-         /* If optimization is turned on, the SAVE_EXPRs that describe
-            how to access the upper bound values are essentially bogus.
-            They only describe (at best) how to get at these values at
-            the points in the generated code right after they have just
-            been computed.  Worse yet, in the typical case, the upper
-            bound values will not even *be* computed in the optimized
-            code, so these SAVE_EXPRs are entirely bogus.
-
-            In order to compensate for this fact, we check here to see
-            if optimization is enabled, and if so, we effectively create
-            an empty location description for the (unknown and unknowable)
-            upper bound.
-
-            This should not cause too much trouble for existing (stupid?)
-            debuggers because they have to deal with empty upper bounds
-            location descriptions anyway in order to be able to deal with
-            incomplete array types.
-
-            Of course an intelligent debugger (GDB?) should be able to
-            comprehend that a missing upper bound specification in a
-            array type used for a storage class `auto' local array variable
-            indicates that the upper bound is both unknown (at compile-
-            time) and unknowable (at run-time) due to optimization.
-         */
+      /* Dynamic bounds may be represented by NOP_EXPR nodes containing
+        SAVE_EXPR nodes, in which case we can do something, or as
+        an expression, which we cannot represent.  */
+      {
+       char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
+       char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+       sprintf (begin_label, BOUND_BEGIN_LABEL_FMT,
+                current_dienum, dim_num, u_or_l);
+
+       sprintf (end_label, BOUND_END_LABEL_FMT,
+                current_dienum, dim_num, u_or_l);
+
+       ASM_OUTPUT_DWARF_DELTA2 (asm_out_file, end_label, begin_label);
+       ASM_OUTPUT_LABEL (asm_out_file, begin_label);
+
+       /* If optimization is turned on, the SAVE_EXPRs that describe
+          how to access the upper bound values are essentially bogus.
+          They only describe (at best) how to get at these values at
+          the points in the generated code right after they have just
+          been computed.  Worse yet, in the typical case, the upper
+          bound values will not even *be* computed in the optimized
+          code, so these SAVE_EXPRs are entirely bogus.
+
+          In order to compensate for this fact, we check here to see
+          if optimization is enabled, and if so, we effectively create
+          an empty location description for the (unknown and unknowable)
+          upper bound.
+
+          This should not cause too much trouble for existing (stupid?)
+          debuggers because they have to deal with empty upper bounds
+          location descriptions anyway in order to be able to deal with
+          incomplete array types.
+
+          Of course an intelligent debugger (GDB?) should be able to
+          comprehend that a missing upper bound specification in a
+          array type used for a storage class `auto' local array variable
+          indicates that the upper bound is both unknown (at compile-
+          time) and unknowable (at run-time) due to optimization. */
+
+       if (! optimize)
+         {
+           while (TREE_CODE (bound) == NOP_EXPR
+                  || TREE_CODE (bound) == CONVERT_EXPR)
+             bound = TREE_OPERAND (bound, 0);
 
-         if (! optimize)
-           output_loc_descriptor
-             (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
+           if (TREE_CODE (bound) == SAVE_EXPR)
+             output_loc_descriptor
+               (eliminate_regs (SAVE_EXPR_RTL (bound), 0, NULL_RTX));
+         }
 
-         ASM_OUTPUT_LABEL (asm_out_file, end_label);
-       }
-       break;
+       ASM_OUTPUT_LABEL (asm_out_file, end_label);
+      }
+      break;
 
-      default:
-       abort ();
     }
 }
 
@@ -1613,7 +1859,7 @@ output_enumeral_list (link)
 /* Given an unsigned value, round it up to the lowest multiple of `boundary'
    which is not less than the value itself.  */
 
-inline unsigned
+static inline unsigned
 ceiling (value, boundary)
      register unsigned value;
      register unsigned boundary;
@@ -1625,7 +1871,7 @@ ceiling (value, boundary)
    pointer to the declared type for the relevant field variable, or return
    `integer_type_node' if the given node turns out to be an ERROR_MARK node.  */
 
-inline tree
+static inline tree
 field_type (decl)
      register tree decl;
 {
@@ -1644,7 +1890,7 @@ field_type (decl)
    node, return the alignment in bits for the type, or else return
    BITS_PER_WORD if the node actually turns out to be an ERROR_MARK node.  */
 
-inline unsigned
+static inline unsigned
 simple_type_align_in_bits (type)
      register tree type;
 {
@@ -1657,7 +1903,7 @@ simple_type_align_in_bits (type)
    constant, or else return BITS_PER_WORD if the type actually turns out
    to be an ERROR_MARK node.  */
 
-inline unsigned
+static inline unsigned
 simple_type_size_in_bits (type)
      register tree type;
 {
@@ -1752,7 +1998,7 @@ field_byte_offset (decl)
      for the declared type of the field) which it can possibly use, subject
      to the condition that there is still enough available space remaining
      in the containing object (when allocated at the selected point) to
-     fully accomodate all of the bits of the bit-field itself.
+     fully accommodate all of the bits of the bit-field itself.
 
      This simple rule makes it obvious why GCC allocates 8 bytes for each
      object of the structure type shown above.  When looking for a place to
@@ -1801,7 +2047,7 @@ field_byte_offset (decl)
 
 /* Generate an AT_sibling attribute.  */
 
-inline void
+static inline void
 sibling_attribute ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -1831,13 +2077,27 @@ location_attribute (rtl)
   /* Handle a special case.  If we are about to output a location descriptor
      for a variable or parameter which has been optimized out of existence,
      don't do that.  Instead we output a zero-length location descriptor
-     value as part of the location attribute.  Note that we cannot simply
-     suppress the entire location attribute, because the absence of a
-     location attribute in certain kinds of DIEs is used to indicate some-
-     thing entirely different... i.e. that the DIE represents an object
-     declaration, but not a definition.  So sayeth the PLSIG.  */
+     value as part of the location attribute.
+
+     A variable which has been optimized out of existence will have a
+     DECL_RTL value which denotes a pseudo-reg.
+
+     Currently, in some rare cases, variables can have DECL_RTL values
+     which look like (MEM (REG pseudo-reg#)).  These cases are due to
+     bugs elsewhere in the compiler.  We treat such cases
+     as if the variable(s) in question had been optimized out of existence.
+
+     Note that in all cases where we wish to express the fact that a
+     variable has been optimized out of existence, we do not simply
+     suppress the generation of the entire location attribute because
+     the absence of a location attribute in certain kinds of DIEs is
+     used to indicate something else entirely... i.e. that the DIE
+     represents an object declaration, but not a definition.  So saith
+     the PLSIG.
+  */
 
-  if (! is_pseudo_reg (rtl))
+  if (! is_pseudo_reg (rtl)
+      && (GET_CODE (rtl) != MEM || ! is_pseudo_reg (XEXP (rtl, 0))))
     output_loc_descriptor (eliminate_regs (rtl, 0, NULL_RTX));
 
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
@@ -1862,17 +2122,21 @@ location_attribute (rtl)
    object" which will be given in the AT_byte_size attribute for this
    bit-field.  (See the `byte_size_attribute' function below.)  It is
    also used when calculating the value of the AT_bit_offset attribute.
-   (See the `bit_offset_attribute' function below.)
-*/
+   (See the `bit_offset_attribute' function below.)  */
 
 static void
-data_member_location_attribute (decl)
-     register tree decl;
+data_member_location_attribute (t)
+     register tree t;
 {
-  register unsigned object_offset_in_bytes = field_byte_offset (decl);
+  register unsigned object_offset_in_bytes;
   char begin_label[MAX_ARTIFICIAL_LABEL_BYTES];
   char end_label[MAX_ARTIFICIAL_LABEL_BYTES];
 
+  if (TREE_CODE (t) == TREE_VEC)
+    object_offset_in_bytes = TREE_INT_CST_LOW (BINFO_OFFSET (t));
+  else
+    object_offset_in_bytes = field_byte_offset (t);
+
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_location);
   sprintf (begin_label, LOC_BEGIN_LABEL_FMT, current_dienum);
   sprintf (end_label, LOC_END_LABEL_FMT, current_dienum);
@@ -1985,68 +2249,107 @@ location_or_const_value_attribute (decl)
     return;
 
   if ((TREE_CODE (decl) != VAR_DECL) && (TREE_CODE (decl) != PARM_DECL))
-    abort ();
+    {
+      /* Should never happen.  */
+      abort ();
+      return;
+    }
 
-  /* Existing Dwarf debuggers need and expect the location descriptors for
-     formal parameters to reflect either the place where the parameters get
-     passed (if they are passed on the stack and in memory) or else the
-     (preserved) registers which the parameters get copied to during the
-     function prologue.
-
-     At least this is the way things are for most common CISC machines
-     (e.g. x86 and m68k) where parameters are passed in the stack, and for
-     most common RISC machines (e.g. i860 and m88k) where parameters are
-     passed in registers.
-
-     The rules for Sparc are a little weird for some reason.  The DWARF
-     generated by the USL C compiler for the Sparc/svr4 reference port says
-     that the parameters are passed in the stack.  I haven't figured out
-     how to duplicate that behavior here (for the Sparc) yet, or even if
-     I really need to.
-
-     Note that none of this is clearly spelled out in the current Dwarf
-     version 1 specification, but it's obvious if you look at the output of
-     the CI5 compiler, or if you try to use the svr4 SDB debugger.  Hopefully,
-     a later version of the Dwarf specification will clarify this.  For now,
-     we just need to generate the right thing.  Note that Dwarf version 2
-     will provide us with a means to describe *all* of the locations in which
-     a given variable or parameter resides (and the PC ranges over which it
-     occupies each one), but for now we can only describe one "location"
-     for each formal parameter passed, and so we just try to mimic existing
-     practice as much as possible.
+  /* Here we have to decide where we are going to say the parameter "lives"
+     (as far as the debugger is concerned).  We only have a couple of choices.
+     GCC provides us with DECL_RTL and with DECL_INCOMING_RTL.  DECL_RTL
+     normally indicates where the parameter lives during most of the activa-
+     tion of the function.  If optimization is enabled however, this could
+     be either NULL or else a pseudo-reg.  Both of those cases indicate that
+     the parameter doesn't really live anywhere (as far as the code generation
+     parts of GCC are concerned) during most of the function's activation.
+     That will happen (for example) if the parameter is never referenced
+     within the function.
+
+     We could just generate a location descriptor here for all non-NULL
+     non-pseudo values of DECL_RTL and ignore all of the rest, but we can
+     be a little nicer than that if we also consider DECL_INCOMING_RTL in
+     cases where DECL_RTL is NULL or is a pseudo-reg.
+
+     Note however that we can only get away with using DECL_INCOMING_RTL as
+     a backup substitute for DECL_RTL in certain limited cases.  In cases
+     where DECL_ARG_TYPE(decl) indicates the same type as TREE_TYPE(decl)
+     we can be sure that the parameter was passed using the same type as it
+     is declared to have within the function, and that its DECL_INCOMING_RTL
+     points us to a place where a value of that type is passed.  In cases
+     where DECL_ARG_TYPE(decl) and TREE_TYPE(decl) are different types
+     however, we cannot (in general) use DECL_INCOMING_RTL as a backup
+     substitute for DECL_RTL because in these cases, DECL_INCOMING_RTL
+     points us to a value of some type which is *different* from the type
+     of the parameter itself.  Thus, if we tried to use DECL_INCOMING_RTL
+     to generate a location attribute in such cases, the debugger would
+     end up (for example) trying to fetch a `float' from a place which
+     actually contains the first part of a `double'.  That would lead to
+     really incorrect and confusing output at debug-time, and we don't
+     want that now do we?
+
+     So in general, we DO NOT use DECL_INCOMING_RTL as a backup for DECL_RTL
+     in cases where DECL_ARG_TYPE(decl) != TREE_TYPE(decl).  There are a
+     couple of cute exceptions however.  On little-endian machines we can
+     get away with using DECL_INCOMING_RTL even when DECL_ARG_TYPE(decl) is
+     not the same as TREE_TYPE(decl) but only when DECL_ARG_TYPE(decl) is
+     an integral type which is smaller than TREE_TYPE(decl).  These cases
+     arise when (on a little-endian machine) a non-prototyped function has
+     a parameter declared to be of type `short' or `char'.  In such cases,
+     TREE_TYPE(decl) will be `short' or `char', DECL_ARG_TYPE(decl) will be
+     `int', and DECL_INCOMING_RTL will point to the lowest-order byte of the
+     passed `int' value.  If the debugger then uses that address to fetch a
+     `short' or a `char' (on a little-endian machine) the result will be the
+     correct data, so we allow for such exceptional cases below.
+
+     Note that our goal here is to describe the place where the given formal
+     parameter lives during most of the function's activation (i.e. between
+     the end of the prologue and the start of the epilogue).  We'll do that
+     as best as we can.  Note however that if the given formal parameter is
+     modified sometime during the execution of the function, then a stack
+     backtrace (at debug-time) will show the function as having been called
+     with the *new* value rather than the value which was originally passed
+     in.  This happens rarely enough that it is not a major problem, but it
+     *is* a problem, and I'd like to fix it.  A future version of dwarfout.c
+     may generate two additional attributes for any given TAG_formal_parameter
+     DIE which will describe the "passed type" and the "passed location" for
+     the given formal parameter in addition to the attributes we now generate
+     to indicate the "declared type" and the "active location" for each
+     parameter.  This additional set of attributes could be used by debuggers
+     for stack backtraces.
+
+     Separately, note that sometimes DECL_RTL can be NULL and DECL_INCOMING_RTL
+     can be NULL also.  This happens (for example) for inlined-instances of
+     inline function formal parameters which are never referenced.  This really
+     shouldn't be happening.  All PARM_DECL nodes should get valid non-NULL
+     DECL_INCOMING_RTL values, but integrate.c doesn't currently generate
+     these values for inlined instances of inline function parameters, so
+     when we see such cases, we are just SOL (shit-out-of-luck) for the time
+     being (until integrate.c gets fixed).
   */
 
-  if (TREE_CODE (decl) != PARM_DECL)
-    /*  If this decl is not a formal parameter, just use DECL_RTL.  */
-    rtl = DECL_RTL (decl);
-  else
-    {
-      if (GET_CODE (DECL_INCOMING_RTL (decl)) == MEM)
-        /* Parameter was passed in memory, so say that's where it lives.  */
-       rtl = DECL_INCOMING_RTL (decl);
-      else
-       {
-          /* Parameter was passed in a register, so say it lives in the
-            register it will be copied to during the prologue.  */
-          rtl = DECL_RTL (decl);
-
-         /* Note that in cases where the formal parameter is never used
-            and where this compilation is done with -O, the copying of
-            of an incoming register parameter to another register (in
-            the prologue) can be totally optimized away.  (In such cases
-            the DECL_RTL will indicate a pseudo-register.)  We could just
-            use the DECL_RTL (as we normally do for register parameters)
-            in these cases, but if we did that, we would end up generating
-            a null location descriptor.  (See `location_attribute' above.)
-            That would be acceptable (according to the DWARF spec) but it
-            is probably more useful to say that the formal resides where
-            it was passed instead of saying that it resides nowhere.  */
-         if (is_pseudo_reg (rtl))
-           rtl = DECL_INCOMING_RTL (decl);
-       }
-    }
+  /* Use DECL_RTL as the "location" unless we find something better.  */
+  rtl = DECL_RTL (decl);
+
+  if (TREE_CODE (decl) == PARM_DECL)
+    if (rtl == NULL_RTX || is_pseudo_reg (rtl))
+      {
+       /* This decl represents a formal parameter which was optimized out.  */
+        register tree declared_type = type_main_variant (TREE_TYPE (decl));
+        register tree passed_type = type_main_variant (DECL_ARG_TYPE (decl));
+
+       /* Note that DECL_INCOMING_RTL may be NULL in here, but we handle
+          *all* cases where (rtl == NULL_RTX) just below.  */
+
+       if (declared_type == passed_type)
+         rtl = DECL_INCOMING_RTL (decl);
+       else if (! BYTES_BIG_ENDIAN)
+         if (TREE_CODE (declared_type) == INTEGER_TYPE)
+           if (TYPE_SIZE (declared_type) <= TYPE_SIZE (passed_type))
+             rtl = DECL_INCOMING_RTL (decl);
+      }
 
-  if (rtl == NULL)
+  if (rtl == NULL_RTX)
     return;
 
   switch (GET_CODE (rtl))
@@ -2075,7 +2378,7 @@ location_or_const_value_attribute (decl)
 /* Generate an AT_name attribute given some string value to be included as
    the value of the attribute. */
 
-inline void
+static inline void
 name_attribute (name_string)
      register char *name_string;
 {
@@ -2086,7 +2389,7 @@ name_attribute (name_string)
     }
 }
 
-inline void
+static inline void
 fund_type_attribute (ft_code)
      register unsigned ft_code;
 {
@@ -2114,7 +2417,7 @@ mod_fund_type_attribute (type, decl_const, decl_volatile)
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
 
-inline void
+static inline void
 user_def_type_attribute (type)
      register tree type;
 {
@@ -2147,7 +2450,7 @@ mod_u_d_type_attribute (type, decl_const, decl_volatile)
 }
 
 #ifdef USE_ORDERING_ATTRIBUTE
-inline void
+static inline void
 ordering_attribute (ordering)
      register unsigned ordering;
 {
@@ -2204,7 +2507,7 @@ subscript_data_attribute (type)
          if (! type_is_fundamental (domain))
            abort ();
 
-         /* Output the representation format byte for this dimension. */
+         /* Output the representation format byte for this dimension.  */
 
          ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file,
                                  FMT_CODE (1,
@@ -2250,7 +2553,7 @@ subscript_data_attribute (type)
        }
     }
 
-  /* Output the prefix byte that says that the element type is comming up.  */
+  /* Output the prefix byte that says that the element type is coming up.  */
 
   ASM_OUTPUT_DWARF_FMT_BYTE (asm_out_file, FMT_ET);
 
@@ -2277,6 +2580,7 @@ byte_size_attribute (tree_node)
       case ENUMERAL_TYPE:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
        size = int_size_in_bytes (tree_node);
        break;
 
@@ -2317,10 +2621,9 @@ byte_size_attribute (tree_node)
 
    Note that it is the size (in bytes) of the hypothetical "containing
    object" which will be given in the AT_byte_size attribute for this
-   bit-field.  (See `byte_size_attribute' above.)
-*/
+   bit-field.  (See `byte_size_attribute' above.) */
 
-inline void
+static inline void
 bit_offset_attribute (decl)
     register tree decl;
 {
@@ -2352,19 +2655,18 @@ bit_offset_attribute (decl)
   highest_order_object_bit_offset = object_offset_in_bytes * BITS_PER_UNIT;
   highest_order_field_bit_offset = bitpos_int;
 
-#if (BYTES_BIG_ENDIAN == 0)
-  highest_order_field_bit_offset
-    += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
+  if (! BYTES_BIG_ENDIAN)
+    {
+      highest_order_field_bit_offset
+       += (unsigned) TREE_INT_CST_LOW (DECL_SIZE (decl));
 
-  highest_order_object_bit_offset += simple_type_size_in_bits (type);
-#endif /* (BYTES_BIG_ENDIAN == 0) */
+      highest_order_object_bit_offset += simple_type_size_in_bits (type);
+    }
 
   bit_offset =
-#if (BYTES_BIG_ENDIAN == 0)
-         highest_order_object_bit_offset - highest_order_field_bit_offset;
-#else /* (BYTES_BIG_ENDIAN != 0) */
-         highest_order_field_bit_offset - highest_order_object_bit_offset;
-#endif /* (BYTES_BIG_ENDIAN != 0) */
+    (! BYTES_BIG_ENDIAN
+     ? highest_order_object_bit_offset - highest_order_field_bit_offset
+     : highest_order_field_bit_offset - highest_order_object_bit_offset);
 
   ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_bit_offset);
   ASM_OUTPUT_DWARF_DATA2 (asm_out_file, bit_offset);
@@ -2373,7 +2675,7 @@ bit_offset_attribute (decl)
 /* For a FIELD_DECL node which represents a bit field, output an attribute
    which specifies the length in bits of the given field.  */
 
-inline void
+static inline void
 bit_size_attribute (decl)
     register tree decl;
 {
@@ -2390,7 +2692,7 @@ bit_size_attribute (decl)
    all of the enumeration constants associated with the given enumeration
    type.  */
 
-inline void
+static inline void
 element_list_attribute (element)
      register tree element;
 {
@@ -2416,7 +2718,7 @@ element_list_attribute (element)
 /* Generate an AT_stmt_list attribute. These are normally present only in
    DIEs with a TAG_compile_unit tag.  */
 
-inline void
+static inline void
 stmt_list_attribute (label)
     register char *label;
 {
@@ -2428,7 +2730,7 @@ stmt_list_attribute (label)
 /* Generate an AT_low_pc attribute for a label DIE, a lexical_block DIE or
    for a subroutine DIE.  */
 
-inline void
+static inline void
 low_pc_attribute (asm_low_label)
      register char *asm_low_label;
 {
@@ -2439,7 +2741,7 @@ low_pc_attribute (asm_low_label)
 /* Generate an AT_high_pc attribute for a lexical_block DIE or for a
    subroutine DIE.  */
 
-inline void
+static inline void
 high_pc_attribute (asm_high_label)
     register char *asm_high_label;
 {
@@ -2447,10 +2749,30 @@ high_pc_attribute (asm_high_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_high_label);
 }
 
+/* Generate an AT_body_begin attribute for a subroutine DIE.  */
+
+static inline void
+body_begin_attribute (asm_begin_label)
+     register char *asm_begin_label;
+{
+  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_begin);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_begin_label);
+}
+
+/* Generate an AT_body_end attribute for a subroutine DIE.  */
+
+static inline void
+body_end_attribute (asm_end_label)
+     register char *asm_end_label;
+{
+  ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_body_end);
+  ASM_OUTPUT_DWARF_ADDR (asm_out_file, asm_end_label);
+}
+
 /* Generate an AT_language attribute given a LANG value.  These attributes
    are used only within TAG_compile_unit DIEs.  */
 
-inline void
+static inline void
 language_attribute (language_code)
      register unsigned language_code;
 {
@@ -2458,7 +2780,7 @@ language_attribute (language_code)
   ASM_OUTPUT_DWARF_DATA4 (asm_out_file, language_code);
 }
 
-inline void
+static inline void
 member_attribute (context)
     register tree context;
 {
@@ -2466,9 +2788,7 @@ member_attribute (context)
 
   /* Generate this attribute only for members in C++.  */
 
-  if (context != NULL
-      && (TREE_CODE (context) == RECORD_TYPE
-         || TREE_CODE (context) == UNION_TYPE))
+  if (context != NULL && is_tagged_type (context))
     {
       ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_member);
       sprintf (label, TYPE_NAME_FMT, TYPE_UID (context));
@@ -2476,7 +2796,7 @@ member_attribute (context)
     }
 }
 
-inline void
+static inline void
 string_length_attribute (upper_bound)
      register tree upper_bound;
 {
@@ -2492,7 +2812,7 @@ string_length_attribute (upper_bound)
   ASM_OUTPUT_LABEL (asm_out_file, end_label);
 }
 
-inline void
+static inline void
 comp_dir_attribute (dirname)
      register char *dirname;
 {
@@ -2500,7 +2820,7 @@ comp_dir_attribute (dirname)
   ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
 }
 
-inline void
+static inline void
 sf_names_attribute (sf_names_start_label)
      register char *sf_names_start_label;
 {
@@ -2509,7 +2829,7 @@ sf_names_attribute (sf_names_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, sf_names_start_label);
 }
 
-inline void
+static inline void
 src_info_attribute (src_info_start_label)
      register char *src_info_start_label;
 {
@@ -2518,7 +2838,7 @@ src_info_attribute (src_info_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, src_info_start_label);
 }
 
-inline void
+static inline void
 mac_info_attribute (mac_info_start_label)
      register char *mac_info_start_label;
 {
@@ -2527,7 +2847,7 @@ mac_info_attribute (mac_info_start_label)
   ASM_OUTPUT_DWARF_ADDR (asm_out_file, mac_info_start_label);
 }
 
-inline void
+static inline void
 prototyped_attribute (func_type)
      register tree func_type;
 {
@@ -2539,7 +2859,7 @@ prototyped_attribute (func_type)
     }
 }
 
-inline void
+static inline void
 producer_attribute (producer)
      register char *producer;
 {
@@ -2547,7 +2867,7 @@ producer_attribute (producer)
   ASM_OUTPUT_DWARF_STRING (asm_out_file, producer);
 }
 
-inline void
+static inline void
 inline_attribute (decl)
      register tree decl;
 {
@@ -2558,7 +2878,7 @@ inline_attribute (decl)
     }
 }
 
-inline void
+static inline void
 containing_type_attribute (containing_type)
      register tree containing_type;
 {
@@ -2569,7 +2889,7 @@ containing_type_attribute (containing_type)
   ASM_OUTPUT_DWARF_REF (asm_out_file, label);
 }
 
-inline void
+static inline void
 abstract_origin_attribute (origin)
      register tree origin;
 {
@@ -2594,7 +2914,7 @@ abstract_origin_attribute (origin)
 }
 
 #ifdef DWARF_DECL_COORDINATES
-inline void
+static inline void
 src_coords_attribute (src_fileno, src_lineno)
      register unsigned src_fileno;
      register unsigned src_lineno;
@@ -2605,15 +2925,17 @@ src_coords_attribute (src_fileno, src_lineno)
 }
 #endif /* defined(DWARF_DECL_COORDINATES) */
 
-inline void
+static inline void
 pure_or_virtual_attribute (func_decl)
      register tree func_decl;
 {
   if (DECL_VIRTUAL_P (func_decl))
     {
+#if 0 /* DECL_ABSTRACT_VIRTUAL_P is C++-specific.  */
       if (DECL_ABSTRACT_VIRTUAL_P (func_decl))
         ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_pure_virtual);
       else
+#endif
         ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
       ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
     }
@@ -2694,7 +3016,16 @@ type_attribute (type, decl_const, decl_volatile)
     if (root_type_modified)
        mod_u_d_type_attribute (type, decl_const, decl_volatile);
     else
-       user_def_type_attribute (type);
+       /* We have to get the type_main_variant here (and pass that to the
+          `user_def_type_attribute' routine) because the ..._TYPE node we
+          have might simply be a *copy* of some original type node (where
+          the copy was created to help us keep track of typedef names)
+          and that copy might have a different TYPE_UID from the original
+          ..._TYPE node.  (Note that when `equate_type_number_to_die_number'
+          is labeling a given type DIE for future reference, it always and
+          only creates labels for DIEs representing *main variants*, and it
+          never even knows about non-main-variants.)  */
+       user_def_type_attribute (type_main_variant (type));
 }
 
 /* Given a tree pointer to a struct, class, union, or enum type node, return
@@ -2714,25 +3045,14 @@ type_tag (type)
       /* Find the IDENTIFIER_NODE for the type name.  */
       if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
        t = TYPE_NAME (type);
-#if 0
-      /* The g++ front end makes the TYPE_NAME of *each* tagged type point
-        to a TYPE_DECL node, regardless of whether or not a `typedef' was
-        involved.  This is distinctly different from what the gcc front-end
-        does.  It always makes the TYPE_NAME for each tagged type be either
-        NULL (signifying an anonymous tagged type) or else a pointer to an
-        IDENTIFIER_NODE.  Obviously, we would like to generate correct Dwarf
-        for both C and C++, but given this inconsistency in the TREE
-        representation of tagged types for C and C++ in the GNU front-ends,
-        we cannot support both languages correctly unless we introduce some
-        front-end specific code here, and rms objects to that, so we can
-        only generate correct Dwarf for one of these two languages.  C is
-        more important, so for now we'll do the right thing for C and let
-        g++ go fish.  */
 
-      else
-       if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
+      /* The g++ front end makes the TYPE_NAME of *each* tagged type point to 
+         a TYPE_DECL node, regardless of whether or not a `typedef' was
+         involved.  */
+      else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
+              && ! DECL_IGNORED_P (TYPE_NAME (type)))
          t = DECL_NAME (TYPE_NAME (type));
-#endif
+
       /* Now get the name as a string, or invent one.  */
       if (t != 0)
        name = IDENTIFIER_POINTER (t);
@@ -2741,7 +3061,7 @@ type_tag (type)
   return (name == 0 || *name == '\0') ? 0 : name;
 }
 
-inline void
+static inline void
 dienum_push ()
 {
   /* Start by checking if the pending_sibling_stack needs to be expanded.
@@ -2762,13 +3082,13 @@ dienum_push ()
 /* Pop the sibling stack so that the most recently pushed DIEnum becomes the
    NEXT_DIE_NUM.  */
 
-inline void
+static inline void
 dienum_pop ()
 {
   pending_siblings--;
 }
 
-inline tree
+static inline tree
 member_declared_type (member)
      register tree member;
 {
@@ -2777,6 +3097,28 @@ member_declared_type (member)
           : TREE_TYPE (member);
 }
 
+/* Get the function's label, as described by its RTL.
+   This may be different from the DECL_NAME name used
+   in the source file.  */
+
+static char *
+function_start_label (decl)
+    register tree decl;
+{
+  rtx x;
+  char *fnname;
+
+  x = DECL_RTL (decl);
+  if (GET_CODE (x) != MEM)
+    abort ();
+  x = XEXP (x, 0);
+  if (GET_CODE (x) != SYMBOL_REF)
+              abort ();
+  fnname = XSTR (x, 0);
+  return fnname;
+}
+
+
 /******************************* DIEs ************************************/
 
 /* Output routines for individual types of DIEs.  */
@@ -2825,6 +3167,7 @@ output_set_type_die (arg)
 
 #if 0
 /* Implement this when there is a GNU FORTRAN or GNU Ada front end.  */
+
 static void
 output_entry_point_die (arg)
      register void *arg;
@@ -2846,7 +3189,7 @@ output_entry_point_die (arg)
   if (DECL_ABSTRACT (decl))
     equate_decl_number_to_die_number (decl);
   else
-    low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+    low_pc_attribute (function_start_label (decl));
 }
 #endif
 
@@ -3001,13 +3344,21 @@ output_global_subroutine_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (! DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && decl == current_function_decl)
        {
-         char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
+         char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
-         sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number);
-         high_pc_attribute (func_end_label);
+         low_pc_attribute (function_start_label (decl));
+         sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+         high_pc_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3037,7 +3388,8 @@ output_global_variable_die (arg)
     equate_decl_number_to_die_number (decl);
   else
     {
-      if (!DECL_EXTERNAL (decl))
+      if (! DECL_EXTERNAL (decl) && ! in_class
+         && current_function_decl == decl_function_context (decl))
        location_or_const_value_attribute (decl);
     }
 }
@@ -3163,7 +3515,7 @@ output_member_die (arg)
   member_attribute (DECL_CONTEXT (decl));
   type_attribute (member_declared_type (decl),
                  TREE_READONLY (decl), TREE_THIS_VOLATILE (decl));
-  if (DECL_BIT_FIELD_TYPE (decl))      /* If this is a bit field... */
+  if (DECL_BIT_FIELD_TYPE (decl))      /* If this is a bit field...  */
     {
       byte_size_attribute (decl);
       bit_size_attribute (decl);
@@ -3176,9 +3528,9 @@ output_member_die (arg)
 /* Don't generate either pointer_type DIEs or reference_type DIEs.  Use
    modified types instead.
 
-   We keep this code here just in case these types of DIEs may be needed
-   to represent certain things in other languages (e.g. Pascal) someday.
-*/
+   We keep this code here just in case these types of DIEs may be
+   needed to represent certain things in other languages (e.g. Pascal)
+   someday.  */
 
 static void
 output_pointer_type_die (arg)
@@ -3241,6 +3593,10 @@ output_compile_unit_die (arg)
 
   if (strcmp (language_string, "GNU C++") == 0)
     language_attribute (LANG_C_PLUS_PLUS);
+  else if (strcmp (language_string, "GNU Ada") == 0)
+    language_attribute (LANG_ADA83);
+  else if (strcmp (language_string, "GNU F77") == 0)
+    language_attribute (LANG_FORTRAN77);
   else if (flag_traditional)
     language_attribute (LANG_C);
   else
@@ -3257,7 +3613,7 @@ output_compile_unit_die (arg)
       comp_dir_attribute (wd);
   }
 
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_NORMAL && use_gnu_debug_info_extensions)
     {
       sf_names_attribute (SFNAMES_BEGIN_LABEL);
       src_info_attribute (SRCINFO_BEGIN_LABEL);
@@ -3282,6 +3638,33 @@ output_string_type_die (arg)
 }
 
 static void
+output_inheritance_die (arg)
+     register void *arg;
+{
+  register tree binfo = arg;
+
+  ASM_OUTPUT_DWARF_TAG (asm_out_file, TAG_inheritance);
+  sibling_attribute ();
+  type_attribute (BINFO_TYPE (binfo), 0, 0);
+  data_member_location_attribute (binfo);
+  if (TREE_VIA_VIRTUAL (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_virtual);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+  if (TREE_VIA_PUBLIC (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_public);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+  else if (TREE_VIA_PROTECTED (binfo))
+    {
+      ASM_OUTPUT_DWARF_ATTRIBUTE (asm_out_file, AT_protected);
+      ASM_OUTPUT_DWARF_STRING (asm_out_file, "");
+    }
+}  
+
+static void
 output_structure_type_die (arg)
      register void *arg;
 {
@@ -3341,11 +3724,17 @@ output_local_subroutine_die (arg)
 
       if (TREE_ASM_WRITTEN (decl))
        {
-         char func_end_label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
-         sprintf (func_end_label, FUNC_END_LABEL_FMT, current_funcdef_number);
-         high_pc_attribute (func_end_label);
+         char label[MAX_ARTIFICIAL_LABEL_BYTES];
+         low_pc_attribute (function_start_label (decl));
+         sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
+         high_pc_attribute (label);
+         if (use_gnu_debug_info_extensions)
+           {
+             sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+             body_begin_attribute (label);
+             sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+             body_end_attribute (label);
+           }
        }
     }
 }
@@ -3515,11 +3904,11 @@ end_sibling_chain ()
    parameters as specified in some function type specification (except
    for those which appear as part of a function *definition*).
 
-   Note that we must be careful here to output all of the parameter DIEs
-   *before* we output any DIEs needed to represent the types of the formal
-   parameters.  This keeps svr4 SDB happy because it (incorrectly) thinks
-   that the first non-parameter DIE it sees ends the formal parameter list.
-*/
+   Note that we must be careful here to output all of the parameter
+   DIEs *before* we output any DIEs needed to represent the types of
+   the formal parameters.  This keeps svr4 SDB happy because it
+   (incorrectly) thinks that the first non-parameter DIE it sees ends
+   the formal parameter list.  */
 
 static void
 output_formal_types (function_or_method_type)
@@ -3600,32 +3989,22 @@ pend_type (type)
 
 /* Return non-zero if it is legitimate to output DIEs to represent a
    given type while we are generating the list of child DIEs for some
-   DIE associated with a given scope.
-
-   This function returns non-zero if *either* of the following two conditions
-   is satisfied:
-
-        o      the type actually belongs to the given scope (as evidenced
-               by its TYPE_CONTEXT value), or
+   DIE (e.g. a function or lexical block DIE) associated with a given scope.
 
-        o      the type is anonymous, and the `scope' in question is *not*
-               a RECORD_TYPE or UNION_TYPE.
-
-   In theory, we should be able to generate DIEs for anonymous types
-   *anywhere* (since the scope of an anonymous type is irrelevant)
-   however svr4 SDB doesn't want to see other type DIEs within the
-   lists of child DIEs for a TAG_structure_type or TAG_union_type DIE.
+   See the comments within the function for a description of when it is
+   considered legitimate to output DIEs for various kinds of types.
 
    Note that TYPE_CONTEXT(type) may be NULL (to indicate global scope)
    or it may point to a BLOCK node (for types local to a block), or to a
    FUNCTION_DECL node (for types local to the heading of some function
    definition), or to a FUNCTION_TYPE node (for types local to the
    prototyped parameter list of a function type specification), or to a
-   RECORD_TYPE or UNION_TYPE node (in the case of C++ nested types).
+   RECORD_TYPE, UNION_TYPE, or QUAL_UNION_TYPE node
+   (in the case of C++ nested types).
 
    The `scope' parameter should likewise be NULL or should point to a
    BLOCK node, a FUNCTION_DECL node, a FUNCTION_TYPE node, a RECORD_TYPE
-   node, or a UNION_TYPE node.
+   node, a UNION_TYPE node, or a QUAL_UNION_TYPE node.
 
    This function is used only for deciding when to "pend" and when to
    "un-pend" types to/from the pending_types_list.
@@ -3636,28 +4015,39 @@ pend_type (type)
    It order to delay the production of DIEs representing types of formal
    parameters, callers of this function supply `fake_containing_scope' as
    the `scope' parameter to this function.  Given that fake_containing_scope
-   is *not* the containing scope for *any* other type, the desired effect
-   is achieved, i.e. output of DIEs representing types is temporarily
-   suspended, and any type DIEs which would have been output otherwise
-   are instead placed onto the pending_types_list.  Later on, we can force
-   these (temporarily pended) types to be output simply by calling
+   is a tagged type which is *not* the containing scope for *any* other type,
+   the desired effect is achieved, i.e. output of DIEs representing types
+   is temporarily suspended, and any type DIEs which would have otherwise
+   been output are instead placed onto the pending_types_list.  Later on,
+   we force these (temporarily pended) types to be output simply by calling
    `output_pending_types_for_scope' with an actual argument equal to the
-   true scope of the types we temporarily pended.
-*/
+   true scope of the types we temporarily pended.  */
 
-static int
+static inline int
 type_ok_for_scope (type, scope)
     register tree type;
     register tree scope;
 {
-  return (TYPE_CONTEXT (type) == scope
-         || (TYPE_NAME (type) == NULL
-             && TREE_CODE (scope) != RECORD_TYPE
-             && TREE_CODE (scope) != UNION_TYPE));
+  /* Tagged types (i.e. struct, union, and enum types) must always be
+     output only in the scopes where they actually belong (or else the
+     scoping of their own tag names and the scoping of their member
+     names will be incorrect).  Non-tagged-types on the other hand can
+     generally be output anywhere, except that svr4 SDB really doesn't
+     want to see them nested within struct or union types, so here we
+     say it is always OK to immediately output any such a (non-tagged)
+     type, so long as we are not within such a context.  Note that the
+     only kinds of non-tagged types which we will be dealing with here
+     (for C and C++ anyway) will be array types and function types.  */
+
+  return is_tagged_type (type)
+        ? (TYPE_CONTEXT (type) == scope
+           || (scope == NULL_TREE && is_tagged_type (TYPE_CONTEXT (type))
+               && TREE_ASM_WRITTEN (TYPE_CONTEXT (type))))
+        : (scope == NULL_TREE || ! is_tagged_type (scope));
 }
 
 /* Output any pending types (from the pending_types list) which we can output
-   now (given the limitations of the scope that we are working on now).
+   now (taking into account the scope that we are working on now).
 
    For each type output, remove the given type from the pending_types_list
    *before* we try to output it.
@@ -3665,8 +4055,7 @@ type_ok_for_scope (type, scope)
    Note that we have to process the list in beginning-to-end order,
    because the call made here to output_type may cause yet more types
    to be added to the end of the list, and we may have to output some
-   of them too.
-*/
+   of them too.  */
 
 static void
 output_pending_types_for_scope (containing_scope)
@@ -3716,11 +4105,22 @@ output_type (type, containing_scope)
      of this type (i.e. without any const or volatile qualifiers) so get
      the main variant (i.e. the unqualified version) of this type now.  */
 
-  type = TYPE_MAIN_VARIANT (type);
+  type = type_main_variant (type);
 
   if (TREE_ASM_WRITTEN (type))
     return;
 
+  /* If this is a nested type whose containing class hasn't been
+     written out yet, writing it out will cover this one, too.  */
+
+  if (TYPE_CONTEXT (type)
+      && TREE_CODE_CLASS (TREE_CODE (TYPE_CONTEXT (type))) == 't'
+      && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+    {
+      output_type (TYPE_CONTEXT (type), containing_scope);
+      return;
+    }
+
   /* Don't generate any DIEs for this type now unless it is OK to do so
      (based upon what `type_ok_for_scope' tells us).  */
 
@@ -3738,7 +4138,7 @@ output_type (type, containing_scope)
       case POINTER_TYPE:
       case REFERENCE_TYPE:
        /* For these types, all that is required is that we output a DIE
-          (or a set of DIEs) to represent that "basis" type.  */
+          (or a set of DIEs) to represent the "basis" type.  */
        output_type (TREE_TYPE (type), containing_scope);
        break;
 
@@ -3754,7 +4154,7 @@ output_type (type, containing_scope)
        break;
 
       case SET_TYPE:
-       output_type (TREE_TYPE (type), containing_scope);
+       output_type (TYPE_DOMAIN (type), containing_scope);
        output_die (output_set_type_die, type);
        break;
 
@@ -3763,11 +4163,6 @@ output_type (type, containing_scope)
        abort ();       /* No way to represent these in Dwarf yet!  */
        break;
 
-      case STRING_TYPE:
-       output_type (TREE_TYPE (type), containing_scope);
-       output_die (output_string_type_die, type);
-       break;
-
       case FUNCTION_TYPE:
        /* Force out return type (in case it wasn't forced out already).  */
        output_type (TREE_TYPE (type), containing_scope);
@@ -3784,31 +4179,38 @@ output_type (type, containing_scope)
        end_sibling_chain ();
        break;
 
-      case ARRAY_TYPE:
-       {
-         register tree element_type;
+      case ARRAY_TYPE: 
+       if (TYPE_STRING_FLAG (type) && TREE_CODE(TREE_TYPE(type)) == CHAR_TYPE)
+         {
+           output_type (TREE_TYPE (type), containing_scope);
+           output_die (output_string_type_die, type);
+         }
+       else
+         {
+           register tree element_type;
 
-         element_type = TREE_TYPE (type);
-         while (TREE_CODE (element_type) == ARRAY_TYPE)
-           element_type = TREE_TYPE (element_type);
+           element_type = TREE_TYPE (type);
+           while (TREE_CODE (element_type) == ARRAY_TYPE)
+             element_type = TREE_TYPE (element_type);
 
-         output_type (element_type, containing_scope);
-         output_die (output_array_type_die, type);
-       }
+           output_type (element_type, containing_scope);
+           output_die (output_array_type_die, type);
+         }
        break;
 
       case ENUMERAL_TYPE:
       case RECORD_TYPE:
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
 
        /* For a non-file-scope tagged type, we can always go ahead and
           output a Dwarf description of this type right now, even if
           the type in question is still incomplete, because if this
           local type *was* ever completed anywhere within its scope,
           that complete definition would already have been attached to
-          this RECORD_TYPE, UNION_TYPE or ENUMERAL_TYPE node by the
-          time we reach this point.  That's true because of the way the
-          front-end does its processing of file-scope declarations (of
+          this RECORD_TYPE, UNION_TYPE, QUAL_UNION_TYPE or ENUMERAL_TYPE
+          node by the time we reach this point.  That's true because of the
+          way the front-end does its processing of file-scope declarations (of
           functions and class types) within which other types might be
           nested.  The C and C++ front-ends always gobble up such "local
           scope" things en-mass before they try to output *any* debugging
@@ -3829,10 +4231,9 @@ output_type (type, containing_scope)
           time, we will certainly know as much about each file-scope tagged
           type as we are ever going to know, so at that point in time, we
           can safely generate correct Dwarf descriptions for these file-
-          scope tagged types.
-       */
+          scope tagged types.  */
 
-       if (TYPE_SIZE (type) == 0 && TYPE_CONTEXT (type) == NULL && !finalizing)
+       if (TYPE_SIZE (type) == 0 && !finalizing)
          return;       /* EARLY EXIT!  Avoid setting TREE_ASM_WRITTEN.  */
 
        /* Prevent infinite recursion in cases where the type of some
@@ -3853,6 +4254,7 @@ output_type (type, containing_scope)
            break;
 
          case UNION_TYPE:
+         case QUAL_UNION_TYPE:
            output_die (output_union_type_die, type);
            break;
 
@@ -3879,10 +4281,23 @@ output_type (type, containing_scope)
 
        if (TYPE_SIZE (type))
          {
+           /* First output info about the base classes.  */
+           if (TYPE_BINFO (type) && TYPE_BINFO_BASETYPES (type))
+             {
+               register tree bases = TYPE_BINFO_BASETYPES (type);
+               register int n_bases = TREE_VEC_LENGTH (bases);
+               register int i;
+
+               for (i = 0; i < n_bases; i++)
+                 output_die (output_inheritance_die, TREE_VEC_ELT (bases, i));
+             }
+
+           ++in_class;
+
            {
              register tree normal_member;
 
-             /* First output info about the data members and type members.  */
+             /* Now output info about the data members and type members.  */
 
              for (normal_member = TYPE_FIELDS (type);
                   normal_member;
@@ -3891,32 +4306,24 @@ output_type (type, containing_scope)
            }
 
            {
-             register tree vec_base;
+             register tree func_member;
 
              /* Now output info about the function members (if any).  */
 
-             vec_base = TYPE_METHODS (type);
-             if (vec_base)
-               {
-                 register tree first_func_member = TREE_VEC_ELT (vec_base, 0);
-                 register tree func_member;
-
-                 /* This isn't documented, but the first element of the
-                    vector of member functions can be NULL in cases where
-                    the class type in question didn't have either a
-                    constructor or a destructor declared for it.  We have
-                    to make allowances for that here.  */
-
-                 if (first_func_member == NULL)
-                   first_func_member = TREE_VEC_ELT (vec_base, 1);
-
-                 for (func_member = first_func_member;
-                      func_member;
-                      func_member = TREE_CHAIN (func_member))
-                   output_decl (func_member, type);
-               }
+             for (func_member = TYPE_METHODS (type);
+                  func_member;
+                  func_member = TREE_CHAIN (func_member))
+               output_decl (func_member, type);
            }
 
+           --in_class;
+
+           /* RECORD_TYPEs, UNION_TYPEs, and QUAL_UNION_TYPEs are themselves
+              scopes (at least in C++) so we must now output any nested
+              pending types which are local just to this type.  */
+
+           output_pending_types_for_scope (type);
+
            end_sibling_chain ();       /* Terminate member chain.  */
          }
 
@@ -3952,7 +4359,7 @@ output_tagged_type_instantiation (type)
      sure that we have the main variant (i.e. the unqualified version) of
      this type now.  */
 
-  assert (type == TYPE_MAIN_VARIANT (type));
+  assert (type == type_main_variant (type));
 
   assert (TREE_ASM_WRITTEN (type));
 
@@ -3970,6 +4377,7 @@ output_tagged_type_instantiation (type)
        break;
 
       case UNION_TYPE:
+      case QUAL_UNION_TYPE:
        output_die (output_inlined_union_type_die, type);
        break;
 
@@ -3982,36 +4390,71 @@ output_tagged_type_instantiation (type)
    the things which are local to the given block.  */
 
 static void
-output_block (stmt)
+output_block (stmt, depth)
     register tree stmt;
+    int depth;
 {
-  register int have_significant_locals = 0;
+  register int must_output_die = 0;
+  register tree origin;
+  register enum tree_code origin_code;
 
   /* Ignore blocks never really used to make RTL.  */
 
   if (! stmt || ! TREE_USED (stmt))
     return;
 
-  /* Determine if this block contains any "significant" local declarations
-     which we need to output DIEs for.  */
+  /* Determine the "ultimate origin" of this block.  This block may be an
+     inlined instance of an inlined instance of inline function, so we
+     have to trace all of the way back through the origin chain to find
+     out what sort of node actually served as the original seed for the
+     creation of the current block.  */
 
-  if (BLOCK_INLINE_FUNCTION (stmt))
-    /* The outer scopes for inlinings *must* always be represented.  */
-    have_significant_locals = 1;
-  else
-    if (debug_info_level > DINFO_LEVEL_TERSE)
-      have_significant_locals = (BLOCK_VARS (stmt) != NULL);
-    else
-      {
-        register tree decl;
+  origin = block_ultimate_origin (stmt);
+  origin_code = (origin != NULL) ? TREE_CODE (origin) : ERROR_MARK;
+
+  /* Determine if we need to output any Dwarf DIEs at all to represent this
+     block.  */
 
-       for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
-         if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+  if (origin_code == FUNCTION_DECL)
+    /* The outer scopes for inlinings *must* always be represented.  We
+       generate TAG_inlined_subroutine DIEs for them.  (See below.)  */
+    must_output_die = 1;
+  else
+    {
+      /* In the case where the current block represents an inlining of the
+        "body block" of an inline function, we must *NOT* output any DIE
+        for this block because we have already output a DIE to represent
+        the whole inlined function scope and the "body block" of any
+        function doesn't really represent a different scope according to
+        ANSI C rules.  So we check here to make sure that this block does
+        not represent a "body block inlining" before trying to set the
+        `must_output_die' flag.  */
+
+      if (! is_body_block (origin ? origin : stmt))
+       {
+         /* Determine if this block directly contains any "significant"
+            local declarations which we will need to output DIEs for.  */
+
+         if (debug_info_level > DINFO_LEVEL_TERSE)
+           /* We are not in terse mode so *any* local declaration counts
+              as being a "significant" one.  */
+           must_output_die = (BLOCK_VARS (stmt) != NULL);
+         else
            {
-             have_significant_locals = 1;
-             break;
+             register tree decl;
+
+             /* We are in terse mode, so only local (nested) function
+                definitions count as "significant" local declarations.  */
+
+             for (decl = BLOCK_VARS (stmt); decl; decl = TREE_CHAIN (decl))
+               if (TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
+                 {
+                   must_output_die = 1;
+                   break;
+                 }
            }
-      }
+       }
+    }
 
   /* It would be a waste of space to generate a Dwarf TAG_lexical_block
      DIE for any block which contains no significant local declarations
@@ -4021,32 +4464,36 @@ output_block (stmt)
      a "significant" local declaration gets restricted to include only
      inlined function instances and local (nested) function definitions.  */
 
-  if (have_significant_locals)
+  if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
+    /* We don't care about an abstract inlined subroutine.  */;
+  else if (must_output_die)
     {
-      output_die (BLOCK_INLINE_FUNCTION (stmt)
-                       ? output_inlined_subroutine_die
-                       : output_lexical_block_die,
+      output_die ((origin_code == FUNCTION_DECL)
+                   ? output_inlined_subroutine_die
+                   : output_lexical_block_die,
                  stmt);
-      output_decls_for_scope (stmt);
+      output_decls_for_scope (stmt, depth);
       end_sibling_chain ();
     }
   else
-    output_decls_for_scope (stmt);
+    output_decls_for_scope (stmt, depth);
 }
 
 /* Output all of the decls declared within a given scope (also called
    a `binding contour') and (recursively) all of it's sub-blocks.  */
 
 static void
-output_decls_for_scope (stmt)
+output_decls_for_scope (stmt, depth)
      register tree stmt;
+     int depth;
 {
   /* Ignore blocks never really used to make RTL.  */
 
   if (! stmt || ! TREE_USED (stmt))
     return;
 
-  next_block_number++;
+  if (! BLOCK_ABSTRACT (stmt) && depth > 0)
+    next_block_number++;
 
   /* Output the DIEs to represent all of the data objects, functions,
      typedefs, and tagged types declared directly within this block
@@ -4070,10 +4517,28 @@ output_decls_for_scope (stmt)
     for (subblocks = BLOCK_SUBBLOCKS (stmt);
          subblocks;
          subblocks = BLOCK_CHAIN (subblocks))
-      output_block (subblocks);
+      output_block (subblocks, depth + 1);
   }
 }
 
+/* Is this a typedef we can avoid emitting?  */
+
+inline int
+is_redundant_typedef (decl)
+     register tree decl;
+{
+  if (TYPE_DECL_IS_STUB (decl))
+    return 1;
+  if (DECL_ARTIFICIAL (decl)
+      && DECL_CONTEXT (decl)
+      && is_tagged_type (DECL_CONTEXT (decl))
+      && TREE_CODE (TYPE_NAME (DECL_CONTEXT (decl))) == TYPE_DECL
+      && DECL_NAME (decl) == DECL_NAME (TYPE_NAME (DECL_CONTEXT (decl))))
+    /* Also ignore the artificial member typedef for the class name.  */
+    return 1;
+  return 0;
+}
+
 /* Output Dwarf .debug information for a decl described by DECL.  */
 
 static void
@@ -4081,9 +4546,26 @@ output_decl (decl, containing_scope)
      register tree decl;
      register tree containing_scope;
 {
+  /* Make a note of the decl node we are going to be working on.  We may
+     need to give the user the source coordinates of where it appeared in
+     case we notice (later on) that something about it looks screwy.  */
+
+  dwarf_last_decl = decl;
+
   if (TREE_CODE (decl) == ERROR_MARK)
     return;
 
+  /* If a structure is declared within an initialization, e.g. as the
+     operand of a sizeof, then it will not have a name.  We don't want
+     to output a DIE for it, as the tree nodes are in the temporary obstack */
+
+  if ((TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE
+       || TREE_CODE (TREE_TYPE (decl)) == UNION_TYPE)
+      && ((DECL_NAME (decl) == 0 && TYPE_NAME (TREE_TYPE (decl)) == 0)
+         || (TYPE_FIELDS (TREE_TYPE (decl)) 
+             && (TREE_CODE (TYPE_FIELDS (TREE_TYPE (decl))) == ERROR_MARK))))
+    return;
+  
   /* If this ..._DECL node is marked to be ignored, then ignore it.
      But don't ignore a function definition, since that would screw
      up our count of blocks, and that it turn will completely screw up the
@@ -4102,11 +4584,11 @@ output_decl (decl, containing_scope)
 
     case FUNCTION_DECL:
       /* If we are in terse mode, don't output any DIEs to represent
-        mere external function declarations.  Also, if we are conforming
+        mere function declarations.  Also, if we are conforming
         to the DWARF version 1 specification, don't output DIEs for
-        mere external function declarations.  */
+        mere function declarations.  */
 
-      if (DECL_EXTERNAL (decl))
+      if (DECL_INITIAL (decl) == NULL_TREE)
 #if (DWARF_VERSION > 1)
        if (debug_info_level <= DINFO_LEVEL_TERSE)
 #endif
@@ -4117,6 +4599,13 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (TREE_TYPE (decl)), containing_scope);
 
+      {
+       /* And its containing type.  */
+       register tree origin = decl_class_context (decl);
+       if (origin)
+         output_type (origin, containing_scope);
+      }
+
       /* If the following DIE will represent a function definition for a
         function with "extern" linkage, output a special "pubnames" DIE
         label just ahead of the actual DIE.  A reference to this label
@@ -4149,182 +4638,139 @@ output_decl (decl, containing_scope)
         ends with a void_type_node then there should *not* be an ellipsis
         at the end.  */
 
-      /* In the case where we are describing an external function, all
+      /* In the case where we are describing a mere function declaration, all
         we need to do here (and all we *can* do here) is to describe
         the *types* of its formal parameters.  */
 
-      if (DECL_EXTERNAL (decl))
+      if (decl != current_function_decl || in_class)
        output_formal_types (TREE_TYPE (decl));
       else
        {
-         register tree arg_decls = DECL_ARGUMENTS (decl);
+         /* Generate DIEs to represent all known formal parameters */
 
-         {
-           register tree last_arg;
+         register tree arg_decls = DECL_ARGUMENTS (decl);
+         register tree parm;
+
+         /* WARNING!  Kludge zone ahead!  Here we have a special
+            hack for svr4 SDB compatibility.  Instead of passing the
+            current FUNCTION_DECL node as the second parameter (i.e.
+            the `containing_scope' parameter) to `output_decl' (as
+            we ought to) we instead pass a pointer to our own private
+            fake_containing_scope node.  That node is a RECORD_TYPE
+            node which NO OTHER TYPE may ever actually be a member of.
+
+            This pointer will ultimately get passed into `output_type'
+            as its `containing_scope' parameter.  `Output_type' will
+            then perform its part in the hack... i.e. it will pend
+            the type of the formal parameter onto the pending_types
+            list.  Later on, when we are done generating the whole
+            sequence of formal parameter DIEs for this function
+            definition, we will un-pend all previously pended types
+            of formal parameters for this function definition.
+
+            This whole kludge prevents any type DIEs from being
+            mixed in with the formal parameter DIEs.  That's good
+            because svr4 SDB believes that the list of formal
+            parameter DIEs for a function ends wherever the first
+            non-formal-parameter DIE appears.  Thus, we have to
+            keep the formal parameter DIEs segregated.  They must
+            all appear (consecutively) at the start of the list of
+            children for the DIE representing the function definition.
+            Then (and only then) may we output any additional DIEs
+            needed to represent the types of these formal parameters.
+         */
 
-           last_arg = (arg_decls && TREE_CODE (arg_decls) != ERROR_MARK)
-                       ? tree_last (arg_decls)
-                       : NULL;
+         /*
+            When generating DIEs, generate the unspecified_parameters
+            DIE instead if we come across the arg "__builtin_va_alist"
+         */
 
-           /* Generate DIEs to represent all known formal parameters, but
-              don't do it if this looks like a varargs function.  A given
-              function is considered to be a varargs function if (and only
-              if) its last named argument is named `__builtin_va_alist'.  */
+         for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
+           if (TREE_CODE (parm) == PARM_DECL)
+              {
+               if (DECL_NAME(parm) &&
+                   !strcmp(IDENTIFIER_POINTER(DECL_NAME(parm)),
+                           "__builtin_va_alist") )
+                 output_die (output_unspecified_parameters_die, decl);
+               else
+                 output_decl (parm, fake_containing_scope);
+             }
 
-           if (! last_arg
-               || ! DECL_NAME (last_arg)
-               || strcmp (IDENTIFIER_POINTER (DECL_NAME (last_arg)),
-                          "__builtin_va_alist"))
-             {
-               register tree parm;
-
-               /* WARNING!  Kludge zone ahead!  Here we have a special
-                  hack for svr4 SDB compatibility.  Instead of passing the
-                  current FUNCTION_DECL node as the second parameter (i.e.
-                  the `containing_scope' parameter) to `output_decl' (as
-                  we ought to) we instead pass a pointer to our own private
-                  fake_containing_scope node.  That node is a RECORD_TYPE
-                  node which NO OTHER TYPE may ever actually be a member of.
-
-                  This pointer will ultimately get passed into `output_type'
-                  as its `containing_scope' parameter.  `Output_type' will
-                  then perform its part in the hack... i.e. it will pend
-                  the type of the formal parameter onto the pending_types
-                  list.  Later on, when we are done generating the whole
-                  sequence of formal parameter DIEs for this function
-                  definition, we will un-pend all previously pended types
-                  of formal parameters for this function definition.
-
-                  This whole kludge prevents any type DIEs from being
-                  mixed in with the formal parameter DIEs.  That's good
-                  because svr4 SDB believes that the list of formal
-                  parameter DIEs for a function ends wherever the first
-                  non-formal-parameter DIE appears.  Thus, we have to
-                  keep the formal parameter DIEs segregated.  They must
-                  all appear (consecutively) at the start of the list of
-                  children for the DIE representing the function definition.
-                  Then (and only then) may we output any additional DIEs
-                  needed to represent the types of these formal parameters.
-               */
-
-               for (parm = arg_decls; parm; parm = TREE_CHAIN (parm))
-                 if (TREE_CODE (parm) == PARM_DECL)
-                   output_decl (parm, fake_containing_scope);
-
-               /* Now that we have finished generating all of the DIEs to
-                  represent the formal parameters themselves, force out
-                  any DIEs needed to represent their types.  We do this
-                  simply by un-pending all previously pended types which
-                  can legitimately go into the chain of children DIEs for
-                  the current FUNCTION_DECL.  */
+         /*
+            Now that we have finished generating all of the DIEs to
+            represent the formal parameters themselves, force out
+            any DIEs needed to represent their types.  We do this
+            simply by un-pending all previously pended types which
+            can legitimately go into the chain of children DIEs for
+            the current FUNCTION_DECL.
+         */
 
-               output_pending_types_for_scope (decl);
-             }
-         }
+         output_pending_types_for_scope (decl);
 
-         /* Now try to decide if we should put an ellipsis at the end. */
+         /*
+           Decide whether we need a unspecified_parameters DIE at the end.
+           There are 2 more cases to do this for:
+           1) the ansi ... declaration - this is detectable when the end
+               of the arg list is not a void_type_node
+           2) an unprototyped function declaration (not a definition).  This
+               just means that we have no info about the parameters at all.
+         */
 
          {
-           register int has_ellipsis = TRUE;   /* default assumption */
            register tree fn_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
 
            if (fn_arg_types)
              {
-               /* This function declaration/definition was prototyped.  */
-
-               /* If the list of formal argument types ends with a
-                  void_type_node, then the formals list did *not* end
-                  with an ellipsis.  */
-
-               if (TREE_VALUE (tree_last (fn_arg_types)) == void_type_node)
-                 has_ellipsis = FALSE;
-             }
-           else
-             {
-               /* This function declaration/definition was not prototyped.  */
-
-               /* Note that all non-prototyped function *declarations* are
-                  assumed to represent varargs functions (until proven
-                  otherwise).  */
-
-               if (DECL_INITIAL (decl)) /* if this is a func definition */
-                 {
-                   if (!arg_decls)
-                     has_ellipsis = FALSE; /* no args == (void) */
-                   else
-                     {
-                       /* For a non-prototyped function definition which
-                          declares one or more formal parameters, if the name
-                          of the first formal parameter is *not*
-                          __builtin_va_alist then we must assume that this
-                          is *not* a varargs function.  */
-
-                       if (DECL_NAME (arg_decls)
-                         && strcmp (IDENTIFIER_POINTER (DECL_NAME (arg_decls)),
-                                    "__builtin_va_alist"))
-                         has_ellipsis = FALSE;
-                     }
-                 }
-             }
-
-           if (has_ellipsis)
-             output_die (output_unspecified_parameters_die, decl);
+             /* this is the prototyped case, check for ...  */
+             if (TREE_VALUE (tree_last (fn_arg_types)) != void_type_node)
+               output_die (output_unspecified_parameters_die, decl);
+              }
+            else
+              {
+             /* this is unprototyped, check for undefined (just declaration) */
+              if (!DECL_INITIAL (decl))
+                output_die (output_unspecified_parameters_die, decl);
+              }
          }
-       }
-
-      /* Output Dwarf info for all of the stuff within the body of the
-        function (if it has one - it may be just a declaration).  */
 
-      {
-       register tree outer_scope = DECL_INITIAL (decl);
+         /* Output Dwarf info for all of the stuff within the body of the
+            function (if it has one - it may be just a declaration).  */
 
-       if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
          {
-           /* Note that here, `outer_scope' is a pointer to the outermost
-              BLOCK node created to represent a function.
-              This outermost BLOCK actually represents the outermost
-              binding contour for the function, i.e. the contour in which
-              the function's formal parameters and labels get declared.
-
-              Curiously, it appears that the front end doesn't actually
-              put the PARM_DECL nodes for the current function onto the
-              BLOCK_VARS list for this outer scope.  (They are strung
-              off of the DECL_ARGUMENTS list for the function instead.)
-              The BLOCK_VARS list for the `outer_scope' does provide us
-              with a list of the LABEL_DECL nodes for the function however,
-              and we output DWARF info for those here.
-
-              Just within the `outer_scope' there will be another BLOCK
-              node representing the function's outermost pair of curly
-              braces.  We musn't generate a lexical_block DIE for this
-              outermost pair of curly braces because that is not really an
-              independent scope according to ANSI C rules.  Rather, it is
-              the same scope in which the parameters were declared.  */
-
-           {
-             register tree label;
-
-             for (label = BLOCK_VARS (outer_scope);
-                  label;
-                  label = TREE_CHAIN (label))
-               output_decl (label, outer_scope);
-           }
-
-           /* Note here that `BLOCK_SUBBLOCKS (outer_scope)' points to a
-              list of BLOCK nodes which is always only one element long.
-              That one element represents the outermost pair of curley
-              braces for the function body.  */
-
-           output_decls_for_scope (BLOCK_SUBBLOCKS (outer_scope));
+           register tree outer_scope = DECL_INITIAL (decl);
 
-           /* Finally, force out any pending types which are local to the
-              outermost block of this function definition.  These will
-              all have a TYPE_CONTEXT which points to the FUNCTION_DECL
-              node itself.  */
+           if (outer_scope && TREE_CODE (outer_scope) != ERROR_MARK)
+             {
+               /* Note that here, `outer_scope' is a pointer to the outermost
+                  BLOCK node created to represent a function.
+                  This outermost BLOCK actually represents the outermost
+                  binding contour for the function, i.e. the contour in which
+                  the function's formal parameters and labels get declared.
+
+                  Curiously, it appears that the front end doesn't actually
+                  put the PARM_DECL nodes for the current function onto the
+                  BLOCK_VARS list for this outer scope.  (They are strung
+                  off of the DECL_ARGUMENTS list for the function instead.)
+                  The BLOCK_VARS list for the `outer_scope' does provide us
+                  with a list of the LABEL_DECL nodes for the function however,
+                  and we output DWARF info for those here.
+
+                  Just within the `outer_scope' there will be a BLOCK node
+                  representing the function's outermost pair of curly braces,
+                  and any blocks used for the base and member initializers of
+                  a C++ constructor function.  */
+
+               output_decls_for_scope (outer_scope, 0);
+
+               /* Finally, force out any pending types which are local to the
+                  outermost block of this function definition.  These will
+                  all have a TYPE_CONTEXT which points to the FUNCTION_DECL
+                  node itself.  */
 
-           output_pending_types_for_scope (decl);
+               output_pending_types_for_scope (decl);
+             }
          }
-      }
+       }
 
       /* Generate a terminator for the list of stuff `owned' by this
         function.  */
@@ -4341,19 +4787,19 @@ output_decl (decl, containing_scope)
         a return type or a formal parameter type of some function.  */
 
       if (debug_info_level <= DINFO_LEVEL_TERSE)
-       if (DECL_NAME (decl) != NULL
-           || ! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)))
+       if (! TYPE_DECL_IS_STUB (decl)
+           || (! TYPE_USED_FOR_FUNCTION (TREE_TYPE (decl)) && ! in_class))
           return;
 
-      /* In the special case of a null-named TYPE_DECL node (representing
-        the declaration of some type tag), if the given TYPE_DECL is
+      /* In the special case of a TYPE_DECL node representing
+        the declaration of some type tag, if the given TYPE_DECL is
         marked as having been instantiated from some other (original)
         TYPE_DECL node (e.g. one which was generated within the original
         definition of an inline function) we have to generate a special
         (abbreviated) TAG_structure_type, TAG_union_type, or
         TAG_enumeration-type DIE here.  */
 
-      if (! DECL_NAME (decl) && DECL_ABSTRACT_ORIGIN (decl))
+      if (TYPE_DECL_IS_STUB (decl) && DECL_ABSTRACT_ORIGIN (decl))
        {
          output_tagged_type_instantiation (TREE_TYPE (decl));
          return;
@@ -4361,16 +4807,7 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
-      /* Note that unlike the gcc front end (which generates a NULL named
-        TYPE_DECL node for each complete tagged type, each array type,
-        and each function type node created) the g++ front end generates
-        a *named* TYPE_DECL node for each tagged type node created.
-        Unfortunately, these g++ TYPE_DECL nodes cause us to output many
-        superfluous and unnecessary TAG_typedef DIEs here.  When g++ is
-        fixed to stop generating these superfluous named TYPE_DECL nodes,
-        the superfluous TAG_typedef DIEs will likewise cease.  */
-
-      if (DECL_NAME (decl))
+      if (! is_redundant_typedef (decl))
        /* Output a DIE to represent the typedef itself.  */
        output_die (output_typedef_die, decl);
       break;
@@ -4400,6 +4837,13 @@ output_decl (decl, containing_scope)
 
       output_type (TREE_TYPE (decl), containing_scope);
 
+      {
+       /* And its containing type.  */
+       register tree origin = decl_class_context (decl);
+       if (origin)
+         output_type (origin, containing_scope);
+      }
+
       /* If the following DIE will represent a data object definition for a
         data object with "extern" linkage, output a special "pubnames" DIE
         label just ahead of the actual DIE.  A reference to this label
@@ -4494,17 +4938,37 @@ dwarfout_file_scope_decl (decl, set_finalizing)
       if (DECL_EXTERNAL (decl) && DECL_FUNCTION_CODE (decl))
         return;
 
-      /* Ignore this FUNCTION_DECL if it refers to a file-scope extern
-        function declaration and if the declaration was never even
-        referenced from within this entire compilation unit.  We
-        suppress these DIEs in order to save space in the .debug section
-        (by eliminating entries which are probably useless).  Note that
-        we must not suppress block-local extern declarations (whether
-        used or not) because that would screw-up the debugger's name
-        lookup mechanism and cause it to miss things which really ought
-        to be in scope at a given point.  */
-
-      if (DECL_EXTERNAL (decl) && !TREE_USED (decl))
+      /* What we would really like to do here is to filter out all mere
+        file-scope declarations of file-scope functions which are never
+        referenced later within this translation unit (and keep all of
+        ones that *are* referenced later on) but we aren't clairvoyant,
+        so we have no idea which functions will be referenced in the
+        future (i.e. later on within the current translation unit).
+        So here we just ignore all file-scope function declarations
+        which are not also definitions.  If and when the debugger needs
+        to know something about these functions, it wil have to hunt
+        around and find the DWARF information associated with the
+        *definition* of the function.
+
+        Note that we can't just check `DECL_EXTERNAL' to find out which
+        FUNCTION_DECL nodes represent definitions and which ones represent
+        mere declarations.  We have to check `DECL_INITIAL' instead.  That's
+        because the C front-end supports some weird semantics for "extern
+        inline" function definitions.  These can get inlined within the
+        current translation unit (an thus, we need to generate DWARF info
+        for their abstract instances so that the DWARF info for the
+        concrete inlined instances can have something to refer to) but
+        the compiler never generates any out-of-lines instances of such
+        things (despite the fact that they *are* definitions).  The
+        important point is that the C front-end marks these "extern inline"
+        functions as DECL_EXTERNAL, but we need to generate DWARF for them
+        anyway.
+
+        Note that the C++ front-end also plays some similar games for inline
+        function definitions appearing within include files which also
+        contain `#pragma interface' pragmas.  */
+
+      if (DECL_INITIAL (decl) == NULL_TREE)
        return;
 
       if (TREE_PUBLIC (decl)
@@ -4587,9 +5051,18 @@ dwarfout_file_scope_decl (decl, set_finalizing)
       break;
 
     case TYPE_DECL:
-      /* Don't generate any DIEs to represent the standard built-in types.  */
-
-      if (DECL_SOURCE_LINE (decl) == 0)
+      /* Don't bother trying to generate any DIEs to represent any of the
+        normal built-in types for the language we are compiling, except
+        in cases where the types in question are *not* DWARF fundamental
+        types.  We make an exception in the case of non-fundamental types
+        for the sake of objective C (and perhaps C++) because the GNU
+        front-ends for these languages may in fact create certain "built-in"
+        types which are (for example) RECORD_TYPEs.  In such cases, we
+        really need to output these (non-fundamental) types because other
+        DIEs may contain references to them.  */
+
+      if (DECL_SOURCE_LINE (decl) == 0
+         && type_is_fundamental (TREE_TYPE (decl)))
        return;
 
       /* If we are in terse mode, don't generate any DIEs to represent
@@ -4646,7 +5119,7 @@ dwarfout_begin_block (blocknum)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  function_section (current_function_decl);
   sprintf (label, BLOCK_BEGIN_LABEL_FMT, blocknum);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -4660,7 +5133,7 @@ dwarfout_end_block (blocknum)
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  function_section (current_function_decl);
   sprintf (label, BLOCK_END_LABEL_FMT, blocknum);
   ASM_OUTPUT_LABEL (asm_out_file, label);
 }
@@ -4676,13 +5149,44 @@ dwarfout_label (insn)
     {
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-      text_section ();
+      function_section (current_function_decl);
       sprintf (label, INSN_LABEL_FMT, current_funcdef_number,
                                      (unsigned) INSN_UID (insn));
       ASM_OUTPUT_LABEL (asm_out_file, label);
     }
 }
 
+/* Output a marker (i.e. a label) for the point in the generated code where
+   the real body of the function begins (after parameters have been moved
+   to their home locations).  */
+
+void
+dwarfout_begin_function ()
+{
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  if (! use_gnu_debug_info_extensions)
+    return;
+  function_section (current_function_decl);
+  sprintf (label, BODY_BEGIN_LABEL_FMT, current_funcdef_number);
+  ASM_OUTPUT_LABEL (asm_out_file, label);
+}
+
+/* Output a marker (i.e. a label) for the point in the generated code where
+   the real body of the function ends (just before the epilogue code).  */
+
+void
+dwarfout_end_function ()
+{
+  char label[MAX_ARTIFICIAL_LABEL_BYTES];
+
+  if (! use_gnu_debug_info_extensions)
+    return;
+  function_section (current_function_decl);
+  sprintf (label, BODY_END_LABEL_FMT, current_funcdef_number);
+  ASM_OUTPUT_LABEL (asm_out_file, label);
+}
+
 /* Output a marker (i.e. a label) for the absolute end of the generated code
    for a function definition.  This gets called *after* the epilogue code
    has been generated. */
@@ -4770,8 +5274,7 @@ generate_new_sfname_entry ()
    calculated, and where at least one of the two symbol references is a
    forward reference.  (This bug could be tickled by our .debug_srcinfo
    entries if we don't output their corresponding .debug_sfnames entries
-   before them.)
-*/
+   before them.) */
 
 static unsigned
 lookup_filename (file_name)
@@ -4845,20 +5348,28 @@ dwarfout_line (filename, line)
      register char *filename;
      register unsigned line;
 {
-  if (debug_info_level >= DINFO_LEVEL_NORMAL)
+  if (debug_info_level >= DINFO_LEVEL_NORMAL
+      /* We can't emit line number info for functions in separate sections,
+        because the assembler can't subtract labels in different sections.  */
+      && DECL_SECTION_NAME (current_function_decl) == NULL_TREE)
     {
       char label[MAX_ARTIFICIAL_LABEL_BYTES];
       static unsigned last_line_entry_num = 0;
       static unsigned prev_file_entry_num = (unsigned) -1;
-      register unsigned this_file_entry_num = lookup_filename (filename);
+      register unsigned this_file_entry_num;
 
-      text_section ();
+      function_section (current_function_decl);
       sprintf (label, LINE_CODE_LABEL_FMT, ++last_line_entry_num);
       ASM_OUTPUT_LABEL (asm_out_file, label);
 
       fputc ('\n', asm_out_file);
       ASM_OUTPUT_PUSH_SECTION (asm_out_file, LINE_SECTION);
 
+      if (use_gnu_debug_info_extensions)
+       this_file_entry_num = lookup_filename (filename);
+      else
+       this_file_entry_num = (unsigned) -1;
+
       if (this_file_entry_num != prev_file_entry_num)
         {
           char line_entry_label[MAX_ARTIFICIAL_LABEL_BYTES];
@@ -4894,6 +5405,9 @@ generate_macinfo_entry (type_and_offset, string)
      register char *type_and_offset;
      register char *string;
 {
+  if (! use_gnu_debug_info_extensions)
+    return;
+
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, MACINFO_SECTION);
   fprintf (asm_out_file, "\t%s\t%s\n", UNALIGNED_INT_ASM_OP, type_and_offset);
@@ -5019,12 +5533,14 @@ dwarfout_init (asm_out_file, main_input_filename)
   ASM_OUTPUT_LABEL (asm_out_file, DATA_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
   /* Output a starting label for the .data1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, DATA1_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a starting label for the .rodata section.  */
 
@@ -5033,12 +5549,14 @@ dwarfout_init (asm_out_file, main_input_filename)
   ASM_OUTPUT_LABEL (asm_out_file, RODATA_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
   /* Output a starting label for the .rodata1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, RODATA1_BEGIN_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a starting label for the .bss section.  */
 
@@ -5049,26 +5567,36 @@ dwarfout_init (asm_out_file, main_input_filename)
 
   if (debug_info_level >= DINFO_LEVEL_NORMAL)
     {
-      /* Output a starting label and an initial (compilation directory)
-        entry for the .debug_sfnames section.  The starting label will be
-        referenced by the initial entry in the .debug_srcinfo section.  */
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Output a starting label and an initial (compilation directory)
+            entry for the .debug_sfnames section.  The starting label will be
+            referenced by the initial entry in the .debug_srcinfo section.  */
     
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
-      ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
-      {
-       register char *pwd = getpwd ();
-       register unsigned len = strlen (pwd);
-       register char *dirname = (char *) xmalloc (len + 2);
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SFNAMES_SECTION);
+         ASM_OUTPUT_LABEL (asm_out_file, SFNAMES_BEGIN_LABEL);
+         {
+           register char *pwd;
+           register unsigned len;
+           register char *dirname;
+
+           pwd = getpwd ();
+           if (!pwd)
+             pfatal_with_name ("getpwd");
+           len = strlen (pwd);
+           dirname = (char *) xmalloc (len + 2);
     
-       strcpy (dirname, pwd);
-       strcpy (dirname + len, "/");
-        ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
-        free (dirname);
-      }
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+           strcpy (dirname, pwd);
+           strcpy (dirname + len, "/");
+           ASM_OUTPUT_DWARF_STRING (asm_out_file, dirname);
+           free (dirname);
+         }
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
     
-      if (debug_info_level >= DINFO_LEVEL_VERBOSE)
+      if (debug_info_level >= DINFO_LEVEL_VERBOSE
+         && use_gnu_debug_info_extensions)
        {
           /* Output a starting label for the .debug_macinfo section.  This
             label will be referenced by the AT_mac_info attribute in the
@@ -5089,21 +5617,24 @@ dwarfout_init (asm_out_file, main_input_filename)
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     
-      /* Generate the initial entry for the .debug_srcinfo section.  */
-    
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
-      ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Generate the initial entry for the .debug_srcinfo section.  */
+
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+         ASM_OUTPUT_LABEL (asm_out_file, SRCINFO_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, LINE_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, SFNAMES_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_ADDR (asm_out_file, TEXT_END_LABEL);
 #ifdef DWARF_TIMESTAMPS
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, time (NULL));
 #else
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
 #endif
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
     
       /* Generate the initial entry for the .debug_pubnames section.  */
     
@@ -5175,7 +5706,7 @@ dwarfout_finish ()
      (or blame).  I didn't think of this scheme.  I just conformed to it.
   */
 
-  output_die (output_padded_null_die, (void *)0);
+  output_die (output_padded_null_die, (void *) 0);
   dienum_pop ();
 
   sprintf (label, DIE_BEGIN_LABEL_FMT, NEXT_DIE_NUM);
@@ -5196,12 +5727,14 @@ dwarfout_finish ()
   ASM_OUTPUT_LABEL (asm_out_file, DATA_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
   /* Output a terminator label for the .data1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, DATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, DATA1_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a terminator label for the .rodata section.  */
 
@@ -5210,12 +5743,14 @@ dwarfout_finish ()
   ASM_OUTPUT_LABEL (asm_out_file, RODATA_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
   /* Output a terminator label for the .rodata1 section.  */
 
   fputc ('\n', asm_out_file);
   ASM_OUTPUT_PUSH_SECTION (asm_out_file, RODATA1_SECTION);
   ASM_OUTPUT_LABEL (asm_out_file, RODATA1_END_LABEL);
   ASM_OUTPUT_POP_SECTION (asm_out_file);
+#endif
 
   /* Output a terminator label for the .bss section.  */
 
@@ -5237,14 +5772,17 @@ dwarfout_finish ()
       ASM_OUTPUT_LABEL (asm_out_file, LINE_END_LABEL);
       ASM_OUTPUT_POP_SECTION (asm_out_file);
     
-      /* Output a terminating entry for the .debug_srcinfo section.  */
-    
-      fputc ('\n', asm_out_file);
-      ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
-      ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
-                              LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
-      ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
-      ASM_OUTPUT_POP_SECTION (asm_out_file);
+      if (use_gnu_debug_info_extensions)
+       {
+         /* Output a terminating entry for the .debug_srcinfo section.  */
+
+         fputc ('\n', asm_out_file);
+         ASM_OUTPUT_PUSH_SECTION (asm_out_file, SRCINFO_SECTION);
+         ASM_OUTPUT_DWARF_DELTA4 (asm_out_file,
+                                  LINE_LAST_ENTRY_LABEL, LINE_BEGIN_LABEL);
+         ASM_OUTPUT_DWARF_DATA4 (asm_out_file, -1);
+         ASM_OUTPUT_POP_SECTION (asm_out_file);
+       }
 
       if (debug_info_level >= DINFO_LEVEL_VERBOSE)
        {
@@ -5290,17 +5828,21 @@ dwarfout_finish ()
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA_END_LABEL, DATA_BEGIN_LABEL);
 
+#if 0 /* GNU C doesn't currently use .data1.  */
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, DATA1_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, DATA1_END_LABEL,
                                             DATA1_BEGIN_LABEL);
+#endif
 
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA_END_LABEL,
                                             RODATA_BEGIN_LABEL);
 
+#if 0 /* GNU C doesn't currently use .rodata1.  */
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, RODATA1_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, RODATA1_END_LABEL,
                                             RODATA1_BEGIN_LABEL);
+#endif
 
       ASM_OUTPUT_DWARF_ADDR (asm_out_file, BSS_BEGIN_LABEL);
       ASM_OUTPUT_DWARF_DELTA4 (asm_out_file, BSS_END_LABEL, BSS_BEGIN_LABEL);