The following fixes a LTO dwarf2out ICE when mixing C and C++ TUs.
is_cxx then claims we're C++ but we are not happy to see a C typedef
handled by

gen_typedef_die (tree decl, dw_die_ref context_die)
{
...
          if (is_naming_typedef_decl (TYPE_NAME (type)))
            {
              /* Here, we are in the case of decl being a typedef naming
                 an anonymous type, e.g:
                     typedef struct {...} foo;
                 In that case TREE_TYPE (decl) is not a typedef variant
                 type and TYPE_NAME of the anonymous type is set to the
                 TYPE_DECL of the typedef. This construct is emitted by
                 the C++ FE.

                 TYPE is the anonymous struct named by the typedef
                 DECL. As we need the DW_AT_type attribute of the
                 DW_TAG_typedef to point to the DIE of TYPE, let's
                 generate that DIE right away. add_type_attribute
                 called below will then pick (via lookup_type_die) that
                 anonymous struct DIE.  */
              if (!TREE_ASM_WRITTEN (type))
                gen_tagged_type_die (type, context_die, 
DINFO_USAGE_DIR_USE);

              /* This is a GNU Extension.  We are adding a
                 DW_AT_linkage_name attribute to the DIE of the
                 anonymous struct TYPE.  The value of that attribute
                 is the name of the typedef decl naming the anonymous
                 struct.  This greatly eases the work of consumers of
                 this debug info.  */
              add_linkage_name_raw (lookup_type_die (type), decl);
            }

Here gen_tagged_type_die -> gen_member_die eventually ICEs not expecting a
variant type.  "Fixing" that assert just shows that add_linkage_name_raw
fails as we do not have a DECL_ASSEMBLER_NAME for the type decl and
we do not allow deferred asm names late (the C type decl won't ever
get an assembler name anyway...).

Thus the following provides an overload to is_cxx () we can feed
with context (to see whether the typedef decl was created by the C++ FE).

Hopefully with GCC 8 we'll get early LTO debug and all these issues
gone...

LTO bootstrapped and tested on x86_64-unknown-linux-gnu, ok for trunk
and branches?

Thanks,
Richard.

2017-01-05  Richard Biener  <rguent...@suse.de>

        PR debug/79000
        * dwarf2out.c (is_cxx): New overload with context.
        (is_naming_typedef_decl): Use it.

        * g++.dg/lto/pr79000_0.C: New testcase.
        * g++.dg/lto/pr79000_1.c: Likewise.

Index: gcc/dwarf2out.c
===================================================================
*** gcc/dwarf2out.c     (revision 244093)
--- gcc/dwarf2out.c     (working copy)
*************** static int get_AT_flag (dw_die_ref, enum
*** 3356,3361 ****
--- 3356,3362 ----
  static unsigned get_AT_unsigned (dw_die_ref, enum dwarf_attribute);
  static inline dw_die_ref get_AT_ref (dw_die_ref, enum dwarf_attribute);
  static bool is_cxx (void);
+ static bool is_cxx (const_tree);
  static bool is_fortran (void);
  static bool is_ada (void);
  static bool remove_AT (dw_die_ref, enum dwarf_attribute);
*************** is_cxx (void)
*** 4990,4995 ****
--- 4991,5012 ----
          || lang == DW_LANG_C_plus_plus_11 || lang == DW_LANG_C_plus_plus_14);
  }
  
+ /* Return TRUE if DECL was created by the C++ frontend.  */
+ 
+ static bool
+ is_cxx (const_tree decl)
+ {
+   if (in_lto_p)
+     {
+       while (DECL_CONTEXT (decl))
+       decl = DECL_CONTEXT (decl);
+       if (TREE_CODE (decl) == TRANSLATION_UNIT_DECL
+         && TRANSLATION_UNIT_LANGUAGE (decl))
+       return strncmp (TRANSLATION_UNIT_LANGUAGE (decl), "GNU C++", 7) == 0;
+     }
+   return is_cxx ();
+ }
+ 
  /* Return TRUE if the language is Java.  */
  
  static inline bool
*************** is_naming_typedef_decl (const_tree decl)
*** 24762,24768 ****
        /* It looks like Ada produces TYPE_DECLs that are very similar
           to C++ naming typedefs but that have different
           semantics. Let's be specific to c++ for now.  */
!       || !is_cxx ())
      return FALSE;
  
    return (DECL_ORIGINAL_TYPE (decl) == NULL_TREE
--- 24779,24785 ----
        /* It looks like Ada produces TYPE_DECLs that are very similar
           to C++ naming typedefs but that have different
           semantics. Let's be specific to c++ for now.  */
!       || !is_cxx (decl))
      return FALSE;
  
    return (DECL_ORIGINAL_TYPE (decl) == NULL_TREE
Index: gcc/testsuite/g++.dg/lto/pr79000_0.C
===================================================================
*** gcc/testsuite/g++.dg/lto/pr79000_0.C        (revision 0)
--- gcc/testsuite/g++.dg/lto/pr79000_0.C        (working copy)
***************
*** 0 ****
--- 1,7 ----
+ // { dg-lto-do link }
+ // { dg-lto-options { "-flto -g" } }
+ // { dg-extra-ld-options "-r -nostdlib" }
+ 
+ struct a {
+   a();
+ } b;
Index: gcc/testsuite/g++.dg/lto/pr79000_1.c
===================================================================
*** gcc/testsuite/g++.dg/lto/pr79000_1.c        (revision 0)
--- gcc/testsuite/g++.dg/lto/pr79000_1.c        (working copy)
***************
*** 0 ****
--- 1,5 ----
+ typedef struct a b;
+ typedef struct a { } b;
+ struct {
+   b c;
+ } d;

Reply via email to