diff options
-rw-r--r-- | gcc/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/c-common.c | 9 | ||||
-rw-r--r-- | gcc/c-common.h | 1 | ||||
-rw-r--r-- | gcc/cp/ChangeLog | 9 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl.c | 10 | ||||
-rw-r--r-- | gcc/cp/tree.c | 8 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 186 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/debug/dwarf2/typedef3.C | 19 | ||||
-rw-r--r-- | gcc/tree.c | 17 | ||||
-rw-r--r-- | gcc/tree.h | 2 |
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); |