On 9/4/18 5:59 PM, Tom de Vries wrote: > [ Adding Jason as addressee ] > > On 08/28/2018 08:20 PM, Omar Sandoval wrote: >> On Fri, Aug 17, 2018 at 12:16:07AM -0700, Omar Sandoval wrote: >>> On Thu, Aug 16, 2018 at 11:54:53PM -0700, Omar Sandoval wrote: >>>> On Thu, Aug 16, 2018 at 10:27:48PM -0700, Andrew Pinski wrote: >>>>> On Thu, Aug 16, 2018 at 9:29 PM Omar Sandoval <osan...@osandov.com> wrote: >>>>>> Hi, >>>>>> >>>>>> This fixes the issue that it is impossible to distinguish a zero-length >>>>>> array >>>>>> type from a flexible array type given the DWARF produced by GCC (which I >>>>>> reported here [1]). We do so by adding a DW_AT_count attribute with a >>>>>> value of >>>>>> zero only for zero-length arrays (this is what clang does in this case, >>>>>> too). >>>>>> >>>>>> 1: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86985 >>>>>> >>>>>> The reproducer from the PR now produces the expected output: >>>>>> >>>>>> $ ~/gcc-build/gcc/xgcc -B ~/gcc-build/gcc -g -c zero_length.c >>>>>> $ ~/gcc-build/gcc/xgcc -B ~/gcc-build/gcc -g -c flexible.c >>>>>> $ gdb -batch -ex 'ptype baz' zero_length.o >>>>>> type = struct { >>>>>> int foo; >>>>>> int bar[0]; >>>>>> } >>>>>> $ gdb -batch -ex 'ptype baz' flexible.o >>>>>> type = struct { >>>>>> int foo; >>>>>> int bar[]; >>>>>> } >>>>>> >>>>>> This was bootstrapped and tested on x86_64-pc-linux-gnu. >>>>>> >>>>>> I don't have commit rights (first time contributor), so if this change >>>>>> is okay >>>>>> could it please be applied? >>> [snip] >>> >>> Here's the patch with the is_c () helper instead. >>> >>> 2018-08-17 Omar Sandoval <osan...@osandov.com> >>> > I've added the PR number here. > >>> * dwarf2out.c (is_c): New. >>> (add_subscript_info): Add DW_AT_count of 0 for C zero-length arrays. >>> >>> diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c >>> index 5a74131d332..189f9bb381f 100644 >>> --- a/gcc/dwarf2out.c >>> +++ b/gcc/dwarf2out.c >>> @@ -3671,6 +3671,7 @@ static const char *get_AT_string (dw_die_ref, enum >>> dwarf_attribute); >>> static int get_AT_flag (dw_die_ref, enum dwarf_attribute); >>> 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_c (void); >>> static bool is_cxx (void); >>> static bool is_cxx (const_tree); >>> static bool is_fortran (void); >>> @@ -5434,6 +5435,19 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute >>> attr_kind) >>> return a ? AT_file (a) : NULL; >>> } >>> >>> +/* Return TRUE if the language is C. */ >>> + >>> +static inline bool >>> +is_c (void) >>> +{ >>> + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); >>> + >>> + return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_C99 >>> + || lang == DW_LANG_C11 || lang == DW_LANG_ObjC); >>> + >>> + >>> +} >>> + >>> /* Return TRUE if the language is C++. */ >>> >>> static inline bool >>> @@ -20918,12 +20932,24 @@ add_subscript_info (dw_die_ref type_die, tree >>> type, bool collapse_p) >>> dimension arr(N:*) >>> Since the debugger is definitely going to need to know N >>> to produce useful results, go ahead and output the lower >>> - bound solo, and hope the debugger can cope. */ >>> + bound solo, and hope the debugger can cope. >>> + >>> + For C and C++, if upper is NULL, this may be a zero-length array >>> + or a flexible array; we'd like to be able to distinguish between >>> + the two. Set DW_AT_count to 0 for the former. TYPE_SIZE is NULL >>> + for the latter. */ >>> > I found inserting this comment here confusing, I've moved it down and > shortened it. > >>> if (!get_AT (subrange_die, DW_AT_lower_bound)) >>> add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL); >>> - if (upper && !get_AT (subrange_die, DW_AT_upper_bound)) >>> - add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL); >>> + if (!get_AT (subrange_die, DW_AT_upper_bound) >>> + && !get_AT (subrange_die, DW_AT_count)) >>> + { >>> + if (upper) >>> + add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL); >>> + else if ((is_c () || is_cxx ()) && TYPE_SIZE (type)) >>> + add_bound_info (subrange_die, DW_AT_count, >>> + build_int_cst (TREE_TYPE (lower), 0), NULL); >>> + } >>> } >>> >>> /* Otherwise we have an array type with an unspecified length. The >> Ping. Does this version look okay for trunk? >> > Looks ok to me (but I can't approve). > > Also, I've added a testcase. > > OK for trunk? >
Ping. Thanks, - Tom > > > 0001-debug-DWARF-add-DW_AT_count-to-zero-length-arrays.patch > > [debug] DWARF: add DW_AT_count to zero-length arrays > > 2018-09-04 Omar Sandoval <osan...@osandov.com> > Tom de Vries <tdevr...@suse.de> > > PR debug/86985 > * dwarf2out.c (is_c): New function. > (add_subscript_info): Add DW_AT_count of 0 for C zero-length arrays. > > * gcc.dg/guality/zero-length-array.c: New test. > > --- > gcc/dwarf2out.c | 26 > ++++++++++++++++++++++-- > gcc/testsuite/gcc.dg/guality/zero-length-array.c | 21 +++++++++++++++++++ > 2 files changed, 45 insertions(+), 2 deletions(-) > > diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c > index 77317ed2575..58c3906cdbf 100644 > --- a/gcc/dwarf2out.c > +++ b/gcc/dwarf2out.c > @@ -3679,6 +3679,7 @@ static const char *get_AT_string (dw_die_ref, enum > dwarf_attribute); > static int get_AT_flag (dw_die_ref, enum dwarf_attribute); > 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_c (void); > static bool is_cxx (void); > static bool is_cxx (const_tree); > static bool is_fortran (void); > @@ -5442,6 +5443,19 @@ get_AT_file (dw_die_ref die, enum dwarf_attribute > attr_kind) > return a ? AT_file (a) : NULL; > } > > +/* Return TRUE if the language is C. */ > + > +static inline bool > +is_c (void) > +{ > + unsigned int lang = get_AT_unsigned (comp_unit_die (), DW_AT_language); > + > + return (lang == DW_LANG_C || lang == DW_LANG_C89 || lang == DW_LANG_C99 > + || lang == DW_LANG_C11 || lang == DW_LANG_ObjC); > + > + > +} > + > /* Return TRUE if the language is C++. */ > > static inline bool > @@ -20952,8 +20966,16 @@ add_subscript_info (dw_die_ref type_die, tree type, > bool collapse_p) > > if (!get_AT (subrange_die, DW_AT_lower_bound)) > add_bound_info (subrange_die, DW_AT_lower_bound, lower, NULL); > - if (upper && !get_AT (subrange_die, DW_AT_upper_bound)) > - add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL); > + if (!get_AT (subrange_die, DW_AT_upper_bound) > + && !get_AT (subrange_die, DW_AT_count)) > + { > + if (upper) > + add_bound_info (subrange_die, DW_AT_upper_bound, upper, NULL); > + else if ((is_c () || is_cxx ()) && TYPE_SIZE (type)) > + /* Zero-length array. */ > + add_bound_info (subrange_die, DW_AT_count, > + build_int_cst (TREE_TYPE (lower), 0), NULL); > + } > } > > /* Otherwise we have an array type with an unspecified length. The > diff --git a/gcc/testsuite/gcc.dg/guality/zero-length-array.c > b/gcc/testsuite/gcc.dg/guality/zero-length-array.c > new file mode 100644 > index 00000000000..33f34d98ac2 > --- /dev/null > +++ b/gcc/testsuite/gcc.dg/guality/zero-length-array.c > @@ -0,0 +1,21 @@ > +/* PR debug/86985 */ > +/* { dg-do run } */ > +/* { dg-options "-g" } */ > + > +struct { > + int foo; > + int bar[0]; > +} zla; /* Zero length array. */ > + > +struct { > + int foo; > + int bar[]; > +} fam; /* Flexible array member. */ > + > +int > +main () > +{ > + /* { dg-final { gdb-test . "type:zla" "struct { int foo; int bar[0]; }" } > } */ > + /* { dg-final { gdb-test . "type:fam" "struct { int foo; int bar[]; }" } } > */ > + return 0; > +} >