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