The patch has been tested using the following
make bootstrap -j 4
make -k check -j 4
on x86_64-linux-gnu.
Thanks,
Akshat
gcc/ChangeLog:
2019-07-30 Akshat Garg <xks...@gmail.com>
* c-family/c-common.c (struct c_common_resword c_common_reswords):
Add "_Dependent_ptr".
(c_apply_type_quals_to_decl): Set the flag for _Dependent_ptr if
qualified.
(keyword_is_type_qualifier): Add RID_DEPENDENT_PTR.
* c-family/c-common.h (enum rid): Add RID_DEPENDENT_PTR.
* c-family/c-format.c (check_format_types): Add dependent pointer
as a qualifier check.
* c-family/c-pretty-print.c (pp_c_cv_qualifiers): Handle dependent
pointer qualifier.
* c/c-aux-info.c (gen_type): Handle dependent pointer qualifier.
(gen_decl): Handle dependent pointer qualifier.
* c/c-decl.c (merge_decls): Set old declaration as having dependent
pointer qualification if new declaration has one.
(shadow_tag_warned): Add dependent_ptr_p to declspecs check.
(quals_from_declspecs): Add dependent_ptr_p to declspecs check.
(grokdeclarator): Add checks for dependent pointer qualifier and
warn of duplicate or errors. Allow dependent pointer for pointer types only.
* c/c-parser.c (c_keyword_starts_typename, c_token_is_qualifier,
c_token_starts_declspecs): Add RID_DEPENDENT_PTR.
(c_parser_static_assert_declaration_no_semi): Add _Dependent_ptr
qualifier in comments.
(c_parser_declspecs, c_parser_attribute_any_word): Add
RID_DEPENDENT_PTR.
* c/c-tree.h (C_TYPE_FIELDS_DEPENDENT_PTR): New macro to mark
dependent pointer.
(enum c_declspec_word): Add cdw_dependent_ptr.
(struct c_declspecs): Add dependent_ptr_p field.
* print-tree.c (print_node): Print dependent_ptr qualifier.
* tree-core.hi (enum cv_qualifier): Add TYPE_QUAL_DEPENDENT_PTR.
(enum tree_index): Add TI_DEPENDENT_PTR_TYPE.
(struct tree_base): Add dependent_ptr_flag field.
* tree-pretty-print.c (dump_generic_node): Print dependent pointer
type qualifier.
* tree.c (fld_type_variant, set_type_quals): Set TYPE_DEPENDENT_PTR.
* tree.h (TREE_THIS_DEPENDENT_PTR): New macro. To access
dependent_ptr_flag field in tree_base.
(TYPE_DEPENDENT_PTR): New accessor macro.
(TYPE_QUALS, TYPE_QUALS_NO_ADDR_SPACE): Add TYPE_QUAL_DEPENDENT_PTR.
(dependent_ptrTI_type_node): Add new type node.
gcc/testsuite/ChangeLog:
2019-07-30 Akshat Garg <xks...@gmail.com>
* gcc.dg/c11-dependent_ptr-test-1.c: New test for _Dependent_ptr
qualifier.
* gcc.dg/{p0190r4_fig8, p0190r4_fig9, p0190r4_fig10, p0190r4_fig11,
p0190r4_fig12, p0190r4_fig13}.c: New tests from document P0190R4 for
_Dependent_ptr qualifier.
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index cb92710..4f09037 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -345,6 +345,7 @@ const struct c_common_resword c_common_reswords[] =
{ "_Alignas", RID_ALIGNAS, D_CONLY },
{ "_Alignof", RID_ALIGNOF, D_CONLY },
{ "_Atomic", RID_ATOMIC, D_CONLY },
+ { "_Dependent_ptr", RID_DEPENDENT_PTR, 0 },
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
@@ -3546,6 +3547,11 @@ c_apply_type_quals_to_decl (int type_quals, tree
decl)
TREE_SIDE_EFFECTS (decl) = 1;
TREE_THIS_VOLATILE (decl) = 1;
}
+ if (type_quals & TYPE_QUAL_DEPENDENT_PTR)
+ {
+ TREE_SIDE_EFFECTS (decl) = 1;
+ TREE_THIS_DEPENDENT_PTR (decl) = 1;
+ }
if (type_quals & TYPE_QUAL_RESTRICT)
{
while (type && TREE_CODE (type) == ARRAY_TYPE)
@@ -7851,6 +7857,7 @@ keyword_is_type_qualifier (enum rid keyword)
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATOMIC:
+ case RID_DEPENDENT_PTR:
return true;
default:
return false;
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 117d729..ab55882 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -68,7 +68,7 @@ enum rid
RID_UNSIGNED, RID_LONG, RID_CONST, RID_EXTERN,
RID_REGISTER, RID_TYPEDEF, RID_SHORT, RID_INLINE,
RID_VOLATILE, RID_SIGNED, RID_AUTO, RID_RESTRICT,
- RID_NORETURN, RID_ATOMIC,
+ RID_NORETURN, RID_ATOMIC, RID_DEPENDENT_PTR,
/* C extensions */
RID_COMPLEX, RID_THREAD, RID_SAT,
diff --git a/gcc/c-family/c-format.c b/gcc/c-family/c-format.c
index d134116..00769bb 100644
--- a/gcc/c-family/c-format.c
+++ b/gcc/c-family/c-format.c
@@ -4172,6 +4172,7 @@ check_format_types (const substring_loc &fmt_loc,
&& (TYPE_READONLY (cur_type)
|| TYPE_VOLATILE (cur_type)
|| TYPE_ATOMIC (cur_type)
+ || TYPE_DEPENDENT_PTR (cur_type)
|| TYPE_RESTRICT (cur_type)))
warning (OPT_Wformat_, "extra type qualifiers in format "
"argument (argument %d)",
diff --git a/gcc/c-family/c-pretty-print.c b/gcc/c-family/c-pretty-print.c
index 3e25624..e034a8f 100644
--- a/gcc/c-family/c-pretty-print.c
+++ b/gcc/c-family/c-pretty-print.c
@@ -181,6 +181,8 @@ pp_c_cv_qualifiers (c_pretty_printer *pp, int
qualifiers, bool func_type)
if (qualifiers & TYPE_QUAL_ATOMIC)
pp_c_ws_string (pp, "_Atomic");
+ if (qualifiers & TYPE_QUAL_DEPENDENT_PTR)
+ pp_c_ws_string (pp, "_Dependent_ptr");
if (qualifiers & TYPE_QUAL_CONST)
pp_c_ws_string (pp, func_type ? "__attribute__((const))" : "const");
if (qualifiers & TYPE_QUAL_VOLATILE)
diff --git a/gcc/c/c-aux-info.c b/gcc/c/c-aux-info.c
index 96bb2e2..514093c 100644
--- a/gcc/c/c-aux-info.c
+++ b/gcc/c/c-aux-info.c
@@ -284,6 +284,8 @@ gen_type (const char *ret_val, tree t, formals_style
style)
case POINTER_TYPE:
if (TYPE_ATOMIC (t))
ret_val = concat ("_Atomic ", ret_val, NULL);
+ if (TYPE_DEPENDENT_PTR (t))
+ ret_val = concat ("_Dependent_ptr ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
@@ -427,6 +429,8 @@ gen_type (const char *ret_val, tree t, formals_style
style)
}
if (TYPE_ATOMIC (t))
ret_val = concat ("_Atomic ", ret_val, NULL);
+ if (TYPE_DEPENDENT_PTR (t))
+ ret_val = concat ("_Dependent_ptr ", ret_val, NULL);
if (TYPE_READONLY (t))
ret_val = concat ("const ", ret_val, NULL);
if (TYPE_VOLATILE (t))
@@ -474,6 +478,8 @@ gen_decl (tree decl, int is_func_definition,
formals_style style)
ret_val = concat ("volatile ", ret_val, NULL);
if (TREE_READONLY (decl))
ret_val = concat ("const ", ret_val, NULL);
+ if (TREE_THIS_DEPENDENT_PTR (decl))
+ ret_val = concat ("dependent_ptr ", ret_val, NULL);
data_type = "";
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index f85f481..2047575 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -2587,6 +2587,9 @@ merge_decls (tree newdecl, tree olddecl, tree
newtype, tree oldtype)
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
+ if (TREE_THIS_DEPENDENT_PTR (newdecl))
+ TREE_THIS_DEPENDENT_PTR (olddecl) = 1;
+
/* Merge deprecatedness. */
if (TREE_DEPRECATED (newdecl))
TREE_DEPRECATED (olddecl) = 1;
@@ -2638,6 +2641,7 @@ merge_decls (tree newdecl, tree olddecl, tree
newtype, tree oldtype)
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
+ TREE_THIS_DEPENDENT_PTR (newdecl) |= TREE_THIS_DEPENDENT_PTR (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
if (DECL_IS_OPERATOR_NEW_P (olddecl))
DECL_SET_IS_OPERATOR_NEW (newdecl, true);
@@ -4544,6 +4548,7 @@ shadow_tag_warned (const struct c_declspecs
*declspecs, int warned)
&& (declspecs->const_p
|| declspecs->volatile_p
|| declspecs->atomic_p
+ || declspecs->dependent_ptr_p
|| declspecs->restrict_p
|| declspecs->address_space))
{
@@ -4672,6 +4677,7 @@ quals_from_declspecs (const struct c_declspecs *specs)
| (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
| (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0)
| (specs->atomic_p ? TYPE_QUAL_ATOMIC : 0)
+ | (specs->dependent_ptr_p ? TYPE_QUAL_DEPENDENT_PTR : 0)
| (ENCODE_QUAL_ADDR_SPACE (specs->address_space)));
gcc_assert (!specs->type
&& !specs->decl_attr
@@ -5837,6 +5843,7 @@ grokdeclarator (const struct c_declarator *declarator,
int restrictp;
int volatilep;
int atomicp;
+ int dependent_ptrp;
int type_quals = TYPE_UNQUALIFIED;
tree name = NULL_TREE;
bool funcdef_flag = false;
@@ -6003,6 +6010,7 @@ grokdeclarator (const struct c_declarator *declarator,
restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
atomicp = declspecs->atomic_p + TYPE_ATOMIC (element_type);
+ dependent_ptrp = declspecs->dependent_ptr_p + TYPE_DEPENDENT_PTR
(element_type);
as1 = declspecs->address_space;
as2 = TYPE_ADDR_SPACE (element_type);
address_space = ADDR_SPACE_GENERIC_P (as1)? as2 : as1;
@@ -6015,6 +6023,8 @@ grokdeclarator (const struct c_declarator *declarator,
pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<volatile%>");
if (atomicp > 1)
pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Atomic%>");
+ if (dependent_ptrp > 1)
+ pedwarn_c90 (loc, OPT_Wpedantic, "duplicate %<_Dependent_ptr%>");
if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2) && as1 !=
as2)
error_at (loc, "conflicting named address spaces (%s vs %s)",
@@ -6031,6 +6041,7 @@ grokdeclarator (const struct c_declarator *declarator,
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0)
| (atomicp ? TYPE_QUAL_ATOMIC : 0)
+ | (dependent_ptrp ? TYPE_QUAL_DEPENDENT_PTR : 0)
| ENCODE_QUAL_ADDR_SPACE (address_space));
if (type_quals != TYPE_QUALS (element_type))
orig_qual_type = NULL_TREE;
@@ -6042,6 +6053,13 @@ grokdeclarator (const struct c_declarator
*declarator,
if (declspecs->atomic_p && TREE_CODE (type) == ARRAY_TYPE)
error_at (loc, "%<_Atomic%>-qualified array type");
+ /* Applying the _Dependent_ptr qualifier to an array type (through
+ the use of typedefs or typeof) must be detected here. If the
+ qualifier is introduced later, any appearance of applying it to
+ an array is actually applying it to an element of that array. */
+ if (declspecs->dependent_ptr_p && TREE_CODE (type) == ARRAY_TYPE)
+ error_at (loc, "%<_Dependent_ptr%>-qualified array type");
+
/* Warn about storage classes that are invalid for certain
kinds of declarations (parameters, typenames, etc.). */
@@ -7214,6 +7232,10 @@ grokdeclarator (const struct c_declarator
*declarator,
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
+ /* _Dependent_ptr qualifier only reserved for pointer type variable */
+ if ((type_quals & TYPE_QUAL_DEPENDENT_PTR) && (!POINTER_TYPE_P (type)))
+ error_at (loc, "invalid use of %<_Dependent_ptr%>");
+
type = c_build_qualified_type (type, type_quals, orig_qual_type,
orig_qual_indirect);
@@ -7294,7 +7316,7 @@ grokdeclarator (const struct c_declarator *declarator,
DECL_REGISTER (decl) = 1;
}
- /* Record constancy and volatility. */
+ /* Record constancy, data dependency and volatility. */
c_apply_type_quals_to_decl (type_quals, decl);
/* Apply _Alignas specifiers. */
@@ -8258,6 +8280,11 @@ finish_struct (location_t loc, tree t, tree
fieldlist, tree attributes,
if (TREE_THIS_VOLATILE (x))
C_TYPE_FIELDS_VOLATILE (t) = 1;
+ /* Any field that is a dependent pointer means variables of this
+ type must be treated in some ways as dependent pointer. */
+ if (TREE_THIS_DEPENDENT_PTR (x))
+ C_TYPE_FIELDS_DEPENDENT_PTR (t) = 1;
+
/* Any field of nominal variable size implies structure is too. */
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
@@ -10177,6 +10204,12 @@ declspecs_add_qual (location_t loc,
prev_loc = specs->locations[cdw_atomic];
specs->locations[cdw_atomic] = loc;
break;
+ case RID_DEPENDENT_PTR:
+ dupe = specs->dependent_ptr_p;
+ specs->dependent_ptr_p = true;
+ prev_loc = specs->locations[cdw_dependent_ptr];
+ specs->locations[cdw_dependent_ptr] = loc;
+ break;
default:
gcc_unreachable ();
}
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 6721049..35e25bb 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -503,6 +503,7 @@ c_keyword_starts_typename (enum rid keyword)
case RID_TYPEOF:
case RID_CONST:
case RID_ATOMIC:
+ case RID_DEPENDENT_PTR:
case RID_VOLATILE:
case RID_RESTRICT:
case RID_ATTRIBUTE:
@@ -606,6 +607,7 @@ c_token_is_qualifier (c_token *token)
case RID_RESTRICT:
case RID_ATTRIBUTE:
case RID_ATOMIC:
+ case RID_DEPENDENT_PTR:
return true;
default:
return false;
@@ -687,6 +689,7 @@ c_token_starts_declspecs (c_token *token)
case RID_SAT:
case RID_ALIGNAS:
case RID_ATOMIC:
+ case RID_DEPENDENT_PTR:
case RID_AUTO_TYPE:
return true;
default:
@@ -2575,6 +2578,7 @@ c_parser_static_assert_declaration_no_semi (c_parser
*parser)
volatile
address-space-qualifier
_Atomic
+ _Dependent_ptr
(restrict is new in C99.)
(_Atomic is new in C11.)
@@ -2865,6 +2869,11 @@ c_parser_declspecs (c_parser *parser, struct
c_declspecs *specs,
else
declspecs_add_qual (loc, specs, value);
break;
+ case RID_DEPENDENT_PTR:
+ attrs_ok = true;
+ declspecs_add_qual (loc, specs, c_parser_peek_token (parser)->value);
+ c_parser_consume_token (parser);
+ break;
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
@@ -4275,6 +4284,7 @@ c_parser_attribute_any_word (c_parser *parser)
case RID_TRANSACTION_ATOMIC:
case RID_TRANSACTION_CANCEL:
case RID_ATOMIC:
+ case RID_DEPENDENT_PTR:
case RID_AUTO_TYPE:
case RID_INT_N_0:
case RID_INT_N_1:
diff --git a/gcc/c/c-tree.h b/gcc/c/c-tree.h
index dae2979..0e416f2 100644
--- a/gcc/c/c-tree.h
+++ b/gcc/c/c-tree.h
@@ -34,6 +34,9 @@ along with GCC; see the file COPYING3. If not see
/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is volatile.
*/
#define C_TYPE_FIELDS_VOLATILE(TYPE) TREE_LANG_FLAG_2 (TYPE)
+/* In a RECORD_TYPE or UNION_TYPE, nonzero if any component is dependent
pointer. */
+#define C_TYPE_FIELDS_DEPENDENT_PTR(TYPE) TREE_LANG_FLAG_3 (TYPE)
+
/* In a RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE
nonzero if the definition of the type has already started. */
#define C_TYPE_BEING_DEFINED(TYPE) TYPE_LANG_FLAG_0 (TYPE)
@@ -279,6 +282,7 @@ enum c_declspec_word {
cdw_volatile,
cdw_restrict,
cdw_atomic,
+ cdw_dependent_ptr,
cdw_saturating,
cdw_alignas,
cdw_address_space,
@@ -387,6 +391,8 @@ struct c_declspecs {
BOOL_BITFIELD restrict_p : 1;
/* Whether "_Atomic" was specified. */
BOOL_BITFIELD atomic_p : 1;
+ /* Whether "_Dependent_ptr" was specified. */
+ BOOL_BITFIELD dependent_ptr_p : 1;
/* Whether "_Sat" was specified. */
BOOL_BITFIELD saturating_p : 1;
/* Whether any alignment specifier (even with zero alignment) was
diff --git a/gcc/print-tree.c b/gcc/print-tree.c
index debea2b..ec4e3db 100644
--- a/gcc/print-tree.c
+++ b/gcc/print-tree.c
@@ -348,6 +348,8 @@ print_node (FILE *file, const char *prefix, tree node,
int indent,
fputs (" addressable", file);
if (TREE_THIS_VOLATILE (node))
fputs (" volatile", file);
+ if (TREE_THIS_DEPENDENT_PTR (node))
+ fputs (" dependent_ptr", file);
if (TREE_ASM_WRITTEN (node))
fputs (" asm_written", file);
if (TREE_USED (node))
diff --git a/gcc/tree-core.h b/gcc/tree-core.h
index 60d8c68..3f3e682 100644
--- a/gcc/tree-core.h
+++ b/gcc/tree-core.h
@@ -567,7 +567,8 @@ enum cv_qualifier {
TYPE_QUAL_CONST = 0x1,
TYPE_QUAL_VOLATILE = 0x2,
TYPE_QUAL_RESTRICT = 0x4,
- TYPE_QUAL_ATOMIC = 0x8
+ TYPE_QUAL_ATOMIC = 0x8,
+ TYPE_QUAL_DEPENDENT_PTR = 0x10
};
/* Standard named or nameless data types of the C compiler. */
@@ -591,6 +592,8 @@ enum tree_index {
TI_ATOMICDI_TYPE,
TI_ATOMICTI_TYPE,
+ TI_DEPENDENT_PTR_TYPE,
+
TI_UINT16_TYPE,
TI_UINT32_TYPE,
TI_UINT64_TYPE,
@@ -969,6 +972,7 @@ struct GTY(()) tree_base {
unsigned asm_written_flag: 1;
unsigned nowarning_flag : 1;
unsigned visited : 1;
+ unsigned dependent_ptr_flag : 1;
unsigned used_flag : 1;
unsigned nothrow_flag : 1;
diff --git a/gcc/tree-pretty-print.c b/gcc/tree-pretty-print.c
index 9bea132..ae59cea 100644
--- a/gcc/tree-pretty-print.c
+++ b/gcc/tree-pretty-print.c
@@ -1622,6 +1622,8 @@ dump_generic_node (pretty_printer *pp, tree node, int
spc, dump_flags_t flags,
pp_string (pp, "atomic ");
if (quals & TYPE_QUAL_CONST)
pp_string (pp, "const ");
+ if (quals & TYPE_QUAL_DEPENDENT_PTR)
+ pp_string (pp, "dependent_ptr ");
else if (quals & TYPE_QUAL_VOLATILE)
pp_string (pp, "volatile ");
else if (quals & TYPE_QUAL_RESTRICT)
@@ -1768,6 +1770,8 @@ dump_generic_node (pretty_printer *pp, tree node, int
spc, dump_flags_t flags,
pp_string (pp, " volatile");
if (quals & TYPE_QUAL_RESTRICT)
pp_string (pp, " restrict");
+ if (quals & TYPE_QUAL_DEPENDENT_PTR)
+ pp_string (pp, " dependent_ptr");
if (!ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (node)))
{
@@ -1871,6 +1875,8 @@ dump_generic_node (pretty_printer *pp, tree node, int
spc, dump_flags_t flags,
if (quals & TYPE_QUAL_ATOMIC)
pp_string (pp, "atomic ");
+ if (quals & TYPE_QUAL_DEPENDENT_PTR)
+ pp_string (pp, "dependent_ptr ");
if (quals & TYPE_QUAL_CONST)
pp_string (pp, "const ");
if (quals & TYPE_QUAL_VOLATILE)
diff --git a/gcc/tree.c b/gcc/tree.c
index 8cf75f2..b4dff8d 100644
--- a/gcc/tree.c
+++ b/gcc/tree.c
@@ -5213,6 +5213,7 @@ fld_type_variant (tree first, tree t, class
free_lang_data_d *fld,
TYPE_READONLY (v) = TYPE_READONLY (t);
TYPE_VOLATILE (v) = TYPE_VOLATILE (t);
TYPE_ATOMIC (v) = TYPE_ATOMIC (t);
+ TYPE_DEPENDENT_PTR (v) = TYPE_DEPENDENT_PTR (t);
TYPE_RESTRICT (v) = TYPE_RESTRICT (t);
TYPE_ADDR_SPACE (v) = TYPE_ADDR_SPACE (t);
TYPE_NAME (v) = TYPE_NAME (t);
@@ -6348,6 +6349,7 @@ set_type_quals (tree type, int type_quals)
TYPE_VOLATILE (type) = (type_quals & TYPE_QUAL_VOLATILE) != 0;
TYPE_RESTRICT (type) = (type_quals & TYPE_QUAL_RESTRICT) != 0;
TYPE_ATOMIC (type) = (type_quals & TYPE_QUAL_ATOMIC) != 0;
+ TYPE_DEPENDENT_PTR (type) = (type_quals & TYPE_QUAL_DEPENDENT_PTR) != 0;
TYPE_ADDR_SPACE (type) = DECODE_QUAL_ADDR_SPACE (type_quals);
}
diff --git a/gcc/tree.h b/gcc/tree.h
index 4aa2c4a..0c2f192 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -789,6 +789,9 @@ extern void omp_clause_range_check_failed (const_tree,
const char *, int,
If this bit is set in an expression, so is TREE_SIDE_EFFECTS. */
#define TREE_THIS_VOLATILE(NODE) ((NODE)->base.volatile_flag)
+/* Nonzero means this expression is involved in some data dependency. */
+#define TREE_THIS_DEPENDENT_PTR(NODE) ((NODE)->base.dependent_ptr_flag)
+
/* Nonzero means this node will not trap. In an INDIRECT_REF, means
accessing the memory pointed to won't generate a trap. However,
this only applies to an object when used appropriately: it doesn't
@@ -2070,6 +2073,9 @@ extern machine_mode vector_type_mode (const_tree);
/* Nonzero in a type considered atomic as a whole. */
#define TYPE_ATOMIC(NODE) (TYPE_CHECK (NODE)->base.u.bits.atomic_flag)
+/* Nonzero in a type considered dependent_ptr as a whole. */
+#define TYPE_DEPENDENT_PTR(NODE) (TYPE_CHECK
(NODE)->base.dependent_ptr_flag)
+
/* Means this type is const-qualified. */
#define TYPE_READONLY(NODE) (TYPE_CHECK (NODE)->base.readonly_flag)
@@ -2100,6 +2106,7 @@ extern machine_mode vector_type_mode (const_tree);
((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
| (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
| (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
+ | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR) \
| (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT) \
| (ENCODE_QUAL_ADDR_SPACE (TYPE_ADDR_SPACE (NODE)))))
@@ -2108,6 +2115,7 @@ extern machine_mode vector_type_mode (const_tree);
((int) ((TYPE_READONLY (NODE) * TYPE_QUAL_CONST) \
| (TYPE_VOLATILE (NODE) * TYPE_QUAL_VOLATILE) \
| (TYPE_ATOMIC (NODE) * TYPE_QUAL_ATOMIC) \
+ | (TYPE_DEPENDENT_PTR (NODE) * TYPE_QUAL_DEPENDENT_PTR) \
| (TYPE_RESTRICT (NODE) * TYPE_QUAL_RESTRICT)))
/* The same as TYPE_QUALS without the address space and atomic
@@ -3940,6 +3948,8 @@ tree_strip_any_location_wrapper (tree exp)
#define atomicDI_type_node global_trees[TI_ATOMICDI_TYPE]
#define atomicTI_type_node global_trees[TI_ATOMICTI_TYPE]
+#define dependent_ptrTI_type_node global_trees[TI_DEPENDENT_PTR_TYPE]
+
#define uint16_type_node global_trees[TI_UINT16_TYPE]
#define uint32_type_node global_trees[TI_UINT32_TYPE]
#define uint64_type_node global_trees[TI_UINT64_TYPE]
diff --git a/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
b/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
new file mode 100644
index 0000000..8a70733
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/c11-dependent_ptr-test-1.c
@@ -0,0 +1,62 @@
+/* Test for _Dependent_ptr. _Dependent_ptr qualified pointer
initialization tests. */
+/* { dg-do run } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+
+#define TEST_SIMPLE_ASSIGN(TYPE) \
+ do \
+ { \
+ static volatile _Atomic (TYPE) * _Dependent_ptr a; \
+ static volatile _Atomic (TYPE) b; \
+ a = &b; \
+ if (a != &b) \
+ abort(); \
+ } \
+ while (0)
+
+#define TEST_SIMPLE_ASSIGN_POINTER() \
+ do \
+ { \
+ TEST_SIMPLE_ASSIGN (_Bool); \
+ TEST_SIMPLE_ASSIGN (char); \
+ TEST_SIMPLE_ASSIGN (signed char); \
+ TEST_SIMPLE_ASSIGN (unsigned char); \
+ TEST_SIMPLE_ASSIGN (signed short); \
+ TEST_SIMPLE_ASSIGN (unsigned short); \
+ TEST_SIMPLE_ASSIGN (signed int); \
+ TEST_SIMPLE_ASSIGN (unsigned int); \
+ TEST_SIMPLE_ASSIGN (signed long); \
+ TEST_SIMPLE_ASSIGN (unsigned long); \
+ TEST_SIMPLE_ASSIGN (signed long long); \
+ TEST_SIMPLE_ASSIGN (unsigned long long); \
+ TEST_SIMPLE_ASSIGN (float); \
+ TEST_SIMPLE_ASSIGN (double); \
+ TEST_SIMPLE_ASSIGN (long double); \
+ TEST_SIMPLE_ASSIGN (_Complex float); \
+ TEST_SIMPLE_ASSIGN (_Complex double); \
+ TEST_SIMPLE_ASSIGN (_Complex long double); \
+ struct new_struct { struct new_struct * _Dependent_ptr next; }; \
+ struct new_struct * _Dependent_ptr s; \
+ s = malloc (sizeof (struct new_struct)); \
+ struct new_struct t; \
+ s->next = &t; \
+ if (s->next != &t) \
+ abort(); \
+ } \
+ while (0)
+
+static void
+test_simple_assign (void)
+{
+ TEST_SIMPLE_ASSIGN_POINTER ();
+}
+
+int main (void)
+{
+ test_simple_assign ();
+ exit (0);
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig10.c
b/gcc/testsuite/gcc.dg/p0190r4_fig10.c
new file mode 100644
index 0000000..057c2ba
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig10.c
@@ -0,0 +1,46 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test for checking dependency
through non-local storage. Refer figure 10 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+_Atomic struct rcutest *gp;
+struct rcutest *gslp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest *_Dependent_ptr p = rcu_dereference (gp); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+ gslp = p;
+ p = gslp;
+ if (p)
+ assert (p->a = 42);
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig11.c
b/gcc/testsuite/gcc.dg/p0190r4_fig11.c
new file mode 100644
index 0000000..39c4b61
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig11.c
@@ -0,0 +1,51 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test in which reload kills
dependency. Refer figure 11 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+_Atomic struct rcutest *gp;
+_Atomic struct rcutest *gsgp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
dg-warning "\\\[-Wincompatible-pointer-types]" } */
+ atomic_store_explicit(&gsgp, p, memory_order_relaxed); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread2 ()
+{
+ struct rcutest *p;
+
+ p = atomic_load_explicit(&gsgp, memory_order_relaxed); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+ if (p)
+ assert(p->a == 42);
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig12.c
b/gcc/testsuite/gcc.dg/p0190r4_fig12.c
new file mode 100644
index 0000000..4f7fcd3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig12.c
@@ -0,0 +1,53 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test when casting a dependency
pointer to another pointer type which in turn reserves the dependency.
Refer figure 12 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+struct rcutest1
+{
+ int a;
+ struct rcutest rt;
+};
+
+_Atomic struct rcutest *gp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest * _Dependent_ptr p;
+ struct rcutest1 *_Dependent_ptr q;
+
+ p = rcu_dereference (gp); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+ q = p; /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+ if (q)
+ assert(q->a == 42);
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig13.c
b/gcc/testsuite/gcc.dg/p0190r4_fig13.c
new file mode 100644
index 0000000..b4010fc
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig13.c
@@ -0,0 +1,48 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test: casting to non-pointer
kills dependency. Refer figure 13 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+_Atomic struct rcutest *gp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest * _Dependent_ptr p;
+ long int q;
+
+ p = rcu_dereference (gp); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+ q = (long int)(p);
+ p = (_Dependent_ptr struct rcutest *)q;
+ if (p)
+ assert(p->a == 42);
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig8.c
b/gcc/testsuite/gcc.dg/p0190r4_fig8.c
new file mode 100644
index 0000000..e706a9b
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig8.c
@@ -0,0 +1,44 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test for checking simple
left-hand side dependency. Refer figure 8 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+_Atomic struct rcutest *gp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ assert (p->a != 43);
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
dg-warning "\\\[-Wincompatible-pointer-types]" } */
+ if (p)
+ p->a = 43;
+}
diff --git a/gcc/testsuite/gcc.dg/p0190r4_fig9.c
b/gcc/testsuite/gcc.dg/p0190r4_fig9.c
new file mode 100644
index 0000000..32f67b3
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/p0190r4_fig9.c
@@ -0,0 +1,43 @@
+/* Test for _Dependent_ptr. _Dependent_ptr test for checking simple
right-hand side dependency. Refer figure 9 in document p0190r4 (
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0190r4.pdf). */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic" } */
+
+#include <stdatomic.h>
+
+typedef __SIZE_TYPE__ size_t;
+extern void abort (void);
+extern void exit (int);
+extern void *malloc (size_t);
+extern int assert ();
+
+struct rcutest
+{
+ int a;
+ int b;
+ int c;
+};
+
+_Atomic struct rcutest *gp;
+
+#define rcu_assign_pointer(p,v) \
+ atomic_store_explicit(&(p), (v), memory_order_release);
+
+#define rcu_dereference(p) \
+ atomic_load_explicit(&(p), memory_order_consume);
+
+void thread0 ()
+{
+ struct rcutest *p;
+
+ p = (struct rcutest *)malloc (sizeof (*p));
+ assert (p);
+ p->a = 42;
+ rcu_assign_pointer (gp,p); /* { dg-warning
"\\\[-Wincompatible-pointer-types]" } */
+}
+
+void thread1 ()
+{
+ struct rcutest * _Dependent_ptr p = rcu_dereference (gp); /* {
dg-warning "\\\[-Wincompatible-pointer-types]" } */
+ if (p)
+ assert (p->a = 42);
+}