[PATCH] Adding _Dependent_ptr type qualifier in C part 1/3
Paul E. McKenney
paulmck@linux.ibm.com
Sun Aug 4 23:11:00 GMT 2019
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);
> >>>+}
> >>>
> >>
>
More information about the Gcc-patches
mailing list