From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id DE4313858C83 for ; Fri, 14 Oct 2022 15:19:56 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org DE4313858C83 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1665760796; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=WUF8cIaTqZ/1YpA/y4wCBYQkrW7vNBj/CZg0IwgbxYA=; b=bCeG0cVP1rdnq4tCk6YfcPj8g/423wPsXMo2VKADCRRGJsGErWlHRHabr2lAhYT815VY0t MeGeR63uFVLEP7l9GgQ6k/jgq9sC3ubzkWEnQscOU8IJZK2yQ6YJYWzkGcR9Bp6WWEnI10 gAFoz6lSOjCjRtyamjDS947Jfy5yYtk= Received: from mail-qt1-f199.google.com (mail-qt1-f199.google.com [209.85.160.199]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_128_GCM_SHA256) id us-mta-588-L43ttdZTMwC6TDtgEWv25g-1; Fri, 14 Oct 2022 11:19:55 -0400 X-MC-Unique: L43ttdZTMwC6TDtgEWv25g-1 Received: by mail-qt1-f199.google.com with SMTP id c11-20020ac87dcb000000b0039cdb815f3bso790973qte.4 for ; Fri, 14 Oct 2022 08:19:54 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:date:message-id :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=WUF8cIaTqZ/1YpA/y4wCBYQkrW7vNBj/CZg0IwgbxYA=; b=ScOedN20xjGlfv1QNUpLaqh6IjcyrktxsesHFyrZrPvQXxMYM+oRa4OJQUz5HXiXnO AuRNKpiRS96/V+wf0g2neJxam23GVgkxIPtGBHHZ1KxTusKo/isUaLC3moKuwh8x+1KK VXIjqQ6stUvzXECUhuFHZnWGiqZ2a9CHwG4R8on+L2lRZjxl4O09qEmvPA5pwWcbloub HgMaQ+DwKH+cE2TLBI4BoZHHe6lzb4ptLth8Vpc9BIkg54yGGoTiIPpURY/d1oPnYDZ0 C09Je5PB8q/y8MIwDRtbXz1DBbdFmVM+b0RFbofssZREKun2rTexL4Plclc1V6maiVp2 i+Pw== X-Gm-Message-State: ACrzQf1pgsMIEyqvZKPShxCRQL4QWP4ahQUpAEXULqbWbpODeqZUbdF8 yuhmO1dQdcsVpncwZUTpB4WTFVDbeg8+lLfs/jASHM83CI7m/swvuob3JQiZL56HXeVPtcz3R39 k7AJuF8mKmugd4TqEoQ== X-Received: by 2002:ad4:5f0e:0:b0:4b1:cfa3:d57b with SMTP id fo14-20020ad45f0e000000b004b1cfa3d57bmr4363036qvb.65.1665760792885; Fri, 14 Oct 2022 08:19:52 -0700 (PDT) X-Google-Smtp-Source: AMsMyM7a9P+7V0yFB3bSKzOiR4KlWe9RsBqPsvYVkAEYOs9DN+HYb7TEs3PfVhkEBLXUOHefCwm9cw== X-Received: by 2002:ad4:5f0e:0:b0:4b1:cfa3:d57b with SMTP id fo14-20020ad45f0e000000b004b1cfa3d57bmr4362972qvb.65.1665760792037; Fri, 14 Oct 2022 08:19:52 -0700 (PDT) Received: from [192.168.1.101] (130-44-159-43.s15913.c3-0.arl-cbr1.sbo-arl.ma.cable.rcncustomer.com. [130.44.159.43]) by smtp.gmail.com with ESMTPSA id n1-20020a05620a294100b006ee949b8051sm2790962qkp.51.2022.10.14.08.19.51 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Fri, 14 Oct 2022 08:19:51 -0700 (PDT) Message-ID: <4026cae9-e371-a2ee-2b36-7abc9224afa1@redhat.com> Date: Fri, 14 Oct 2022 11:19:50 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:102.0) Gecko/20100101 Thunderbird/102.3.2 Subject: Re: [PATCH v2] c++: parser - Support for target address spaces in C++ To: Paul Iannetta Cc: gcc-patches@gcc.gnu.org References: <20221009161256.p63tnxsqzwcnvh5h@ws2202.lin.mbt.kalray.eu> <20221011220017.pvs5jawrzqoaqkkf@ws2202.lin.mbt.kalray.eu> <19526772-3afb-87d1-190a-5ab0ffb566a9@redhat.com> <20221013005158.mfahyohzbywlyl7i@ws2202.lin.mbt.kalray.eu> <1bd40afb-f4ee-9f5d-87e5-ed35a26bd21f@redhat.com> <20221013152341.bztoqunwtmhdzi3f@ws2202.lin.mbt.kalray.eu> <20221013160227.sdlv6yaw5gr4zcvd@ws2202.lin.mbt.kalray.eu> <20221013215643.o2bymrmffwbtuppu@ws2202.lin.mbt.kalray.eu> From: Jason Merrill In-Reply-To: <20221013215643.o2bymrmffwbtuppu@ws2202.lin.mbt.kalray.eu> X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,NICE_REPLY_A,RCVD_IN_DNSWL_NONE,SPF_HELO_NONE,SPF_NONE,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: 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 int f (T *a) { return *a; } > int main () { return f (a); } // f(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 struct strip; >>>>>>> template struct strip<__seg_fs T *> { typedef T type; }; >>>>>>> template struct strip<__seg_gs T *> { typedef T type; }; >>>>>>> >>>>>>> int >>>>>>> main () >>>>>>> { >>>>>>> *(strip::type *) fs1 == *(strip::type *) gs1; >>>>>>> return 0; >>>>>>> } >>>>>>> ``` >>>>>>> >>>>>>> Ex2: >>>>>>> ``` >>>>>>> int __seg_fs * fs1; >>>>>>> int __seg_fs * fs2; >>>>>>> >>>>>>> template auto f (T __seg_fs * a, U __seg_gs * b) { return a; } >>>>>>> template 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 >>>>>>> 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 % qualifier for %qs", >>>>>>> + c_addr_space_name (address_space), name); >>>>>>> + break; >>>>>>> + case sc_register: >>>>>>> + error ("%qs combined with % 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 % 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 >>>>>>> +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 >>>>>>> + 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 >>>>>>> +int f (T __seg_gs *p) { return *p; } // { dg-note "candidate: 'template 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. */ >>>>>>> >>>>>>> >>>>>>> >>>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>>> >>>>> >>>>> >>>>> >>>>> >>>>> >>>> >>>> >>>> >>>> >>>> >>>> >>>> >>> >>> >>> >>> >>> >>> >> >> >> >> >> >> >> > > > > > >