This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3


Many thanks for your feedback on the proposal and the patch.
As you said, the feature should be available only for -std=c2x. I will look
into this how can it be done.
As you also said, we need some more extensive test coverage. Here is one
example I tried to make for invalid use of _Dependent_ptr.

/* Test for _Dependent_ptr. _Dependent_ptr qualified pointer initialization
tests. */
/* { dg-do compile } */
/* { dg-options "-pedantic-errors" } */

typedef __SIZE_TYPE__ size_t;
extern void exit (int);

#define TEST_SIMPLE_DECLARE(TYPE)           \
  do                   \
    {                 \
      TYPE _Dependent_ptr p; /* { dg-error " invalid use of
'_Dependent_ptr'" } */       \
    }                                                             \
  while (0)

#define TEST_SIMPLE_DECLARE_VARIABLE()           \
  do                                                               \
    {                                                             \
      TEST_SIMPLE_DECLARE (_Bool);         \
      TEST_SIMPLE_DECLARE (char);           \
      TEST_SIMPLE_DECLARE (signed char);         \
      TEST_SIMPLE_DECLARE (unsigned char);       \
      TEST_SIMPLE_DECLARE (signed short);         \
      TEST_SIMPLE_DECLARE (unsigned short);         \
      TEST_SIMPLE_DECLARE (signed int);           \
      TEST_SIMPLE_DECLARE (unsigned int);         \
      TEST_SIMPLE_DECLARE (signed long);         \
      TEST_SIMPLE_DECLARE (unsigned long);       \
      TEST_SIMPLE_DECLARE (signed long long);         \
      TEST_SIMPLE_DECLARE (unsigned long long);         \
      TEST_SIMPLE_DECLARE (float);         \
      TEST_SIMPLE_DECLARE (double);           \
      TEST_SIMPLE_DECLARE (long double);         \
      TEST_SIMPLE_DECLARE (_Complex float);         \
      TEST_SIMPLE_DECLARE (_Complex double);       \
      TEST_SIMPLE_DECLARE (_Complex long double);       \
     }                 \
  while (0)

static void
test_simple_declare (void)
{
  TEST_SIMPLE_DECLARE_VARIABLE ();
}

int main (void)
{
  test_simple_declare ();
  exit (0);
}
Let me know if this is what you want to see.
For function pointers, I am not sure how this qualifier should behave. But,
as you said, indeed the code for rejecting invalid _Dependent_ptr
declarations allows the function pointers usage. I have made one example as
shown, also let me know if this looks correct:

#include "../gcc/gcc/ginclude/stddef.h"
#include "../gcc/gcc/ginclude/stdatomic.h"

typedef __SIZE_TYPE__ size_t;
extern void abort (void);
extern void exit (int);
extern void *malloc (size_t);
extern int assert ();

_Atomic void (*fp)();
int count = 0;

#define rcu_assign_pointer(p,v)		\
  atomic_store_explicit(&(p), (v), memory_order_release);

#define rcu_dereference(p) 		\
  atomic_load_explicit(&(p), memory_order_consume);

void my_function(){
  count++;
}

void thread0 ()

{

	rcu_assign_pointer(fp, &my_function);
}

void thread1 ()
{
	 void (* _Dependent_ptr p)();
	p = rcu_dereference(fp);
	if (p)
	  (*p)();
}

 I will try to make some new test cases for the conversions between
different qualifiers, starting with the list provided by Paul and looking
over the test cases made for other qualifiers and let you guys know.
In example p0190r4_fig10.c, the dg-warning directives are used to suppress
the warnings issues which compiler gives when the assignment is between
incompatible pointer types. These warnings are not our main tests. The main
test is to see if the declarations are defined properly and the statements
with dependency have not changed or reordered (what I think).
rcu_assign_pointer() does not starts the dependency. The dependency starts
from the first assignment like

struct rcutest * _Dependent_ptr p = rcu_dereference(gp);

and the latter references made to variable p should not be reordered or
being replaced by the other variables that may break the user intended
dependency chain. Making p _Dependent_ptr qualified ensures that. Also,
rcu_dereference() is atomic_load_explicit() and rcu_assign_pointer is
atomic_store_explicit.
Kindly, let me know if that makes sense to you.

Akshat

On Sat, Aug 3, 2019 at 8:00 AM Martin Sebor <msebor@gmail.com> wrote:

> On 8/1/19 9:26 AM, Paul McKenney wrote:
> > Excellent point, this discussion needs to be made official.
> > Please see attached for an initial draft of a working paper.
> >
> > Thoughts?
>
> The draft is a start but it (obviously) needs a lot of work to cover
> the constraints and semantics so I'll just comment on the patch in
> a bit more detail.
>
> Since the feature is being (or will be) proposed to WG14 and could
> change I would expect it to be only available under -std=c2x and
> disabled otherwise, so that code that makes use of it does so with
> the understanding that it's only experimental.  (I just noticed
> Akshat email with a tweak to the patch.  I'm not sure that issuing
> a pedantic warning and having the name in the implementation namepace
> is enough but others (the C FE maintainers) will know better.)
>
> Other than that, I would also expect to see more extensive test
> coverage, at a minimum to exercise error detection (invalid uses,
> conversions, etc.).  For example, I see the code that rejects it
> but no tests for declaring, say, a _Dependent_ptr-qualified integer.
> What I don't think I see is code that rejects _Dependent_ptr-qualified
> function pointers (AFAIK, POINTER_TYPE_P evaluates to nonzero for both).
> Is that intended?  (And if so, what does it mean?)    I also see that
> the new tests look for warnings but it's not clear to me that that's
> their intent or that the dg-warning directives are being used to
> "suppress" warnings for issues in the tests.  For instance, this
> is common:
>
>    rcu_assign_pointer (gp,p);           /* { dg-warning
> "\\\[-Wincompatible-pointer-types]" } */
>
> but neither gp nor p is a  _Dependent_ptr.  (I may be missing
> the purpose of the compile-only tests.  E.g., the only thing
> p0190r4_fig10.c seems to be exercising besides that the _Dependent_ptr
> qualifier is accepted is a couple of warnings, one of which is the one
> above.)  I would suggest to look at tests for other qualifiers for
> examples and model the new ones after those.
>
> I'm also wondering how the new qualifier interacts with others like
> const.  Should all combinations of qualifiers be accepted and do
> they affect the semantics in any interesting way?  This is probably
> something to cover in the proposal.
>
> Martin
>
> >
> >                                           Thanx, Paul
> >
> > On Tue, Jul 30, 2019 at 12:46 PM Martin Sebor <msebor@gmail.com> wrote:
> >>
> >> On 7/30/19 1:13 AM, Akshat Garg wrote:
> >>> Hi,
> >>> This patch includes C front-end code for a type qualifier
> _Dependent_ptr.
> >>
> >> Just some very high-level comments/questions.  I only followed
> >> the _Dependent_ptr discussion from a distance and I'm likely
> >> missing some context so the first thing I looked for in this
> >> patch is documentation of the new qualifier.  Unless it's
> >> a proposed C2x feature that I missed I would expect to find it
> >> in section 6 - Extensions to the C Language Family of the manual.
> >> I saw the references to WG21's p0190r4 in the tests but the paper
> >> doesn't mention _Dependent_ptr, and I found no references to a C
> >> paper that does.  If it has been proposed for C2X as well can
> >> you point to it?  (In that case, or if a proposal is planned,
> >> the feature should probably either only be available with
> >> -std=c2x and -std=gnu2x or a pedantic warning should be issued
> >> for its use in earlier modes similarly to how uses of _Atomic
> >> are diagnosed in pre-C11 modes.)
> >>
> >> Martin
> >>
> >>> The patch has been tested using the following
> >>> make bootstrap -j 4
> >>> make -k check -j 4
> >>>
> >>> on x86_64-linux-gnu.
> >>>
> >>> Thanks,
> >>> Akshat
> >>>
> >>> gcc/ChangeLog:
> >>>
> >>> 2019-07-30  Akshat Garg <xkspr7@gmail.com>
> >>>
> >>>           * c-family/c-common.c (struct c_common_resword
> c_common_reswords):
> >>> Add "_Dependent_ptr".
> >>>           (c_apply_type_quals_to_decl): Set the flag for
> _Dependent_ptr if
> >>> qualified.
> >>>           (keyword_is_type_qualifier): Add RID_DEPENDENT_PTR.
> >>>           * c-family/c-common.h (enum rid): Add RID_DEPENDENT_PTR.
> >>>           * c-family/c-format.c (check_format_types): Add dependent
> pointer
> >>> as a qualifier check.
> >>>           * c-family/c-pretty-print.c (pp_c_cv_qualifiers): Handle
> dependent
> >>> pointer qualifier.
> >>>           * c/c-aux-info.c (gen_type): Handle dependent pointer
> qualifier.
> >>>           (gen_decl): Handle dependent pointer qualifier.
> >>>           * c/c-decl.c (merge_decls): Set old declaration as having
> dependent
> >>> pointer qualification if new declaration has one.
> >>>           (shadow_tag_warned): Add dependent_ptr_p to declspecs check.
> >>>           (quals_from_declspecs): Add dependent_ptr_p to declspecs
> check.
> >>>           (grokdeclarator): Add checks for dependent pointer qualifier
> and
> >>> warn of duplicate or errors. Allow dependent pointer for pointer types
> only.
> >>>           * c/c-parser.c (c_keyword_starts_typename,
> c_token_is_qualifier,
> >>> c_token_starts_declspecs): Add RID_DEPENDENT_PTR.
> >>>           (c_parser_static_assert_declaration_no_semi): Add
> _Dependent_ptr
> >>> qualifier in comments.
> >>>           (c_parser_declspecs, c_parser_attribute_any_word): Add
> >>> RID_DEPENDENT_PTR.
> >>>           * c/c-tree.h (C_TYPE_FIELDS_DEPENDENT_PTR): New macro to mark
> >>> dependent pointer.
> >>>           (enum c_declspec_word): Add cdw_dependent_ptr.
> >>>           (struct c_declspecs): Add dependent_ptr_p field.
> >>>           * print-tree.c (print_node): Print dependent_ptr qualifier.
> >>>           * tree-core.hi (enum cv_qualifier): Add
> TYPE_QUAL_DEPENDENT_PTR.
> >>>           (enum tree_index): Add TI_DEPENDENT_PTR_TYPE.
> >>>           (struct tree_base): Add dependent_ptr_flag field.
> >>>           * tree-pretty-print.c (dump_generic_node): Print dependent
> pointer
> >>> type qualifier.
> >>>           * tree.c (fld_type_variant, set_type_quals): Set
> TYPE_DEPENDENT_PTR.
> >>>           * tree.h (TREE_THIS_DEPENDENT_PTR): New macro. To access
> >>> dependent_ptr_flag field in tree_base.
> >>>           (TYPE_DEPENDENT_PTR): New accessor macro.
> >>>           (TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add
> TYPE_QUAL_DEPENDENT_PTR.
> >>>           (dependent_ptrTI_type_node): Add new type node.
> >>>
> >>> gcc/testsuite/ChangeLog:
> >>>
> >>> 2019-07-30  Akshat Garg <xkspr7@gmail.com>
> >>>
> >>>           * gcc.dg/c11-dependent_ptr-test-1.c: New test for
> _Dependent_ptr
> >>> qualifier.
> >>>           * gcc.dg/{p0190r4_fig8, p0190r4_fig9, p0190r4_fig10,
> p0190r4_fig11,
> >>> p0190r4_fig12, p0190r4_fig13}.c: New tests from document P0190R4 for
> >>> _Dependent_ptr qualifier.
> >>>
> >>> diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
> >>> index cb92710..4f09037 100644
> >>> --- a/gcc/c-family/c-common.c
> >>> +++ b/gcc/c-family/c-common.c
> >>> @@ -345,6 +345,7 @@ const struct c_common_resword c_common_reswords[] =
> >>>      { "_Alignas", RID_ALIGNAS,   D_CONLY },
> >>>      { "_Alignof", RID_ALIGNOF,   D_CONLY },
> >>>      { "_Atomic", RID_ATOMIC,    D_CONLY },
> >>> + { "_Dependent_ptr",   RID_DEPENDENT_PTR,  0 },
> >>>      { "_Bool", RID_BOOL,      D_CONLY },
> >>>      { "_Complex", RID_COMPLEX, 0 },
> >>>      { "_Imaginary", RID_IMAGINARY, D_CONLY },
> >>> @@ -3546,6 +3547,11 @@ c_apply_type_quals_to_decl (int type_quals, tree
> >>> decl)
> >>>          TREE_SIDE_EFFECTS (decl) = 1;
> >>>          TREE_THIS_VOLATILE (decl) = 1;
> >>>        }
> >>> +  if (type_quals & TYPE_QUAL_DEPENDENT_PTR)
> >>> +    {
> >>> +      TREE_SIDE_EFFECTS (decl) = 1;
> >>> +      TREE_THIS_DEPENDENT_PTR (decl) = 1;
> >>> +    }
> >>>      if (type_quals & TYPE_QUAL_RESTRICT)
> >>>        {
> >>>          while (type && TREE_CODE (type) == ARRAY_TYPE)
> >>> @@ -7851,6 +7857,7 @@ keyword_is_type_qualifier (enum rid keyword)
> >>>        case RID_VOLATILE:
> >>>        case RID_RESTRICT:
> >>>        case RID_ATOMIC:
> >>> +    case RID_DEPENDENT_PTR:
> >>>          return true;
> >>>        default:
> >>>          return false;
> >>> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> >>> index 117d729..ab55882 100644
> >>> --- a/gcc/c-family/c-common.h
> >>> +++ b/gcc/c-family/c-common.h
> >>> @@ -68,7 +68,7 @@ enum rid
> >>>      RID_UNSIGNED, RID_LONG,    RID_CONST, RID_EXTERN,
> >>>      RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
> >>>      RID_VOLATILE, RID_SIGNED,  RID_AUTO,  RID_RESTRICT,
> >>> -  RID_NORETURN, RID_ATOMIC,
> >>> +  RID_NORETURN, RID_ATOMIC, RID_DEPENDENT_PTR,
> >>>
> >>>      /* C extensions */
> >>>      RID_COMPLEX, RID_THREAD, RID_SAT,
> >>> diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
> >>> index d134116..00769bb 100644
> >>> --- a/gcc/c-family/c-format.c
> >>> +++ b/gcc/c-family/c-format.c
> >>> @@ -4172,6 +4172,7 @@ check_format_types (const substring_loc &fmt_loc,
> >>>      && (TYPE_READONLY (cur_type)
> >>>          || TYPE_VOLATILE (cur_type)
> >>>          || TYPE_ATOMIC (cur_type)
> >>> +      || TYPE_DEPENDENT_PTR (cur_type)
> >>>          || TYPE_RESTRICT (cur_type)))
> >>>     warning (OPT_Wformat_, "extra type qualifiers in format "
> >>>     "argument (argument %d)",
> >>> diff --git a/gcc/c-family/c-pretty-print.c
> b/gcc/c-family/c-pretty-print.c
> >>> index 3e25624..e034a8f 100644
> >>> --- a/gcc/c-family/c-pretty-print.c
> >>> +++ b/gcc/c-family/c-pretty-print.c
> >>> @@ -181,6 +181,8 @@ pp_c_cv_qualifiers (c_pretty_printer *pp, int
> >>> qualifiers, bool func_type)
> >>>
> >>>      if (qualifiers & TYPE_QUAL_ATOMIC)
> >>>        pp_c_ws_string (pp, "_Atomic");
> >>> +  if (qualifiers & TYPE_QUAL_DEPENDENT_PTR)
> >>> +    pp_c_ws_string (pp, "_Dependent_ptr");
> >>>      if (qualifiers & TYPE_QUAL_CONST)
> >>>        pp_c_ws_string (pp, func_type ? "__attribute__((const))" :
> "const");
> >>>      if (qualifiers & TYPE_QUAL_VOLATILE)
> >>> diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
> >>> index 96bb2e2..514093c 100644
> >>> --- a/gcc/c/c-aux-info.c
> >>> +++ b/gcc/c/c-aux-info.c
> >>> @@ -284,6 +284,8 @@ gen_type (const char *ret_val, tree t,
> formals_style
> >>> style)
> >>>     case POINTER_TYPE:
> >>>      if (TYPE_ATOMIC (t))
> >>>        ret_val = concat ("_Atomic ", ret_val, NULL);
> >>> +  if (TYPE_DEPENDENT_PTR (t))
> >>> +    ret_val = concat ("_Dependent_ptr ", ret_val, NULL);
> >>>      if (TYPE_READONLY (t))
> >>>        ret_val = concat ("const ", ret_val, NULL);
> >>>      if (TYPE_VOLATILE (t))
> >>> @@ -427,6 +429,8 @@ gen_type (const char *ret_val, tree t,
> formals_style
> >>> style)
> >>>        }
> >>>      if (TYPE_ATOMIC (t))
> >>>        ret_val = concat ("_Atomic ", ret_val, NULL);
> >>> +  if (TYPE_DEPENDENT_PTR (t))
> >>> +    ret_val = concat ("_Dependent_ptr ", ret_val, NULL);
> >>>      if (TYPE_READONLY (t))
> >>>        ret_val = concat ("const ", ret_val, NULL);
> >>>      if (TYPE_VOLATILE (t))
> >>> @@ -474,6 +478,8 @@ gen_decl (tree decl, int is_func_definition,
> >>> formals_style style)
> >>>        ret_val = concat ("volatile ", ret_val, NULL);
> >>>      if (TREE_READONLY (decl))
> >>>        ret_val = concat ("const ", ret_val, NULL);
> >>> +  if (TREE_THIS_DEPENDENT_PTR (decl))
> >>> +    ret_val = concat ("dependent_ptr ", ret_val, NULL);
> >>>
> >>>      data_type = "";
> >>>
> >>> diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
> >>> index f85f481..2047575 100644
> >>> --- a/gcc/c/c-decl.c
> >>> +++ b/gcc/c/c-decl.c
> >>> @@ -2587,6 +2587,9 @@ merge_decls (tree newdecl, tree olddecl, tree
> >>> newtype, tree oldtype)
> >>>      if (TREE_THIS_VOLATILE (newdecl))
> >>>        TREE_THIS_VOLATILE (olddecl) = 1;
> >>>
> >>> +  if (TREE_THIS_DEPENDENT_PTR (newdecl))
> >>> +    TREE_THIS_DEPENDENT_PTR (olddecl) = 1;
> >>> +
> >>>      /* Merge deprecatedness.  */
> >>>      if (TREE_DEPRECATED (newdecl))
> >>>        TREE_DEPRECATED (olddecl) = 1;
> >>> @@ -2638,6 +2641,7 @@ merge_decls (tree newdecl, tree olddecl, tree
> >>> newtype, tree oldtype)
> >>>      DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
> >>>        |= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
> >>>      TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
> >>> +  TREE_THIS_DEPENDENT_PTR (newdecl) |= TREE_THIS_DEPENDENT_PTR
> (olddecl);
> >>>      DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
> >>>      if (DECL_IS_OPERATOR_NEW_P (olddecl))
> >>>        DECL_SET_IS_OPERATOR_NEW (newdecl, true);
> >>> @@ -4544,6 +4548,7 @@ shadow_tag_warned (const struct c_declspecs
> >>> *declspecs, int warned)
> >>>       && (declspecs->const_p
> >>>           || declspecs->volatile_p
> >>>           || declspecs->atomic_p
> >>> +       || declspecs->dependent_ptr_p
> >>>           || declspecs->restrict_p
> >>>           || declspecs->address_space))
> >>>        {
> >>> @@ -4672,6 +4677,7 @@ quals_from_declspecs (const struct c_declspecs
> *specs)
> >>>           | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
> >>>           | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
> >>>           | (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
> >>> +       | (specs->dependent_ptr_p ? TYPE_QUAL_DEPENDENT_PTR : 0)
> >>>           | (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
> >>>      gcc_assert (!specs->type
> >>>          && !specs->decl_attr
> >>> @@ -5837,6 +5843,7 @@ grokdeclarator (const struct c_declarator
> *declarator,
> >>>      int restrictp;
> >>>      int volatilep;
> >>>      int atomicp;
> >>> +  int dependent_ptrp;
> >>>      int type_quals = TYPE_UNQUALIFIED;
> >>>      tree name = NULL_TREE;
> >>>      bool funcdef_flag = false;
> >>> @@ -6003,6 +6010,7 @@ grokdeclarator (const struct c_declarator
> *declarator,
> >>>      restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
> >>>      volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
> >>>      atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
> >>> +  dependent_ptrp = declspecs->dependent_ptr_p + TYPE_DEPENDENT_PTR
> >>> (element_type);
> >>>      as1 = declspecs->address_space;
> >>>      as2 = TYPE_ADDR_SPACE (element_type);
> >>>      address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
> >>> @@ -6015,6 +6023,8 @@ grokdeclarator (const struct c_declarator
> *declarator,
> >>>        pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>");
> >>>      if (atomicp > 1)
> >>>        pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
> >>> +  if (dependent_ptrp > 1)
> >>> +    pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Dependent_ptr%>");
> >>>
> >>>      if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) &&
> as1 !=
> >>> as2)
> >>>        error_at (loc, "conflicting named address spaces (%s vs %s)",
> >>> @@ -6031,6 +6041,7 @@ grokdeclarator (const struct c_declarator
> *declarator,
> >>>     | (restrictp ? TYPE_QUAL_RESTRICT : 0)
> >>>     | (volatilep ? TYPE_QUAL_VOLATILE : 0)
> >>>     | (atomicp ? TYPE_QUAL_ATOMIC : 0)
> >>> + | (dependent_ptrp ? TYPE_QUAL_DEPENDENT_PTR : 0)
> >>>     | ENCODE_QUAL_ADDR_SPACE (address_space));
> >>>      if (type_quals != TYPE_QUALS (element_type))
> >>>        orig_qual_type = NULL_TREE;
> >>> @@ -6042,6 +6053,13 @@ grokdeclarator (const struct c_declarator
> >>> *declarator,
> >>>      if (declspecs->atomic_p && TREE_CODE (type) == ARRAY_TYPE)
> >>>        error_at (loc, "%<_Atomic%>-qualified array type");
> >>>
> >>> +  /* Applying the _Dependent_ptr qualifier to an array type (through
> >>> +     the use of typedefs or typeof) must be detected here.  If the
> >>> +     qualifier is introduced later, any appearance of applying it to
> >>> +     an array is actually applying it to an element of that array.  */
> >>> +  if (declspecs->dependent_ptr_p && TREE_CODE (type) == ARRAY_TYPE)
> >>> +    error_at (loc, "%<_Dependent_ptr%>-qualified array type");
> >>> +
> >>>      /* Warn about storage classes that are invalid for certain
> >>>         kinds of declarations (parameters, typenames, etc.).  */
> >>>
> >>> @@ -7214,6 +7232,10 @@ grokdeclarator (const struct c_declarator
> >>> *declarator,
> >>>     /* An uninitialized decl with `extern' is a reference.  */
> >>>     int extern_ref = !initialized && storage_class == csc_extern;
> >>>
> >>> + /* _Dependent_ptr qualifier only reserved for pointer type variable
> */
> >>> + if ((type_quals & TYPE_QUAL_DEPENDENT_PTR) && (!POINTER_TYPE_P
> (type)))
> >>> +  error_at (loc, "invalid use of %<_Dependent_ptr%>");
> >>> +
> >>>     type = c_build_qualified_type (type, type_quals, orig_qual_type,
> >>>           orig_qual_indirect);
> >>>
> >>> @@ -7294,7 +7316,7 @@ grokdeclarator (const struct c_declarator
> *declarator,
> >>>     DECL_REGISTER (decl) = 1;
> >>>          }
> >>>
> >>> -    /* Record constancy and volatility.  */
> >>> +    /* Record constancy, data dependency and volatility.  */
> >>>        c_apply_type_quals_to_decl (type_quals, decl);
> >>>
> >>>        /* Apply _Alignas specifiers.  */
> >>> @@ -8258,6 +8280,11 @@ finish_struct (location_t loc, tree t, tree
> >>> fieldlist, tree attributes,
> >>>          if (TREE_THIS_VOLATILE (x))
> >>>     C_TYPE_FIELDS_VOLATILE (t) = 1;
> >>>
> >>> +      /* Any field that is a dependent pointer means variables of this
> >>> + type must be treated in some ways as dependent pointer.  */
> >>> +      if (TREE_THIS_DEPENDENT_PTR (x))
> >>> + C_TYPE_FIELDS_DEPENDENT_PTR (t) = 1;
> >>> +
> >>>          /* Any field of nominal variable size implies structure is
> too.  */
> >>>          if (C_DECL_VARIABLE_SIZE (x))
> >>>     C_TYPE_VARIABLE_SIZE (t) = 1;
> >>> @@ -10177,6 +10204,12 @@ declspecs_add_qual (location_t loc,
> >>>          prev_loc = specs->locations[cdw_atomic];
> >>>          specs->locations[cdw_atomic] = loc;
> >>>          break;
> >>> +    case RID_DEPENDENT_PTR:
> >>> +      dupe = specs->dependent_ptr_p;
> >>> +      specs->dependent_ptr_p = true;
> >>> +      prev_loc = specs->locations[cdw_dependent_ptr];
> >>> +      specs->locations[cdw_dependent_ptr] = loc;
> >>> +      break;
> >>>        default:
> >>>          gcc_unreachable ();
> >>>        }
> >>> diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
> >>> index 6721049..35e25bb 100644
> >>> --- a/gcc/c/c-parser.c
> >>> +++ b/gcc/c/c-parser.c
> >>> @@ -503,6 +503,7 @@ c_keyword_starts_typename (enum rid keyword)
> >>>        case RID_TYPEOF:
> >>>        case RID_CONST:
> >>>        case RID_ATOMIC:
> >>> +    case RID_DEPENDENT_PTR:
> >>>        case RID_VOLATILE:
> >>>        case RID_RESTRICT:
> >>>        case RID_ATTRIBUTE:
> >>> @@ -606,6 +607,7 @@ c_token_is_qualifier (c_token *token)
> >>>     case RID_RESTRICT:
> >>>     case RID_ATTRIBUTE:
> >>>     case RID_ATOMIC:
> >>> + case RID_DEPENDENT_PTR:
> >>>      return true;
> >>>     default:
> >>>      return false;
> >>> @@ -687,6 +689,7 @@ c_token_starts_declspecs (c_token *token)
> >>>     case RID_SAT:
> >>>     case RID_ALIGNAS:
> >>>     case RID_ATOMIC:
> >>> + case RID_DEPENDENT_PTR:
> >>>     case RID_AUTO_TYPE:
> >>>      return true;
> >>>     default:
> >>> @@ -2575,6 +2578,7 @@ c_parser_static_assert_declaration_no_semi
> (c_parser
> >>> *parser)
> >>>         volatile
> >>>         address-space-qualifier
> >>>         _Atomic
> >>> +     _Dependent_ptr
> >>>
> >>>       (restrict is new in C99.)
> >>>       (_Atomic is new in C11.)
> >>> @@ -2865,6 +2869,11 @@ c_parser_declspecs (c_parser *parser, struct
> >>> c_declspecs *specs,
> >>>      else
> >>>        declspecs_add_qual (loc, specs, value);
> >>>      break;
> >>> + case RID_DEPENDENT_PTR:
> >>> +  attrs_ok = true;
> >>> +  declspecs_add_qual (loc, specs, c_parser_peek_token
> (parser)->value);
> >>> +  c_parser_consume_token (parser);
> >>> +  break;
> >>>     case RID_CONST:
> >>>     case RID_VOLATILE:
> >>>     case RID_RESTRICT:
> >>> @@ -4275,6 +4284,7 @@ c_parser_attribute_any_word (c_parser *parser)
> >>>     case RID_TRANSACTION_ATOMIC:
> >>>     case RID_TRANSACTION_CANCEL:
> >>>     case RID_ATOMIC:
> >>> + case RID_DEPENDENT_PTR:
> >>>     case RID_AUTO_TYPE:
> >>>     case RID_INT_N_0:
> >>>     case RID_INT_N_1:
> >>> diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
> >>> index dae2979..0e416f2 100644
> >>> --- a/gcc/c/c-tree.h
> >>> +++ b/gcc/c/c-tree.h
> >>> @@ -34,6 +34,9 @@ along with GCC; see the file COPYING3.  If not see
> >>>    /* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is
> volatile.
> >>>    */
> >>>    #define C_TYPE_FIELDS_VOLATILE(TYPE) TREE_LANG_FLAG_2 (TYPE)
> >>>
> >>> +/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is
> dependent
> >>> pointer.  */
> >>> +#define C_TYPE_FIELDS_DEPENDENT_PTR(TYPE) TREE_LANG_FLAG_3 (TYPE)
> >>> +
> >>>    /* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
> >>>       nonzero if the definition of the type has already started.  */
> >>>    #define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
> >>> @@ -279,6 +282,7 @@ enum c_declspec_word {
> >>>      cdw_volatile,
> >>>      cdw_restrict,
> >>>      cdw_atomic,
> >>> +  cdw_dependent_ptr,
> >>>      cdw_saturating,
> >>>      cdw_alignas,
> >>>      cdw_address_space,
> >>> @@ -387,6 +391,8 @@ struct c_declspecs {
> >>>      BOOL_BITFIELD restrict_p : 1;
> >>>      /* Whether "_Atomic" was specified.  */
> >>>      BOOL_BITFIELD atomic_p : 1;
> >>> +  /* Whether "_Dependent_ptr" was specified.  */
> >>> +  BOOL_BITFIELD dependent_ptr_p : 1;
> >>>      /* Whether "_Sat" was specified.  */
> >>>      BOOL_BITFIELD saturating_p : 1;
> >>>      /* Whether any alignment specifier (even with zero alignment) was
> >>> diff --git a/gcc/print-tree.c b/gcc/print-tree.c
> >>> index debea2b..ec4e3db 100644
> >>> --- a/gcc/print-tree.c
> >>> +++ b/gcc/print-tree.c
> >>> @@ -348,6 +348,8 @@ print_node (FILE *file, const char *prefix, tree
> node,
> >>> int indent,
> >>>        fputs (" addressable", file);
> >>>      if (TREE_THIS_VOLATILE (node))
> >>>        fputs (" volatile", file);
> >>> +  if (TREE_THIS_DEPENDENT_PTR (node))
> >>> +    fputs (" dependent_ptr", file);
> >>>      if (TREE_ASM_WRITTEN (node))
> >>>        fputs (" asm_written", file);
> >>>      if (TREE_USED (node))
> >>> diff --git a/gcc/tree-core.h b/gcc/tree-core.h
> >>> index 60d8c68..3f3e682 100644
> >>> --- a/gcc/tree-core.h
> >>> +++ b/gcc/tree-core.h
> >>> @@ -567,7 +567,8 @@ enum cv_qualifier {
> >>>      TYPE_QUAL_CONST    = 0x1,
> >>>      TYPE_QUAL_VOLATILE = 0x2,
> >>>      TYPE_QUAL_RESTRICT = 0x4,
> >>> -  TYPE_QUAL_ATOMIC   = 0x8
> >>> +  TYPE_QUAL_ATOMIC   = 0x8,
> >>> +  TYPE_QUAL_DEPENDENT_PTR = 0x10
> >>>    };
> >>>
> >>>    /* Standard named or nameless data types of the C compiler.  */
> >>> @@ -591,6 +592,8 @@ enum tree_index {
> >>>      TI_ATOMICDI_TYPE,
> >>>      TI_ATOMICTI_TYPE,
> >>>
> >>> +  TI_DEPENDENT_PTR_TYPE,
> >>> +
> >>>      TI_UINT16_TYPE,
> >>>      TI_UINT32_TYPE,
> >>>      TI_UINT64_TYPE,
> >>> @@ -969,6 +972,7 @@ struct GTY(()) tree_base {
> >>>      unsigned asm_written_flag: 1;
> >>>      unsigned nowarning_flag : 1;
> >>>      unsigned visited : 1;
> >>> +  unsigned dependent_ptr_flag : 1;
> >>>
> >>>      unsigned used_flag : 1;
> >>>      unsigned nothrow_flag : 1;
> >>> diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
> >>> index 9bea132..ae59cea 100644
> >>> --- a/gcc/tree-pretty-print.c
> >>> +++ b/gcc/tree-pretty-print.c
> >>> @@ -1622,6 +1622,8 @@ dump_generic_node (pretty_printer *pp, tree
> node, int
> >>> spc, dump_flags_t flags,
> >>>      pp_string (pp, "atomic ");
> >>>     if (quals & TYPE_QUAL_CONST)
> >>>      pp_string (pp, "const ");
> >>> + if (quals & TYPE_QUAL_DEPENDENT_PTR)
> >>> +  pp_string (pp, "dependent_ptr ");
> >>>     else if (quals & TYPE_QUAL_VOLATILE)
> >>>      pp_string (pp, "volatile ");
> >>>     else if (quals & TYPE_QUAL_RESTRICT)
> >>> @@ -1768,6 +1770,8 @@ dump_generic_node (pretty_printer *pp, tree
> node, int
> >>> spc, dump_flags_t flags,
> >>>        pp_string (pp, " volatile");
> >>>      if (quals & TYPE_QUAL_RESTRICT)
> >>>        pp_string (pp, " restrict");
> >>> +  if (quals & TYPE_QUAL_DEPENDENT_PTR)
> >>> +    pp_string (pp, " dependent_ptr");
> >>>
> >>>      if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
> >>>        {
> >>> @@ -1871,6 +1875,8 @@ dump_generic_node (pretty_printer *pp, tree
> node, int
> >>> spc, dump_flags_t flags,
> >>>
> >>>     if (quals & TYPE_QUAL_ATOMIC)
> >>>      pp_string (pp, "atomic ");
> >>> + if (quals & TYPE_QUAL_DEPENDENT_PTR)
> >>> +  pp_string (pp, "dependent_ptr ");
> >>>     if (quals & TYPE_QUAL_CONST)
> >>>      pp_string (pp, "const ");
> >>>     if (quals & TYPE_QUAL_VOLATILE)
> >>> diff --git a/gcc/tree.c b/gcc/tree.c
> >>> index 8cf75f2..b4dff8d 100644
> >>> --- a/gcc/tree.c
> >>> +++ b/gcc/tree.c
> >>> @@ -5213,6 +5213,7 @@ fld_type_variant (tree first, tree t, class
> >>> free_lang_data_d *fld,
> >>>      TYPE_READONLY (v) = TYPE_READONLY (t);
> >>>      TYPE_VOLATILE (v) = TYPE_VOLATILE (t);
> >>>      TYPE_ATOMIC (v) = TYPE_ATOMIC (t);
> >>> +  TYPE_DEPENDENT_PTR (v) = TYPE_DEPENDENT_PTR (t);
> >>>      TYPE_RESTRICT (v) = TYPE_RESTRICT (t);
> >>>      TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t);
> >>>      TYPE_NAME (v) = TYPE_NAME (t);
> >>> @@ -6348,6 +6349,7 @@ set_type_quals (tree type, int type_quals)
> >>>      TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
> >>>      TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
> >>>      TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
> >>> +  TYPE_DEPENDENT_PTR (type) = (type_quals & TYPE_QUAL_DEPENDENT_PTR)
> != 0;
> >>>      TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
> >>>    }
> >>>
> >>> diff --git a/gcc/tree.h b/gcc/tree.h
> >>> index 4aa2c4a..0c2f192 100644
> >>> --- a/gcc/tree.h
> >>> +++ b/gcc/tree.h
> >>> @@ -789,6 +789,9 @@ extern void omp_clause_range_check_failed
> (const_tree,
> >>> const char *, int,
> >>>       If this bit is set in an expression, so is TREE_SIDE_EFFECTS.  */
> >>>    #define TREE_THIS_VOLATILE(NODE) ((NODE)->base.volatile_flag)
> >>>
> >>> +/* Nonzero means this expression is involved in some data
> dependency.  */
> >>> +#define TREE_THIS_DEPENDENT_PTR(NODE)
> ((NODE)->base.dependent_ptr_flag)
> >>> +
> >>>    /* Nonzero means this node will not trap.  In an INDIRECT_REF, means
> >>>       accessing the memory pointed to won't generate a trap.  However,
> >>>       this only applies to an object when used appropriately: it
> doesn't
> >>> @@ -2070,6 +2073,9 @@ extern machine_mode vector_type_mode
> (const_tree);
> >>>    /* Nonzero in a type considered atomic as a whole.  */
> >>>    #define TYPE_ATOMIC(NODE) (TYPE_CHECK
> (NODE)->base.u.bits.atomic_flag)
> >>>
> >>> +/* Nonzero in a type considered dependent_ptr as a whole.  */
> >>> +#define TYPE_DEPENDENT_PTR(NODE) (TYPE_CHECK
> >>> (NODE)->base.dependent_ptr_flag)
> >>> +
> >>>    /* Means this type is const-qualified.  */
> >>>    #define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag)
> >>>
> >>> @@ -2100,6 +2106,7 @@ extern machine_mode vector_type_mode
> (const_tree);
> >>>      ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
> >>>      | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
> >>>      | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
> >>> +  | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR)   \
> >>>      | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \
> >>>      | (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
> >>>
> >>> @@ -2108,6 +2115,7 @@ extern machine_mode vector_type_mode
> (const_tree);
> >>>      ((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
> >>>      | (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
> >>>      | (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
> >>> +  | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR)   \
> >>>      | (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
> >>>
> >>>    /* The same as TYPE_QUALS without the address space and atomic
> >>> @@ -3940,6 +3948,8 @@ tree_strip_any_location_wrapper (tree exp)
> >>>    #define atomicDI_type_node global_trees[TI_ATOMICDI_TYPE]
> >>>    #define atomicTI_type_node global_trees[TI_ATOMICTI_TYPE]
> >>>
> >>> +#define dependent_ptrTI_type_node global_trees[TI_DEPENDENT_PTR_TYPE]
> >>> +
> >>>    #define uint16_type_node global_trees[TI_UINT16_TYPE]
> >>>    #define uint32_type_node global_trees[TI_UINT32_TYPE]
> >>>    #define uint64_type_node global_trees[TI_UINT64_TYPE]
> >>> diff --git a/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
> >>> b/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
> >>> new file mode 100644
> >>> index 0000000..8a70733
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
> >>> @@ -0,0 +1,62 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr qualified pointer
> >>> initialization tests. */
> >>> +/* { dg-do run } */
> >>> +/* { dg-options "-std=c11 -pedantic-errors" } */
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +
> >>> +#define TEST_SIMPLE_ASSIGN(TYPE)           \
> >>> +  do                   \
> >>> +    {                 \
> >>> +      static volatile _Atomic (TYPE) * _Dependent_ptr a;     \
> >>> +      static volatile _Atomic (TYPE) b;         \
> >>> +      a = &b;               \
> >>> +      if (a != &b)               \
> >>> +   abort();               \
> >>> +    }                                                             \
> >>> +  while (0)
> >>> +
> >>> +#define TEST_SIMPLE_ASSIGN_POINTER()           \
> >>> +  do                                                               \
> >>> +    {                                                             \
> >>> +      TEST_SIMPLE_ASSIGN (_Bool);         \
> >>> +      TEST_SIMPLE_ASSIGN (char);           \
> >>> +      TEST_SIMPLE_ASSIGN (signed char);         \
> >>> +      TEST_SIMPLE_ASSIGN (unsigned char);       \
> >>> +      TEST_SIMPLE_ASSIGN (signed short);         \
> >>> +      TEST_SIMPLE_ASSIGN (unsigned short);         \
> >>> +      TEST_SIMPLE_ASSIGN (signed int);           \
> >>> +      TEST_SIMPLE_ASSIGN (unsigned int);         \
> >>> +      TEST_SIMPLE_ASSIGN (signed long);         \
> >>> +      TEST_SIMPLE_ASSIGN (unsigned long);       \
> >>> +      TEST_SIMPLE_ASSIGN (signed long long);         \
> >>> +      TEST_SIMPLE_ASSIGN (unsigned long long);         \
> >>> +      TEST_SIMPLE_ASSIGN (float);         \
> >>> +      TEST_SIMPLE_ASSIGN (double);           \
> >>> +      TEST_SIMPLE_ASSIGN (long double);         \
> >>> +      TEST_SIMPLE_ASSIGN (_Complex float);         \
> >>> +      TEST_SIMPLE_ASSIGN (_Complex double);       \
> >>> +      TEST_SIMPLE_ASSIGN (_Complex long double);       \
> >>> +      struct new_struct { struct new_struct * _Dependent_ptr next;
> };   \
> >>> +      struct new_struct * _Dependent_ptr s;         \
> >>> +      s = malloc (sizeof (struct new_struct));         \
> >>> +      struct new_struct t;             \
> >>> +      s->next = &t;             \
> >>> +      if (s->next != &t)             \
> >>> +        abort();               \
> >>> +    }                 \
> >>> +  while (0)
> >>> +
> >>> +static void
> >>> +test_simple_assign (void)
> >>> +{
> >>> +  TEST_SIMPLE_ASSIGN_POINTER ();
> >>> +}
> >>> +
> >>> +int main (void)
> >>> +{
> >>> +  test_simple_assign ();
> >>> +  exit (0);
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig10.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig10.c
> >>> new file mode 100644
> >>> index 0000000..057c2ba
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig10.c
> >>> @@ -0,0 +1,46 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test for checking
> dependency
> >>> through non-local storage. Refer figure 10 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +struct rcutest *gslp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest *_Dependent_ptr p = rcu_dereference (gp); /* {
> dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +  gslp = p;
> >>> +  p = gslp;
> >>> +  if (p)
> >>> +    assert (p->a = 42);
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig11.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig11.c
> >>> new file mode 100644
> >>> index 0000000..39c4b61
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig11.c
> >>> @@ -0,0 +1,51 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test in which reload kills
> >>> dependency. Refer figure 11 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +_Atomic struct rcutest *gsgp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
> >>> dg-warning "\\\[-Wincompatible-pointer-types]" } */
> >>> +  atomic_store_explicit(&gsgp, p, memory_order_relaxed); /* {
> dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread2 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = atomic_load_explicit(&gsgp, memory_order_relaxed); /* {
> dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +  if (p)
> >>> +    assert(p->a == 42);
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig12.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig12.c
> >>> new file mode 100644
> >>> index 0000000..4f7fcd3
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig12.c
> >>> @@ -0,0 +1,53 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test when casting a
> dependency
> >>> pointer to another pointer type which in turn reserves the dependency.
> >>> Refer figure 12 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +struct rcutest1
> >>> +{
> >>> +  int a;
> >>> +  struct rcutest rt;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest * _Dependent_ptr p;
> >>> +  struct rcutest1 *_Dependent_ptr q;
> >>> +
> >>> +  p = rcu_dereference (gp); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +  q = p;                /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +  if (q)
> >>> +    assert(q->a == 42);
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig13.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig13.c
> >>> new file mode 100644
> >>> index 0000000..b4010fc
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig13.c
> >>> @@ -0,0 +1,48 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test: casting to
> non-pointer
> >>> kills dependency. Refer figure 13 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest * _Dependent_ptr p;
> >>> +  long int q;
> >>> +
> >>> +  p = rcu_dereference (gp); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +  q = (long int)(p);
> >>> +  p = (_Dependent_ptr struct rcutest *)q;
> >>> +  if (p)
> >>> +    assert(p->a == 42);
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig8.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig8.c
> >>> new file mode 100644
> >>> index 0000000..e706a9b
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig8.c
> >>> @@ -0,0 +1,44 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test for checking simple
> >>> left-hand side dependency. Refer figure 8 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  assert (p->a != 43);
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
> >>> dg-warning "\\\[-Wincompatible-pointer-types]" } */
> >>> +  if (p)
> >>> +    p->a = 43;
> >>> +}
> >>> diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig9.c
> >>> b/gcc/testsuite/gcc.dg/p0190r4_fig9.c
> >>> new file mode 100644
> >>> index 0000000..32f67b3
> >>> --- /dev/null
> >>> +++ b/gcc/testsuite/gcc.dg/p0190r4_fig9.c
> >>> @@ -0,0 +1,43 @@
> >>> +/* Test for _Dependent_ptr. _Dependent_ptr test for checking simple
> >>> right-hand side dependency. Refer figure 9 in document p0190r4 (
> >>> http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf).
> */
> >>> +/* { dg-do compile } */
> >>> +/* { dg-options "-std=c11 -pedantic" } */
> >>> +
> >>> +#include <stdatomic.h>
> >>> +
> >>> +typedef __SIZE_TYPE__ size_t;
> >>> +extern void abort (void);
> >>> +extern void exit (int);
> >>> +extern void *malloc (size_t);
> >>> +extern int assert ();
> >>> +
> >>> +struct rcutest
> >>> +{
> >>> +  int a;
> >>> +  int b;
> >>> +  int c;
> >>> +};
> >>> +
> >>> +_Atomic struct rcutest *gp;
> >>> +
> >>> +#define rcu_assign_pointer(p,v) \
> >>> +  atomic_store_explicit(&(p), (v), memory_order_release);
> >>> +
> >>> +#define rcu_dereference(p) \
> >>> +  atomic_load_explicit(&(p), memory_order_consume);
> >>> +
> >>> +void thread0 ()
> >>> +{
> >>> +  struct rcutest *p;
> >>> +
> >>> +  p = (struct rcutest *)malloc (sizeof (*p));
> >>> +  assert (p);
> >>> +  p->a = 42;
> >>> +  rcu_assign_pointer (gp,p); /* { dg-warning
> >>> "\\\[-Wincompatible-pointer-types]" } */
> >>> +}
> >>> +
> >>> +void thread1 ()
> >>> +{
> >>> +  struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
> >>> dg-warning "\\\[-Wincompatible-pointer-types]" } */
> >>> +  if (p)
> >>> +    assert (p->a = 42);
> >>> +}
> >>>
> >>
>
>


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]