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: Fri, 14 Oct 2022 11:19:50 -0400 [thread overview]
Message-ID: <4026cae9-e371-a2ee-2b36-7abc9224afa1@redhat.com> (raw)
In-Reply-To: <20221013215643.o2bymrmffwbtuppu@ws2202.lin.mbt.kalray.eu>
On 10/13/22 17:57, Paul Iannetta wrote:
> On Thu, Oct 13, 2022 at 03:41:16PM -0400, Jason Merrill wrote:
>> On 10/13/22 12:02, Paul Iannetta wrote:
>>> On Thu, Oct 13, 2022 at 11:47:42AM -0400, Jason Merrill wrote:
>>>> On 10/13/22 11:23, Paul Iannetta wrote:
>>>>> On Thu, Oct 13, 2022 at 11:02:24AM -0400, Jason Merrill wrote:
>>>>>> On 10/12/22 20:52, Paul Iannetta wrote:
>>>>>>> On Tue, Oct 11, 2022 at 09:49:43PM -0400, Jason Merrill wrote:
>>>>>>>>
>>>>>>>> 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?
>>>>>>>>
>>>>>>>
>>>>>>> Indeed, I was missing quite a few things here. Thanks.
>>>>>>> I used the draft as basis this time and imported from the C
>>>>>>> implementation the relevant parts. This time, the errors get properly
>>>>>>> emitted when an address space is unduly specified; and comparisons,
>>>>>>> assignments and comparisons are taken care of.
>>>>>>>
>>>>>>> There are quite a few things I would like to clarify concerning some
>>>>>>> implementation details.
>>>>>>> - A variable with automatic storage (which is neither a pointer nor
>>>>>>> a reference) cannot be qualified with an address space. I detect
>>>>>>> this by the combination of `sc_none' and `! toplevel_bindings_p ()',
>>>>>>> but I've also seen the use of `at_function_scope' at other places.
>>>>>>> And I'm unsure which one is appropriate here.
>>>>>>> This detection happens at the very end of grokdeclarator because I
>>>>>>> need to know that the type is a pointer, which is not know until
>>>>>>> very late in the function.
>>>>>>
>>>>>> At that point you have the decl, and you can ask directly what its storage
>>>>>> duration is, perhaps using decl_storage_duration.
>>>>>>
>>>>>> But why do you need to know whether the type is a pointer? The attribute
>>>>>> applies to the target type of the pointer, not the pointer type. I think
>>>>>> the problem is that you're looking at declspecs when you ought to be looking
>>>>>> at type_quals.
>>>>>
>>>>> I need to know that the base type is a pointer to reject invalid
>>>>> declarations such as:
>>>>>
>>>>> int f (__seg_fs int a) { } or int f () { __seg_fs int a; }
>>>>>
>>>>> because parameters and auto variables can have an address space
>>>>> qualifier only if they are pointer or reference type, which I can't
>>>>> tell only from type_quals.
>>>>
>>>> But "int *__seg_fs a" is just as invalid as the above; the difference is not
>>>> whether a is a pointer, but whether the address-space-qualified is the type
>>>> of a itself or some sub-type.
>>>
>>> I agree that "int * __seg_fs a" is invalid but it is accepted by the C
>>> front-end, and by clang (both C and C++), the behavior is that the
>>> address-name is silently ignored.
>>
>> Hmm, that sounds like a bug; in that case, presumably the user meant to
>> qualify the pointed-to type, and silently ignoring seems unlikely to give
>> the effect they want.
>>
>
> Well, actually, I'm re-reading the draft and "int * __seg_fs a" is
> valid. It means "pointer in address space __seg_fs pointing to an
> object in the generic address space", whereas "__seg_fs int * a" means
> "pointer in the generic address space pointing to an object in the
> __seg_fs address-space".
>
> Oddities such as, "__seg_fs int * __seg_gs a" are also perfectly
> valid.
If a has static storage duration, sure; I was still thinking about
declarations with automatic storage duration such as in your example above.
> The reason why I wrongly assumed that the address space was silently
> ignored is that I made a simple test which only relied on the mangled
> function name...
>
> ```
> int * __seg_fs a;
> template <typename T> int f (T *a) { return *a; }
> int main () { return f (a); } // f<int>(int*), since a is in __seg_fs
> // but the pointer is to the generic
> // address-space.
> ```
>
> Implementation-wise, I think I handle that correctly but I'll do a recheck.
>
>>>> You need to look at the qualifiers on type (which should also be the ones in
>>>> type_quals), not the qualifiers in the declspecs.
>>>
>>> I'll have another look, thanks.
>>>
>>>>>>> - I'm having some trouble deciding whether I include those three
>>>>>>> stub programs as tests, they all compile fine and clang accepts
>>>>>>> them as well.
>>>>>>
>>>>>> Why not?
>>>>>
>>>>> I thought they were pretty contrived, since it does not make much
>>>>> sense to strip address space qualifiers, even though it does prove
>>>>> that the implementation support those contrived but valid uses.
>>>>
>>>> Testcases are full of contrived examples testing corner cases. :)
>>>>
>>>>>>
>>>>>>> Ex1:
>>>>>>> ```
>>>>>>> int __seg_fs * fs1;
>>>>>>> int __seg_gs * gs1;
>>>>>>>
>>>>>>> template<typename T> struct strip;
>>>>>>> template<typename T> struct strip<__seg_fs T *> { typedef T type; };
>>>>>>> template<typename T> struct strip<__seg_gs T *> { typedef T type; };
>>>>>>>
>>>>>>> int
>>>>>>> main ()
>>>>>>> {
>>>>>>> *(strip<decltype(fs1)>::type *) fs1 == *(strip<decltype(gs1)>::type *) gs1;
>>>>>>> return 0;
>>>>>>> }
>>>>>>> ```
>>>>>>>
>>>>>>> Ex2:
>>>>>>> ```
>>>>>>> int __seg_fs * fs1;
>>>>>>> int __seg_fs * fs2;
>>>>>>>
>>>>>>> template<typename T, typename U> auto f (T __seg_fs * a, U __seg_gs * b) { return a; }
>>>>>>> template<typename T, typename U> auto f (T __seg_gs * a, U __seg_fs * b) { return a; }
>>>>>>>
>>>>>>> int
>>>>>>> main ()
>>>>>>> {
>>>>>>> f (fs1, gs1);
>>>>>>> f (gs1, fs1);
>>>>>>> return 0;
>>>>>>> }
>>>>>>> ```
>>>>>>>
>>>>>>> Ex3:
>>>>>>> ```
>>>>>>> int __seg_fs * fs1;
>>>>>>> int __seg_gs * gs1;
>>>>>>>
>>>>>>> template<typename T, typename U>
>>>>>>> auto f (T __seg_fs * a, U __seg_gs * b)
>>>>>>> {
>>>>>>> return *(T *) a == *(U *) b;
>>>>>>> }
>>>>>>>
>>>>>>> int
>>>>>>> main ()
>>>>>>> {
>>>>>>> return f (fs1, gs1);
>>>>>>> }
>>>>>>> ```
>>>>>>>
>>>>>>>
>>>>>>> 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.
>>>>>>> (grokdeclarator): 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.
>>>>>>> (same_type_ignoring_top_level_qualifiers_p): 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.
>>>>>>> * g++.dg/ext/addr-space-decl.C: New test.
>>>>>>> * g++.dg/ext/addr-space-ref.C: New test.
>>>>>>> * g++.dg/ext/addr-space-ops.C: New test.
>>>>>>>
>>>>>>> # Please enter the commit message for your changes. Lines starting
>>>>>>> # with '#' will be ignored, and an empty message aborts the commit.
>>>>>>> #
>>>>>>> # Date: Sun Oct 9 16:02:22 2022 +0200
>>>>>>> #
>>>>>>> # On branch releases/gcc-12
>>>>>>> # Your branch is ahead of 'origin/releases/gcc-12' by 2 commits.
>>>>>>> # (use "git push" to publish your local commits)
>>>>>>> #
>>>>>>> # Changes to be committed:
>>>>>>> # modified: gcc/c-family/c-common.cc
>>>>>>> # modified: gcc/c-family/c-common.h
>>>>>>> # modified: gcc/c/c-decl.cc
>>>>>>> # modified: gcc/c/c-typeck.cc
>>>>>>> # modified: gcc/cp/cp-tree.h
>>>>>>> # modified: gcc/cp/decl.cc
>>>>>>> # modified: gcc/cp/mangle.cc
>>>>>>> # modified: gcc/cp/parser.cc
>>>>>>> # modified: gcc/cp/pt.cc
>>>>>>> # modified: gcc/cp/tree.cc
>>>>>>> # modified: gcc/cp/typeck.cc
>>>>>>> # modified: gcc/doc/extend.texi
>>>>>>> # new file: gcc/testsuite/g++.dg/abi/mangle-addr-space1.C
>>>>>>> # new file: gcc/testsuite/g++.dg/abi/mangle-addr-space2.C
>>>>>>> # new file: gcc/testsuite/g++.dg/ext/addr-space-decl.C
>>>>>>> # new file: gcc/testsuite/g++.dg/ext/addr-space-ops.C
>>>>>>> # new file: gcc/testsuite/g++.dg/ext/addr-space-ref.C
>>>>>>> # new file: gcc/testsuite/g++.dg/parse/addr-space.C
>>>>>>> # new file: gcc/testsuite/g++.dg/parse/addr-space1.C
>>>>>>> # new file: gcc/testsuite/g++.dg/parse/addr-space2.C
>>>>>>> # new file: gcc/testsuite/g++.dg/template/spec-addr-space.C
>>>>>>> # modified: gcc/tree.h
>>>>>>> #
>>>>>>> # Untracked files:
>>>>>>> # Makefile
>>>>>>> # addr-space-decl.C
>>>>>>> # addr-space-decl.s
>>>>>>> # addr-space-ops.C
>>>>>>> # addr-space-ref.C
>>>>>>> # addr-space-template.C
>>>>>>> # addr-space-template.s
>>>>>>> # addr-space-template2.C
>>>>>>> # addr-space-template2.C.006t.gimple
>>>>>>> # addr-space-template2.s
>>>>>>> # addr-space-traits.C
>>>>>>> # addr-space4.C
>>>>>>> # addr-space4.C.006t.gimple
>>>>>>> # addr-space4.s
>>>>>>> # build-x86_64-pc-linux-gnu/
>>>>>>> # compare
>>>>>>> # host-x86_64-pc-linux-gnu/
>>>>>>> # mangle-addr-space1.s
>>>>>>> # prev-x86_64-pc-linux-gnu/
>>>>>>> # rename
>>>>>>> # stage1-x86_64-pc-linux-gnu/
>>>>>>> # stage_current
>>>>>>> # stage_final
>>>>>>> # stage_last
>>>>>>> # x86_64-pc-linux-gnu/
>>>>>>> #
>>>>>>> # ------------------------ >8 ------------------------
>>>>>>> # Do not modify or remove the line above.
>>>>>>> # Everything below it will be ignored.
>>>>>>> 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..fa5a1ddb21d 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 "
>>>>>>> @@ -14572,6 +14578,57 @@ grokdeclarator (const cp_declarator *declarator,
>>>>>>> if (!processing_template_decl)
>>>>>>> cp_apply_type_quals_to_decl (type_quals, decl);
>>>>>>> + addr_space_t address_space = declspecs->address_space;
>>>>>>> + if (!ADDR_SPACE_GENERIC_P (address_space) && !INDIRECT_TYPE_P (type))
>>>>>>> + {
>>>>>>> + if (decl_context == NORMAL)
>>>>>>> + {
>>>>>>> + switch (storage_class)
>>>>>>> + {
>>>>>>> + case sc_auto:
>>>>>>> + error ("%qs combined with C++98 %<auto%> qualifier for %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + break;
>>>>>>> + case sc_register:
>>>>>>> + error ("%qs combined with %<register%> qualifier for %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + break;
>>>>>>> + case sc_none:
>>>>>>> + if (! toplevel_bindings_p ())
>>>>>>> + error ("%qs specified for auto variable %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + break;
>>>>>>> + case sc_mutable:
>>>>>>> + error ("%qs combined with %<mutable%> qualifier for %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + break;
>>>>>>> + case sc_static:
>>>>>>> + case sc_extern:
>>>>>>> + break;
>>>>>>> + default:
>>>>>>> + gcc_unreachable ();
>>>>>>> + }
>>>>>>> + }
>>>>>>> + else if (decl_context == PARM && TREE_CODE (type) != ARRAY_TYPE)
>>>>>>> + {
>>>>>>> + if (name)
>>>>>>> + error ("%qs specified for parameter %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + else
>>>>>>> + error ("%qs specified for unnamed parameter",
>>>>>>> + c_addr_space_name (address_space));
>>>>>>> + }
>>>>>>> + else if (decl_context == FIELD)
>>>>>>> + {
>>>>>>> + if (name)
>>>>>>> + error ("%qs specified for structure field %qs",
>>>>>>> + c_addr_space_name (address_space), name);
>>>>>>> + else
>>>>>>> + error ("%qs specified for structure field",
>>>>>>> + c_addr_space_name (address_space));
>>>>>>> + }
>>>>>>> + }
>>>>>>> +
>>>>>>> return decl;
>>>>>>> }
>>>>>>> }
>>>>>>> diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
>>>>>>> index eb53e0ebeb4..16cb2ff4332 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))
>>>>>>> + {
>>>>>>> + 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;
>>>>>>> + }
>>>>>>> /* 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..c9d1c01f4ce 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 space constraints it can
>>>>>>> + fully match the address space of ARG. However, if PARM contains an
>>>>>>> + address space constraint, 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 ? 0 : as_arg;
>>>>>>> +
>>>>>>> /* 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..7d810c6a12c 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);
>>>>>>> @@ -1579,7 +1595,9 @@ comptypes (tree t1, tree t2, int strict)
>>>>>>> }
>>>>>>> /* Returns nonzero iff TYPE1 and TYPE2 are the same type, ignoring
>>>>>>> - top-level qualifiers. */
>>>>>>> + top-level qualifiers, except for named address spaces. If the pointers point
>>>>>>> + to different named addresses spaces, then we must determine if one address
>>>>>>> + space is a subset of the other. */
>>>>>>> bool
>>>>>>> same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
>>>>>>> @@ -1589,6 +1607,14 @@ same_type_ignoring_top_level_qualifiers_p (tree type1, tree type2)
>>>>>>> if (type1 == type2)
>>>>>>> return true;
>>>>>>> + addr_space_t as_type1 = TYPE_ADDR_SPACE (type1);
>>>>>>> + addr_space_t as_type2 = TYPE_ADDR_SPACE (type2);
>>>>>>> + addr_space_t as_common;
>>>>>>> +
>>>>>>> + /* Fail if pointers point to incompatible address spaces. */
>>>>>>> + if (!addr_space_superset (as_type1, as_type2, &as_common))
>>>>>>> + return false;
>>>>>>> +
>>>>>>> type1 = cp_build_qualified_type (type1, TYPE_UNQUALIFIED);
>>>>>>> type2 = cp_build_qualified_type (type2, TYPE_UNQUALIFIED);
>>>>>>> return same_type_p (type1, type2);
>>>>>>> @@ -6374,10 +6400,32 @@ static tree
>>>>>>> pointer_diff (location_t loc, tree op0, tree op1, tree ptrtype,
>>>>>>> tsubst_flags_t complain, tree *instrument_expr)
>>>>>>> {
>>>>>>> - tree result, inttype;
>>>>>>> tree restype = ptrdiff_type_node;
>>>>>>> + tree result, inttype;
>>>>>>> +
>>>>>>> + addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
>>>>>>> + addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
>>>>>>> tree target_type = TREE_TYPE (ptrtype);
>>>>>>> + /* If the operands point into different address spaces, we need to
>>>>>>> + explicitly convert them to pointers into the common address space
>>>>>>> + before we can subtract the numerical address values. */
>>>>>>> + if (as0 != as1)
>>>>>>> + {
>>>>>>> + addr_space_t as_common;
>>>>>>> + tree common_type;
>>>>>>> +
>>>>>>> + /* Determine the common superset address space. This is guaranteed
>>>>>>> + to exist because the caller verified that comp_target_types
>>>>>>> + returned non-zero. */
>>>>>>> + if (!addr_space_superset (as0, as1, &as_common))
>>>>>>> + gcc_unreachable ();
>>>>>>> +
>>>>>>> + common_type = common_pointer_type (TREE_TYPE (op0), TREE_TYPE (op1));
>>>>>>> + op0 = convert (common_type, op0);
>>>>>>> + op1 = convert (common_type, op1);
>>>>>>> + }
>>>>>>> +
>>>>>>> if (!complete_type_or_maybe_complain (target_type, NULL_TREE, complain))
>>>>>>> return error_mark_node;
>>>>>>> @@ -10805,6 +10853,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/ext/addr-space-decl.C b/gcc/testsuite/g++.dg/ext/addr-space-decl.C
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..c04d2f497da
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/g++.dg/ext/addr-space-decl.C
>>>>>>> @@ -0,0 +1,5 @@
>>>>>>> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
>>>>>>> +__seg_fs char a, b, c;
>>>>>>> +__seg_fs const int *p;
>>>>>>> +static /* give internal linkage to the following anonymous struct */
>>>>>>> +__seg_fs struct { int a; char b; } * __seg_gs q;
>>>>>>> diff --git a/gcc/testsuite/g++.dg/ext/addr-space-ops.C b/gcc/testsuite/g++.dg/ext/addr-space-ops.C
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..86c02d1e7f5
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/g++.dg/ext/addr-space-ops.C
>>>>>>> @@ -0,0 +1,20 @@
>>>>>>> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
>>>>>>> +int __seg_fs * fs1;
>>>>>>> +int __seg_fs * fs2;
>>>>>>> +float __seg_gs * gs1;
>>>>>>> +float __seg_gs * gs2;
>>>>>>> +
>>>>>>> +int
>>>>>>> +main ()
>>>>>>> +{
>>>>>>> + fs1 + fs2; // { dg-error "invalid operands of types .__seg_fs int.. and .__seg_fs int.. to binary .operator.." }
>>>>>>> + fs1 - fs2;
>>>>>>> + fs1 - gs2; // { dg-error "invalid operands of types .__seg_fs int.. and .__seg_gs float.. to binary .operator.." }
>>>>>>> + fs1 == fs2;
>>>>>>> + fs1 != gs2; // { dg-error "comparison between distinct pointer types .__seg_fs int.. and .__seg_gs float.. lacks a cast" }
>>>>>>> + fs1 = fs2;
>>>>>>> + fs1 = gs2; // { dg-error "cannot convert .__seg_gs float.. to .__seg_fs int.. in assignment" }
>>>>>>> + fs1 > fs2;
>>>>>>> + fs1 < gs2; // { dg-error "comparison between distinct pointer types .__seg_fs int.. and .__seg_gs float.. lacks a cast" }
>>>>>>> + return 0;
>>>>>>> +}
>>>>>>> diff --git a/gcc/testsuite/g++.dg/ext/addr-space-ref.C b/gcc/testsuite/g++.dg/ext/addr-space-ref.C
>>>>>>> new file mode 100644
>>>>>>> index 00000000000..12d7975e560
>>>>>>> --- /dev/null
>>>>>>> +++ b/gcc/testsuite/g++.dg/ext/addr-space-ref.C
>>>>>>> @@ -0,0 +1,31 @@
>>>>>>> +// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
>>>>>>> +// { dg-prune-output "does not allow .register. storage class specifier" }
>>>>>>> +int __seg_fs * outer_b;
>>>>>>> +
>>>>>>> +struct s {
>>>>>>> + __seg_fs int * ok;
>>>>>>> + __seg_gs int ko; // { dg-error ".__seg_gs. specified for structure field .ko." }
>>>>>>> +};
>>>>>>> +
>>>>>>> +int register __seg_fs reg_fs; // { dg-error ".__seg_fs. combined with .register. qualifier for .reg_fs." }
>>>>>>> +
>>>>>>> +namespace ns_a
>>>>>>> +{
>>>>>>> + int __seg_fs * inner_b;
>>>>>>> +
>>>>>>> + template<typename T>
>>>>>>> + int f (T &a) { return a; }
>>>>>>> + int g (__seg_fs int a) { return a; } // { dg-error ".__seg_fs. specified for parameter .a." }
>>>>>>> + int h (__seg_fs int *a) { return *a; }
>>>>>>> +}
>>>>>>> +
>>>>>>> +int
>>>>>>> +main ()
>>>>>>> +{
>>>>>>> + int register __seg_gs reg_gs; // { dg-error ".__seg_gs. combined with .register. qualifier for .reg_gs." }
>>>>>>> + static __seg_gs int static_gs;
>>>>>>> + __seg_fs int auto_fs; // { dg-error ".__seg_fs. specified for auto variable .auto_fs." }
>>>>>>> + __seg_fs int *pa = outer_b;
>>>>>>> + __seg_fs int& ra = *ns_a::inner_b;
>>>>>>> + return ns_a::f(ra) + ns_a::f(*pa);
>>>>>>> +}
>>>>>>> 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-14 15:19 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
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 [this message]
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=4026cae9-e371-a2ee-2b36-7abc9224afa1@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).