public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Paul Iannetta <piannetta@kalrayinc.com>
To: Jason Merrill <jason@redhat.com>
Cc: gcc-patches@gcc.gnu.org
Subject: Re: [PATCH v2] c++: parser - Support for target address spaces in C++
Date: Thu, 13 Oct 2022 17:23:41 +0200	[thread overview]
Message-ID: <20221013152341.bztoqunwtmhdzi3f@ws2202.lin.mbt.kalray.eu> (raw)
In-Reply-To: <1bd40afb-f4ee-9f5d-87e5-ed35a26bd21f@redhat.com>

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.

> >    - 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.

> 
> > 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.  */
> > 
> > 
> > 
> > 
> 
> 
> 
> 
> 
> 
> 






  reply	other threads:[~2022-10-13 15:23 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 [this message]
2022-10-13 15:47                 ` Jason Merrill
2022-10-13 16:02                   ` Paul Iannetta
2022-10-13 19:41                     ` Jason Merrill
2022-10-13 21:57                       ` Paul Iannetta
2022-10-14 15:19                         ` Jason Merrill
2022-10-18  7:37                           ` [PATCH v3] " Paul Iannetta
2022-10-18 14:24                             ` Jason Merrill
2022-10-18 17:01                               ` Paul Iannetta
2022-10-19 18:55                                 ` Jason Merrill
2022-10-26  7:18                                   ` Paul Iannetta
2022-10-26 16:28                                     ` Jason Merrill
2022-11-10 15:42                                       ` [PATCH v4] " Paul Iannetta
2022-11-03 13:38                                     ` [PATCH v3] " Georg-Johann Lay
2022-11-10 14:08                                       ` Paul Iannetta
2022-11-10 16:40                                         ` Georg-Johann Lay
2022-11-14 17:55                                           ` Jason Merrill
2022-11-15 12:15                                             ` Georg-Johann Lay

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221013152341.bztoqunwtmhdzi3f@ws2202.lin.mbt.kalray.eu \
    --to=piannetta@kalrayinc.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=jason@redhat.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).