summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/c-common.c9
-rw-r--r--gcc/c-common.h1
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c10
-rw-r--r--gcc/cp/tree.c8
-rw-r--r--gcc/dwarf2out.c186
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/debug/dwarf2/typedef3.C19
-rw-r--r--gcc/tree.c17
-rw-r--r--gcc/tree.h2
12 files changed, 206 insertions, 78 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index c2306ea5c08..af844b58376 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+2010-05-25 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/44188
+ * c-common.c (is_typedef_decl): Move this definition ...
+ * tree.c (is_typedef_decl): ... here.
+ (typdef_variant_p): Move definition here from gcc/cp/tree.c.
+ * c-common.h (is_typedef_decl): Move this declaration ...
+ * tree.h (is_typedef_decl): ... here.
+ (typedef_variant_p): Move declaration here from gcc/cp/cp-tree.h
+ * dwarf2out.c (is_naming_typedef_decl): New function.
+ (gen_tagged_type_die): Split out of ...
+ (gen_type_die_with_usage): ... this function. When an anonymous
+ tagged type is named by a typedef, make sure a DW_TAG_typedef DIE
+ is emitted for the typedef.
+ (gen_typedef_die): Emit DW_TAG_typedef also for typedefs naming
+ anonymous tagged types.
+
2010-05-27 Jason Merrill <jason@redhat.com>
* print-tree.c (debug_vec_tree): New fn.
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 1fd11c50c64..e72aaf90101 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -9387,15 +9387,6 @@ set_underlying_type (tree x)
}
}
-/* Returns true if X is a typedef decl. */
-
-bool
-is_typedef_decl (tree x)
-{
- return (x && TREE_CODE (x) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
-}
-
/* Record the types used by the current global variable declaration
being parsed, so that we can decide later to emit their debug info.
Those types are in types_used_by_cur_var_decl, and we are going to
diff --git a/gcc/c-common.h b/gcc/c-common.h
index 039edbee974..ec63e0c4163 100644
--- a/gcc/c-common.h
+++ b/gcc/c-common.h
@@ -1055,7 +1055,6 @@ extern void warn_for_sign_compare (location_t,
tree result_type,
enum tree_code resultcode);
extern void set_underlying_type (tree x);
-extern bool is_typedef_decl (tree x);
extern VEC(tree,gc) *make_tree_vector (void);
extern void release_tree_vector (VEC(tree,gc) *);
extern VEC(tree,gc) *make_tree_vector_single (tree);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index f63703ead04..f359b213d07 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,12 @@
+2010-05-25 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/44188
+ * cp-tree.h (typedef_variant_p): Move this declaration to
+ gcc/tree.h.
+ * tree.c (typedef_variant_p): Move this definition to gcc/tree.c.
+ * decl.c (grokdeclarator): Do not rename debug info of an
+ anonymous tagged type named by a typedef.
+
2010-05-27 Jason Merrill <jason@redhat.com>
PR c++/43555
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 37a0f1e50ea..4d3cf7dd90b 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5256,7 +5256,6 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
-extern bool typedef_variant_p (tree);
extern void cp_set_underlying_type (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0d303403588..533b56f48b9 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -9081,10 +9081,12 @@ grokdeclarator (const cp_declarator *declarator,
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
- {
- debug_hooks->set_name (t, decl);
- TYPE_NAME (t) = decl;
- }
+ /* We do not rename the debug info representing the
+ anonymous tagged type because the standard says in
+ [dcl.typedef] that the naming applies only for
+ linkage purposes. */
+ /*debug_hooks->set_name (t, decl);*/
+ TYPE_NAME (t) = decl;
}
if (TYPE_LANG_SPECIFIC (type))
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index d5ccd65a790..5421980a052 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1055,14 +1055,6 @@ strip_typedefs (tree t)
return cp_build_qualified_type (result, cp_type_quals (t));
}
-/* Returns true iff TYPE is a type variant created for a typedef. */
-
-bool
-typedef_variant_p (tree type)
-{
- return is_typedef_decl (TYPE_NAME (type));
-}
-
/* Setup a TYPE_DECL node as a typedef representation.
See comments of set_underlying_type in c-common.c. */
diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c
index ca2194f2b48..a0de6551e19 100644
--- a/gcc/dwarf2out.c
+++ b/gcc/dwarf2out.c
@@ -6202,6 +6202,7 @@ 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 int is_redundant_typedef (const_tree);
+static bool is_naming_typedef_decl (const_tree);
static inline dw_die_ref get_context_die (tree);
static void gen_namespace_die (tree, dw_die_ref);
static void gen_decl_die (tree, tree, dw_die_ref);
@@ -6213,6 +6214,8 @@ static struct dwarf_file_data * lookup_filename (const char *);
static void retry_incomplete_types (void);
static void gen_type_die_for_member (tree, tree, dw_die_ref);
static void gen_generic_params_dies (tree);
+static void gen_tagged_type_die (tree, dw_die_ref, enum debug_info_usage);
+static void gen_type_die_with_usage (tree, dw_die_ref, enum debug_info_usage);
static void splice_child_die (dw_die_ref, dw_die_ref);
static int file_info_cmp (const void *, const void *);
static dw_loc_list_ref new_loc_list (dw_loc_descr_ref, const char *,
@@ -19408,10 +19411,33 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
equate_type_number_to_die (TREE_TYPE (decl), type_die);
}
else
- type = TREE_TYPE (decl);
+ {
+ /* 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 = TREE_TYPE (decl);
+
+ /* 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. */
+ gen_tagged_type_die (type, context_die, DINFO_USAGE_DIR_USE);
+ }
add_type_attribute (type_die, type, TREE_READONLY (decl),
TREE_THIS_VOLATILE (decl), context_die);
+
+ if (is_naming_typedef_decl (decl))
+ /* We want that all subsequent calls to lookup_type_die with
+ TYPE in argument yield the DW_TAG_typedef we have just
+ created. */
+ equate_type_number_to_die (type, type_die);
}
if (DECL_ABSTRACT (decl))
@@ -19421,13 +19447,74 @@ gen_typedef_die (tree decl, dw_die_ref context_die)
add_pubtype (decl, type_die);
}
+/* Generate a DIE for a struct, class, enum or union type. */
+
+static void
+gen_tagged_type_die (tree type,
+ dw_die_ref context_die,
+ enum debug_info_usage usage)
+{
+ int need_pop;
+
+ /* If this is a nested type whose containing class hasn't been written
+ out yet, writing it out will cover this one, too. This does not apply
+ to instantiations of member class templates; they need to be added to
+ the containing class as they are generated. FIXME: This hurts the
+ idea of combining type decls from multiple TUs, since we can't predict
+ what set of template instantiations we'll get. */
+ if (TYPE_CONTEXT (type)
+ && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
+ && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
+ {
+ gen_type_die_with_usage (TYPE_CONTEXT (type), context_die, usage);
+
+ if (TREE_ASM_WRITTEN (type))
+ return;
+
+ /* If that failed, attach ourselves to the stub. */
+ push_decl_scope (TYPE_CONTEXT (type));
+ context_die = lookup_type_die (TYPE_CONTEXT (type));
+ need_pop = 1;
+ }
+ else if (TYPE_CONTEXT (type) != NULL_TREE
+ && (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL))
+ {
+ /* If this type is local to a function that hasn't been written
+ out yet, use a NULL context for now; it will be fixed up in
+ decls_for_scope. */
+ context_die = lookup_decl_die (TYPE_CONTEXT (type));
+ need_pop = 0;
+ }
+ else
+ {
+ context_die = declare_in_namespace (type, context_die);
+ need_pop = 0;
+ }
+
+ if (TREE_CODE (type) == ENUMERAL_TYPE)
+ {
+ /* This might have been written out by the call to
+ declare_in_namespace. */
+ if (!TREE_ASM_WRITTEN (type))
+ gen_enumeration_type_die (type, context_die);
+ }
+ else
+ gen_struct_or_union_type_die (type, context_die, usage);
+
+ if (need_pop)
+ pop_decl_scope ();
+
+ /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
+ it up if it is ever completed. gen_*_type_die will set it for us
+ when appropriate. */
+}
+
/* Generate a type description DIE. */
static void
gen_type_die_with_usage (tree type, dw_die_ref context_die,
enum debug_info_usage usage)
{
- int need_pop;
struct array_descr_info info;
if (type == NULL_TREE || type == error_mark_node)
@@ -19435,8 +19522,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
/* If TYPE is a typedef type variant, let's generate debug info
for the parent typedef which TYPE is a type of. */
- if (TYPE_NAME (type) && TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
- && DECL_ORIGINAL_TYPE (TYPE_NAME (type)))
+ if (typedef_variant_p (type))
{
if (TREE_ASM_WRITTEN (type))
return;
@@ -19451,6 +19537,21 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
TREE_ASM_WRITTEN (type) = 1;
+
+ gen_decl_die (TYPE_NAME (type), NULL, context_die);
+ return;
+ }
+
+ /* If type is an anonymous tagged type named by a typedef, let's
+ generate debug info for the typedef. */
+ if (is_naming_typedef_decl (TYPE_NAME (type)))
+ {
+ /* Use the DIE of the containing namespace as the parent DIE of
+ the type description DIE we want to generate. */
+ if (DECL_CONTEXT (TYPE_NAME (type))
+ && TREE_CODE (DECL_CONTEXT (TYPE_NAME (type))) == NAMESPACE_DECL)
+ context_die = get_context_die (DECL_CONTEXT (TYPE_NAME (type)));
+
gen_decl_die (TYPE_NAME (type), NULL, context_die);
return;
}
@@ -19538,57 +19639,7 @@ gen_type_die_with_usage (tree type, dw_die_ref context_die,
case RECORD_TYPE:
case UNION_TYPE:
case QUAL_UNION_TYPE:
- /* If this is a nested type whose containing class hasn't been written
- out yet, writing it out will cover this one, too. This does not apply
- to instantiations of member class templates; they need to be added to
- the containing class as they are generated. FIXME: This hurts the
- idea of combining type decls from multiple TUs, since we can't predict
- what set of template instantiations we'll get. */
- if (TYPE_CONTEXT (type)
- && AGGREGATE_TYPE_P (TYPE_CONTEXT (type))
- && ! TREE_ASM_WRITTEN (TYPE_CONTEXT (type)))
- {
- gen_type_die_with_usage (TYPE_CONTEXT (type), context_die, usage);
-
- if (TREE_ASM_WRITTEN (type))
- return;
-
- /* If that failed, attach ourselves to the stub. */
- push_decl_scope (TYPE_CONTEXT (type));
- context_die = lookup_type_die (TYPE_CONTEXT (type));
- need_pop = 1;
- }
- else if (TYPE_CONTEXT (type) != NULL_TREE
- && (TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL))
- {
- /* If this type is local to a function that hasn't been written
- out yet, use a NULL context for now; it will be fixed up in
- decls_for_scope. */
- context_die = lookup_decl_die (TYPE_CONTEXT (type));
- need_pop = 0;
- }
- else
- {
- context_die = declare_in_namespace (type, context_die);
- need_pop = 0;
- }
-
- if (TREE_CODE (type) == ENUMERAL_TYPE)
- {
- /* This might have been written out by the call to
- declare_in_namespace. */
- if (!TREE_ASM_WRITTEN (type))
- gen_enumeration_type_die (type, context_die);
- }
- else
- gen_struct_or_union_type_die (type, context_die, usage);
-
- if (need_pop)
- pop_decl_scope ();
-
- /* Don't set TREE_ASM_WRITTEN on an incomplete struct; we want to fix
- it up if it is ever completed. gen_*_type_die will set it for us
- when appropriate. */
+ gen_tagged_type_die (type, context_die, usage);
return;
case VOID_TYPE:
@@ -19796,6 +19847,31 @@ is_redundant_typedef (const_tree decl)
return 0;
}
+/* Return TRUE if TYPE is a typedef that names a type for linkage
+ purposes. This kind of typedefs is produced by the C++ FE for
+ constructs like:
+
+ typedef struct {...} foo;
+
+ In that case, there is no typedef variant type produced for foo.
+ Rather, the TREE_TYPE of the TYPE_DECL of foo is the anonymous
+ struct type. */
+
+static bool
+is_naming_typedef_decl (const_tree decl)
+{
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != TYPE_DECL
+ || !is_tagged_type (TREE_TYPE (decl))
+ || is_redundant_typedef (decl))
+ return FALSE;
+
+ return (DECL_ORIGINAL_TYPE (decl) == NULL_TREE
+ && TYPE_NAME (TREE_TYPE (decl)) == decl
+ && (TYPE_STUB_DECL (TREE_TYPE (decl))
+ != TYPE_NAME (TREE_TYPE (decl))));
+}
+
/* Returns the DIE for a context. */
static inline dw_die_ref
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 5501c8dd93e..e36bb0d1f85 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2010-05-25 Dodji Seketeli <dodji@redhat.com>
+
+ PR c++/44188
+ * g++.dg/debug/dwarf2/typedef3.C: New test.
+
2010-05-27 Jason Merrill <jason@redhat.com>
PR c++/43555
diff --git a/gcc/testsuite/g++.dg/debug/dwarf2/typedef3.C b/gcc/testsuite/g++.dg/debug/dwarf2/typedef3.C
new file mode 100644
index 00000000000..ca70d9cacfa
--- /dev/null
+++ b/gcc/testsuite/g++.dg/debug/dwarf2/typedef3.C
@@ -0,0 +1,19 @@
+// Origin: PR debug/44188
+// { dg-options "-g -dA" }
+// { dg-do compile }
+
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_typedef\\)" 1 } }
+
+// { dg-final { scan-assembler-times "\[^\n\r\]*\\(DIE\[^\n\r\]*DW_TAG_structure_type\\)" 1 } }
+
+typedef struct
+{
+ int i;
+} AAA;
+
+int
+main(void)
+{
+ AAA aa;
+ return 0;
+}
diff --git a/gcc/tree.c b/gcc/tree.c
index 743293e288a..8b04c376594 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -10825,4 +10825,21 @@ get_binfo_at_offset (tree binfo, HOST_WIDE_INT offset, tree expected_type)
return binfo;
}
+/* Returns true if X is a typedef decl. */
+
+bool
+is_typedef_decl (tree x)
+{
+ return (x && TREE_CODE (x) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (x) != NULL_TREE);
+}
+
+/* Returns true iff TYPE is a type variant created for a typedef. */
+
+bool
+typedef_variant_p (tree type)
+{
+ return is_typedef_decl (TYPE_NAME (type));
+}
+
#include "gt-tree.h"
diff --git a/gcc/tree.h b/gcc/tree.h
index 5acadb499cb..94379fe4dcf 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -4820,6 +4820,8 @@ extern tree create_artificial_label (location_t);
extern const char *get_name (tree);
extern bool stdarg_p (tree);
extern bool prototype_p (tree);
+extern bool is_typedef_decl (tree x);
+extern bool typedef_variant_p (tree);
extern bool auto_var_in_fn_p (const_tree, const_tree);
extern tree build_low_bits_mask (tree, unsigned);
extern tree tree_strip_nop_conversions (tree);