gdb: work around negative DW_AT_data_member_location GCC 11 bug
[binutils-gdb.git] / gdb / dwarf2 / read.c
index 3fe6c3ab90cf7585cd3fe35dbafe66a712560c9a..1a749eac334fe6a25a511d2268722f1089441500 100644 (file)
@@ -10630,8 +10630,13 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
 
   /* Decode line number information if present.  We do this before
      processing child DIEs, so that the line header table is available
-     for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, fnd, lowpc);
+     for DW_AT_decl_file.  The PC check is here because, if LOWPC and
+     HIGHPC are both 0x0, then there won't be any interesting code in
+     the CU, but a check later on (in
+     lnp_state_machine::check_line_address) will fail to properly
+     exclude an entry that was removed via --gc-sections.  */
+  if (lowpc != highpc)
+    handle_DW_AT_stmt_list (die, cu, fnd, lowpc);
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -14315,6 +14320,7 @@ check_producer (struct dwarf2_cu *cu)
     {
       cu->producer_is_gxx_lt_4_6 = major < 4 || (major == 4 && minor < 6);
       cu->producer_is_gcc_lt_4_3 = major < 4 || (major == 4 && minor < 3);
+      cu->producer_is_gcc_11 = major == 11;
     }
   else if (producer_is_icc (cu->producer, &major, &minor))
     {
@@ -14459,6 +14465,19 @@ handle_member_location (struct die_info *die, struct dwarf2_cu *cu,
       if (attr->form_is_constant ())
        {
          LONGEST offset = attr->constant_value (0);
+
+         /* Work around this GCC 11 bug, where it would erroneously use -1
+            data member locations, instead of 0:
+
+              Negative DW_AT_data_member_location
+              https://gcc.gnu.org/bugzilla/show_bug.cgi?id=101378
+            */
+         if (offset == -1 && cu->producer_is_gcc_11)
+           {
+             complaint (_("DW_AT_data_member_location value of -1, assuming 0"));
+             offset = 0;
+           }
+
          field->set_loc_bitpos (offset * bits_per_byte);
        }
       else if (attr->form_is_section_offset ())