]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/dbxout.c
c++: Handle multiple aggregate overloads [PR95319].
[thirdparty/gcc.git] / gcc / dbxout.c
index 5492c7011ba187dfb31722611f436e7510c63332..5a20fdecdcc4055e1d70c92eb685562f99a97ac3 100644 (file)
@@ -1,7 +1,5 @@
 /* Output dbx-format symbol table information from GNU compiler.
-   Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
-   2011 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -71,28 +69,29 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
-#include "tm.h"
-
-#include "tree.h"
+#include "target.h"
+#include "function.h"
 #include "rtl.h"
-#include "flags.h"
-#include "regs.h"
+#include "tree.h"
+#include "memmodel.h"
+#include "tm_p.h"
+#include "stringpool.h"
 #include "insn-config.h"
+#include "emit-rtl.h"
+#include "cgraph.h"
+#include "diagnostic-core.h"
+#include "fold-const.h"
+#include "varasm.h"
+#include "stor-layout.h"
 #include "reload.h"
 #include "output.h"
 #include "dbxout.h"
-#include "diagnostic-core.h"
 #include "toplev.h"
-#include "tm_p.h"
-#include "ggc.h"
 #include "debug.h"
-#include "function.h"
-#include "target.h"
 #include "common/common-target.h"
 #include "langhooks.h"
-#include "obstack.h"
 #include "expr.h"
-#include "cgraph.h"
+#include "file-prefix-map.h" /* remap_debug_filename()  */
 
 #ifdef XCOFF_DEBUGGING_INFO
 #include "xcoffout.h"
@@ -246,6 +245,10 @@ static GTY(()) int source_label_number = 1;
 
 static GTY(()) const char *lastfile;
 
+/* Last line number mentioned in a NOTE insn.  */
+
+static GTY(()) unsigned int lastlineno;
+
 /* Used by PCH machinery to detect if 'lastfile' should be reset to
    base_input_file.  */
 static GTY(()) int lastfile_is_base;
@@ -325,7 +328,8 @@ static int dbxout_symbol_location (tree, tree, const char *, rtx);
 static void dbxout_symbol_name (tree, const char *, int);
 static void dbxout_common_name (tree, const char *, stab_code_type);
 static const char *dbxout_common_check (tree, int *);
-static void dbxout_global_decl (tree);
+static void dbxout_early_global_decl (tree);
+static void dbxout_late_global_decl (tree);
 static void dbxout_type_decl (tree, int);
 static void dbxout_handle_pch (unsigned);
 static void debug_free_queue (void);
@@ -333,8 +337,10 @@ static void debug_free_queue (void);
 /* The debug hooks structure.  */
 #if defined (DBX_DEBUGGING_INFO)
 
-static void dbxout_source_line (unsigned int, const char *, int, bool);
-static void dbxout_begin_prologue (unsigned int, const char *);
+static void dbxout_source_line (unsigned int, unsigned int, const char *,
+                               int, bool);
+static void dbxout_switch_text_section (void);
+static void dbxout_begin_prologue (unsigned int, unsigned int, const char *);
 static void dbxout_source_file (const char *);
 static void dbxout_function_end (tree);
 static void dbxout_begin_function (tree);
@@ -346,6 +352,7 @@ const struct gcc_debug_hooks dbx_debug_hooks =
 {
   dbxout_init,
   dbxout_finish,
+  debug_nothing_charstar,
   debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
@@ -365,16 +372,22 @@ const struct gcc_debug_hooks dbx_debug_hooks =
   debug_nothing_tree,                   /* begin_function */
 #endif
   debug_nothing_int,                    /* end_function */
+  debug_nothing_tree,                   /* register_main_translation_unit */
   dbxout_function_decl,
-  dbxout_global_decl,                   /* global_decl */
+  dbxout_early_global_decl,             /* early_global_decl */
+  dbxout_late_global_decl,              /* late_global_decl */
   dbxout_type_decl,                     /* type_decl */
-  debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
+  debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+  debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+  debug_nothing_tree_charstar_uhwi,      /* register_external_die */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
-  debug_nothing_rtx,                    /* label */
+  debug_nothing_rtx_code_label,                 /* label */
   dbxout_handle_pch,                    /* handle_pch */
-  debug_nothing_rtx,                    /* var_location */
-  debug_nothing_void,                    /* switch_text_section */
+  debug_nothing_rtx_insn,               /* var_location */
+  debug_nothing_tree,                   /* inline_entry */
+  debug_nothing_tree,                   /* size_function */
+  dbxout_switch_text_section,            /* switch_text_section */
   debug_nothing_tree_tree,              /* set_name */
   0,                                     /* start_end_main_source_file */
   TYPE_SYMTAB_IS_ADDRESS                 /* tree_type_symtab_field */
@@ -386,6 +399,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
 {
   dbxout_init,
   dbxout_finish,
+  debug_nothing_charstar,
   debug_nothing_void,
   debug_nothing_int_charstar,
   debug_nothing_int_charstar,
@@ -401,15 +415,21 @@ const struct gcc_debug_hooks xcoff_debug_hooks =
   xcoffout_end_epilogue,
   debug_nothing_tree,                   /* begin_function */
   xcoffout_end_function,
+  debug_nothing_tree,                   /* register_main_translation_unit */
   debug_nothing_tree,                   /* function_decl */
-  dbxout_global_decl,                   /* global_decl */
+  dbxout_early_global_decl,             /* early_global_decl */
+  dbxout_late_global_decl,              /* late_global_decl */
   dbxout_type_decl,                     /* type_decl */
-  debug_nothing_tree_tree_tree_bool,    /* imported_module_or_decl */
+  debug_nothing_tree_tree_tree_bool_bool,/* imported_module_or_decl */
+  debug_false_tree_charstarstar_uhwistar,/* die_ref_for_decl */
+  debug_nothing_tree_charstar_uhwi,      /* register_external_die */
   debug_nothing_tree,                   /* deferred_inline_function */
   debug_nothing_tree,                   /* outlining_inline_function */
-  debug_nothing_rtx,                    /* label */
+  debug_nothing_rtx_code_label,                 /* label */
   dbxout_handle_pch,                    /* handle_pch */
-  debug_nothing_rtx,                    /* var_location */
+  debug_nothing_rtx_insn,               /* var_location */
+  debug_nothing_tree,                   /* inline_entry */
+  debug_nothing_tree,                   /* size_function */
   debug_nothing_void,                    /* switch_text_section */
   debug_nothing_tree_tree,              /* set_name */
   0,                                     /* start_end_main_source_file */
@@ -444,7 +464,7 @@ dbxout_int (int num)
   if (num < 0)
     {
       putc ('-', asm_out_file);
-      unum = -num;
+      unum = -(unsigned int) num;
     }
   else
     unum = num;
@@ -638,7 +658,7 @@ dbxout_begin_complex_stabs_noforcetext (void)
 #define stabstr_C(chr) obstack_1grow (&stabstr_ob, chr)
 
 /* Add STR, a normal C string, to the string being built.  */
-#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen(str))
+#define stabstr_S(str) obstack_grow (&stabstr_ob, str, strlen (str))
 
 /* Add the text of ID, an IDENTIFIER_NODE, to the string being built.  */
 #define stabstr_I(id) obstack_grow (&stabstr_ob, \
@@ -651,7 +671,7 @@ stabstr_D (HOST_WIDE_INT num)
 {
   char buf[64];
   char *p = buf + sizeof buf;
-  unsigned int unum;
+  unsigned HOST_WIDE_INT unum;
 
   if (num == 0)
     {
@@ -661,7 +681,7 @@ stabstr_D (HOST_WIDE_INT num)
   if (num < 0)
     {
       stabstr_C ('-');
-      unum = -num;
+      unum = -(unsigned HOST_WIDE_INT) num;
     }
   else
     unum = num;
@@ -692,88 +712,39 @@ stabstr_U (unsigned HOST_WIDE_INT num)
 static void
 stabstr_O (tree cst)
 {
-  unsigned HOST_WIDE_INT high = TREE_INT_CST_HIGH (cst);
-  unsigned HOST_WIDE_INT low = TREE_INT_CST_LOW (cst);
-
-  char buf[128];
-  char *p = buf + sizeof buf;
-
-  /* GDB wants constants with no extra leading "1" bits, so
-     we need to remove any sign-extension that might be
-     present.  */
-  {
-    const unsigned int width = TYPE_PRECISION (TREE_TYPE (cst));
-    if (width == HOST_BITS_PER_DOUBLE_INT)
-      ;
-    else if (width > HOST_BITS_PER_WIDE_INT)
-      high &= (((HOST_WIDE_INT) 1 << (width - HOST_BITS_PER_WIDE_INT)) - 1);
-    else if (width == HOST_BITS_PER_WIDE_INT)
-      high = 0;
-    else
-      high = 0, low &= (((HOST_WIDE_INT) 1 << width) - 1);
-  }
+  int prec = TYPE_PRECISION (TREE_TYPE (cst));
+  int res_pres = prec % 3;
+  int i;
+  unsigned int digit;
 
   /* Leading zero for base indicator.  */
   stabstr_C ('0');
 
   /* If the value is zero, the base indicator will serve as the value
      all by itself.  */
-  if (high == 0 && low == 0)
+  if (wi::to_wide (cst) == 0)
     return;
 
-  /* If the high half is zero, we need only print the low half normally.  */
-  if (high == 0)
-    NUMBER_FMT_LOOP (p, low, 8);
-  else
+  /* GDB wants constants with no extra leading "1" bits, so
+     we need to remove any sign-extension that might be
+     present.  */
+  if (res_pres == 1)
     {
-      /* When high != 0, we need to print enough zeroes from low to
-        give the digits from high their proper place-values.  Hence
-        NUMBER_FMT_LOOP cannot be used.  */
-      const int n_digits = HOST_BITS_PER_WIDE_INT / 3;
-      int i;
-
-      for (i = 1; i <= n_digits; i++)
-       {
-         unsigned int digit = low % 8;
-         low /= 8;
-         *--p = '0' + digit;
-       }
-
-      /* Octal digits carry exactly three bits of information.  The
-        width of a HOST_WIDE_INT is not normally a multiple of three.
-        Therefore, the next digit printed probably needs to carry
-        information from both low and high.  */
-      if (HOST_BITS_PER_WIDE_INT % 3 != 0)
-       {
-         const int n_leftover_bits = HOST_BITS_PER_WIDE_INT % 3;
-         const int n_bits_from_high = 3 - n_leftover_bits;
-
-         const unsigned HOST_WIDE_INT
-           low_mask = (((unsigned HOST_WIDE_INT)1) << n_leftover_bits) - 1;
-         const unsigned HOST_WIDE_INT
-           high_mask = (((unsigned HOST_WIDE_INT)1) << n_bits_from_high) - 1;
-
-         unsigned int digit;
-
-         /* At this point, only the bottom n_leftover_bits bits of low
-            should be set.  */
-         gcc_assert (!(low & ~low_mask));
-
-         digit = (low | ((high & high_mask) << n_leftover_bits));
-         high >>= n_bits_from_high;
-
-         *--p = '0' + digit;
-       }
-
-      /* Now we can format high in the normal manner.  However, if
-        the only bits of high that were set were handled by the
-        digit split between low and high, high will now be zero, and
-        we don't want to print extra digits in that case.  */
-      if (high)
-       NUMBER_FMT_LOOP (p, high, 8);
+      digit = wi::extract_uhwi (wi::to_wide (cst), prec - 1, 1);
+      stabstr_C ('0' + digit);
+    }
+  else if (res_pres == 2)
+    {
+      digit = wi::extract_uhwi (wi::to_wide (cst), prec - 2, 2);
+      stabstr_C ('0' + digit);
     }
 
-  obstack_grow (&stabstr_ob, p, (buf + sizeof buf) - p);
+  prec -= res_pres;
+  for (i = prec - 3; i >= 0; i = i - 3)
+    {
+      digit = wi::extract_uhwi (wi::to_wide (cst), i, 3);
+      stabstr_C ('0' + digit);
+    }
 }
 
 /* Called whenever it is safe to break a stabs string into multiple
@@ -939,7 +910,7 @@ dbxout_function_end (tree decl ATTRIBUTE_UNUSED)
 
   /* The Lscope label must be emitted even if we aren't doing anything
      else; dbxout_block needs it.  */
-  switch_to_section (function_section (current_function_decl));
+  switch_to_section (current_function_section ());
 
   /* Convert Lscope into the appropriate format for local labels in case
      the system doesn't insert underscores in front of user generated
@@ -957,14 +928,15 @@ dbxout_function_end (tree decl ATTRIBUTE_UNUSED)
 
   /* By convention, GCC will mark the end of a function with an N_FUN
      symbol and an empty string.  */
-  if (flag_reorder_blocks_and_partition)
+  if (crtl->has_bb_partition)
     {
       dbxout_begin_empty_stabs (N_FUN);
-      dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label,
-                                   crtl->subsections.hot_section_label);
-      dbxout_begin_empty_stabs (N_FUN);
-      dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label,
-                                   crtl->subsections.cold_section_label);
+      if (in_cold_section_p)
+       dbxout_stab_value_label_diff (crtl->subsections.cold_section_end_label,
+                                     crtl->subsections.cold_section_label);
+      else
+       dbxout_stab_value_label_diff (crtl->subsections.hot_section_end_label,
+                                     crtl->subsections.hot_section_label);
     }
   else
     {
@@ -985,17 +957,14 @@ static unsigned int ATTRIBUTE_UNUSED
 get_lang_number (void)
 {
   const char *language_string = lang_hooks.name;
-
-  if (strcmp (language_string, "GNU C") == 0)
+  if (lang_GNU_C ())
     return N_SO_C;
-  else if (strcmp (language_string, "GNU C++") == 0)
+  else if (lang_GNU_CXX ())
     return N_SO_CC;
   else if (strcmp (language_string, "GNU F77") == 0)
     return N_SO_FORTRAN;
-  else if (strcmp (language_string, "GNU Fortran") == 0)
+  else if (lang_GNU_Fortran ())
     return N_SO_FORTRAN90; /* CHECKME */
-  else if (strcmp (language_string, "GNU Pascal") == 0)
-    return N_SO_PASCAL;
   else if (strcmp (language_string, "GNU Objective-C") == 0)
     return N_SO_OBJC;
   else if (strcmp (language_string, "GNU Objective-C++") == 0)
@@ -1025,7 +994,7 @@ dbxout_init (const char *input_file_name)
   const char *mapped_name;
 
   typevec_len = 100;
-  typevec = ggc_alloc_cleared_vec_typeinfo (typevec_len);
+  typevec = ggc_cleared_vec_alloc<typeinfo> (typevec_len);
 
   /* stabstr_ob contains one string, which will be just fine with
      1-byte alignment.  */
@@ -1255,7 +1224,7 @@ dbxout_handle_pch (unsigned at_end)
 
 #if defined (DBX_DEBUGGING_INFO)
 
-static void dbxout_block (tree, int, tree);
+static bool dbxout_block (tree, int, tree, int);
 
 /* Output debugging info to FILE to switch to sourcefile FILENAME.  */
 
@@ -1284,7 +1253,9 @@ dbxout_source_file (const char *filename)
    function scope  */
 
 static void
-dbxout_begin_prologue (unsigned int lineno, const char *filename)
+dbxout_begin_prologue (unsigned int lineno,
+                      unsigned int column ATTRIBUTE_UNUSED,
+                      const char *filename)
 {
   if (use_gnu_debug_info_extensions
       && !NO_DBX_FUNCTION_END
@@ -1295,7 +1266,7 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename)
   /* pre-increment the scope counter */
   scope_labelno++;
 
-  dbxout_source_line (lineno, filename, 0, true);
+  dbxout_source_line (lineno, 0, filename, 0, true);
   /* Output function begin block at function scope, referenced
      by dbxout_block, dbxout_source_line and dbxout_function_end.  */
   emit_pending_bincls_if_required ();
@@ -1306,8 +1277,8 @@ dbxout_begin_prologue (unsigned int lineno, const char *filename)
    number LINENO.  */
 
 static void
-dbxout_source_line (unsigned int lineno, const char *filename,
-                    int discriminator ATTRIBUTE_UNUSED,
+dbxout_source_line (unsigned int lineno, unsigned int column ATTRIBUTE_UNUSED,
+                   const char *filename, int discriminator ATTRIBUTE_UNUSED,
                     bool is_stmt ATTRIBUTE_UNUSED)
 {
   dbxout_source_file (filename);
@@ -1327,6 +1298,60 @@ dbxout_source_line (unsigned int lineno, const char *filename,
   else
     dbxout_stabd (N_SLINE, lineno);
 #endif
+  lastlineno = lineno;
+}
+
+/* Unfortunately, at least when emitting relative addresses, STABS
+   has no way to express multiple partitions.  Represent a function
+   as two functions in this case.  */
+
+static void
+dbxout_switch_text_section (void)
+{
+  /* The N_FUN tag at the end of the function is a GNU extension,
+     which may be undesirable, and is unnecessary if we do not have
+     named sections.  */
+  in_cold_section_p = !in_cold_section_p;
+  switch_to_section (current_function_section ());
+  dbxout_block (DECL_INITIAL (current_function_decl), 0,
+               DECL_ARGUMENTS (current_function_decl), -1);
+  dbxout_function_end (current_function_decl);
+  in_cold_section_p = !in_cold_section_p;
+
+  switch_to_section (current_function_section ());
+
+  tree context = decl_function_context (current_function_decl);
+  extern tree cold_function_name;
+
+  dbxout_begin_complex_stabs ();
+  stabstr_I (cold_function_name);
+  stabstr_S (":f");
+
+  tree type = TREE_TYPE (current_function_decl);
+  if (TREE_TYPE (type))
+    dbxout_type (TREE_TYPE (type), 0);
+  else
+    dbxout_type (void_type_node, 0);
+
+  if (context != 0)
+    {
+      stabstr_C (',');
+      stabstr_I (cold_function_name);
+      stabstr_C (',');
+      stabstr_I (DECL_NAME (context));
+    }
+
+  dbxout_finish_complex_stabs (current_function_decl, N_FUN, 0,
+                              crtl->subsections.cold_section_label, 0);
+
+  /* pre-increment the scope counter */
+  scope_labelno++;
+
+  dbxout_source_line (lastlineno, 0, lastfile, 0, true);
+  /* Output function begin block at function scope, referenced
+     by dbxout_block, dbxout_source_line and dbxout_function_end.  */
+  emit_pending_bincls_if_required ();
+  targetm.asm_out.internal_label (asm_out_file, "LFBB", scope_labelno);
 }
 
 /* Describe the beginning of an internal block within a function.  */
@@ -1360,18 +1385,24 @@ dbxout_function_decl (tree decl)
 #ifndef DBX_FUNCTION_FIRST
   dbxout_begin_function (decl);
 #endif
-  dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl));
+  dbxout_block (DECL_INITIAL (decl), 0, DECL_ARGUMENTS (decl), -1);
   dbxout_function_end (decl);
 }
 
 #endif /* DBX_DEBUGGING_INFO  */
 
+static void
+dbxout_early_global_decl (tree decl ATTRIBUTE_UNUSED)
+{
+  /* NYI for non-dwarf.  */
+}
+
 /* Debug information for a global DECL.  Called from toplev.c after
    compilation proper has finished.  */
 static void
-dbxout_global_decl (tree decl)
+dbxout_late_global_decl (tree decl)
 {
-  if (TREE_CODE (decl) == VAR_DECL && !DECL_EXTERNAL (decl))
+  if (VAR_P (decl) && !DECL_EXTERNAL (decl))
     {
       int saved_tree_used = TREE_USED (decl);
       TREE_USED (decl) = 1;
@@ -1516,14 +1547,17 @@ dbxout_type_fields (tree type)
 
       /* Omit here local type decls until we know how to support them.  */
       if (TREE_CODE (tem) == TYPE_DECL
+         || TREE_CODE (tem) == TEMPLATE_DECL
+         /* Member functions emitted after fields.  */
+         || TREE_CODE (tem) == FUNCTION_DECL
          /* Omit here the nameless fields that are used to skip bits.  */
          || DECL_IGNORED_P (tem)
          /* Omit fields whose position or size are variable or too large to
             represent.  */
          || (TREE_CODE (tem) == FIELD_DECL
-             && (! host_integerp (bit_position (tem), 0)
+             && (! tree_fits_shwi_p (bit_position (tem))
                  || ! DECL_SIZE (tem)
-                 || ! host_integerp (DECL_SIZE (tem), 1))))
+                 || ! tree_fits_uhwi_p (DECL_SIZE (tem)))))
        continue;
 
       else if (TREE_CODE (tem) != CONST_DECL)
@@ -1549,7 +1583,7 @@ dbxout_type_fields (tree type)
                        && DECL_BIT_FIELD_TYPE (tem))
                       ? DECL_BIT_FIELD_TYPE (tem) : TREE_TYPE (tem), 0);
 
-         if (TREE_CODE (tem) == VAR_DECL)
+         if (VAR_P (tem))
            {
              if (TREE_STATIC (tem) && use_gnu_debug_info_extensions)
                {
@@ -1568,7 +1602,7 @@ dbxout_type_fields (tree type)
              stabstr_C (',');
              stabstr_D (int_bit_position (tem));
              stabstr_C (',');
-             stabstr_D (tree_low_cst (DECL_SIZE (tem), 1));
+             stabstr_D (tree_to_uhwi (DECL_SIZE (tem)));
              stabstr_C (';');
            }
        }
@@ -1612,64 +1646,47 @@ dbxout_type_method_1 (tree decl)
   stabstr_C (c1);
   stabstr_C (c2);
 
-  if (DECL_VINDEX (decl) && host_integerp (DECL_VINDEX (decl), 0))
+  if (DECL_VINDEX (decl) && tree_fits_shwi_p (DECL_VINDEX (decl)))
     {
-      stabstr_D (tree_low_cst (DECL_VINDEX (decl), 0));
+      stabstr_D (tree_to_shwi (DECL_VINDEX (decl)));
       stabstr_C (';');
       dbxout_type (DECL_CONTEXT (decl), 0);
       stabstr_C (';');
     }
 }
 \f
-/* Subroutine of `dbxout_type'.  Output debug info about the methods defined
-   in TYPE.  */
+/* Subroutine of `dbxout_type'.  Output debug info about the member
+   functions defined in TYPE.  */
 
 static void
 dbxout_type_methods (tree type)
 {
-  /* C++: put out the method names and their parameter lists */
-  tree methods = TYPE_METHODS (type);
-  tree fndecl;
-  tree last;
-
-  if (methods == NULL_TREE)
-    return;
-
-  if (TREE_CODE (methods) != TREE_VEC)
-    fndecl = methods;
-  else if (TREE_VEC_ELT (methods, 0) != NULL_TREE)
-    fndecl = TREE_VEC_ELT (methods, 0);
-  else
-    fndecl = TREE_VEC_ELT (methods, 1);
-
-  while (fndecl)
+  for (tree fndecl = TYPE_FIELDS (type); fndecl;)
     {
       int need_prefix = 1;
 
       /* Group together all the methods for the same operation.
         These differ in the types of the arguments.  */
-      for (last = NULL_TREE;
+      for (tree last = NULL_TREE;
           fndecl && (last == NULL_TREE || DECL_NAME (fndecl) == DECL_NAME (last));
           fndecl = DECL_CHAIN (fndecl))
        /* Output the name of the field (after overloading), as
           well as the name of the field before overloading, along
           with its parameter list */
        {
-         /* Skip methods that aren't FUNCTION_DECLs.  (In C++, these
-            include TEMPLATE_DECLs.)  The debugger doesn't know what
-            to do with such entities anyhow.  */
+         /* Skip non-functions.  */
          if (TREE_CODE (fndecl) != FUNCTION_DECL)
            continue;
 
-         CONTIN;
-
-         last = fndecl;
-
          /* Also ignore abstract methods; those are only interesting to
             the DWARF backends.  */
-         if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT (fndecl))
+         if (DECL_IGNORED_P (fndecl) || DECL_ABSTRACT_P (fndecl))
            continue;
 
+         CONTIN;
+
+         last = fndecl;
+
          /* Redundantly output the plain name, since that's what gdb
             expects.  */
          if (need_prefix)
@@ -1698,7 +1715,7 @@ dbxout_range_type (tree type, tree low, tree high)
   if (TREE_TYPE (type))
     dbxout_type (TREE_TYPE (type), 0);
   else if (TREE_CODE (type) != INTEGER_TYPE)
-    dbxout_type (type, 0); /* E.g. Pascal's ARRAY [BOOLEAN] of INTEGER */
+    dbxout_type (type, 0);
   else
     {
       /* Traditionally, we made sure 'int' was type 1, and builtin types
@@ -1720,23 +1737,23 @@ dbxout_range_type (tree type, tree low, tree high)
     }
 
   stabstr_C (';');
-  if (low && host_integerp (low, 0))
+  if (low && tree_fits_shwi_p (low))
     {
       if (print_int_cst_bounds_in_octal_p (type, low, high))
         stabstr_O (low);
       else
-        stabstr_D (tree_low_cst (low, 0));
+        stabstr_D (tree_to_shwi (low));
     }
   else
     stabstr_C ('0');
 
   stabstr_C (';');
-  if (high && host_integerp (high, 0))
+  if (high && tree_fits_shwi_p (high))
     {
       if (print_int_cst_bounds_in_octal_p (type, low, high))
         stabstr_O (high);
       else
-        stabstr_D (tree_low_cst (high, 0));
+        stabstr_D (tree_to_shwi (high));
       stabstr_C (';');
     }
   else
@@ -1866,7 +1883,7 @@ dbxout_type (tree type, int full)
         Sun dbx crashes if we do.  */
       if (! full || !COMPLETE_TYPE_P (type)
          /* No way in DBX fmt to describe a variable size.  */
-         || ! host_integerp (TYPE_SIZE (type), 1))
+         || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
        return;
       break;
     case TYPE_DEFINED:
@@ -1891,7 +1908,7 @@ dbxout_type (tree type, int full)
         && !full)
        || !COMPLETE_TYPE_P (type)
        /* No way in DBX fmt to describe a variable size.  */
-       || ! host_integerp (TYPE_SIZE (type), 1))
+       || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
       {
        typevec[TYPE_SYMTAB_ADDRESS (type)].status = TYPE_XREF;
        return;
@@ -2149,7 +2166,7 @@ dbxout_type (tree type, int full)
             && !full)
            || !COMPLETE_TYPE_P (type)
            /* No way in DBX fmt to describe a variable size.  */
-           || ! host_integerp (TYPE_SIZE (type), 1))
+           || ! tree_fits_uhwi_p (TYPE_SIZE (type)))
          {
            /* If the type is just a cross reference, output one
               and mark the type as partially described.
@@ -2159,12 +2176,12 @@ dbxout_type (tree type, int full)
               another type's definition; instead, output an xref
               and let the definition come when the name is defined.  */
            stabstr_S ((TREE_CODE (type) == RECORD_TYPE) ? "xs" : "xu");
-           if (TYPE_NAME (type) != 0
-               /* The C frontend creates for anonymous variable length
-                  records/unions TYPE_NAME with DECL_NAME NULL.  */
-               && (TREE_CODE (TYPE_NAME (type)) != TYPE_DECL
-                   || DECL_NAME (TYPE_NAME (type))))
-             dbxout_type_name (type);
+           if (TYPE_IDENTIFIER (type))
+             {
+               /* Note that the C frontend creates for anonymous variable
+                  length records/unions TYPE_NAME with DECL_NAME NULL.  */
+               dbxout_type_name (type);
+             }
            else
              {
                stabstr_S ("$$");
@@ -2184,7 +2201,7 @@ dbxout_type (tree type, int full)
          {
            int i;
            tree child;
-           VEC(tree,gc) *accesses = BINFO_BASE_ACCESSES (binfo);
+           vec<tree, va_gc> *accesses = BINFO_BASE_ACCESSES (binfo);
 
            if (use_gnu_debug_info_extensions)
              {
@@ -2197,8 +2214,7 @@ dbxout_type (tree type, int full)
              }
            for (i = 0; BINFO_BASE_ITERATE (binfo, i, child); i++)
              {
-               tree access = (accesses ? VEC_index (tree, accesses, i)
-                              : access_public_node);
+               tree access = (accesses ? (*accesses)[i] : access_public_node);
 
                if (use_gnu_debug_info_extensions)
                  {
@@ -2207,16 +2223,16 @@ dbxout_type (tree type, int full)
                                   access == access_protected_node
                                   ? '1' :'0');
                    if (BINFO_VIRTUAL_P (child)
-                       && (strcmp (lang_hooks.name, "GNU C++") == 0
+                       && (lang_GNU_CXX ()
                            || strcmp (lang_hooks.name, "GNU Objective-C++") == 0))
                      /* For a virtual base, print the (negative)
                         offset within the vtable where we must look
                         to find the necessary adjustment.  */
                      stabstr_D
-                       (tree_low_cst (BINFO_VPTR_FIELD (child), 0)
+                       (tree_to_shwi (BINFO_VPTR_FIELD (child))
                         * BITS_PER_UNIT);
                    else
-                     stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+                     stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
                                       * BITS_PER_UNIT);
                    stabstr_C (',');
                    dbxout_type (BINFO_TYPE (child), 0);
@@ -2231,11 +2247,11 @@ dbxout_type (tree type, int full)
                    stabstr_C (':');
                    dbxout_type (BINFO_TYPE (child), full);
                    stabstr_C (',');
-                   stabstr_D (tree_low_cst (BINFO_OFFSET (child), 0)
+                   stabstr_D (tree_to_shwi (BINFO_OFFSET (child))
                                     * BITS_PER_UNIT);
                    stabstr_C (',');
                    stabstr_D
-                     (tree_low_cst (TYPE_SIZE (BINFO_TYPE (child)), 0)
+                     (tree_to_shwi (TYPE_SIZE (BINFO_TYPE (child)))
                       * BITS_PER_UNIT);
                    stabstr_C (';');
                  }
@@ -2245,10 +2261,8 @@ dbxout_type (tree type, int full)
 
       /* Write out the field declarations.  */
       dbxout_type_fields (type);
-      if (use_gnu_debug_info_extensions && TYPE_METHODS (type) != NULL_TREE)
-       {
-         dbxout_type_methods (type);
-       }
+      if (use_gnu_debug_info_extensions)
+       dbxout_type_methods (type);
 
       stabstr_C (';');
 
@@ -2302,10 +2316,7 @@ dbxout_type (tree type, int full)
           if (TREE_CODE (value) == CONST_DECL)
             value = DECL_INITIAL (value);
 
-         if (TREE_INT_CST_HIGH (value) == 0)
-           stabstr_D (TREE_INT_CST_LOW (value));
-         else if (TREE_INT_CST_HIGH (value) == -1
-                  && (HOST_WIDE_INT) TREE_INT_CST_LOW (value) < 0)
+         if (cst_and_fits_in_hwi (value))
            stabstr_D (TREE_INT_CST_LOW (value));
          else
            stabstr_O (value);
@@ -2369,6 +2380,17 @@ dbxout_type (tree type, int full)
       break;
 
     default:
+      /* A C++ function with deduced return type can have a TEMPLATE_TYPE_PARM
+        named 'auto' in its type.
+        No debug info for TEMPLATE_TYPE_PARM type supported yet.  */
+      if (lang_GNU_CXX ())
+       {
+         tree name = TYPE_IDENTIFIER (type);
+         if (name == get_identifier ("auto")
+             || name == get_identifier ("decltype(auto)"))
+           break;
+       }
+
       gcc_unreachable ();
     }
 }
@@ -2428,8 +2450,8 @@ dbxout_type_name (tree type)
   stabstr_I (t);
 }
 
-/* Output leading leading struct or class names needed for qualifying
-   type whose scope is limited to a struct or class.  */
+/* Output leading struct or class names needed for qualifying type
+   whose scope is limited to a struct or class.  */
 
 static void
 dbxout_class_name_qualifiers (tree decl)
@@ -2437,7 +2459,7 @@ dbxout_class_name_qualifiers (tree decl)
   tree context = decl_type_context (decl);
 
   if (context != NULL_TREE
-      && TREE_CODE(context) == RECORD_TYPE
+      && TREE_CODE (context) == RECORD_TYPE
       && TYPE_NAME (context) != 0
       && (TREE_CODE (TYPE_NAME (context)) == IDENTIFIER_NODE
           || (DECL_NAME (TYPE_NAME (context)) != 0)))
@@ -2482,8 +2504,8 @@ dbxout_expand_expr (tree expr)
          /* If this is a var that might not be actually output,
             return NULL, otherwise stabs might reference an undefined
             symbol.  */
-         struct varpool_node *node = varpool_get_node (expr);
-         if (!node || !node->analyzed)
+         varpool_node *node = varpool_node::get (expr);
+         if (!node || !node->definition)
            return NULL;
        }
       /* FALLTHRU */
@@ -2505,26 +2527,26 @@ dbxout_expand_expr (tree expr)
     case ARRAY_RANGE_REF:
     case BIT_FIELD_REF:
       {
-       enum machine_mode mode;
-       HOST_WIDE_INT bitsize, bitpos;
+       machine_mode mode;
+       poly_int64 bitsize, bitpos;
        tree offset, tem;
-       int volatilep = 0, unsignedp = 0;
+       int unsignedp, reversep, volatilep = 0;
        rtx x;
 
-       tem = get_inner_reference (expr, &bitsize, &bitpos, &offset,
-                                  &mode, &unsignedp, &volatilep, true);
+       tem = get_inner_reference (expr, &bitsize, &bitpos, &offset, &mode,
+                                  &unsignedp, &reversep, &volatilep);
 
        x = dbxout_expand_expr (tem);
        if (x == NULL || !MEM_P (x))
          return NULL;
        if (offset != NULL)
          {
-           if (!host_integerp (offset, 0))
+           if (!tree_fits_shwi_p (offset))
              return NULL;
-           x = adjust_address_nv (x, mode, tree_low_cst (offset, 0));
+           x = adjust_address_nv (x, mode, tree_to_shwi (offset));
          }
-       if (bitpos != 0)
-         x = adjust_address_nv (x, mode, bitpos / BITS_PER_UNIT);
+       if (maybe_ne (bitpos, 0))
+         x = adjust_address_nv (x, mode, bits_to_bytes_round_down (bitpos));
 
        return x;
       }
@@ -2537,12 +2559,9 @@ dbxout_expand_expr (tree expr)
 /* Helper function for output_used_types.  Queue one entry from the
    used types hash to be output.  */
 
-static int
-output_used_types_helper (void **slot, void *data)
+bool
+output_used_types_helper (tree const &type, vec<tree> *types_p)
 {
-  tree type = (tree) *slot;
-  VEC(tree, heap) **types_p = (VEC(tree, heap) **) data;
-
   if ((TREE_CODE (type) == RECORD_TYPE
        || TREE_CODE (type) == UNION_TYPE
        || TREE_CODE (type) == QUAL_UNION_TYPE
@@ -2550,12 +2569,12 @@ output_used_types_helper (void **slot, void *data)
       && TYPE_STUB_DECL (type)
       && DECL_P (TYPE_STUB_DECL (type))
       && ! DECL_IGNORED_P (TYPE_STUB_DECL (type)))
-    VEC_quick_push (tree, *types_p, TYPE_STUB_DECL (type));
+    types_p->quick_push (TYPE_STUB_DECL (type));
   else if (TYPE_NAME (type)
           && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
-    VEC_quick_push (tree, *types_p, TYPE_NAME (type));
+    types_p->quick_push (TYPE_NAME (type));
 
-  return 1;
+  return true;
 }
 
 /* This is a qsort callback which sorts types and declarations into a
@@ -2593,20 +2612,21 @@ output_used_types (void)
 {
   if (cfun && cfun->used_types_hash)
     {
-      VEC(tree, heap) *types;
+      vec<tree> types;
       int i;
       tree type;
 
-      types = VEC_alloc (tree, heap, htab_elements (cfun->used_types_hash));
-      htab_traverse (cfun->used_types_hash, output_used_types_helper, &types);
+      types.create (cfun->used_types_hash->elements ());
+      cfun->used_types_hash->traverse<vec<tree> *, output_used_types_helper>
+               (&types);
 
       /* Sort by UID to prevent dependence on hash table ordering.  */
-      VEC_qsort (tree, types, output_types_sort);
+      types.qsort (output_types_sort);
 
-      FOR_EACH_VEC_ELT (tree, types, i, type)
+      FOR_EACH_VEC_ELT (types, i, type)
        debug_queue_symbol (type);
 
-      VEC_free (tree, heap, types);
+      types.release ();
     }
 }
 
@@ -2639,7 +2659,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
 
   if (flag_debug_only_used_symbols
       && (!TREE_USED (decl)
-          && (TREE_CODE (decl) != VAR_DECL || !DECL_INITIAL (decl))))
+          && (!VAR_P (decl) || !DECL_INITIAL (decl))))
     DBXOUT_DECR_NESTING_AND_RETURN (0);
 
   /* If dbxout_init has not yet run, queue this symbol for later.  */
@@ -2797,13 +2817,11 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
                 /* Do not generate a tag for incomplete records.  */
                 && COMPLETE_TYPE_P (type)
                /* Do not generate a tag for records of variable size,
-                  since this type can not be properly described in the
+                  since this type cannot be properly described in the
                   DBX format, and it confuses some tools such as objdump.  */
-               && host_integerp (TYPE_SIZE (type), 1))
+               && tree_fits_uhwi_p (TYPE_SIZE (type)))
              {
-               tree name = TYPE_NAME (type);
-               if (TREE_CODE (name) == TYPE_DECL)
-                 name = DECL_NAME (name);
+               tree name = TYPE_IDENTIFIER (type);
 
                dbxout_begin_complex_stabs ();
                stabstr_I (name);
@@ -2860,9 +2878,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
               This is what represents `struct foo' with no typedef.  */
            /* In C++, the name of a type is the corresponding typedef.
               In C, it is an IDENTIFIER_NODE.  */
-           tree name = TYPE_NAME (type);
-           if (TREE_CODE (name) == TYPE_DECL)
-             name = DECL_NAME (name);
+           tree name = TYPE_IDENTIFIER (type);
 
            dbxout_begin_complex_stabs ();
            stabstr_I (name);
@@ -2898,9 +2914,9 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       /* PARM_DECLs go in their own separate chain and are output by
         dbxout_reg_parms and dbxout_parms, except for those that are
         disguised VAR_DECLs like Out parameters in Ada.  */
-      gcc_assert (TREE_CODE (decl) == VAR_DECL);
+      gcc_assert (VAR_P (decl));
 
-      /* ... fall through ...  */
+      /* fall through */
 
     case RESULT_DECL:
     case VAR_DECL:
@@ -2915,7 +2931,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
         ??? Why do we skip emitting the type and location in this case?  */
       if (TREE_STATIC (decl) && TREE_READONLY (decl)
          && DECL_INITIAL (decl) != 0
-         && host_integerp (DECL_INITIAL (decl), 0)
+         && tree_fits_shwi_p (DECL_INITIAL (decl))
          && ! TREE_ASM_WRITTEN (decl)
          && (DECL_FILE_SCOPE_P (decl)
              || TREE_CODE (DECL_CONTEXT (decl)) == BLOCK
@@ -2927,7 +2943,7 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
          if (TREE_CODE (TREE_TYPE (decl)) == INTEGER_TYPE
              || TREE_CODE (TREE_TYPE (decl)) == ENUMERAL_TYPE)
            {
-             HOST_WIDE_INT ival = TREE_INT_CST_LOW (DECL_INITIAL (decl));
+             HOST_WIDE_INT ival = tree_to_shwi (DECL_INITIAL (decl));
 
              dbxout_begin_complex_stabs ();
              dbxout_symbol_name (decl, NULL, 'c');
@@ -2946,7 +2962,8 @@ dbxout_symbol (tree decl, int local ATTRIBUTE_UNUSED)
       if (!decl_rtl)
        DBXOUT_DECR_NESTING_AND_RETURN (0);
 
-      decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
+      if (!is_global_var (decl))
+       decl_rtl = eliminate_regs (decl_rtl, VOIDmode, NULL_RTX);
 #ifdef LEAF_REG_REMAP
       if (crtl->uses_only_leaf_regs)
        leaf_renumber_regs_insn (decl_rtl);
@@ -3023,7 +3040,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
          int offs;
          letter = 'G';
          code = N_GSYM;
-         if (NULL != dbxout_common_check (decl, &offs))
+         if (dbxout_common_check (decl, &offs) != NULL)
            {
              letter = 'V';
              addr = 0;
@@ -3072,12 +3089,12 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
             we rely on the fact that error_mark_node initializers always
             end up in bss for C++ and never end up in bss for C.  */
          if (DECL_INITIAL (decl) == 0
-             || (!strcmp (lang_hooks.name, "GNU C++")
+             || (lang_GNU_CXX ()
                  && DECL_INITIAL (decl) == error_mark_node))
            {
              int offs;
              code = N_LCSYM;
-             if (NULL != dbxout_common_check (decl, &offs))
+             if (dbxout_common_check (decl, &offs) != NULL)
                {
                  addr = 0;
                  number = offs;
@@ -3176,7 +3193,7 @@ dbxout_symbol_location (tree decl, tree type, const char *suffix, rtx home)
       int offs;
       code = N_LCSYM;
       letter = 'V';
-      if (NULL == dbxout_common_check (decl, &offs))
+      if (dbxout_common_check (decl, &offs) == NULL)
         addr = XEXP (XEXP (home, 0), 0);
       else
         {
@@ -3304,9 +3321,9 @@ dbxout_common_check (tree decl, int *value)
      ??? DECL_THREAD_LOCAL_P check prevents problems with improper .stabs
      for thread-local symbols.  Can be handled via same mechanism as used
      in dwarf2out.c.  */
-  if (TREE_CODE (decl) != VAR_DECL
-      || !TREE_STATIC(decl)
-      || !DECL_HAS_VALUE_EXPR_P(decl)
+  if (!VAR_P (decl)
+      || !TREE_STATIC (decl)
+      || !DECL_HAS_VALUE_EXPR_P (decl)
       || DECL_THREAD_LOCAL_P (decl)
       || !is_fortran ())
     return NULL;
@@ -3340,21 +3357,21 @@ dbxout_common_check (tree decl, int *value)
           if (CONST_INT_P (XEXP (sym_addr, 0)))
             {
               name =
-                targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 1), 0));
+                targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 1), 0));
               *value = INTVAL (XEXP (sym_addr, 0));
               cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 1));
             }
           else
             {
               name =
-                targetm.strip_name_encoding(XSTR (XEXP (sym_addr, 0), 0));
+                targetm.strip_name_encoding (XSTR (XEXP (sym_addr, 0), 0));
               *value = INTVAL (XEXP (sym_addr, 1));
               cdecl = SYMBOL_REF_DECL (XEXP (sym_addr, 0));
             }
           break;
 
         case SYMBOL_REF:
-          name = targetm.strip_name_encoding(XSTR (sym_addr, 0));
+          name = targetm.strip_name_encoding (XSTR (sym_addr, 0));
           *value = 0;
           cdecl = SYMBOL_REF_DECL (sym_addr);
           break;
@@ -3367,7 +3384,7 @@ dbxout_common_check (tree decl, int *value)
       /* Check area common symbol is offset into.  If this is not public, then
          it is not a symbol in a common block.  It must be a .lcomm symbol, not
          a .comm symbol.  */
-      if (cdecl == NULL || !TREE_PUBLIC(cdecl))
+      if (cdecl == NULL || !TREE_PUBLIC (cdecl))
         name = NULL;
     }
   else
@@ -3435,12 +3452,16 @@ dbxout_parms (tree parms)
 {
   ++debug_nesting;
   emit_pending_bincls_if_required ();
+  fixed_size_mode rtl_mode, type_mode;
 
   for (; parms; parms = DECL_CHAIN (parms))
     if (DECL_NAME (parms)
        && TREE_TYPE (parms) != error_mark_node
        && DECL_RTL_SET_P (parms)
-       && DECL_INCOMING_RTL (parms))
+       && DECL_INCOMING_RTL (parms)
+       /* We can't represent variable-sized types in this format.  */
+       && is_a <fixed_size_mode> (TYPE_MODE (TREE_TYPE (parms)), &type_mode)
+       && is_a <fixed_size_mode> (GET_MODE (DECL_RTL (parms)), &rtl_mode))
       {
        tree eff_type;
        char letter;
@@ -3597,10 +3618,9 @@ dbxout_parms (tree parms)
            /* Make a big endian correction if the mode of the type of the
               parameter is not the same as the mode of the rtl.  */
            if (BYTES_BIG_ENDIAN
-               && TYPE_MODE (TREE_TYPE (parms)) != GET_MODE (DECL_RTL (parms))
-               && GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))) < UNITS_PER_WORD)
-             number += (GET_MODE_SIZE (GET_MODE (DECL_RTL (parms)))
-                        - GET_MODE_SIZE (TYPE_MODE (TREE_TYPE (parms))));
+               && type_mode != rtl_mode
+               && GET_MODE_SIZE (type_mode) < UNITS_PER_WORD)
+             number += GET_MODE_SIZE (rtl_mode) - GET_MODE_SIZE (type_mode);
          }
        else
          /* ??? We don't know how to represent this argument.  */
@@ -3703,6 +3723,26 @@ dbx_output_rbrac (const char *label,
     dbxout_stab_value_label (label);
 }
 
+/* Return true if at least one block among BLOCK, its children or siblings
+   has TREE_USED, TREE_ASM_WRITTEN and BLOCK_IN_COLD_SECTION_P
+   set.  If there is none, clear TREE_USED bit on such blocks.  */
+
+static bool
+dbx_block_with_cold_children (tree block)
+{
+  bool ret = false;
+  for (; block; block = BLOCK_CHAIN (block))
+    if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
+      {
+       bool children = dbx_block_with_cold_children (BLOCK_SUBBLOCKS (block));
+       if (BLOCK_IN_COLD_SECTION_P (block) || children)
+         ret = true;
+       else
+         TREE_USED (block) = false;
+      }
+  return ret;
+}
+
 /* Output everything about a symbol block (a BLOCK node
    that represents a scope level),
    including recursive output of contained blocks.
@@ -3718,22 +3758,31 @@ dbx_output_rbrac (const char *label,
    except for the outermost block.
 
    Actually, BLOCK may be several blocks chained together.
-   We handle them all in sequence.  */
+   We handle them all in sequence.
 
-static void
-dbxout_block (tree block, int depth, tree args)
+   Return true if we emitted any LBRAC/RBRAC.  */
+
+static bool
+dbxout_block (tree block, int depth, tree args, int parent_blocknum)
 {
+  bool ret = false;
   char begin_label[20];
   /* Reference current function start using LFBB.  */
   ASM_GENERATE_INTERNAL_LABEL (begin_label, "LFBB", scope_labelno);
 
-  while (block)
+  /* If called for the second partition, ignore blocks that don't have
+     any children in the second partition.  */
+  if (crtl->has_bb_partition && in_cold_section_p && depth == 0)
+    dbx_block_with_cold_children (block);
+
+  for (; block; block = BLOCK_CHAIN (block))
     {
       /* Ignore blocks never expanded or otherwise marked as real.  */
       if (TREE_USED (block) && TREE_ASM_WRITTEN (block))
        {
          int did_output;
          int blocknum = BLOCK_NUMBER (block);
+         int this_parent = parent_blocknum;
 
          /* In dbx format, the syms of a block come before the N_LBRAC.
             If nothing is output, we don't need the N_LBRAC, either.  */
@@ -3747,11 +3796,13 @@ dbxout_block (tree block, int depth, tree args)
             the block.  Use the block's tree-walk order to generate
             the assembler symbols LBBn and LBEn
             that final will define around the code in this block.  */
-         if (did_output)
+         if (did_output
+             && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p)
            {
              char buf[20];
              const char *scope_start;
 
+             ret = true;
              if (depth == 0)
                /* The outermost block doesn't get LBB labels; use
                   the LFBB local symbol emitted by dbxout_begin_prologue.  */
@@ -3760,16 +3811,21 @@ dbxout_block (tree block, int depth, tree args)
                {
                  ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", blocknum);
                  scope_start = buf;
+                 this_parent = blocknum;
                }
 
              dbx_output_lbrac (scope_start, begin_label);
            }
 
          /* Output the subblocks.  */
-         dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE);
+         bool children
+           = dbxout_block (BLOCK_SUBBLOCKS (block), depth + 1, NULL_TREE,
+                           this_parent);
+         ret |= children;
 
          /* Refer to the marker for the end of the block.  */
-         if (did_output)
+         if (did_output
+             && BLOCK_IN_COLD_SECTION_P (block) == in_cold_section_p)
            {
              char buf[100];
              if (depth == 0)
@@ -3782,9 +3838,29 @@ dbxout_block (tree block, int depth, tree args)
 
              dbx_output_rbrac (buf, begin_label);
            }
+         else if (did_output && !children)
+           {
+             /* If we emitted any vars and didn't output any LBRAC/RBRAC,
+                either at this level or any lower level, we need to emit
+                an empty LBRAC/RBRAC pair now.  */
+             char buf[30];
+             const char *scope_start;
+
+             ret = true;
+             if (parent_blocknum == -1)
+               scope_start = begin_label;
+             else
+               {
+                 ASM_GENERATE_INTERNAL_LABEL (buf, "LBB", parent_blocknum);
+                 scope_start = buf;
+               }
+
+             dbx_output_lbrac (scope_start, begin_label);
+             dbx_output_rbrac (scope_start, begin_label);
+           }
        }
-      block = BLOCK_CHAIN (block);
     }
+  return ret;
 }
 
 /* Output the information about a function and its arguments and result.