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 EE29D3857025 for ; Mon, 10 Oct 2022 19:20:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org EE29D3857025 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=1665429618; 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=QpLPLKPPcXCUqyW3yqmL2kW78ap59sNYC3c+Mu1jn84=; b=dr/vjYMuAEOO9nvbFUgpFrDobuTX2JrjJa+SLrgKnLWQPFAlwuGK7SOl1KDoajYj2Kh7vF IStUhJSVp9bGPLgDEGqgJZcZLTOyDiRM2jD9o7saSSzBD/RugLMZgjRG4aRvAcTxx9CWYQ 32ciNwHj4VajupDfyXxOXYEjGUOOT/0= 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-374-InIOhnuZO5CGsy8VUm5O0w-1; Mon, 10 Oct 2022 15:20:17 -0400 X-MC-Unique: InIOhnuZO5CGsy8VUm5O0w-1 Received: by mail-qt1-f199.google.com with SMTP id ff14-20020a05622a4d8e00b00394aaf0f653so7352590qtb.19 for ; Mon, 10 Oct 2022 12:20:17 -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=QpLPLKPPcXCUqyW3yqmL2kW78ap59sNYC3c+Mu1jn84=; b=CG7oO/2SO30e0yF2xOHO8lC38XUVLK6jOvc0GngRIrb4NzxiulDpP18iM5DOfVeU0Q ZvKU6u07CGJRdOshDK7vOKeYkHpSpKd4z/H1B7OSi+ZuKrPBB3V7jag+pYNIPFt011ul 2wJKXzytbB31mQoL1ZquXweD9rBJTfai2d/hXM/KIgqtbiryiHoGfTqPPm1x0XRxoLNT 1yzv+RJkUrQH0NY0X/azaWAkkBFVcvbz3I3VP+K6F3dJcWzOPyt4rS/NZPK7ppBa+2hC rbl6rBgGicGI6kqnUrayw/knlwnA/Q80/NB+xfn7f8GREA1plgv2gp8eHmTByIurcDy3 TeyA== X-Gm-Message-State: ACrzQf1kCoc44GjuHXgeF5CAywddk3P5KaI0NlaBlIynnsxtSG8xvAhI y+QmMGXSkRQDveSOMMqaxnNqRjDp+Cd36pa4GVrVXrTT/WZGbuTVwj0+jInAj8qDGwPB0BMpEh8 t3ksrSlmOkZ0QDOEkLw== X-Received: by 2002:a05:6214:1941:b0:4b1:81aa:b1dd with SMTP id q1-20020a056214194100b004b181aab1ddmr16325293qvk.67.1665429616360; Mon, 10 Oct 2022 12:20:16 -0700 (PDT) X-Google-Smtp-Source: AMsMyM4sbXv16qq5/YUcJGf7CkW34ptbnTBK39dPQoUvcooMlRwUf0AVzcilihjDqxcqWCueIAAVZg== X-Received: by 2002:a05:6214:1941:b0:4b1:81aa:b1dd with SMTP id q1-20020a056214194100b004b181aab1ddmr16325261qvk.67.1665429615820; Mon, 10 Oct 2022 12:20:15 -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 l7-20020ac84a87000000b003996aa171b9sm4033322qtq.97.2022.10.10.12.20.14 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Mon, 10 Oct 2022 12:20:15 -0700 (PDT) Message-ID: Date: Mon, 10 Oct 2022 15:20:13 -0400 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.13.1 Subject: Re: [PATCH] c++: parser - Support for target address spaces in C++ To: Paul Iannetta Cc: gcc-patches@gcc.gnu.org References: <20221006143400.es3u6ebqt3xkw6jp@ws2202.lin.mbt.kalray.eu> <697f23be-7318-1c87-5625-2411b1ab18a3@redhat.com> <20221009161256.p63tnxsqzwcnvh5h@ws2202.lin.mbt.kalray.eu> From: Jason Merrill In-Reply-To: <20221009161256.p63tnxsqzwcnvh5h@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=-13.2 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,GIT_PATCH_0,KAM_ASCII_DIVIDERS,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/9/22 12:12, Paul Iannetta wrote: > Hi, > > On Thu, Oct 06, 2022 at 01:34:40PM -0400, Jason Merrill wrote: > [snip] >> >> Hmm? We mangle __restrict: >> >> void f(int *__restrict *p) { } // _Z1fPrPi >> > > Indeed, I have overlooked that point. Thank you for pointing it out. > >> but cv-qualifiers (including restrict) are dropped on the top-level type of >> a parameter. >> >> If address spaces should be mangled, it probably makes sense to use the same >> mangling that we already use for attributes in >> write_CV_qualifiers_for_type. >> > > That's a nice feature! LLVM is using AS 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. > Following your advice, > I implemented the mangling of address_names as U__address_name > (eg., U8__seg_fs), underscores may appear but that does not seem to be > a problem. > > I don't think that there should be anything to do on the template > side, but I am no expert of what is expected of templates when it > comes to strip or forward qualifiers. So, please tell me if I > overlooked something on that side. You certainly want some template tests, say template int f (T *p) { return *p; } __seg_fs int *a; int main() { f(a); } // test for mangling of f<__seg_fs int> ----- template int f (T __seg_gs *p) { return *p; } __seg_fs int *a; int main() { f(a); } // error, conflicting address spaces > Now concerning the meat of the patch itself. > > The C part of the support of address spaces does not appear to have > dedicated tests, especially since it is mostly a target specific > feature. I, however, added a few tests, one for the mangling, > and others which test the different error messages that might > appear when using address spaces in an unsafe way. > > Most of the patch tries to mirror the commit > 309434d678721acedb299f20cdc2b4778062b180 > which introduces address spaces to the C front-end. The C and C++ > parsers share a lot but are subtly different so there might be some > discrepancies. In particular, I ensure that address spaces do not > conflict, that only one address space can be specified at a time, and > that the type conversion mechanism pick the superset of the address > spaces if available. I also forbid address spaces in compound literals. > > I have only tested the patch on x86 and on our not-yet-upstream > architecture, without seeing any regressions. > > NB: I do not add a DSO for the moment because I have started the process of > assigning copyright to the FSF. > > # ------------------------ >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): Add prototype. > > 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. > * 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/parse/addr-space.C: New test. > * g++.dg/parse/addr-space1.C: New test. > * g++.dg/parse/addr-space2.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; So it's not possible for the two spaces to both be subsets of a third? > +} > + > /* 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 e130196a3a7..17185fd3da4 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..f1da04c6c58 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, > @@ -6278,6 +6279,8 @@ struct cp_decl_specifier_seq { > /* True iff the alternate "__intN__" form of the __intN type has been > used. */ > BOOL_BITFIELD int_n_alt: 1; > + /* The address space that the declaration belongs to. */ > + addr_space_t address_space; New non-bit-fields should be added before the bit-fields. > }; > > /* The various kinds of declarators. */ > 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..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. > + 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..110ceafc98b 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,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. > + > if (!cv_qualifier) > break; > > @@ -32705,6 +32730,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 +32764,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/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 84e6f6694ab..c89df8778b2 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/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/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. */ > > > >