The following patch is based on and extends the guality test from my earlier "Pass type modifiers as flags arguments. Add guality type test." patch.
gcc/ChangeLog PR debug/59051 * dwarf2out.h (enum dw_mod_flag): Add dw_mod_restrict. * dwarf2out.c (dw_mod_decl_flags): Handle TYPE_RESTRICT. (dw_mod_type_flags): Likewise. (dw_mods_to_quals): New function. (dw_mod_qualified_type): Likewise. (modified_type_die): Handle dw_mod_restrict. gcc/testsuite/ChangeLog PR debug/59051 * gcc.dg/guality/restrict.c: New test. --- gcc/ChangeLog | 10 ++++ gcc/dwarf2out.c | 76 +++++++++++++++++++++++++----- gcc/dwarf2out.h | 1 + gcc/testsuite/ChangeLog | 4 ++ gcc/testsuite/gcc.dg/guality/restrict.c | 48 +++++++++++++++++++ 5 files changed, 126 insertions(+), 13 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/guality/restrict.c diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 4dfd9a5..06a8767 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,15 @@ 2014-06-20 Mark Wielaard <m...@redhat.com> + PR debug/59051 + * dwarf2out.h (enum dw_mod_flag): Add dw_mod_restrict. + * dwarf2out.c (dw_mod_decl_flags): Handle TYPE_RESTRICT. + (dw_mod_type_flags): Likewise. + (dw_mods_to_quals): New function. + (dw_mod_qualified_type): Likewise. + (modified_type_die): Handle dw_mod_restrict. + +2014-06-20 Mark Wielaard <m...@redhat.com> + * dwarf2out.h (enum dw_mod_flag): New enum. * dwarf2out.c (dw_mod_decl_flags): New function. (dw_mod_type_flags): Likewise. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 3d3508d..b99d1b9 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -10504,14 +10504,52 @@ static int dw_mod_decl_flags (const_tree decl) { return ((TREE_READONLY (decl) ? dw_mod_const : dw_mod_none) - | (TREE_THIS_VOLATILE (decl) ? dw_mod_volatile : dw_mod_none)); + | (TREE_THIS_VOLATILE (decl) ? dw_mod_volatile : dw_mod_none) + | ((POINTER_TYPE_P (TREE_TYPE (decl)) + && TYPE_RESTRICT (TREE_TYPE (decl))) + ? dw_mod_restrict : dw_mod_none)); } static int dw_mod_type_flags (const_tree type) { return ((TYPE_READONLY (type) ? dw_mod_const : dw_mod_none) - | (TYPE_VOLATILE (type) ? dw_mod_volatile : dw_mod_none)); + | (TYPE_VOLATILE (type) ? dw_mod_volatile : dw_mod_none) + | ((POINTER_TYPE_P (type) && TYPE_RESTRICT (type)) + ? dw_mod_restrict : dw_mod_none)); +} + +static int +dw_mods_to_quals (int mods) +{ + return (((mods & dw_mod_const) ? TYPE_QUAL_CONST : 0) + | ((mods & dw_mod_volatile) ? TYPE_QUAL_VOLATILE : 0) + | ((mods & dw_mod_restrict) ? TYPE_QUAL_RESTRICT : 0)); +} + +/* Returns true if there is a qualified type with at least one + modifier given in mods. Returns false if mods == dw_mod_none or + there is no qualified type with at least one of the given mods. */ + +static bool +dw_mod_qualified_type (tree type, int mods) +{ + if (mods == dw_mod_none) + return false; + + if (get_qualified_type (type, dw_mods_to_quals (mods)) != NULL_TREE) + return true; + + if (mods & dw_mod_const) + return dw_mod_qualified_type (type, mods & ~dw_mod_const); + + if (mods & dw_mod_volatile) + return dw_mod_qualified_type (type, mods & ~dw_mod_volatile); + + if (mods & dw_mod_restrict) + return dw_mod_qualified_type (type, mods & ~dw_mod_restrict); + + gcc_unreachable (); } /* Given a pointer to an arbitrary ..._TYPE tree node, return a debugging @@ -10531,13 +10569,15 @@ modified_type_die (tree type, int mods, dw_die_ref context_die) if (code == ERROR_MARK) return NULL; + /* Don't emit DW_TAG_restrict_type for DWARFv2, since it is a type + tag modifier (and not an attribute) old consumers won't be able + to handle it. */ + if (dwarf_version < 3) + mods &= ~dw_mod_restrict; + /* See if we already have the appropriately qualified variant of this type. */ - qualified_type - = get_qualified_type (type, (((mods & dw_mod_const) - ? TYPE_QUAL_CONST : 0) - | ((mods & dw_mod_volatile) - ? TYPE_QUAL_VOLATILE : 0))); + qualified_type = get_qualified_type (type, dw_mods_to_quals (mods)); if (qualified_type == sizetype && TYPE_NAME (qualified_type) @@ -10577,8 +10617,10 @@ modified_type_die (tree type, int mods, dw_die_ref context_die) } else if ((mods & dw_mod_const) < TYPE_READONLY (dtype) || (mods & dw_mod_volatile) < TYPE_VOLATILE (dtype) + || (mods & dw_mod_restrict) < TYPE_RESTRICT (dtype) || ((mods & dw_mod_const) <= TYPE_READONLY (dtype) && (mods & dw_mod_volatile) <= TYPE_VOLATILE (dtype) + && (mods & dw_mod_restrict) <= TYPE_RESTRICT (dtype) && DECL_ORIGINAL_TYPE (name) != type)) /* cv-unqualified version of named type. Just use the unnamed type to which it refers. */ @@ -10590,20 +10632,28 @@ modified_type_die (tree type, int mods, dw_die_ref context_die) mod_scope = scope_die_for (type, context_die); if ((mods & dw_mod_const) - /* If both const_type and volatile_type, prefer the path - which leads to a qualified type. */ - && (!(mods & dw_mod_volatile) - || get_qualified_type (type, TYPE_QUAL_CONST) == NULL_TREE - || get_qualified_type (type, TYPE_QUAL_VOLATILE) != NULL_TREE)) + /* If there are multiple type modifiers, prefer a path which + leads to a qualified type. */ + && (((mods & ~dw_mod_const) == dw_mod_none) + || get_qualified_type (type, dw_mods_to_quals (mods)) == NULL_TREE + || dw_mod_qualified_type (type, mods & ~dw_mod_const))) { mod_type_die = new_die (DW_TAG_const_type, mod_scope, type); sub_die = modified_type_die (type, mods & ~dw_mod_const, context_die); } - else if (mods & dw_mod_volatile) + else if ((mods & dw_mod_volatile) + && (((mods & ~dw_mod_volatile) == dw_mod_none) + || get_qualified_type (type, dw_mods_to_quals (mods)) == NULL_TREE + || dw_mod_qualified_type (type, mods & ~dw_mod_volatile))) { mod_type_die = new_die (DW_TAG_volatile_type, mod_scope, type); sub_die = modified_type_die (type, mods & ~dw_mod_volatile, context_die); } + else if (mods & dw_mod_restrict) + { + mod_type_die = new_die (DW_TAG_restrict_type, mod_scope, type); + sub_die = modified_type_die (type, mods & ~dw_mod_restrict, context_die); + } else if (code == POINTER_TYPE) { mod_type_die = new_die (DW_TAG_pointer_type, mod_scope, type); diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index e7de4f8..7c109ea 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -50,6 +50,7 @@ enum dw_cfi_oprnd_type { modified_type_die () to chain a base type. */ enum dw_mod_flag { dw_mod_none = 0, + dw_mod_restrict = 1, dw_mod_const = 1 << 1, dw_mod_volatile = 1 << 2 }; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 1a94e1b..9c5418c 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,9 @@ 2014-06-20 Mark Wielaard <m...@redhat.com> + * gcc.dg/guality/restrict.c: New test. + +2014-06-20 Mark Wielaard <m...@redhat.com> + * lib/gcc-gdb-test.exp (gdb-test): Handle type:var for gdb ptype matching. * gcc/testsuite/gcc.dg/guality/const-volatile.c: New test. diff --git a/gcc/testsuite/gcc.dg/guality/restrict.c b/gcc/testsuite/gcc.dg/guality/restrict.c new file mode 100644 index 0000000..aba30b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/guality/restrict.c @@ -0,0 +1,48 @@ +/* debuginfo tests for combinations of const, volatile, restrict pointers. */ +/* { dg-do run } */ +/* { dg-options "-std=c99 -g" } */ + +int *ip; +const int *cip; +int * restrict irp; +int * const icp; +const int * restrict cirp; +int * const restrict icrp; +const int * const restrict cicrp; + +int * const volatile restrict cvirp; +const volatile int * restrict pcvir; + +static __attribute__((noclone, noinline)) void * +cpy (void * restrict s1, const void * restrict s2, unsigned int n) +{ + char *t1 = s1; + const char *t2 = s2; + while(n-- > 0) + *t1++ = *t2++; + return s1; +} + +int +main (int argc, char **argv) +{ + void *foo = 0; + if (argc > 16) + foo = cpy (argv[0], argv[1], argc); + + return foo != 0; +} + +/* { dg-final { gdb-test 30 "type:ip" "int *" } } */ +/* { dg-final { gdb-test 30 "type:cip" "const int *" } } */ +/* { dg-final { gdb-test 30 "type:irp" "int * restrict" } } */ +/* { dg-final { gdb-test 30 "type:icp" "int * const" } } */ +/* { dg-final { gdb-test 30 "type:cirp" "const int * restrict" } } */ +/* { dg-final { gdb-test 30 "type:icrp" "int * const restrict" } } */ +/* { dg-final { gdb-test 30 "type:cicrp" "const int * const restrict" } } */ + +/* { dg-final { gdb-test 30 "type:cvirp" "int * const volatile restrict" } } */ +/* { dg-final { gdb-test 30 "type:pcvir" "const volatile int * restrict" } } */ + +/* { dg-final { gdb-test 30 "type:main" "int (int, char **)" } } */ +/* { dg-final { gdb-test 30 "type:cpy" "void *(void * restrict, const void * restrict, unsigned int)" } } */ -- 1.7.1