From: Jason Merrill <jason@redhat.com>
To: Paul Iannetta <piannetta@kalrayinc.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH v2] c++: parser - Support for target address spaces in C++
Date: Tue, 11 Oct 2022 21:49:43 -0400 [thread overview]
Message-ID: <19526772-3afb-87d1-190a-5ab0ffb566a9@redhat.com> (raw)
In-Reply-To: <20221011220017.pvs5jawrzqoaqkkf@ws2202.lin.mbt.kalray.eu>
On 10/11/22 18:03, Paul Iannetta wrote:
> Thank you very much for the comments.
>
> On Mon, Oct 10, 2022 at 03:20:13PM -0400, Jason Merrill wrote:
>> On 10/9/22 12:12, Paul Iannetta wrote:
>>> That's a nice feature! LLVM is using AS<number> to mangle the
>>> address-name qualified types but that would have required an update of
>>> libiberty's demangler in the binutils as well.
>>
>> And they haven't proposed this mangling to
>>
>> https://github.com/itanium-cxx-abi/cxx-abi/
>>
>> yet, either.
>
> When looking at clang/lib/AST/{Microsoft,Itamium}Mangle.cpp, the
> comments may suggest that they wanted to implement them as extended
> qualifiers prefixed by an `U' but that's not what they ended up doing.
>
>> You certainly want some template tests, say
>>
>> template <class T>
>> int f (T *p) { return *p; }
>> __seg_fs int *a;
>> int main() { f(a); }
>> // test for mangling of f<__seg_fs int>
>>
>> -----
>>
>> template <class T>
>> int f (T __seg_gs *p) { return *p; }
>> __seg_fs int *a;
>> int main() { f(a); } // error, conflicting address spaces
>
> Indeed, I was getting the first one right by a stroke of luck but not
> the second. I've consequently adapted the part which checks and
> computes the unification of cv-qualifiers in the presence of address
> spaces. The idea being that a type parameter T can match any address
> spaces but an address-space qualified parameter can't accept more
> general address spaces than itself.
>
>>> +/* Return true if between two named address spaces, whether there is a superset
>>> + named address space that encompasses both address spaces. If there is a
>>> + superset, return which address space is the superset. */
>>> +
>>> +bool
>>> +addr_space_superset (addr_space_t as1, addr_space_t as2,
>>> + addr_space_t * common)
>>> +{
>>> + if (as1 == as2)
>>> + {
>>> + *common = as1;
>>> + return true;
>>> + }
>>> + else if (targetm.addr_space.subset_p (as1, as2))
>>> + {
>>> + *common = as2;
>>> + return true;
>>> + }
>>> + else if (targetm.addr_space.subset_p (as2, as1))
>>> + {
>>> + *common = as1;
>>> + return true;
>>> + }
>>> + else
>>> + return false;
>>
>> So it's not possible for the two spaces to both be subsets of a third?
>>
>
> According to the [N1275, page 38]:
> Address spaces may overlap in a nested fashion. For any two address
> spaces, either the address spaces must be disjoint, they must be
> equivalent, or one must be a subset of the other. [...] There is no
> requirement that named address spaces (intrinsic or otherwise) be
> subsets of the generic address space.
> [N1275]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1275.pdf
>
> Hence, two disjoint address spaces can't be subsets of a third, per
> the draft.
>
>>
>> New non-bit-fields should be added before the bit-fields.
>>
>
> Done.
>
>>> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
>>> index eb53e0ebeb4..06625ad9a4b 100644
>>> --- a/gcc/cp/mangle.cc
>>> +++ b/gcc/cp/mangle.cc
>>> @@ -2509,6 +2509,15 @@ write_CV_qualifiers_for_type (const tree type)
>>> array. */
>>> cp_cv_quals quals = TYPE_QUALS (type);
>>> + if (DECODE_QUAL_ADDR_SPACE (quals))
>>> + {
>>> + addr_space_t as = DECODE_QUAL_ADDR_SPACE (quals);
>>
>> This can be
>>
>> if (addr_space_t as = DECODE_QUAL_ADDR_SPACE (quals))
>>
>> so you don't need to repeat it.
>
> I thought this was c++17 only, but in fact c++17 only broadened the
> idiom. Nice! (It would be even nicer to have this feature in C as
> well)
>>> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
>>> index 763df6f479b..110ceafc98b 100644
>>> --- a/gcc/cp/parser.cc
>>> +++ b/gcc/cp/parser.cc
>>> [...]
>>> @@ -23812,6 +23830,13 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
>>> break;
>>> }
>>> + if (RID_FIRST_ADDR_SPACE <= token->keyword &&
>>> + token->keyword <= RID_LAST_ADDR_SPACE)
>>> + {
>>> + cv_qualifier =
>>> + ENCODE_QUAL_ADDR_SPACE (token->keyword - RID_FIRST_ADDR_SPACE);
>>> + }
>>
>> We usually omit braces around a single statement.
>>
> Done.
>
> # ------------------------ >8 ------------------------
> Add support for custom address spaces in C++
>
> gcc/
> * tree.h (ENCODE_QUAL_ADDR_SPACE): Missing parentheses.
>
> gcc/c/
> * c-decl.cc: Remove c_register_addr_space.
>
> gcc/c-family/
> * c-common.cc (c_register_addr_space): Imported from c-decl.cc
> (addr_space_superset): Imported from gcc/c/c-typecheck.cc
> * c-common.h: Remove the FIXME.
> (addr_space_superset): New declaration.
>
> gcc/cp/
> * cp-tree.h (enum cp_decl_spec): Add addr_space support.
> (struct cp_decl_specifier_seq): Likewise.
> * decl.cc (get_type_quals): Likewise.
> (check_tag_decl): Likewise.
> * parser.cc (cp_parser_type_specifier): Likewise.
> (cp_parser_cv_qualifier_seq_opt): Likewise.
> (cp_parser_postfix_expression): Likewise.
> (cp_parser_type_specifier): Likewise.
> (set_and_check_decl_spec_loc): Likewise.
> * typeck.cc (composite_pointer_type): Likewise
> (comp_ptr_ttypes_real): Likewise.
> * pt.cc (check_cv_quals_for_unify): Likewise.
> (unify): Likewise.
> * tree.cc: Remove c_register_addr_space stub.
> * mangle.cc (write_CV_qualifiers_for_type): Mangle address spaces
> using the extended qualifier notation.
>
> gcc/doc
> * extend.texi (Named Address Spaces): add a mention about C++
> support.
>
> gcc/testsuite/
> * g++.dg/abi/mangle-addr-space1.C: New test.
> * g++.dg/abi/mangle-addr-space2.C: New test.
> * g++.dg/parse/addr-space.C: New test.
> * g++.dg/parse/addr-space1.C: New test.
> * g++.dg/parse/addr-space2.C: New test.
> * g++.dg/parse/template/spec-addr-space.C: New test.
>
> # ------------------------ >8 ------------------------
> diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
> index bb0544eeaea..ff1146ecc25 100644
> --- a/gcc/c-family/c-common.cc
> +++ b/gcc/c-family/c-common.cc
> @@ -615,6 +615,33 @@ c_addr_space_name (addr_space_t as)
> return IDENTIFIER_POINTER (ridpointers [rid]);
> }
>
> +/* Return true if between two named address spaces, whether there is a superset
> + named address space that encompasses both address spaces. If there is a
> + superset, return which address space is the superset. */
> +
> +bool
> +addr_space_superset (addr_space_t as1, addr_space_t as2,
> + addr_space_t * common)
> +{
> + if (as1 == as2)
> + {
> + *common = as1;
> + return true;
> + }
> + else if (targetm.addr_space.subset_p (as1, as2))
> + {
> + *common = as2;
> + return true;
> + }
> + else if (targetm.addr_space.subset_p (as2, as1))
> + {
> + *common = as1;
> + return true;
> + }
> + else
> + return false;
> +}
> +
> /* Push current bindings for the function name VAR_DECLS. */
>
> void
> @@ -2809,6 +2836,25 @@ c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
> return build_nonstandard_integer_type (width, unsignedp);
> }
>
> +/* Register reserved keyword WORD as qualifier for address space AS. */
> +
> +void
> +c_register_addr_space (const char *word, addr_space_t as)
> +{
> + int rid = RID_FIRST_ADDR_SPACE + as;
> + tree id;
> +
> + /* Address space qualifiers are only supported
> + in C with GNU extensions enabled. */
> + if (c_dialect_objc () || flag_no_asm)
> + return;
> +
> + id = get_identifier (word);
> + C_SET_RID_CODE (id, rid);
> + TREE_LANG_FLAG_0 (id) = 1;
> + ridpointers[rid] = id;
> +}
> +
> /* The C version of the register_builtin_type langhook. */
>
> void
> diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
> index 52a85bfb783..d36f9e4975b 100644
> --- a/gcc/c-family/c-common.h
> +++ b/gcc/c-family/c-common.h
> @@ -829,12 +829,11 @@ extern const struct attribute_spec c_common_format_attribute_table[];
>
> extern tree (*make_fname_decl) (location_t, tree, int);
>
> -/* In c-decl.cc and cp/tree.cc. FIXME. */
> -extern void c_register_addr_space (const char *str, addr_space_t as);
> -
> /* In c-common.cc. */
> extern bool in_late_binary_op;
> extern const char *c_addr_space_name (addr_space_t as);
> +extern const char *c_addr_space_name (addr_space_t as);
> +extern bool addr_space_superset (addr_space_t, addr_space_t, addr_space_t *);
> extern tree identifier_global_value (tree);
> extern tree identifier_global_tag (tree);
> extern bool names_builtin_p (const char *);
> @@ -952,6 +951,7 @@ extern void c_common_finish (void);
> extern void c_common_parse_file (void);
> extern FILE *get_dump_info (int, dump_flags_t *);
> extern alias_set_type c_common_get_alias_set (tree);
> +extern void c_register_addr_space (const char *, addr_space_t);
> extern void c_register_builtin_type (tree, const char*);
> extern bool c_promoting_integer_type_p (const_tree);
> extern bool self_promoting_args_p (const_tree);
> diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
> index c701f07befe..e1bb4f1cf37 100644
> --- a/gcc/c/c-decl.cc
> +++ b/gcc/c/c-decl.cc
> @@ -12337,25 +12337,6 @@ c_parse_final_cleanups (void)
> ext_block = NULL;
> }
>
> -/* Register reserved keyword WORD as qualifier for address space AS. */
> -
> -void
> -c_register_addr_space (const char *word, addr_space_t as)
> -{
> - int rid = RID_FIRST_ADDR_SPACE + as;
> - tree id;
> -
> - /* Address space qualifiers are only supported
> - in C with GNU extensions enabled. */
> - if (c_dialect_objc () || flag_no_asm)
> - return;
> -
> - id = get_identifier (word);
> - C_SET_RID_CODE (id, rid);
> - C_IS_RESERVED_WORD (id) = 1;
> - ridpointers [rid] = id;
> -}
> -
> /* Return identifier to look up for omp declare reduction. */
>
> tree
> diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
> index b271af9bedb..c4b01368534 100644
> --- a/gcc/c/c-typeck.cc
> +++ b/gcc/c/c-typeck.cc
> @@ -296,32 +296,6 @@ c_type_promotes_to (tree type)
> return type;
> }
>
> -/* Return true if between two named address spaces, whether there is a superset
> - named address space that encompasses both address spaces. If there is a
> - superset, return which address space is the superset. */
> -
> -static bool
> -addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
> -{
> - if (as1 == as2)
> - {
> - *common = as1;
> - return true;
> - }
> - else if (targetm.addr_space.subset_p (as1, as2))
> - {
> - *common = as2;
> - return true;
> - }
> - else if (targetm.addr_space.subset_p (as2, as1))
> - {
> - *common = as1;
> - return true;
> - }
> - else
> - return false;
> -}
> -
> /* Return a variant of TYPE which has all the type qualifiers of LIKE
> as well as those of TYPE. */
>
> diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
> index 72f4398a8f9..82a6d72f5df 100644
> --- a/gcc/cp/cp-tree.h
> +++ b/gcc/cp/cp-tree.h
> @@ -6206,6 +6206,7 @@ enum cp_decl_spec {
> ds_const,
> ds_volatile,
> ds_restrict,
> + ds_addr_space,
> ds_inline,
> ds_virtual,
> ds_explicit,
> @@ -6252,6 +6253,8 @@ struct cp_decl_specifier_seq {
> cp_storage_class storage_class;
> /* For the __intN declspec, this stores the index into the int_n_* arrays. */
> int int_n_idx;
> + /* The address space that the declaration belongs to. */
> + addr_space_t address_space;
> /* True iff TYPE_SPEC defines a class or enum. */
> BOOL_BITFIELD type_definition_p : 1;
> /* True iff multiple types were (erroneously) specified for this
> diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
> index 9f78c500a15..16cc1917085 100644
> --- a/gcc/cp/decl.cc
> +++ b/gcc/cp/decl.cc
> @@ -5280,6 +5280,8 @@ get_type_quals (const cp_decl_specifier_seq *declspecs)
> type_quals |= TYPE_QUAL_VOLATILE;
> if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
> type_quals |= TYPE_QUAL_RESTRICT;
> + if (decl_spec_seq_has_spec_p (declspecs, ds_addr_space))
> + type_quals |= ENCODE_QUAL_ADDR_SPACE (declspecs->address_space);
>
> return type_quals;
> }
> @@ -5402,6 +5404,10 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
> error_at (declspecs->locations[ds_restrict],
> "%<__restrict%> can only be specified for objects and "
> "functions");
> + else if (decl_spec_seq_has_spec_p (declspecs, ds_addr_space))
> + error_at (declspecs->locations[ds_addr_space],
> + "address space can only be specified for objects and "
> + "functions");
> else if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
> error_at (declspecs->locations[ds_thread],
> "%<__thread%> can only be specified for objects "
> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> index eb53e0ebeb4..8ea6b7c903e 100644
> --- a/gcc/cp/mangle.cc
> +++ b/gcc/cp/mangle.cc
> @@ -2509,6 +2509,14 @@ write_CV_qualifiers_for_type (const tree type)
> array. */
> cp_cv_quals quals = TYPE_QUALS (type);
>
> + if (addr_space_t as DECODE_QUAL_ADDR_SPACE (quals))
Let's still include the =, rather than rely on the parens from the macro.
> + {
> + const char *as_name = c_addr_space_name (as);
> + write_char ('U');
> + write_unsigned_number (strlen (as_name));
> + write_string (as_name);
> + ++num_qualifiers;
> + }
> if (quals & TYPE_QUAL_RESTRICT)
> {
> write_char ('r');
> diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> index 763df6f479b..f0169d83ab0 100644
> --- a/gcc/cp/parser.cc
> +++ b/gcc/cp/parser.cc
> @@ -7640,6 +7640,14 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p, bool cast_p,
> postfix_expression = error_mark_node;
> break;
> }
> + if (type != error_mark_node
> + && !ADDR_SPACE_GENERIC_P (TYPE_ADDR_SPACE (type))
> + && current_function_decl)
> + {
> + error
> + ("compound literal qualified by address-space qualifier");
> + type = error_mark_node;
> + }
It surprises that this is the only place we complain about an object
with an address-space qualifier. Shouldn't we also complain about e.g.
automatic variables/parameters or non-static data members with
address-space qualified type?
> /* Form the representation of the compound-literal. */
> postfix_expression
> = finish_compound_literal (type, initializer,
> @@ -19408,6 +19416,15 @@ cp_parser_type_specifier (cp_parser* parser,
> break;
> }
>
> +
> + if (RID_FIRST_ADDR_SPACE <= keyword && keyword <= RID_LAST_ADDR_SPACE)
> + {
> + ds = ds_addr_space;
> + if (is_cv_qualifier)
> + *is_cv_qualifier = true;
> + }
> +
> +
> /* Handle simple keywords. */
> if (ds != ds_last)
> {
> @@ -23776,6 +23793,7 @@ cp_parser_ptr_operator (cp_parser* parser,
> GNU Extension:
>
> cv-qualifier:
> + address-space-qualifier
> __restrict__
>
> Returns a bitmask representing the cv-qualifiers. */
> @@ -23812,6 +23830,11 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
> break;
> }
>
> + if (RID_FIRST_ADDR_SPACE <= token->keyword &&
> + token->keyword <= RID_LAST_ADDR_SPACE)
> + cv_qualifier =
> + ENCODE_QUAL_ADDR_SPACE (token->keyword - RID_FIRST_ADDR_SPACE);
> +
> if (!cv_qualifier)
> break;
>
> @@ -32705,6 +32728,8 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
> decl_specs->locations[ds] = location;
> if (ds == ds_thread)
> decl_specs->gnu_thread_keyword_p = token_is__thread (token);
> + else if (ds == ds_addr_space)
> + decl_specs->address_space = token->keyword - RID_FIRST_ADDR_SPACE;
> }
> else
> {
> @@ -32737,6 +32762,25 @@ set_and_check_decl_spec_loc (cp_decl_specifier_seq *decl_specs,
> error_at (&richloc, "duplicate %qD", token->u.value);
> }
> }
> + else if (ds == ds_addr_space)
> + {
> + addr_space_t as1 = decl_specs->address_space;
> + addr_space_t as2 = token->keyword - RID_FIRST_ADDR_SPACE;
> +
> + gcc_rich_location richloc (location);
> + richloc.add_fixit_remove ();
> + if (!ADDR_SPACE_GENERIC_P (as1) && !ADDR_SPACE_GENERIC_P (as2)
> + && as1 != as2)
> + error_at (&richloc,
> + "conflicting named address spaces (%s vs %s)",
> + c_addr_space_name (as1), c_addr_space_name (as2));
> + if (as1 == as2 && !ADDR_SPACE_GENERIC_P (as1))
> + error_at (&richloc,
> + "duplicate named address space %s",
> + c_addr_space_name (as1));
> +
> + decl_specs->address_space = as2;
> + }
> else
> {
> static const char *const decl_spec_names[] = {
> diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
> index bef31416fb7..5bb5d657155 100644
> --- a/gcc/cp/pt.cc
> +++ b/gcc/cp/pt.cc
> @@ -23655,8 +23655,19 @@ template_decl_level (tree decl)
> static int
> check_cv_quals_for_unify (int strict, tree arg, tree parm)
> {
> - int arg_quals = cp_type_quals (arg);
> - int parm_quals = cp_type_quals (parm);
> + int arg_quals = CLEAR_QUAL_ADDR_SPACE (cp_type_quals (arg));
> + int parm_quals = CLEAR_QUAL_ADDR_SPACE (cp_type_quals (parm));
> +
> + /* Try to unify ARG's address space into PARM's address space.
> + If PARM does not have any address space qualifiers (ie., as_parm is 0),
> + there are no constraints on address spaces for this type. */
> + addr_space_t as_arg = DECODE_QUAL_ADDR_SPACE (cp_type_quals (arg));
> + addr_space_t as_parm = DECODE_QUAL_ADDR_SPACE (cp_type_quals (parm));
> + addr_space_t as_common;
> + addr_space_superset (as_arg, as_parm, &as_common);
> +
> + if (!(as_parm == as_common || as_parm == 0))
> + return 0;
>
> if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
> && !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
> @@ -24292,10 +24303,26 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
> arg, parm))
> return unify_cv_qual_mismatch (explain_p, parm, arg);
>
> + int arg_cv_quals = cp_type_quals (arg);
> + int parm_cv_quals = cp_type_quals (parm);
> +
> + /* If PARM does not contain any address spaces constraints it can
> + fully match the address space of ARG. However, if PARM contains an
> + address space constraints, it becomes the upper bound. That is,
> + AS_ARG may be promoted to AS_PARM but not the converse. If we
> + ended up here, it means that `check_cv_quals_for_unify' succeeded
> + and that either AS_PARM is 0 (ie., no constraints) or AS_COMMON ==
> + AS_PARM. */
> + addr_space_t as_arg = DECODE_QUAL_ADDR_SPACE (arg_cv_quals);
> + addr_space_t as_parm = DECODE_QUAL_ADDR_SPACE (parm_cv_quals);
> + addr_space_t as_common = !as_parm ? as_arg : as_parm;
> +
> /* Consider the case where ARG is `const volatile int' and
> PARM is `const T'. Then, T should be `volatile int'. */
> - arg = cp_build_qualified_type_real
> - (arg, cp_type_quals (arg) & ~cp_type_quals (parm), tf_none);
> + int unified_cv =
> + CLEAR_QUAL_ADDR_SPACE (arg_cv_quals & ~parm_cv_quals)
> + | ENCODE_QUAL_ADDR_SPACE (as_common);
> + arg = cp_build_qualified_type_real (arg, unified_cv, tf_none);
> if (arg == error_mark_node)
> return unify_invalid (explain_p);
>
> diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
> index 3b37567cbd7..5e14ac837fc 100644
> --- a/gcc/cp/tree.cc
> +++ b/gcc/cp/tree.cc
> @@ -6048,15 +6048,6 @@ cp_free_lang_data (tree t)
> DECL_CHAIN (t) = NULL_TREE;
> }
>
> -/* Stub for c-common. Please keep in sync with c-decl.cc.
> - FIXME: If address space support is target specific, then this
> - should be a C target hook. But currently this is not possible,
> - because this function is called via REGISTER_TARGET_PRAGMAS. */
> -void
> -c_register_addr_space (const char * /*word*/, addr_space_t /*as*/)
> -{
> -}
> -
> /* Return the number of operands in T that we care about for things like
> mangling. */
>
> diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
> index ceb80d9744f..5d48920e687 100644
> --- a/gcc/cp/typeck.cc
> +++ b/gcc/cp/typeck.cc
> @@ -656,10 +656,26 @@ composite_pointer_type (const op_location_t &location,
> else
> return error_mark_node;
> }
> + /* If possible merge the address space into the superset of the address
> + spaces of t1 and t2, or raise an error. */
> + addr_space_t as_t1 = TYPE_ADDR_SPACE (t1);
> + addr_space_t as_t2 = TYPE_ADDR_SPACE (t2);
> + addr_space_t as_common;
> +
> + /* If the two named address spaces are different, determine the common
> + superset address space. If there isn't one, raise an error. */
> + if (!addr_space_superset (as_t1, as_t2, &as_common))
> + {
> + as_common = as_t1;
> + error_at (location,
> + "%qT and %qT are in disjoint named address spaces",
> + t1, t2);
> + }
> result_type
> = cp_build_qualified_type (void_type_node,
> - (cp_type_quals (TREE_TYPE (t1))
> - | cp_type_quals (TREE_TYPE (t2))));
> + (CLEAR_QUAL_ADDR_SPACE (cp_type_quals (TREE_TYPE (t1)))
> + | CLEAR_QUAL_ADDR_SPACE (cp_type_quals (TREE_TYPE (t2)))
> + | ENCODE_QUAL_ADDR_SPACE (as_common)));
> result_type = build_pointer_type (result_type);
> /* Merge the attributes. */
> attributes = (*targetm.merge_type_attributes) (t1, t2);
> @@ -10805,6 +10821,19 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
> to_more_cv_qualified = true;
> }
>
> + /* Warn about conversions between pointers to disjoint
> + address spaces. */
> + if (TREE_CODE (from) == POINTER_TYPE
> + && TREE_CODE (to) == POINTER_TYPE)
> + {
> + addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (from));
> + addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (to));
> + addr_space_t as_common;
> +
> + if (!addr_space_superset (as_to, as_from, &as_common))
> + return false;
> + }
> +
> if (constp > 0)
> constp &= TYPE_READONLY (to);
> }
> diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> index ac3db88566d..1e0d436c02c 100644
> --- a/gcc/doc/extend.texi
> +++ b/gcc/doc/extend.texi
> @@ -1448,7 +1448,7 @@ Fixed-point types are supported by the DWARF debug information format.
> @section Named Address Spaces
> @cindex Named Address Spaces
>
> -As an extension, GNU C supports named address spaces as
> +As an extension, GNU C and GNU C++ support named address spaces as
> defined in the N1275 draft of ISO/IEC DTR 18037. Support for named
> address spaces in GCC will evolve as the draft technical report
> changes. Calling conventions for any target might also change. At
> diff --git a/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C b/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C
> new file mode 100644
> index 00000000000..c01f8d6054a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C
> @@ -0,0 +1,10 @@
> +// { dg-do run { target { i?86-*-* x86_64-*-* } } }
> +// { dg-options "-fabi-version=8 -Wabi -save-temps" }
> +// { dg-final { scan-assembler "_Z1fPU8__seg_fsVi" } }
> +
> +int f (int volatile __seg_fs *a)
> +{
> + return *a;
> +}
> +
> +int main () {}
> diff --git a/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C b/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C
> new file mode 100644
> index 00000000000..862bbbdcdf2
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C
> @@ -0,0 +1,9 @@
> +// { dg-do run { target { i?86-*-* x86_64-*-* } } }
> +// { dg-options "-fabi-version=8 -Wabi -save-temps" }
> +// { dg-final { scan-assembler "_Z1fIU8__seg_fsiEiPT_" } }
> +
> +template <class T>
> +int f (T *p) { return *p; }
> +int g (__seg_fs int *p) { return *p; }
> +__seg_fs int *a;
> +int main() { f(a); }
> diff --git a/gcc/testsuite/g++.dg/parse/addr-space.C b/gcc/testsuite/g++.dg/parse/addr-space.C
> new file mode 100644
> index 00000000000..ebb6316054a
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/addr-space.C
> @@ -0,0 +1,9 @@
> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
> +
> +__seg_fs struct foo; // { dg-error "address space can only be specified for objects and functions" }
> +
> +int
> +main ()
> +{
> + return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/parse/addr-space1.C b/gcc/testsuite/g++.dg/parse/addr-space1.C
> new file mode 100644
> index 00000000000..2e8ee32a885
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/addr-space1.C
> @@ -0,0 +1,10 @@
> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
> +// { dg-options "-std=gnu++98" }
> +
> +int
> +main ()
> +{
> + struct foo {int a; char b[2];} structure;
> + structure = ((__seg_fs struct foo) {1 + 2, 'a', 0}); // { dg-error "compound literal qualified by address-space qualifier" }
> + return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/parse/addr-space2.C b/gcc/testsuite/g++.dg/parse/addr-space2.C
> new file mode 100644
> index 00000000000..5b2c0f28078
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/parse/addr-space2.C
> @@ -0,0 +1,9 @@
> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
> +
> +__seg_fs __seg_gs int *a; // { dg-error "conflicting named address spaces .__seg_fs vs __seg_gs." }
> +
> +int
> +main ()
> +{
> + return 0;
> +}
> diff --git a/gcc/testsuite/g++.dg/template/spec-addr-space.C b/gcc/testsuite/g++.dg/template/spec-addr-space.C
> new file mode 100644
> index 00000000000..ae9f4de0e1f
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/template/spec-addr-space.C
> @@ -0,0 +1,8 @@
> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
> +
> +template <class T>
> +int f (T __seg_gs *p) { return *p; } // { dg-note "candidate: 'template<class T> int f.__seg_gs T\*." }
> + // { dg-note "template argument deduction/substitution failed:" "" { target *-*-* } .-1 }
> +__seg_fs int *a;
> +int main() { f(a); } // { dg-error "no matching" }
> +// { dg-note "types .__seg_gs T. and .__seg_fs int. have incompatible cv-qualifiers" "" { target *-*-* } .-1 }
> diff --git a/gcc/tree.h b/gcc/tree.h
> index 8844471e9a5..b7da4c5141a 100644
> --- a/gcc/tree.h
> +++ b/gcc/tree.h
> @@ -2229,7 +2229,7 @@ extern tree vector_element_bits_tree (const_tree);
>
> /* Encode/decode the named memory support as part of the qualifier. If more
> than 8 qualifiers are added, these macros need to be adjusted. */
> -#define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)
> +#define ENCODE_QUAL_ADDR_SPACE(NUM) (((NUM) & 0xFF) << 8)
> #define DECODE_QUAL_ADDR_SPACE(X) (((X) >> 8) & 0xFF)
>
> /* Return all qualifiers except for the address space qualifiers. */
>
>
>
>
next prev parent reply other threads:[~2022-10-12 1:49 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-10-06 14:34 [RFC] " Paul Iannetta
2022-10-06 17:34 ` Jason Merrill
2022-10-09 16:12 ` [PATCH] " Paul Iannetta
2022-10-10 19:20 ` Jason Merrill
2022-10-11 22:03 ` [PATCH v2] " Paul Iannetta
2022-10-12 1:49 ` Jason Merrill [this message]
2022-10-13 0:52 ` Paul Iannetta
2022-10-13 5:46 ` Jakub Jelinek
2022-10-13 15:14 ` Paul Iannetta
2022-10-13 15:02 ` Jason Merrill
2022-10-13 15:23 ` Paul Iannetta
2022-10-13 15:47 ` Jason Merrill
2022-10-13 16:02 ` Paul Iannetta
2022-10-13 19:41 ` Jason Merrill
2022-10-13 21:57 ` Paul Iannetta
2022-10-14 15:19 ` Jason Merrill
2022-10-18 7:37 ` [PATCH v3] " Paul Iannetta
2022-10-18 14:24 ` Jason Merrill
2022-10-18 17:01 ` Paul Iannetta
2022-10-19 18:55 ` Jason Merrill
2022-10-26 7:18 ` Paul Iannetta
2022-10-26 16:28 ` Jason Merrill
2022-11-10 15:42 ` [PATCH v4] " Paul Iannetta
2022-11-03 13:38 ` [PATCH v3] " Georg-Johann Lay
2022-11-10 14:08 ` Paul Iannetta
2022-11-10 16:40 ` Georg-Johann Lay
2022-11-14 17:55 ` Jason Merrill
2022-11-15 12:15 ` Georg-Johann Lay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=19526772-3afb-87d1-190a-5ab0ffb566a9@redhat.com \
--to=jason@redhat.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=piannetta@kalrayinc.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).