@@ -6454,6 +6454,7 @@ static void gen_typedef_die (tree, dw_die_ref);
static void gen_type_die (tree, dw_die_ref);
static void gen_block_die (tree, dw_die_ref, int);
static void decls_for_scope (tree, dw_die_ref, int);
+static bool is_injected_class_name (const_tree decl);
static int is_redundant_typedef (const_tree);
static bool is_naming_typedef_decl (const_tree);
static inline dw_die_ref get_context_die (tree);
@@ -20251,13 +20252,21 @@ gen_tagged_type_die (tree type,
static void
gen_type_die_with_usage (tree type, dw_die_ref context_die,
- enum debug_info_usage usage)
+ enum debug_info_usage usage)
{
struct array_descr_info info;
if (type == NULL_TREE || type == error_mark_node)
return;
+ /* The C++ FE uses a special typedef variant to represent the
+ injected-class-name of a type. Letting this through confuses us
+ because we'd consider this typedef as bloat and won't generate
+ debug info for it. What we really want is the underlying type of
+ the injected-class-name. */
+ if (is_injected_class_name (TYPE_NAME (type)))
+ type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
+
/* If TYPE is a typedef type variant, let's generate debug info
for the parent typedef which TYPE is a type of. */
if (typedef_variant_p (type))
@@ -20567,6 +20576,22 @@ decls_for_scope (tree stmt, dw_die_ref context_die, int depth)
gen_block_die (subblocks, context_die, depth + 1);
}
+/* Return TRUE if DECL is a C++ injected-class-name. */
+
+static inline bool
+is_injected_class_name (const_tree decl)
+{
+ if (is_typedef_decl (CONST_CAST_TREE (decl))
+ && !TYPE_DECL_IS_STUB (decl)
+ && 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))))
+ return 1;
+ return 0;
+}
+
/* Is this a typedef we can avoid emitting? */
static inline int
@@ -20575,12 +20600,7 @@ is_redundant_typedef (const_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. */
+ if (is_injected_class_name (decl))
return 1;
return 0;
new file mode 100644
@@ -0,0 +1,28 @@
+// Origin: PR debug/45088
+// { dg-do compile }
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
+
+struct A
+{
+ virtual ~A();
+};
+
+struct B : public A
+{
+ virtual ~B(){}
+};
+
+struct C : public B
+{
+ A* a1;
+};
+
+int
+main()
+{
+ C c;
+ c.a1 = 0;
+ return 0;
+}
+
new file mode 100644
@@ -0,0 +1,29 @@
+// Origin: PR debug/45088
+// { dg-do compile }
+// { dg-options "-g -dA" }
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_pointer_type\\)\[\n\r\]{1,2}\[^\n\r\]*DW_AT_byte_size\[\n\r\]{1,2}\[^\n\r\]*DW_AT_type" 4 } }
+
+template<class T>
+struct A
+{
+ virtual ~A();
+};
+
+struct B : public A<int>
+{
+ virtual ~B(){}
+};
+
+struct C : public B
+{
+ A<int>* a1;
+};
+
+int
+main()
+{
+ C c;
+ c.a1 = 0;
+ return 0;
+}
+