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 <mse...@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 <xks...@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 <xks...@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);
+}



Reply via email to