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


On 8/6/19 12:26 PM, Akshat Garg wrote:
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'" } */       \

I don't think wrapping a dg- directive in a macro like this does
quite what you want.  The directive should verify that each of
the invalid declarations below triggers the error.  What it does
instead is verify that at least one of the invalid declarations
fails with the error.  I think it will pass even if only some
are accepted and others rejected.

I would suggest to get rid of the macros and spell out each invalid
declaration separately along with the expected error.

FWIW, the error message is also overly generic.  A better error
would explain why the use is invalid.  E.g.,

"using '_Dependent_ptr' with 'int' is invalid; the qualifier may only be applied to pointer types"

I realize GCC issues the same poor error for 'restrict'.  A better
example to follow here is Clang which prints the much more meaningful:

  error: restrict requires a pointer or reference ('int' is invalid)


     }                                                             \
   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.

If as an implementer you're not sure then that suggests it should
probably be an error :)

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"

I've never seen these sorts of references to GCC's headers in
the test suite.  To include the named headers tests normally
just #include <stddef.h> and #include <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.

Of the qualifiers (_Atomic, const, restrict, and volatile) my
question was mainly whether conversions between them and
_Dependent_ptr were meant to be allowed (and would have a meaning).
If not, it would at a minimum suggest they should be rejected.

Similarly, I would want to make sure that conversions between
_Dependent_ptr-qualified and unqualified pointers are valid in
both directions.  It's fine to convert an unqualified pointer
to a pointer to const but not the other way around:

  char *p = 0;
  const char *q = p;   // okay
  char *r = q;         // not safe (-Wdiscarded-qualifiers)

Does it work the same with _Dependent_ptr?  (And if it does,
with what semantics?  Again, this seems like something to
discuss in the paper.)

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.

It does but the tests doesn't verify any of that.  To verify
the semantic effect the tests will need the rest of the patches
applied (the middle-end and possibly also the back-end).  Then
they will search for the right order of assignments in the IL.

For the front-end patch, all the tests should do is validate
that _Dependent_ptr is accepted where it's meant to be accepted
and rejected with an error (or diagnosed witha warning) where
it isn't.  The thread functions and the rcu_xxx stuff obscures
their intent.

Martin


Akshat

On Sat, Aug 3, 2019 at 8:00 AM Martin Sebor <msebor@gmail.com <mailto: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
    <mailto: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
    <mailto: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
    <mailto: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]