Hi, This patch includes C front-end code for a type qualifier _Dependent_ptr. The patch has been tested using the following make bootstrap -j 4 make -k check -j 4
on x86_64-linux-gnu. Thanks, Akshat gcc/ChangeLog: 2019-07-30 Akshat Garg <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); +}