OSDN Git Service

(fixup_var_refs_1, case ZERO_EXTRACT): Don't call fixup_memory_subreg
[pf3gnuchains/gcc-fork.git] / gcc / dwarfout.c
index 1300afd..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, 1993 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"
 
@@ -34,10 +33,6 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 #include "output.h"
 #include "defaults.h"
 
-#ifndef DWARF_VERSION
-#define DWARF_VERSION 1
-#endif
-
 /* #define NDEBUG 1 */
 #include "assert.h"
 
@@ -70,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.  */
@@ -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;
 
@@ -291,13 +299,126 @@ static unsigned current_funcdef_number = 1;
 
 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.
@@ -346,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
@@ -561,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) \
@@ -584,16 +702,6 @@ static unsigned lookup_filename ();
   } while (0)
 #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");                                           \
-  } while (0)
-#endif
-
 #ifndef ASM_OUTPUT_DWARF_DELTA2
 #define ASM_OUTPUT_DWARF_DELTA2(FILE,LABEL1,LABEL2)                    \
  do {  fprintf ((FILE), "\t%s\t", UNALIGNED_SHORT_ASM_OP);             \
@@ -619,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));                                              \
@@ -631,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));                                              \
@@ -642,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));                                              \
@@ -654,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));                                              \
@@ -665,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));                                              \
@@ -676,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));                                              \
@@ -746,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;
@@ -974,6 +1072,7 @@ dwarf_fmt_byte_name (fmt)
     default:           return "FMT_<unknown>";
     }
 }
+
 static char *
 dwarf_fund_type_name (ft)
      register unsigned ft;
@@ -1020,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";
@@ -1091,6 +1190,27 @@ block_ultimate_origin (block)
     }
 }
 
+/* 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;
@@ -1105,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);
@@ -1137,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);
@@ -1159,7 +1279,7 @@ output_signed_leb128 (value)
    FUNCTION_DECL node.
 */
 
-inline int
+static inline int
 is_body_block (stmt)
      register tree stmt;
 {
@@ -1384,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;
 {
@@ -1409,7 +1529,6 @@ type_is_fundamental (type)
       case METHOD_TYPE:
       case POINTER_TYPE:
       case REFERENCE_TYPE:
-      case STRING_TYPE:
       case FILE_TYPE:
       case OFFSET_TYPE:
       case LANG_TYPE:
@@ -1466,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;
 {
@@ -1499,7 +1618,7 @@ output_reg_number (rtl)
     }
   fprintf (asm_out_file, "\t%s\t0x%x",
           UNALIGNED_INT_ASM_OP, DBX_REGISTER_NUMBER (regno));
-  if (flag_verbose_asm)
+  if (flag_debug_asm)
     {
       fprintf (asm_out_file, "\t%s ", ASM_COMMENT_START);
       PRINT_REG (rtl, 0, asm_out_file);
@@ -1586,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 ();
     }
@@ -1640,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 ();
     }
 }
 
@@ -1737,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;
@@ -1749,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;
 {
@@ -1768,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;
 {
@@ -1781,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;
 {
@@ -1925,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];
@@ -1970,7 +2092,7 @@ location_attribute (rtl)
      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 sayeth
+     represents an object declaration, but not a definition.  So saith
      the PLSIG.
   */
 
@@ -2000,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);
@@ -2217,12 +2343,10 @@ location_or_const_value_attribute (decl)
 
        if (declared_type == passed_type)
          rtl = DECL_INCOMING_RTL (decl);
-#if (BYTES_BIG_ENDIAN == 0)
-       else
+       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);
-#endif /* (BYTES_BIG_ENDIAN == 0) */
       }
 
   if (rtl == NULL_RTX)
@@ -2254,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;
 {
@@ -2265,7 +2389,7 @@ name_attribute (name_string)
     }
 }
 
-inline void
+static inline void
 fund_type_attribute (ft_code)
      register unsigned ft_code;
 {
@@ -2293,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;
 {
@@ -2326,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;
 {
@@ -2383,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,
@@ -2429,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);
 
@@ -2497,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;
 {
@@ -2532,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);
@@ -2553,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;
 {
@@ -2570,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;
 {
@@ -2596,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;
 {
@@ -2608,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;
 {
@@ -2619,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;
 {
@@ -2629,7 +2751,7 @@ high_pc_attribute (asm_high_label)
 
 /* Generate an AT_body_begin attribute for a subroutine DIE.  */
 
-inline void
+static inline void
 body_begin_attribute (asm_begin_label)
      register char *asm_begin_label;
 {
@@ -2639,7 +2761,7 @@ body_begin_attribute (asm_begin_label)
 
 /* Generate an AT_body_end attribute for a subroutine DIE.  */
 
-inline void
+static inline void
 body_end_attribute (asm_end_label)
      register char *asm_end_label;
 {
@@ -2650,7 +2772,7 @@ body_end_attribute (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;
 {
@@ -2658,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;
 {
@@ -2674,7 +2796,7 @@ member_attribute (context)
     }
 }
 
-inline void
+static inline void
 string_length_attribute (upper_bound)
      register tree upper_bound;
 {
@@ -2690,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;
 {
@@ -2698,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;
 {
@@ -2707,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;
 {
@@ -2716,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;
 {
@@ -2725,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;
 {
@@ -2737,7 +2859,7 @@ prototyped_attribute (func_type)
     }
 }
 
-inline void
+static inline void
 producer_attribute (producer)
      register char *producer;
 {
@@ -2745,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;
 {
@@ -2756,7 +2878,7 @@ inline_attribute (decl)
     }
 }
 
-inline void
+static inline void
 containing_type_attribute (containing_type)
      register tree containing_type;
 {
@@ -2767,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;
 {
@@ -2792,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;
@@ -2803,7 +2925,7 @@ 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;
 {
@@ -2923,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);
@@ -2950,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.
@@ -2971,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;
 {
@@ -2986,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.  */
@@ -3034,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;
@@ -3055,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
 
@@ -3210,17 +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 label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+         low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         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);
+         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);
+           }
        }
     }
 }
@@ -3250,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);
     }
 }
@@ -3376,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);
@@ -3389,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)
@@ -3456,6 +3595,8 @@ output_compile_unit_die (arg)
     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
@@ -3472,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);
@@ -3497,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;
 {
@@ -3557,14 +3725,16 @@ output_local_subroutine_die (arg)
       if (TREE_ASM_WRITTEN (decl))
        {
          char label[MAX_ARTIFICIAL_LABEL_BYTES];
-
-         low_pc_attribute (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl)));
+         low_pc_attribute (function_start_label (decl));
          sprintf (label, FUNC_END_LABEL_FMT, current_funcdef_number);
          high_pc_attribute (label);
-         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);
+         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);
+           }
        }
     }
 }
@@ -3734,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)
@@ -3851,10 +4021,9 @@ pend_type (type)
    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.  */
 
-inline int
+static inline int
 type_ok_for_scope (type, scope)
     register tree type;
     register tree scope;
@@ -3871,7 +4040,9 @@ type_ok_for_scope (type, scope)
      (for C and C++ anyway) will be array types and function types.  */
 
   return is_tagged_type (type)
-        ? (TYPE_CONTEXT (type) == scope)
+        ? (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));
 }
 
@@ -3884,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)
@@ -3940,6 +4110,17 @@ output_type (type, containing_scope)
   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).  */
 
@@ -3973,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;
 
@@ -3982,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);
@@ -4003,17 +4179,23 @@ 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:
@@ -4049,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
@@ -4100,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;
@@ -4112,32 +4306,18 @@ 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.  */
@@ -4210,8 +4390,9 @@ 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 must_output_die = 0;
   register tree origin;
@@ -4249,7 +4430,7 @@ output_block (stmt)
         not represent a "body block inlining" before trying to set the
         `must_output_die' flag.  */
 
-      if (origin == NULL || ! is_body_block (origin))
+      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.  */
@@ -4283,32 +4464,35 @@ output_block (stmt)
      a "significant" local declaration gets restricted to include only
      inlined function instances and local (nested) function definitions.  */
 
-  if (must_output_die)
+  if (origin_code == FUNCTION_DECL && BLOCK_ABSTRACT (stmt))
+    /* We don't care about an abstract inlined subroutine.  */;
+  else if (must_output_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;
 
-  if (! BLOCK_ABSTRACT (stmt))
+  if (! BLOCK_ABSTRACT (stmt) && depth > 0)
     next_block_number++;
 
   /* Output the DIEs to represent all of the data objects, functions,
@@ -4333,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
@@ -4353,6 +4555,17 @@ output_decl (decl, containing_scope)
   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
@@ -4386,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
@@ -4422,178 +4642,135 @@ output_decl (decl, containing_scope)
         we need to do here (and all we *can* do here) is to describe
         the *types* of its formal parameters.  */
 
-      if (DECL_INITIAL (decl) == NULL_TREE)
+      if (decl != current_function_decl || in_class)
        output_formal_types (TREE_TYPE (decl));
       else
        {
+         /* Generate DIEs to represent all known formal parameters */
+
          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.
+         */
 
-         {
-           register tree last_arg;
+         /*
+            When generating DIEs, generate the unspecified_parameters
+            DIE instead if we come across the arg "__builtin_va_alist"
+         */
 
-           last_arg = (arg_decls && TREE_CODE (arg_decls) != ERROR_MARK)
-                       ? tree_last (arg_decls)
-                       : NULL;
+         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);
+             }
 
-           /* 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'.  */
+         /*
+            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.
+         */
 
-           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.  */
+         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);
-           }
+           register tree outer_scope = DECL_INITIAL (decl);
 
-           /* 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));
-
-           /* 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.  */
@@ -4610,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;
@@ -4630,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;
@@ -4669,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
@@ -4766,12 +4941,12 @@ dwarfout_file_scope_decl (decl, set_finalizing)
       /* 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 clarvoiant,
+        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 funcstion, it wil have to hunt
+        to know something about these functions, it wil have to hunt
         around and find the DWARF information associated with the
         *definition* of the function.
 
@@ -4786,7 +4961,7 @@ dwarfout_file_scope_decl (decl, set_finalizing)
         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
+        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
@@ -4944,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);
 }
@@ -4958,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);
 }
@@ -4974,7 +5149,7 @@ 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);
@@ -4990,7 +5165,9 @@ dwarfout_begin_function ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  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);
 }
@@ -5003,7 +5180,9 @@ dwarfout_end_function ()
 {
   char label[MAX_ARTIFICIAL_LABEL_BYTES];
 
-  text_section ();
+  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);
 }
@@ -5095,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)
@@ -5170,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];
@@ -5219,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);
@@ -5378,32 +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;
-       register unsigned len;
-       register char *dirname;
-
-       pwd = getpwd ();
-       if (!pwd)
-         pfatal_with_name ("getpwd");
-       len = strlen (pwd);
-       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
@@ -5424,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.  */
     
@@ -5510,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);
@@ -5576,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)
        {