Akshat
On Sat, Aug 3, 2019 at 8:00 AM Martin Sebor <mse...@gmail.com
<mailto:mse...@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 <mse...@gmail.com
<mailto:mse...@gmail.com>> wrote:
>>
>> On 7/30/19 1:13 AM, Akshat Garg wrote:
>>> Hi,
>>> This patch includes C front-end code for a type qualifier
_Dependent_ptr.
>>
>> Just some very high-level comments/questions. I only followed
>> the _Dependent_ptr discussion from a distance and I'm likely
>> missing some context so the first thing I looked for in this
>> patch is documentation of the new qualifier. Unless it's
>> a proposed C2x feature that I missed I would expect to find it
>> in section 6 - Extensions to the C Language Family of the manual.
>> I saw the references to WG21's p0190r4 in the tests but the paper
>> doesn't mention _Dependent_ptr, and I found no references to a C
>> paper that does. If it has been proposed for C2X as well can
>> you point to it? (In that case, or if a proposal is planned,
>> the feature should probably either only be available with
>> -std=c2x and -std=gnu2x or a pedantic warning should be issued
>> for its use in earlier modes similarly to how uses of _Atomic
>> are diagnosed in pre-C11 modes.)
>>
>> Martin
>>
>>> The patch has been tested using the following
>>> make bootstrap -j 4
>>> make -k check -j 4
>>>
>>> on x86_64-linux-gnu.
>>>
>>> Thanks,
>>> Akshat
>>>
>>> gcc/ChangeLog:
>>>
>>> 2019-07-30 Akshat Garg <xks...@gmail.com
<mailto: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
<mailto: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);
>>> +}
>>>
>>