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: Wed, 12 Oct 2022 00:03:04 +0200	[thread overview]
Message-ID: <20221011220017.pvs5jawrzqoaqkkf@ws2202.lin.mbt.kalray.eu> (raw)
In-Reply-To: <efefbab5-a9e7-6b98-f336-5272a484d610@redhat.com>

Thank you very much for the comments.

On Mon, Oct 10, 2022 at 03:20:13PM -0400, Jason Merrill wrote:
> On 10/9/22 12:12, Paul Iannetta wrote:
> > That's a nice feature! LLVM is using AS<number> to mangle the
> > address-name qualified types but that would have required an update of
> > libiberty's demangler in the binutils as well.
> 
> And they haven't proposed this mangling to
> 
>   https://github.com/itanium-cxx-abi/cxx-abi/
> 
> yet, either.

When looking at clang/lib/AST/{Microsoft,Itamium}Mangle.cpp, the
comments may suggest that they wanted to implement them as extended
qualifiers prefixed by an `U' but that's not what they ended up doing.

> You certainly want some template tests, say
> 
> template <class T>
> int f (T *p) { return *p; }
> __seg_fs int *a;
> int main() { f(a); }
> // test for mangling of f<__seg_fs int>
> 
> -----
> 
> template <class T>
> int f (T __seg_gs *p) { return *p; }
> __seg_fs int *a;
> int main() { f(a); } // error, conflicting address spaces

Indeed, I was getting the first one right by a stroke of luck but not
the second.  I've consequently adapted the part which checks and
computes the unification of cv-qualifiers in the presence of address
spaces.  The idea being that a type parameter T can match any address
spaces but an address-space qualified parameter can't accept more
general address spaces than itself.

> > +/* Return true if between two named address spaces, whether there is a superset
> > +   named address space that encompasses both address spaces.  If there is a
> > +   superset, return which address space is the superset.  */
> > +
> > +bool
> > +addr_space_superset (addr_space_t as1, addr_space_t as2,
> > +		     addr_space_t * common)
> > +{
> > +  if (as1 == as2)
> > +    {
> > +      *common = as1;
> > +      return true;
> > +    }
> > +  else if (targetm.addr_space.subset_p (as1, as2))
> > +    {
> > +      *common = as2;
> > +      return true;
> > +    }
> > +  else if (targetm.addr_space.subset_p (as2, as1))
> > +    {
> > +      *common = as1;
> > +      return true;
> > +    }
> > +  else
> > +    return false;
> 
> So it's not possible for the two spaces to both be subsets of a third?
> 

According to the [N1275, page 38]:
Address spaces may overlap in a nested fashion. For any two address
spaces, either the address spaces must be disjoint, they must be
equivalent, or one must be a subset of the other. [...] There is no
requirement that named address spaces (intrinsic or otherwise) be
subsets of the generic address space.
[N1275]: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1275.pdf

Hence, two disjoint address spaces can't be subsets of a third, per
the draft.

> 
> New non-bit-fields should be added before the bit-fields.
> 

Done.

> > diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
> > index eb53e0ebeb4..06625ad9a4b 100644
> > --- a/gcc/cp/mangle.cc
> > +++ b/gcc/cp/mangle.cc
> > @@ -2509,6 +2509,15 @@ write_CV_qualifiers_for_type (const tree type)
> >        array.  */
> >     cp_cv_quals quals = TYPE_QUALS (type);
> > +  if (DECODE_QUAL_ADDR_SPACE (quals))
> > +    {
> > +      addr_space_t as = DECODE_QUAL_ADDR_SPACE (quals);
> 
> This can be
> 
> if (addr_space_t as = DECODE_QUAL_ADDR_SPACE (quals))
> 
> so you don't need to repeat it.

I thought this was c++17 only, but in fact c++17 only broadened the
idiom.  Nice! (It would be even nicer to have this feature in C as
well)
> > diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
> > index 763df6f479b..110ceafc98b 100644
> > --- a/gcc/cp/parser.cc
> > +++ b/gcc/cp/parser.cc
> > [...]
> > @@ -23812,6 +23830,13 @@ cp_parser_cv_qualifier_seq_opt (cp_parser* parser)
> >   	  break;
> >   	}
> > +      if (RID_FIRST_ADDR_SPACE <= token->keyword &&
> > +	  token->keyword <= RID_LAST_ADDR_SPACE)
> > +	{
> > +	  cv_qualifier =
> > +	    ENCODE_QUAL_ADDR_SPACE (token->keyword - RID_FIRST_ADDR_SPACE);
> > +	}
> 
> We usually omit braces around a single statement.
> 
Done.

# ------------------------ >8 ------------------------
Add support for custom address spaces in C++

gcc/
        * tree.h (ENCODE_QUAL_ADDR_SPACE): Missing parentheses.

gcc/c/
        * c-decl.cc: Remove c_register_addr_space.

gcc/c-family/
        * c-common.cc (c_register_addr_space): Imported from c-decl.cc
        (addr_space_superset): Imported from gcc/c/c-typecheck.cc
        * c-common.h: Remove the FIXME.
        (addr_space_superset): New declaration.

gcc/cp/
        * cp-tree.h (enum cp_decl_spec): Add addr_space support.
        (struct cp_decl_specifier_seq): Likewise.
        * decl.cc (get_type_quals): Likewise.
        (check_tag_decl): Likewise.
        * parser.cc (cp_parser_type_specifier): Likewise.
        (cp_parser_cv_qualifier_seq_opt): Likewise.
        (cp_parser_postfix_expression): Likewise.
        (cp_parser_type_specifier): Likewise.
        (set_and_check_decl_spec_loc): Likewise.
        * typeck.cc (composite_pointer_type): Likewise
        (comp_ptr_ttypes_real): Likewise.
        * pt.cc (check_cv_quals_for_unify): Likewise.
        (unify): Likewise.
        * tree.cc: Remove c_register_addr_space stub.
        * mangle.cc (write_CV_qualifiers_for_type): Mangle address spaces
          using the extended qualifier notation.

gcc/doc
        * extend.texi (Named Address Spaces): add a mention about C++
          support.

gcc/testsuite/
        * g++.dg/abi/mangle-addr-space1.C: New test.
        * g++.dg/abi/mangle-addr-space2.C: New test.
        * g++.dg/parse/addr-space.C: New test.
        * g++.dg/parse/addr-space1.C: New test.
        * g++.dg/parse/addr-space2.C: New test.
        * g++.dg/parse/template/spec-addr-space.C: New test.

# ------------------------ >8 ------------------------
diff --git a/gcc/c-family/c-common.cc b/gcc/c-family/c-common.cc
index bb0544eeaea..ff1146ecc25 100644
--- a/gcc/c-family/c-common.cc
+++ b/gcc/c-family/c-common.cc
@@ -615,6 +615,33 @@ c_addr_space_name (addr_space_t as)
   return IDENTIFIER_POINTER (ridpointers [rid]);
 }
 
+/* Return true if between two named address spaces, whether there is a superset
+   named address space that encompasses both address spaces.  If there is a
+   superset, return which address space is the superset.  */
+
+bool
+addr_space_superset (addr_space_t as1, addr_space_t as2,
+		     addr_space_t * common)
+{
+  if (as1 == as2)
+    {
+      *common = as1;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as1, as2))
+    {
+      *common = as2;
+      return true;
+    }
+  else if (targetm.addr_space.subset_p (as2, as1))
+    {
+      *common = as1;
+      return true;
+    }
+  else
+    return false;
+}
+
 /* Push current bindings for the function name VAR_DECLS.  */
 
 void
@@ -2809,6 +2836,25 @@ c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
   return build_nonstandard_integer_type (width, unsignedp);
 }
 
+/* Register reserved keyword WORD as qualifier for address space AS.  */
+
+void
+c_register_addr_space (const char *word, addr_space_t as)
+{
+  int rid = RID_FIRST_ADDR_SPACE + as;
+  tree id;
+
+  /* Address space qualifiers are only supported
+     in C with GNU extensions enabled.  */
+  if (c_dialect_objc () || flag_no_asm)
+    return;
+
+  id = get_identifier (word);
+  C_SET_RID_CODE (id, rid);
+  TREE_LANG_FLAG_0 (id) = 1;
+  ridpointers[rid] = id;
+}
+
 /* The C version of the register_builtin_type langhook.  */
 
 void
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index 52a85bfb783..d36f9e4975b 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -829,12 +829,11 @@ extern const struct attribute_spec c_common_format_attribute_table[];
 
 extern tree (*make_fname_decl) (location_t, tree, int);
 
-/* In c-decl.cc and cp/tree.cc.  FIXME.  */
-extern void c_register_addr_space (const char *str, addr_space_t as);
-
 /* In c-common.cc.  */
 extern bool in_late_binary_op;
 extern const char *c_addr_space_name (addr_space_t as);
+extern const char *c_addr_space_name (addr_space_t as);
+extern bool addr_space_superset (addr_space_t, addr_space_t, addr_space_t *);
 extern tree identifier_global_value (tree);
 extern tree identifier_global_tag (tree);
 extern bool names_builtin_p (const char *);
@@ -952,6 +951,7 @@ extern void c_common_finish (void);
 extern void c_common_parse_file (void);
 extern FILE *get_dump_info (int, dump_flags_t *);
 extern alias_set_type c_common_get_alias_set (tree);
+extern void c_register_addr_space (const char *, addr_space_t);
 extern void c_register_builtin_type (tree, const char*);
 extern bool c_promoting_integer_type_p (const_tree);
 extern bool self_promoting_args_p (const_tree);
diff --git a/gcc/c/c-decl.cc b/gcc/c/c-decl.cc
index c701f07befe..e1bb4f1cf37 100644
--- a/gcc/c/c-decl.cc
+++ b/gcc/c/c-decl.cc
@@ -12337,25 +12337,6 @@ c_parse_final_cleanups (void)
   ext_block = NULL;
 }
 
-/* Register reserved keyword WORD as qualifier for address space AS.  */
-
-void
-c_register_addr_space (const char *word, addr_space_t as)
-{
-  int rid = RID_FIRST_ADDR_SPACE + as;
-  tree id;
-
-  /* Address space qualifiers are only supported
-     in C with GNU extensions enabled.  */
-  if (c_dialect_objc () || flag_no_asm)
-    return;
-
-  id = get_identifier (word);
-  C_SET_RID_CODE (id, rid);
-  C_IS_RESERVED_WORD (id) = 1;
-  ridpointers [rid] = id;
-}
-
 /* Return identifier to look up for omp declare reduction.  */
 
 tree
diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc
index b271af9bedb..c4b01368534 100644
--- a/gcc/c/c-typeck.cc
+++ b/gcc/c/c-typeck.cc
@@ -296,32 +296,6 @@ c_type_promotes_to (tree type)
   return type;
 }
 
-/* Return true if between two named address spaces, whether there is a superset
-   named address space that encompasses both address spaces.  If there is a
-   superset, return which address space is the superset.  */
-
-static bool
-addr_space_superset (addr_space_t as1, addr_space_t as2, addr_space_t *common)
-{
-  if (as1 == as2)
-    {
-      *common = as1;
-      return true;
-    }
-  else if (targetm.addr_space.subset_p (as1, as2))
-    {
-      *common = as2;
-      return true;
-    }
-  else if (targetm.addr_space.subset_p (as2, as1))
-    {
-      *common = as1;
-      return true;
-    }
-  else
-    return false;
-}
-
 /* Return a variant of TYPE which has all the type qualifiers of LIKE
    as well as those of TYPE.  */
 
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 72f4398a8f9..82a6d72f5df 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -6206,6 +6206,7 @@ enum cp_decl_spec {
   ds_const,
   ds_volatile,
   ds_restrict,
+  ds_addr_space,
   ds_inline,
   ds_virtual,
   ds_explicit,
@@ -6252,6 +6253,8 @@ struct cp_decl_specifier_seq {
   cp_storage_class storage_class;
   /* For the __intN declspec, this stores the index into the int_n_* arrays.  */
   int int_n_idx;
+  /* The address space that the declaration belongs to.  */
+  addr_space_t address_space;
   /* True iff TYPE_SPEC defines a class or enum.  */
   BOOL_BITFIELD type_definition_p : 1;
   /* True iff multiple types were (erroneously) specified for this
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 9f78c500a15..16cc1917085 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -5280,6 +5280,8 @@ get_type_quals (const cp_decl_specifier_seq *declspecs)
     type_quals |= TYPE_QUAL_VOLATILE;
   if (decl_spec_seq_has_spec_p (declspecs, ds_restrict))
     type_quals |= TYPE_QUAL_RESTRICT;
+  if (decl_spec_seq_has_spec_p (declspecs, ds_addr_space))
+    type_quals |= ENCODE_QUAL_ADDR_SPACE (declspecs->address_space);
 
   return type_quals;
 }
@@ -5402,6 +5404,10 @@ check_tag_decl (cp_decl_specifier_seq *declspecs,
 	error_at (declspecs->locations[ds_restrict],
 		  "%<__restrict%> can only be specified for objects and "
 		  "functions");
+      else if (decl_spec_seq_has_spec_p (declspecs, ds_addr_space))
+	error_at (declspecs->locations[ds_addr_space],
+		  "address space can only be specified for objects and "
+		  "functions");
       else if (decl_spec_seq_has_spec_p (declspecs, ds_thread))
 	error_at (declspecs->locations[ds_thread],
 		  "%<__thread%> can only be specified for objects "
diff --git a/gcc/cp/mangle.cc b/gcc/cp/mangle.cc
index eb53e0ebeb4..8ea6b7c903e 100644
--- a/gcc/cp/mangle.cc
+++ b/gcc/cp/mangle.cc
@@ -2509,6 +2509,14 @@ write_CV_qualifiers_for_type (const tree type)
      array.  */
   cp_cv_quals quals = TYPE_QUALS (type);
 
+  if (addr_space_t as DECODE_QUAL_ADDR_SPACE (quals))
+    {
+      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..5bb5d657155 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -23655,8 +23655,19 @@ template_decl_level (tree decl)
 static int
 check_cv_quals_for_unify (int strict, tree arg, tree parm)
 {
-  int arg_quals = cp_type_quals (arg);
-  int parm_quals = cp_type_quals (parm);
+  int arg_quals = CLEAR_QUAL_ADDR_SPACE (cp_type_quals (arg));
+  int parm_quals = CLEAR_QUAL_ADDR_SPACE (cp_type_quals (parm));
+
+  /*  Try to unify ARG's address space into PARM's address space.
+      If PARM does not have any address space qualifiers (ie., as_parm is 0),
+      there are no constraints on address spaces for this type.  */
+  addr_space_t as_arg = DECODE_QUAL_ADDR_SPACE (cp_type_quals (arg));
+  addr_space_t as_parm = DECODE_QUAL_ADDR_SPACE (cp_type_quals (parm));
+  addr_space_t as_common;
+  addr_space_superset (as_arg, as_parm, &as_common);
+
+  if (!(as_parm == as_common || as_parm == 0))
+    return 0;
 
   if (TREE_CODE (parm) == TEMPLATE_TYPE_PARM
       && !(strict & UNIFY_ALLOW_OUTER_MORE_CV_QUAL))
@@ -24292,10 +24303,26 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
 					 arg, parm))
 	    return unify_cv_qual_mismatch (explain_p, parm, arg);
 
+	  int arg_cv_quals = cp_type_quals (arg);
+	  int parm_cv_quals = cp_type_quals (parm);
+
+	  /* If PARM does not contain any address spaces constraints it can
+	     fully match the address space of ARG.  However, if PARM contains an
+	     address space constraints, it becomes the upper bound.  That is,
+	     AS_ARG may be promoted to AS_PARM but not the converse.  If we
+	     ended up here, it means that `check_cv_quals_for_unify' succeeded
+	     and that either AS_PARM is 0 (ie., no constraints) or AS_COMMON ==
+	     AS_PARM.  */
+	  addr_space_t as_arg = DECODE_QUAL_ADDR_SPACE (arg_cv_quals);
+	  addr_space_t as_parm = DECODE_QUAL_ADDR_SPACE (parm_cv_quals);
+	  addr_space_t as_common = !as_parm ? as_arg : as_parm;
+
 	  /* Consider the case where ARG is `const volatile int' and
 	     PARM is `const T'.  Then, T should be `volatile int'.  */
-	  arg = cp_build_qualified_type_real
-	    (arg, cp_type_quals (arg) & ~cp_type_quals (parm), tf_none);
+	  int unified_cv =
+	    CLEAR_QUAL_ADDR_SPACE (arg_cv_quals & ~parm_cv_quals)
+	    | ENCODE_QUAL_ADDR_SPACE (as_common);
+	  arg = cp_build_qualified_type_real (arg, unified_cv, tf_none);
 	  if (arg == error_mark_node)
 	    return unify_invalid (explain_p);
 
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc
index 3b37567cbd7..5e14ac837fc 100644
--- a/gcc/cp/tree.cc
+++ b/gcc/cp/tree.cc
@@ -6048,15 +6048,6 @@ cp_free_lang_data (tree t)
     DECL_CHAIN (t) = NULL_TREE;
 }
 
-/* Stub for c-common.  Please keep in sync with c-decl.cc.
-   FIXME: If address space support is target specific, then this
-   should be a C target hook.  But currently this is not possible,
-   because this function is called via REGISTER_TARGET_PRAGMAS.  */
-void
-c_register_addr_space (const char * /*word*/, addr_space_t /*as*/)
-{
-}
-
 /* Return the number of operands in T that we care about for things like
    mangling.  */
 
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc
index ceb80d9744f..5d48920e687 100644
--- a/gcc/cp/typeck.cc
+++ b/gcc/cp/typeck.cc
@@ -656,10 +656,26 @@ composite_pointer_type (const op_location_t &location,
 	  else
 	    return error_mark_node;
         }
+      /* If possible merge the address space into the superset of the address
+	  spaces of t1 and t2, or raise an error. */
+      addr_space_t as_t1 = TYPE_ADDR_SPACE (t1);
+      addr_space_t as_t2 = TYPE_ADDR_SPACE (t2);
+      addr_space_t as_common;
+
+      /* If the two named address spaces are different, determine the common
+	 superset address space.  If there isn't one, raise an error.  */
+      if (!addr_space_superset (as_t1, as_t2, &as_common))
+	{
+	  as_common = as_t1;
+	  error_at (location,
+		    "%qT and %qT are in disjoint named address spaces",
+		    t1, t2);
+	}
       result_type
 	= cp_build_qualified_type (void_type_node,
-				   (cp_type_quals (TREE_TYPE (t1))
-				    | cp_type_quals (TREE_TYPE (t2))));
+				   (CLEAR_QUAL_ADDR_SPACE (cp_type_quals (TREE_TYPE (t1)))
+				    | CLEAR_QUAL_ADDR_SPACE (cp_type_quals (TREE_TYPE (t2)))
+				    | ENCODE_QUAL_ADDR_SPACE (as_common)));
       result_type = build_pointer_type (result_type);
       /* Merge the attributes.  */
       attributes = (*targetm.merge_type_attributes) (t1, t2);
@@ -10805,6 +10821,19 @@ comp_ptr_ttypes_real (tree to, tree from, int constp)
 	      to_more_cv_qualified = true;
 	    }
 
+      /* Warn about conversions between pointers to disjoint
+	 address spaces.  */
+      if (TREE_CODE (from) == POINTER_TYPE
+	  && TREE_CODE (to) == POINTER_TYPE)
+	{
+	  addr_space_t as_from = TYPE_ADDR_SPACE (TREE_TYPE (from));
+	  addr_space_t as_to = TYPE_ADDR_SPACE (TREE_TYPE (to));
+	  addr_space_t as_common;
+
+	  if (!addr_space_superset (as_to, as_from, &as_common))
+	    return false;
+	}
+
 	  if (constp > 0)
 	    constp &= TYPE_READONLY (to);
 	}
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index ac3db88566d..1e0d436c02c 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -1448,7 +1448,7 @@ Fixed-point types are supported by the DWARF debug information format.
 @section Named Address Spaces
 @cindex Named Address Spaces
 
-As an extension, GNU C supports named address spaces as
+As an extension, GNU C and GNU C++ support named address spaces as
 defined in the N1275 draft of ISO/IEC DTR 18037.  Support for named
 address spaces in GCC will evolve as the draft technical report
 changes.  Calling conventions for any target might also change.  At
diff --git a/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C b/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C
new file mode 100644
index 00000000000..c01f8d6054a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle-addr-space1.C
@@ -0,0 +1,10 @@
+// { dg-do run { target { i?86-*-* x86_64-*-* } } }
+// { dg-options "-fabi-version=8 -Wabi -save-temps" }
+// { dg-final { scan-assembler "_Z1fPU8__seg_fsVi" } }
+
+int f (int volatile __seg_fs *a)
+{
+  return *a;
+}
+
+int main () {}
diff --git a/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C b/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C
new file mode 100644
index 00000000000..862bbbdcdf2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/mangle-addr-space2.C
@@ -0,0 +1,9 @@
+// { dg-do run { target { i?86-*-* x86_64-*-* } } }
+// { dg-options "-fabi-version=8 -Wabi -save-temps" }
+// { dg-final { scan-assembler "_Z1fIU8__seg_fsiEiPT_" } }
+
+template <class T>
+int f (T *p) { return *p; }
+int g (__seg_fs int *p) { return *p; }
+__seg_fs int *a;
+int main() { f(a); }
diff --git a/gcc/testsuite/g++.dg/parse/addr-space.C b/gcc/testsuite/g++.dg/parse/addr-space.C
new file mode 100644
index 00000000000..ebb6316054a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/addr-space.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+
+__seg_fs struct foo; // { dg-error "address space can only be specified for objects and functions" }
+
+int
+main ()
+{
+	return 0; 
+}
diff --git a/gcc/testsuite/g++.dg/parse/addr-space1.C b/gcc/testsuite/g++.dg/parse/addr-space1.C
new file mode 100644
index 00000000000..2e8ee32a885
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/addr-space1.C
@@ -0,0 +1,10 @@
+// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+// { dg-options "-std=gnu++98" }
+
+int
+main ()
+{
+	struct foo {int a; char b[2];} structure;
+	structure = ((__seg_fs struct foo) {1 + 2, 'a', 0}); // { dg-error "compound literal qualified by address-space qualifier" }
+	return 0; 
+}
diff --git a/gcc/testsuite/g++.dg/parse/addr-space2.C b/gcc/testsuite/g++.dg/parse/addr-space2.C
new file mode 100644
index 00000000000..5b2c0f28078
--- /dev/null
+++ b/gcc/testsuite/g++.dg/parse/addr-space2.C
@@ -0,0 +1,9 @@
+// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+
+__seg_fs __seg_gs int *a; // { dg-error "conflicting named address spaces .__seg_fs vs __seg_gs." }
+
+int
+main ()
+{
+	return 0; 
+}
diff --git a/gcc/testsuite/g++.dg/template/spec-addr-space.C b/gcc/testsuite/g++.dg/template/spec-addr-space.C
new file mode 100644
index 00000000000..ae9f4de0e1f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/spec-addr-space.C
@@ -0,0 +1,8 @@
+// { dg-do compile { target { i?86-*-* x86_64-*-* } } }
+
+template <class T>
+int f (T __seg_gs *p) { return *p; } // { dg-note "candidate: 'template<class T> int f.__seg_gs T\*." }
+				     // { dg-note "template argument deduction/substitution failed:" "" { target *-*-* } .-1 }
+__seg_fs int *a;
+int main() { f(a); } // { dg-error "no matching" }
+// { dg-note "types .__seg_gs T. and .__seg_fs int. have incompatible cv-qualifiers" "" { target *-*-* } .-1 }
diff --git a/gcc/tree.h b/gcc/tree.h
index 8844471e9a5..b7da4c5141a 100644
--- a/gcc/tree.h
+++ b/gcc/tree.h
@@ -2229,7 +2229,7 @@ extern tree vector_element_bits_tree (const_tree);
 
 /* Encode/decode the named memory support as part of the qualifier.  If more
    than 8 qualifiers are added, these macros need to be adjusted.  */
-#define ENCODE_QUAL_ADDR_SPACE(NUM) ((NUM & 0xFF) << 8)
+#define ENCODE_QUAL_ADDR_SPACE(NUM) (((NUM) & 0xFF) << 8)
 #define DECODE_QUAL_ADDR_SPACE(X) (((X) >> 8) & 0xFF)
 
 /* Return all qualifiers except for the address space qualifiers.  */





  reply	other threads:[~2022-10-11 22:03 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       ` Paul Iannetta [this message]
2022-10-12  1:49         ` [PATCH v2] " Jason Merrill
2022-10-13  0:52           ` Paul Iannetta
2022-10-13  5:46             ` Jakub Jelinek
2022-10-13 15:14               ` Paul Iannetta
2022-10-13 15:02             ` Jason Merrill
2022-10-13 15:23               ` Paul Iannetta
2022-10-13 15:47                 ` Jason Merrill
2022-10-13 16:02                   ` Paul Iannetta
2022-10-13 19:41                     ` Jason Merrill
2022-10-13 21:57                       ` Paul Iannetta
2022-10-14 15:19                         ` Jason Merrill
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=20221011220017.pvs5jawrzqoaqkkf@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).