public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
@ 2019-07-30  7:17 Akshat Garg
  2019-07-30 20:03 ` Martin Sebor
  0 siblings, 1 reply; 12+ messages in thread
From: Akshat Garg @ 2019-07-30  7:17 UTC (permalink / raw)
  To: gcc-patches; +Cc: paulmckrcu, Ramana Radhakrishnan

Hi,
This patch includes C front-end code for a type qualifier _Dependent_ptr.
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);
+}

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-07-30  7:17 [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3 Akshat Garg
@ 2019-07-30 20:03 ` Martin Sebor
       [not found]   ` <CAJzB8QHq1sKQZqKsoqqcTKgE+Vurih_aY5qNWv8PvLxBXZgRjg@mail.gmail.com>
  2019-08-19 22:58   ` Joseph Myers
  0 siblings, 2 replies; 12+ messages in thread
From: Martin Sebor @ 2019-07-30 20:03 UTC (permalink / raw)
  To: Akshat Garg, gcc-patches; +Cc: paulmckrcu, Ramana Radhakrishnan

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);
> +}
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
       [not found]   ` <CAJzB8QHq1sKQZqKsoqqcTKgE+Vurih_aY5qNWv8PvLxBXZgRjg@mail.gmail.com>
@ 2019-08-02  4:44     ` Akshat Garg
  2019-08-03  1:44       ` Akshat Garg
  2019-08-03  2:31     ` Martin Sebor
  1 sibling, 1 reply; 12+ messages in thread
From: Akshat Garg @ 2019-08-02  4:44 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Paul McKenney, Ramana Radhakrishnan, gcc-patches

On Thu, Aug 1, 2019 at 8:57 PM Paul McKenney <paulmckrcu@gmail.com> wrote:

> Excellent point, this discussion needs to be made official.
> Please see attached for an initial draft of a working paper.
>
> Thoughts?
>
>                                          Thanx, Paul
>
Please, find the attachment here (
https://drive.google.com/open?id=0B9Q3hzI3TofcZ3o2aXVMd2V1Ujl4VUZnT3MtXzZpV1I2OHFv
).

>
> 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);
> > > +}
> > >
> >
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-02  4:44     ` Akshat Garg
@ 2019-08-03  1:44       ` Akshat Garg
  0 siblings, 0 replies; 12+ messages in thread
From: Akshat Garg @ 2019-08-03  1:44 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Paul McKenney, Ramana Radhakrishnan, gcc-patches

On Fri, Aug 2, 2019 at 10:14 AM Akshat Garg <xkspr7@gmail.com> wrote:

>
>
> On Thu, Aug 1, 2019 at 8:57 PM Paul McKenney <paulmckrcu@gmail.com> wrote:
>
>> Excellent point, this discussion needs to be made official.
>> Please see attached for an initial draft of a working paper.
>>
>> Thoughts?
>>
>>                                          Thanx, Paul
>>
> Please, find the attachment here (
> https://drive.google.com/open?id=0B9Q3hzI3TofcZ3o2aXVMd2V1Ujl4VUZnT3MtXzZpV1I2OHFv
> ).
>
>>
>> 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
>>
> I have tried this patch which raises pedantic warning with pre-gnu2x
modes. Let us know what you think.

diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 9e80bfee7d4..4d61a38c5b9 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -2870,6 +2870,12 @@ c_parser_declspecs (c_parser *parser, struct
c_declspecs *specs,
            declspecs_add_qual (loc, specs, value);
          break;
        case RID_DEPENDENT_PTR:
+         if (flag_isoc11)
+           pedwarn_c11 (loc, OPT_Wpedantic,
+                        "ISO C11 does not support the %<_Dependent_ptr%>
qualifier");
+         else
+           pedwarn_c99 (loc, OPT_Wpedantic,
+                        "ISO C90 does not support the %<_Dependent_ptr%>
qualifier");
          attrs_ok = true;
          declspecs_add_qual (loc, specs, c_parser_peek_token
(parser)->value);
          c_parser_consume_token (parser);


> >
>> > > 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);
>> > > +}
>> > >
>> >
>>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
       [not found]   ` <CAJzB8QHq1sKQZqKsoqqcTKgE+Vurih_aY5qNWv8PvLxBXZgRjg@mail.gmail.com>
  2019-08-02  4:44     ` Akshat Garg
@ 2019-08-03  2:31     ` Martin Sebor
  2019-08-04 23:11       ` Paul E. McKenney
  2019-08-06 19:17       ` Akshat Garg
  1 sibling, 2 replies; 12+ messages in thread
From: Martin Sebor @ 2019-08-03  2:31 UTC (permalink / raw)
  To: Paul McKenney; +Cc: Akshat Garg, gcc-patches, Ramana Radhakrishnan

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);
>>> +}
>>>
>>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-03  2:31     ` Martin Sebor
@ 2019-08-04 23:11       ` Paul E. McKenney
  2019-08-16 15:06         ` Paul E. McKenney
  2019-08-06 19:17       ` Akshat Garg
  1 sibling, 1 reply; 12+ messages in thread
From: Paul E. McKenney @ 2019-08-04 23:11 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Akshat Garg, gcc-patches, Ramana Radhakrishnan

Good points!

On the type-qualifier interactions, here is an initial list.  Thoughts?

							Thanx, Paul

_Alignas: Dependency-breaking optimizations would be avoided, and the
variable would be aligned as specified.

_Atomic: Dependency-breaking optimizations would be avoided, and the
variable would be accessed using C11 atomics.

const: This is not particularly useful for variables with static storage
duration because compile-time initialization does not require dependency
ordering, but then again, use of _Dependent_ptr on such variables is
suspect to begin with.  Otherwise, the const _Dependent_ptr variable
would normally be initialized from another _Dependent_ptr variable or
from a memory_order_consume load.  The variable would disallow further
stores and avoid breaking dependencies.

extern: Dependency-breaking optimizations would be avoided, and the
variable would be usable within other translation units.  This is
also an unusual addition to a _Dependent_ptr unless also accompanied by
_Thread_local because there are no known non-suspect multi-threaded-access
use cases for _Dependent_ptr.

register: Dependency-breaking optimizations would be avoided, and the
compiler would be given a hint to keep the variable in a register.

restrict: Dependency-breaking optimizations would be avoided, and the
compiler may assume that the pointed-to object is only accessed through
this pointer and through pointers derived from it.

static: Dependency-breaking optimizations would be avoided, and the
variable would be static.  This is also an unusual addition to a
_Dependent_ptr unless also accompanied by _Thread_local because there are
no known non-suspect multi-threaded-access use cases for _Dependent_ptr.

_Thread_local: The dependency-carrying variable is thread-local, and
avoids dependency-breaking optimizations.

volatile: All accesses would be executed as per the abstract machine,
and dependency-breaking optimizations would be avoided.

On Fri, Aug 02, 2019 at 08:30:49PM -0600, Martin Sebor 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);
> >>>+}
> >>>
> >>
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-03  2:31     ` Martin Sebor
  2019-08-04 23:11       ` Paul E. McKenney
@ 2019-08-06 19:17       ` Akshat Garg
  2019-08-07  3:18         ` Martin Sebor
  1 sibling, 1 reply; 12+ messages in thread
From: Akshat Garg @ 2019-08-06 19:17 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Paul McKenney, gcc-patches, Ramana Radhakrishnan

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);
> >>> +}
> >>>
> >>
>
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-06 19:17       ` Akshat Garg
@ 2019-08-07  3:18         ` Martin Sebor
  0 siblings, 0 replies; 12+ messages in thread
From: Martin Sebor @ 2019-08-07  3:18 UTC (permalink / raw)
  To: Akshat Garg; +Cc: Paul McKenney, gcc-patches, Ramana Radhakrishnan

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);
>      >>> +}
>      >>>
>      >>
> 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-04 23:11       ` Paul E. McKenney
@ 2019-08-16 15:06         ` Paul E. McKenney
  0 siblings, 0 replies; 12+ messages in thread
From: Paul E. McKenney @ 2019-08-16 15:06 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Akshat Garg, gcc-patches, Ramana Radhakrishnan

And please see the following URL for an update:

http://www.rdrop.com/~paulmck/submission/DNNNN%20_Dependent_ptr%20to%20simplify%20carries%20a%20dependency.pdf

This adds a description of conversions, warnings, and patches.

							Thanx, Paul

On Sun, Aug 04, 2019 at 04:11:12PM -0700, Paul E. McKenney wrote:
> Good points!
> 
> On the type-qualifier interactions, here is an initial list.  Thoughts?
> 
> 							Thanx, Paul
> 
> _Alignas: Dependency-breaking optimizations would be avoided, and the
> variable would be aligned as specified.
> 
> _Atomic: Dependency-breaking optimizations would be avoided, and the
> variable would be accessed using C11 atomics.
> 
> const: This is not particularly useful for variables with static storage
> duration because compile-time initialization does not require dependency
> ordering, but then again, use of _Dependent_ptr on such variables is
> suspect to begin with.  Otherwise, the const _Dependent_ptr variable
> would normally be initialized from another _Dependent_ptr variable or
> from a memory_order_consume load.  The variable would disallow further
> stores and avoid breaking dependencies.
> 
> extern: Dependency-breaking optimizations would be avoided, and the
> variable would be usable within other translation units.  This is
> also an unusual addition to a _Dependent_ptr unless also accompanied by
> _Thread_local because there are no known non-suspect multi-threaded-access
> use cases for _Dependent_ptr.
> 
> register: Dependency-breaking optimizations would be avoided, and the
> compiler would be given a hint to keep the variable in a register.
> 
> restrict: Dependency-breaking optimizations would be avoided, and the
> compiler may assume that the pointed-to object is only accessed through
> this pointer and through pointers derived from it.
> 
> static: Dependency-breaking optimizations would be avoided, and the
> variable would be static.  This is also an unusual addition to a
> _Dependent_ptr unless also accompanied by _Thread_local because there are
> no known non-suspect multi-threaded-access use cases for _Dependent_ptr.
> 
> _Thread_local: The dependency-carrying variable is thread-local, and
> avoids dependency-breaking optimizations.
> 
> volatile: All accesses would be executed as per the abstract machine,
> and dependency-breaking optimizations would be avoided.
> 
> On Fri, Aug 02, 2019 at 08:30:49PM -0600, Martin Sebor 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);
> > >>>+}
> > >>>
> > >>
> > 

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-07-30 20:03 ` Martin Sebor
       [not found]   ` <CAJzB8QHq1sKQZqKsoqqcTKgE+Vurih_aY5qNWv8PvLxBXZgRjg@mail.gmail.com>
@ 2019-08-19 22:58   ` Joseph Myers
  2019-08-29 21:26     ` Akshat Garg
  1 sibling, 1 reply; 12+ messages in thread
From: Joseph Myers @ 2019-08-19 22:58 UTC (permalink / raw)
  To: Martin Sebor; +Cc: Akshat Garg, gcc-patches, paulmckrcu, Ramana Radhakrishnan

On Tue, 30 Jul 2019, Martin Sebor 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

The first question for any new thing that is syntactically a qualifier is: 
is it intended generally to be counted as a qualifier where the standard 
refers to qualified type, the unqualified version of a type, etc.?  Or is 
it, like _Atomic, a qualifier only syntactically and generally excluded 
from references to qualifiers?

For the _Atomic implementation I had to go through all the references to 
qualifiers or TYPE_MAIN_VARIANT in the front end and consider in each case 
whether it handled _Atomic correctly, given that _Atomic is not counted as 
a qualifier in the standard (so the unqualified version of const _Atomic 
int is _Atomic int not int, and so can't be derived simply by using 
TYPE_MAIN_VARIANT, for example).  Some cases didn't need changing because 
the handling (e.g. diagnostic for different types) was still appropriate 
for _Atomic even though not formally a qualifier, but plenty did need 
changing and associated tests added.

Such a check of front end code is probably unavoidable (before a change is 
ready for trunk, not necessarily for an initial rough RFC patch) for any 
new qualifier, whether it counts as a qualifier in standard terms or not 
(and the patch reviewer will need to do their own check of references to 
qualifiers or TYPE_MAIN_VARIANT that didn't get changed by the patch), but 
the answer to that question helps indicate whether the default is to 
expect code to need changing for the new qualifier or not.

> 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

There should not be any -std=c2x (flag_isoc2x) conditionals simply based 
on "a proposal is planned".  flag_isoc2x conditionals (pedwarn_c11 calls, 
etc.) should be for cases where a feature is *accepted and committed into 
the C2x branch of Jens's git repository for the C standard*, not for 
something that might be proposed, or is proposed, but doesn't yet have 
specific text integrated into the text of the standard.

If something is simply proposed *and we've concluded it's a good feature 
to have as an extension in any case* then you have a normal 
pedwarn-if-pedantic (no condition on standard version) as for any GNU 
extension (and flag_isoc2x conditions / changes to use pedwarn_c11 instead 
can be added later if the extension is added to the standard).

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-19 22:58   ` Joseph Myers
@ 2019-08-29 21:26     ` Akshat Garg
  2019-08-29 21:32       ` Joseph Myers
  0 siblings, 1 reply; 12+ messages in thread
From: Akshat Garg @ 2019-08-29 21:26 UTC (permalink / raw)
  To: Joseph Myers
  Cc: Martin Sebor, gcc-patches, Paul McKenney, Ramana Radhakrishnan

Hi Joseph,
Many thanks for giving us your feedback.

On Tue, Aug 20, 2019 at 3:57 AM Joseph Myers <joseph@codesourcery.com>
wrote:

> On Tue, 30 Jul 2019, Martin Sebor 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
>
> The first question for any new thing that is syntactically a qualifier is:
> is it intended generally to be counted as a qualifier where the standard
> refers to qualified type, the unqualified version of a type, etc.?  Or is
> it, like _Atomic, a qualifier only syntactically and generally excluded
> from references to qualifiers?
>
Can you help me in understanding why the _Atomic is excluded from the
standard references. I referred to the C standard draft N2310 (
http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf) but I couldn't
understand how it is excluded? I want to know what properties should a
qualifier have to be in standard qualifiers list?

Thanks,
Akshat

>
> For the _Atomic implementation I had to go through all the references to
> qualifiers or TYPE_MAIN_VARIANT in the front end and consider in each case
> whether it handled _Atomic correctly, given that _Atomic is not counted as
> a qualifier in the standard (so the unqualified version of const _Atomic
> int is _Atomic int not int, and so can't be derived simply by using
> TYPE_MAIN_VARIANT, for example).  Some cases didn't need changing because
> the handling (e.g. diagnostic for different types) was still appropriate
> for _Atomic even though not formally a qualifier, but plenty did need
> changing and associated tests added.
>
> Such a check of front end code is probably unavoidable (before a change is
> ready for trunk, not necessarily for an initial rough RFC patch) for any
> new qualifier, whether it counts as a qualifier in standard terms or not
> (and the patch reviewer will need to do their own check of references to
> qualifiers or TYPE_MAIN_VARIANT that didn't get changed by the patch), but
> the answer to that question helps indicate whether the default is to
> expect code to need changing for the new qualifier or not.
>
> > 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
>
> There should not be any -std=c2x (flag_isoc2x) conditionals simply based
> on "a proposal is planned".  flag_isoc2x conditionals (pedwarn_c11 calls,
> etc.) should be for cases where a feature is *accepted and committed into
> the C2x branch of Jens's git repository for the C standard*, not for
> something that might be proposed, or is proposed, but doesn't yet have
> specific text integrated into the text of the standard.
>
> If something is simply proposed *and we've concluded it's a good feature
> to have as an extension in any case* then you have a normal
> pedwarn-if-pedantic (no condition on standard version) as for any GNU
> extension (and flag_isoc2x conditions / changes to use pedwarn_c11 instead
> can be added later if the extension is added to the standard).
>
> --
> Joseph S. Myers
> joseph@codesourcery.com
>

^ permalink raw reply	[flat|nested] 12+ messages in thread

* Re: [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
  2019-08-29 21:26     ` Akshat Garg
@ 2019-08-29 21:32       ` Joseph Myers
  0 siblings, 0 replies; 12+ messages in thread
From: Joseph Myers @ 2019-08-29 21:32 UTC (permalink / raw)
  To: Akshat Garg
  Cc: Martin Sebor, gcc-patches, Paul McKenney, Ramana Radhakrishnan

On Fri, 30 Aug 2019, Akshat Garg wrote:

> > The first question for any new thing that is syntactically a qualifier is:
> > is it intended generally to be counted as a qualifier where the standard
> > refers to qualified type, the unqualified version of a type, etc.?  Or is
> > it, like _Atomic, a qualifier only syntactically and generally excluded
> > from references to qualifiers?
> >
> Can you help me in understanding why the _Atomic is excluded from the
> standard references. I referred to the C standard draft N2310 (
> http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2310.pdf) but I couldn't
> understand how it is excluded? I want to know what properties should a
> qualifier have to be in standard qualifiers list?

In the case of _Atomic, it can affect the size and alignment of the type 
to which it is applied, which means it can't be considered a qualifier in 
the nornal semantic sense.

In general you need to consider questions such as: is it safe to convert a 
pointer to unqualified type to a pointer to the corresponding 
_Dependent_ptr-qualified type?  Are conditional expressions between 
pointers whose target types differ in presence or absence of 
_Dependent_ptr safe?  If in general, in such places where the standard 
refers to qualifiers, the existing logic there is also appropriate for 
_Dependent_ptr, that suggests it should be a qualifier semantically.  If 
the standard logic often seems inappropriate for _Dependent_ptr, that 
indicates it's not a qualifier in standard terms.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 12+ messages in thread

end of thread, other threads:[~2019-08-29 20:41 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-07-30  7:17 [PATCH] Adding _Dependent_ptr type qualifier in C part 1/3 Akshat Garg
2019-07-30 20:03 ` Martin Sebor
     [not found]   ` <CAJzB8QHq1sKQZqKsoqqcTKgE+Vurih_aY5qNWv8PvLxBXZgRjg@mail.gmail.com>
2019-08-02  4:44     ` Akshat Garg
2019-08-03  1:44       ` Akshat Garg
2019-08-03  2:31     ` Martin Sebor
2019-08-04 23:11       ` Paul E. McKenney
2019-08-16 15:06         ` Paul E. McKenney
2019-08-06 19:17       ` Akshat Garg
2019-08-07  3:18         ` Martin Sebor
2019-08-19 22:58   ` Joseph Myers
2019-08-29 21:26     ` Akshat Garg
2019-08-29 21:32       ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).