Ping: [PATCH][C++] Pass type uses through the verify_type_context hook
diff mbox series

Message ID mptsglybplx.fsf@arm.com
State New
Headers show
Series
  • Ping: [PATCH][C++] Pass type uses through the verify_type_context hook
Related show

Commit Message

Richard Sandiford Dec. 5, 2019, 6:21 p.m. UTC
Ping.

Richard Sandiford <richard.sandiford@arm.com> writes:
> This patch makes the C++ frontend work with the verify_type_context hook
> [https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00942.html].  We need
> some new type contexts for features that don't exist in C, but otherwise
> the patch is very similar to the C one.
>
> TCTX_CAPTURE_BY_COPY could really be treated as an instance of
> TCTX_FIELD, but the error message is better if we split it out.
>
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?
>
> Richard

2019-11-16  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.h (TCTX_ALLOCATION, TCTX_DEALLOCATION, TCTX_EXCEPTIONS)
	(TCTX_CAPTURE_BY_COPY): New type_context_kinds.
	* config/aarch64/aarch64-sve-builtins.cc (verify_type_context):
	Handle them.

gcc/cp/
	* decl.c (start_decl_1): Use verify_type_context to check whether
	the target allows variables of a particular type to have static
	or thread-local storage duration.
	(check_array_initializer): Use verify_type_context to check whether
	the target allows a particular type to be used as an array element.
	(create_array_type_for_decl): Likewise.
	(cp_finish_decl): Use verify_type_context to check whether
	the target allows static member variables of a particular type.
	(grokdeclarator): Likewise.  Also use verify_type_context to check
	whether the target allows non-static member variables of a particular
	type.
	* except.c: Include target.h.
	(is_admissible_throw_operand_or_catch_parameter): Use
	verify_type_context to check whether the target allows particular
	types to be thrown and caught.
	* typeck2.c (add_exception_specifier): Likewise.
	* init.c (build_new_1): Use verify_type_context to check whether
	the target allows particular types to be dynamically allocated.
	(build_vec_delete_1, build_delete): Use verify_type_context to check
	whether the target allows particular types to be deleted.
	* lambda.c (add_capture): Use verify_type_context to check
	whether the target allows particular types to be captured by copy.
	* pt.c: Include target.h.
	(instantiate_class_template_1): Use verify_type_context to check
	whether the target allows non-static member variables of a particular
	type.
	* typeck.c (cxx_alignof_expr): Use verify_type_context to check
	whether the target allows the alignment of a particular type
	to be measured.
	(pointer_diff, cp_build_unary_op): Use verify_type_context to check
	whether the target allows arithmetic involving pointers to particular
	types.

gcc/testsuite/
	* g++.dg/ext/sve-sizeless-1.C: New test.
	* g++.dg/ext/sve-sizeless-2.C: Likewise.

Comments

Marek Polacek Dec. 5, 2019, 6:34 p.m. UTC | #1
On Thu, Dec 05, 2019 at 06:21:14PM +0000, Richard Sandiford wrote:
> Ping.
> 
> Richard Sandiford <richard.sandiford@arm.com> writes:
> > This patch makes the C++ frontend work with the verify_type_context hook
> > [https://gcc.gnu.org/ml/gcc-patches/2019-11/msg00942.html].  We need
> > some new type contexts for features that don't exist in C, but otherwise
> > the patch is very similar to the C one.
> >
> > TCTX_CAPTURE_BY_COPY could really be treated as an instance of
> > TCTX_FIELD, but the error message is better if we split it out.
> >
> > Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?
...
> Index: gcc/cp/decl.c
> ===================================================================
> --- gcc/cp/decl.c	2019-12-04 10:58:40.000000000 +0000
> +++ gcc/cp/decl.c	2019-12-04 10:59:10.215988487 +0000
> @@ -5470,6 +5470,13 @@ start_decl_1 (tree decl, bool initialize
>        cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
>      }
>  
> +  if (is_global_var (decl))
> +    {
> +      type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
> +				   ? TCTX_THREAD_STORAGE
> +				   : TCTX_STATIC_STORAGE);
> +      verify_type_context (input_location, context, TREE_TYPE (decl));
> +    }
>    if (initialized)
>      /* Is it valid for this decl to have an initializer at all?  */
>      {
> @@ -6527,6 +6534,12 @@ check_array_initializer (tree decl, tree
>  	error ("elements of array %q#T have incomplete type", type);
>        return true;
>      }
> +
> +  location_t loc = (decl && DECL_P (decl)
> +		    ? DECL_SOURCE_LOCATION (decl) : input_location);

Not a review but I suspect you could use location_of here.

--
Marek Polacek • Red Hat, Inc. • 300 A St, Boston, MA
Jason Merrill Dec. 5, 2019, 8:17 p.m. UTC | #2
On 12/5/19 1:21 PM, Richard Sandiford wrote:
> +  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, type))
> +    return false;
> +
> +  else if (TYPE_REF_P (type)
> +	   && !verify_type_context (input_location, TCTX_EXCEPTIONS,
> +				    TREE_TYPE (type)))

You could use the non_reference function to combine these.

Jason
Richard Sandiford Dec. 6, 2019, 2:26 p.m. UTC | #3
Jason Merrill <jason@redhat.com> writes:
> On 12/5/19 1:21 PM, Richard Sandiford wrote:
>> +  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, type))
>> +    return false;
>> +
>> +  else if (TYPE_REF_P (type)
>> +	   && !verify_type_context (input_location, TCTX_EXCEPTIONS,
>> +				    TREE_TYPE (type)))
>
> You could use the non_reference function to combine these.

Thanks.  This patch fixes that and follows Marek's suggestion of using
location_of in check_array_initializer.  (I wondered whether to check
for decl == error_mark_node as well, but that can't currently happen.)

Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

Richard


2019-12-06  Richard Sandiford  <richard.sandiford@arm.com>

gcc/
	* target.h (TCTX_ALLOCATION, TCTX_DEALLOCATION, TCTX_EXCEPTIONS)
	(TCTX_CAPTURE_BY_COPY): New type_context_kinds.
	* config/aarch64/aarch64-sve-builtins.cc (verify_type_context):
	Handle them.

gcc/cp/
	* decl.c (start_decl_1): Use verify_type_context to check whether
	the target allows variables of a particular type to have static
	or thread-local storage duration.
	(check_array_initializer): Use verify_type_context to check whether
	the target allows a particular type to be used as an array element.
	(create_array_type_for_decl): Likewise.
	(cp_finish_decl): Use verify_type_context to check whether
	the target allows static member variables of a particular type.
	(grokdeclarator): Likewise.  Also use verify_type_context to check
	whether the target allows non-static member variables of a particular
	type.
	* except.c: Include target.h.
	(is_admissible_throw_operand_or_catch_parameter): Use
	verify_type_context to check whether the target allows particular
	types to be thrown and caught.
	* typeck2.c (add_exception_specifier): Likewise.
	* init.c (build_new_1): Use verify_type_context to check whether
	the target allows particular types to be dynamically allocated.
	(build_vec_delete_1, build_delete): Use verify_type_context to check
	whether the target allows particular types to be deleted.
	* lambda.c (add_capture): Use verify_type_context to check
	whether the target allows particular types to be captured by copy.
	* pt.c: Include target.h.
	(instantiate_class_template_1): Use verify_type_context to check
	whether the target allows non-static member variables of a particular
	type.
	* typeck.c (cxx_alignof_expr): Use verify_type_context to check
	whether the target allows the alignment of a particular type
	to be measured.
	(pointer_diff, cp_build_unary_op): Use verify_type_context to check
	whether the target allows arithmetic involving pointers to particular
	types.

gcc/testsuite/
	* g++.dg/ext/sve-sizeless-1.C: New test.
	* g++.dg/ext/sve-sizeless-2.C: Likewise.

Index: gcc/target.h
===================================================================
--- gcc/target.h	2019-12-04 13:13:48.000000000 +0000
+++ gcc/target.h	2019-12-06 14:11:28.233552680 +0000
@@ -249,7 +249,19 @@ enum type_context_kind {
 
   /* Adding to or subtracting from a pointer to T, or computing the
      difference between two pointers when one of them is a pointer to T.  */
-  TCTX_POINTER_ARITH
+  TCTX_POINTER_ARITH,
+
+  /* Dynamically allocating objects of type T.  */
+  TCTX_ALLOCATION,
+
+  /* Dynamically deallocating objects of type T.  */
+  TCTX_DEALLOCATION,
+
+  /* Throwing or catching an object of type T.  */
+  TCTX_EXCEPTIONS,
+
+  /* Capturing objects of type T by value in a closure.  */
+  TCTX_CAPTURE_BY_COPY
 };
 
 extern bool verify_type_context (location_t, type_context_kind, const_tree,
Index: gcc/config/aarch64/aarch64-sve-builtins.cc
===================================================================
--- gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-04 13:13:48.000000000 +0000
+++ gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-06 14:11:28.217552787 +0000
@@ -3352,6 +3352,26 @@ verify_type_context (location_t loc, typ
       if (!silent_p)
 	error_at (loc, "array elements cannot have SVE type %qT", type);
       return false;
+
+    case TCTX_ALLOCATION:
+      if (!silent_p)
+	error_at (loc, "cannot allocate objects with SVE type %qT", type);
+      return false;
+
+    case TCTX_DEALLOCATION:
+      if (!silent_p)
+	error_at (loc, "cannot delete objects with SVE type %qT", type);
+      return false;
+
+    case TCTX_EXCEPTIONS:
+      if (!silent_p)
+	error_at (loc, "cannot throw or catch SVE type %qT", type);
+      return false;
+
+    case TCTX_CAPTURE_BY_COPY:
+      if (!silent_p)
+	error_at (loc, "capture by copy of SVE type %qT", type);
+      return false;
     }
   gcc_unreachable ();
 }
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	2019-12-06 10:31:11.638430940 +0000
+++ gcc/cp/decl.c	2019-12-06 14:11:28.221552762 +0000
@@ -5470,6 +5470,13 @@ start_decl_1 (tree decl, bool initialize
       cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
     }
 
+  if (is_global_var (decl))
+    {
+      type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
+				   ? TCTX_THREAD_STORAGE
+				   : TCTX_STATIC_STORAGE);
+      verify_type_context (input_location, context, TREE_TYPE (decl));
+    }
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?  */
     {
@@ -6535,6 +6542,11 @@ check_array_initializer (tree decl, tree
 	error ("elements of array %q#T have incomplete type", type);
       return true;
     }
+
+  location_t loc = (decl ? location_of (decl) : input_location);
+  if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, element_type))
+    return true;
+
   /* A compound literal can't have variable size.  */
   if (init && !decl
       && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
@@ -7482,6 +7494,8 @@ cp_finish_decl (tree decl, tree init, bo
 
   if (VAR_P (decl)
       && DECL_CLASS_SCOPE_P (decl)
+      && verify_type_context (DECL_SOURCE_LOCATION (decl),
+			      TCTX_STATIC_STORAGE, type)
       && DECL_INITIALIZED_IN_CLASS_P (decl))
     check_static_variable_definition (decl, type);
 
@@ -10550,6 +10564,10 @@ create_array_type_for_decl (tree name, t
       break;
     }
 
+  if (!verify_type_context (name ? loc : input_location,
+			    TCTX_ARRAY_ELEMENT, type))
+    return error_mark_node;
+
   /* [dcl.array]
 
      The constant expressions that specify the bounds of the arrays
@@ -13254,6 +13272,14 @@ grokdeclarator (const cp_declarator *dec
 		decl = NULL_TREE;
 	      }
 	  }
+	else if (!verify_type_context (input_location,
+				       staticp
+				       ? TCTX_STATIC_STORAGE
+				       : TCTX_FIELD, type))
+	  {
+	    type = error_mark_node;
+	    decl = NULL_TREE;
+	  }
 	else
 	  {
 	    if (friendp)
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	2019-12-04 13:13:48.000000000 +0000
+++ gcc/cp/except.c	2019-12-06 14:11:28.221552762 +0000
@@ -29,6 +29,7 @@ the Free Software Foundation; either ver
 #include "trans-mem.h"
 #include "attribs.h"
 #include "tree-iterator.h"
+#include "target.h"
 
 static void push_eh_cleanup (tree);
 static tree prepare_eh_type (tree);
@@ -927,6 +928,10 @@ is_admissible_throw_operand_or_catch_par
   if (!complete_ptr_ref_or_void_ptr_p (type, expr))
     return false;
 
+  tree nonref_type = non_reference (type);
+  if (!verify_type_context (input_location, TCTX_EXCEPTIONS, nonref_type))
+    return false;
+
   /* 10.4/3 An abstract class shall not be used as a parameter type,
 	    as a function return type or as type of an explicit
 	    conversion.  */
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	2019-12-05 14:20:16.965063368 +0000
+++ gcc/cp/typeck2.c	2019-12-06 14:11:28.233552680 +0000
@@ -33,6 +33,7 @@ the Free Software Foundation; either ver
 #include "varasm.h"
 #include "intl.h"
 #include "gcc-rich-location.h"
+#include "target.h"
 
 static tree
 process_init_constructor (tree type, tree init, int nested, int flags,
@@ -2401,6 +2402,9 @@ add_exception_specifier (tree list, tree
     ok = true;
   else if (processing_template_decl)
     ok = true;
+  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, core,
+				 !(complain & tf_error)))
+    return error_mark_node;
   else
     {
       ok = true;
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	2019-12-04 13:13:48.000000000 +0000
+++ gcc/cp/init.c	2019-12-06 14:11:28.221552762 +0000
@@ -3058,6 +3058,10 @@ build_new_1 (vec<tree, va_gc> **placemen
 				    complain);
     }
 
+  if (!verify_type_context (input_location, TCTX_ALLOCATION, elt_type,
+			    !(complain & tf_error)))
+    return error_mark_node;
+
   if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error))
     {
       error ("variably modified type not allowed in new-expression");
@@ -3942,6 +3946,10 @@ build_vec_delete_1 (tree base, tree maxi
   if (base == error_mark_node || maxindex == error_mark_node)
     return error_mark_node;
 
+  if (!verify_type_context (input_location, TCTX_DEALLOCATION, type,
+			    !(complain & tf_error)))
+    return error_mark_node;
+
   if (!COMPLETE_TYPE_P (type))
     {
       if (complain & tf_warning)
@@ -4827,6 +4835,11 @@ build_delete (tree otype, tree addr, spe
       if (!VOID_TYPE_P (type))
 	{
 	  complete_type (type);
+	  if (deleting
+	      && !verify_type_context (input_location, TCTX_DEALLOCATION, type,
+				       !(complain & tf_error)))
+	    return error_mark_node;
+
 	  if (!COMPLETE_TYPE_P (type))
 	    {
 	      if (complain & tf_warning)
Index: gcc/cp/lambda.c
===================================================================
--- gcc/cp/lambda.c	2019-12-04 13:13:48.000000000 +0000
+++ gcc/cp/lambda.c	2019-12-06 14:11:28.225552732 +0000
@@ -30,6 +30,7 @@
 #include "tree-iterator.h"
 #include "toplev.h"
 #include "gimplify.h"
+#include "target.h"
 
 /* Constructor for a lambda expression.  */
 
@@ -579,6 +580,9 @@ add_capture (tree lambda, tree id, tree
 	      cxx_incomplete_type_inform (type);
 	      return error_mark_node;
 	    }
+	  else if (!verify_type_context (input_location,
+					 TCTX_CAPTURE_BY_COPY, type))
+	    return error_mark_node;
 	}
     }
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	2019-12-05 14:20:16.969063342 +0000
+++ gcc/cp/pt.c	2019-12-06 14:11:28.229552706 +0000
@@ -42,6 +42,7 @@ the Free Software Foundation; either ver
 #include "gimplify.h"
 #include "gcc-rich-location.h"
 #include "selftest.h"
+#include "target.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -11815,6 +11816,9 @@ instantiate_class_template_1 (tree type)
 			      error ("flexible array member %qD in union", r);
 			      TREE_TYPE (r) = error_mark_node;
 			    }
+			  else if (!verify_type_context (input_location,
+							 TCTX_FIELD, rtype))
+			    TREE_TYPE (r) = error_mark_node;
 			}
 
 		      /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	2019-12-04 13:13:48.000000000 +0000
+++ gcc/cp/typeck.c	2019-12-06 14:11:28.229552706 +0000
@@ -1824,7 +1824,14 @@ cxx_alignof_expr (tree e, tsubst_flags_t
 
   e = mark_type_use (e);
 
-  if (VAR_P (e))
+  if (!verify_type_context (input_location, TCTX_ALIGNOF, TREE_TYPE (e),
+			    !(complain & tf_error)))
+    {
+      if (!(complain & tf_error))
+	return error_mark_node;
+      t = size_one_node;
+    }
+  else if (VAR_P (e))
     t = size_int (DECL_ALIGN_UNIT (e));
   else if (bitfield_p (e))
     {
@@ -5778,6 +5785,13 @@ pointer_diff (location_t loc, tree op0,
       else
 	return error_mark_node;
     }
+  else if (!verify_type_context (loc, TCTX_POINTER_ARITH,
+				 TREE_TYPE (TREE_TYPE (op0)),
+				 !(complain & tf_error))
+	   || !verify_type_context (loc, TCTX_POINTER_ARITH,
+				    TREE_TYPE (TREE_TYPE (op1)),
+				    !(complain & tf_error)))
+    return error_mark_node;
 
   /* Determine integer type result of the subtraction.  This will usually
      be the same as the result type (ptrdiff_t), but may need to be a wider
@@ -6572,6 +6586,10 @@ cp_build_unary_op (enum tree_code code,
                 else
                   return error_mark_node;
               }
+	    else if (!verify_type_context (location, TCTX_POINTER_ARITH,
+					   TREE_TYPE (argtype),
+					   !(complain & tf_error)))
+	      return error_mark_node;
 
 	    inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
 	  }
Index: gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
===================================================================
--- /dev/null	2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/g++.dg/ext/sve-sizeless-1.C	2019-12-06 14:11:28.233552680 +0000
@@ -0,0 +1,420 @@
+// { dg-do compile { target aarch64*-*-* } }
+// { dg-options "-Wclass-memaccess" }
+
+#pragma GCC target "+sve"
+
+typedef __SIZE_TYPE__ size_t;
+inline void *operator new (size_t, void *__p) throw() { return __p; }
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+// Sizeless objects with global scope.
+
+svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
+
+// Sizeless arrays.
+
+typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+// Sizeless member variables.
+
+struct struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+union union1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+#if __cplusplus >= 201103L
+struct static_sve_sc {
+  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
+};
+#endif
+
+// Sizeless member variables in templated structures.
+
+template<typename T>
+struct templated_struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+template<typename T>
+struct templated_struct2 {
+  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
+};
+
+template class templated_struct2<svint8_t>;
+
+template<typename T>
+struct templated_struct3 {
+  T &a;
+};
+
+template class templated_struct3<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<typename T>
+struct templated_struct4 {
+  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+};
+
+template class templated_struct4<svint8_t>;
+#endif
+
+template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
+template class templated_struct5<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<int N> using typedef_sizeless1 = svint8_t;
+template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
+template<typename T> using array = T[2];
+#endif
+
+// Pointers to sizeless types.
+
+svint8_t *global_sve_sc_ptr;
+
+// Sizeless arguments and return values.
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_const_int_ref (const int &);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+// Sizeless types in throw specifications.
+
+#if __cplusplus < 201103L
+void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Main tests for statements and expressions.
+
+void
+statements (int n)
+{
+  // Local declarations.
+
+  svint8_t sve_sc1, sve_sc2;
+  volatile svint8_t volatile_sve_sc1;
+  int8x32_t gnu_sc1;
+  svint16_t sve_sh1;
+
+  // Layout queries.
+
+  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+
+#if __cplusplus >= 201103L
+  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+#endif
+
+  // Initialization.
+
+  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  svint8_t init_sve_sc1 (sve_sc1);
+  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc3 = sve_sc1;
+  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc5 = {};
+  svint8_t init_sve_sc6 = { sve_sc1 };
+  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Constructor calls.
+
+  (0, svint8_t ());
+
+  // Lvalue reference binding
+
+  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
+  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
+  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
+
+  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
+  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
+  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
+
+  // Compound literals.
+
+  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  // Arrays.
+
+  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+  // Assignment.
+
+  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
+
+  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
+  sve_sc1 = sve_sc1;
+  sve_sc1 = gnu_sc1; // { dg-error {cannot convert 'int8x32_t'[^\n]* to 'svint8_t' in assignment} }
+  gnu_sc1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int8x32_t'} }
+  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Casting.
+
+  (void) sve_sc1;
+  (void) volatile_sve_sc1;
+  (void) *&volatile_sve_sc1;
+
+  // Addressing and dereferencing.
+
+  svint8_t *sve_sc_ptr = &sve_sc1;
+  int8x32_t *gnu_sc_ptr = &gnu_sc1;
+  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
+
+  // Pointer assignment.
+
+  gnu_sc_ptr = sve_sc_ptr; // { dg-error {cannot convert 'svint8_t\*' to 'int8x32_t\*'} }
+  sve_sc_ptr = gnu_sc_ptr; // { dg-error {cannot convert 'int8x32_t\*'[^\n]* to 'svint8_t\*'} }
+
+  // Pointer arithmetic.
+
+  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} }
+  sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} }
+  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+
+  // Pointer comparison.
+
+  sve_sc_ptr == &sve_sc1;
+  sve_sc_ptr != &sve_sc1;
+  sve_sc_ptr < &sve_sc1;
+  sve_sc_ptr <= &sve_sc1;
+  sve_sc_ptr > &sve_sc1;
+  sve_sc_ptr >= &sve_sc1;
+  gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+
+  // New and delete.
+
+  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
+  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
+  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
+
+  // Conditional expressions.
+
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
+  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
+  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc_ptr : sve_sc_ptr;
+  0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
+  0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
+
+  // Function arguments.
+
+  ext_consume_sve_sc (sve_sc1);
+  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
+  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
+  ext_consume_varargs (1, sve_sc1);
+
+  // Function returns.
+
+  ext_produce_sve_sc ();
+  sve_sc1 = ext_produce_sve_sc ();
+  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
+
+  // Auto
+
+#if __cplusplus >= 201103L
+  auto auto_sve_sc1 = sve_sc1;
+  auto auto_sve_sc1_return = ext_produce_sve_sc ();
+#endif
+
+  // Varargs processing.
+
+  __builtin_va_list valist;
+  __builtin_va_arg (valist, svint8_t);
+
+  // Other built-ins
+
+  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
+  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
+
+  // Lambdas
+
+#if __cplusplus >= 201103L
+  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
+  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
+  [&] () { sve_sc1 = sve_sc2; };
+  [] () { return ext_produce_sve_sc (); } ();
+#endif
+
+  // Exceptions
+
+  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t *x) {}
+#if __cplusplus < 201103L
+  thrower2 ();
+#endif
+
+  // Use in traits.  Doesn't use static_assert so that tests work with
+  // earlier -std=s.
+
+  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
+  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
+     for int8x32_t changes then the behavior for svint8_t should change in the same
+     way.  */
+  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+}
+
+// Function parameters in definitions.
+
+void
+unnamed_st1 (svint8_t)
+{
+}
+
+void
+named_st1 (svint8_t param1)
+{
+  svint8_t sve_sc1 = param1;
+}
+
+// Function return values in definitions.
+
+svint8_t
+ret_st1 (svint8_t param)
+{
+  return param;
+}
+
+svint8_t
+bad_ret_st1 (svint16_t param)
+{
+  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
+}
+
+#if __cplusplus >= 201103L
+template<typename T>
+void
+const_to_sve_sc (T i)
+{
+  constexpr svint8_t a = (svint8_t) i;
+}
+#endif
+
+template<typename T>
+int
+get_x (T *a)
+{
+  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
+}
+template int get_x<svint8_t>(svint8_t *);
+
+#if __cplusplus < 201103L
+void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Using "auto" as a return type.
+
+#if __cplusplus >= 201402L
+auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
+const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
+#endif
Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
===================================================================
--- /dev/null	2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C	2019-12-06 14:11:28.233552680 +0000
@@ -0,0 +1,420 @@
+// { dg-do compile { target aarch64*-*-* } }
+// { dg-options "-Wclass-memaccess -msve-vector-bits=256" }
+
+#pragma GCC target "+sve"
+
+typedef __SIZE_TYPE__ size_t;
+inline void *operator new (size_t, void *__p) throw() { return __p; }
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+// Sizeless objects with global scope.
+
+svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
+
+// Sizeless arrays.
+
+typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+// Sizeless member variables.
+
+struct struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+union union1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+#if __cplusplus >= 201103L
+struct static_sve_sc {
+  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
+};
+#endif
+
+// Sizeless member variables in templated structures.
+
+template<typename T>
+struct templated_struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+template<typename T>
+struct templated_struct2 {
+  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
+};
+
+template class templated_struct2<svint8_t>;
+
+template<typename T>
+struct templated_struct3 {
+  T &a;
+};
+
+template class templated_struct3<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<typename T>
+struct templated_struct4 {
+  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+};
+
+template class templated_struct4<svint8_t>;
+#endif
+
+template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
+template class templated_struct5<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<int N> using typedef_sizeless1 = svint8_t;
+template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
+template<typename T> using array = T[2];
+#endif
+
+// Pointers to sizeless types.
+
+svint8_t *global_sve_sc_ptr;
+
+// Sizeless arguments and return values.
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_const_int_ref (const int &);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+// Sizeless types in throw specifications.
+
+#if __cplusplus < 201103L
+void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Main tests for statements and expressions.
+
+void
+statements (int n)
+{
+  // Local declarations.
+
+  svint8_t sve_sc1, sve_sc2;
+  volatile svint8_t volatile_sve_sc1;
+  int8x32_t gnu_sc1;
+  svint16_t sve_sh1;
+
+  // Layout queries.
+
+  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+
+#if __cplusplus >= 201103L
+  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+#endif
+
+  // Initialization.
+
+  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  svint8_t init_sve_sc1 (sve_sc1);
+  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc3 = sve_sc1;
+  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc5 = {};
+  svint8_t init_sve_sc6 = { sve_sc1 };
+  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Constructor calls.
+
+  (0, svint8_t ());
+
+  // Lvalue reference binding
+
+  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
+  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
+  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
+
+  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
+  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
+  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
+
+  // Compound literals.
+
+  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  // Arrays.
+
+  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+  // Assignment.
+
+  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
+
+  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
+  sve_sc1 = sve_sc1;
+  sve_sc1 = gnu_sc1;
+  gnu_sc1 = sve_sc1;
+  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Casting.
+
+  (void) sve_sc1;
+  (void) volatile_sve_sc1;
+  (void) *&volatile_sve_sc1;
+
+  // Addressing and dereferencing.
+
+  svint8_t *sve_sc_ptr = &sve_sc1;
+  int8x32_t *gnu_sc_ptr = &gnu_sc1;
+  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
+
+  // Pointer assignment.
+
+  gnu_sc_ptr = sve_sc_ptr;
+  sve_sc_ptr = gnu_sc_ptr;
+
+  // Pointer arithmetic.
+
+  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+
+  // Pointer comparison.
+
+  sve_sc_ptr == &sve_sc1;
+  sve_sc_ptr != &sve_sc1;
+  sve_sc_ptr < &sve_sc1;
+  sve_sc_ptr <= &sve_sc1;
+  sve_sc_ptr > &sve_sc1;
+  sve_sc_ptr >= &sve_sc1;
+  gnu_sc_ptr == sve_sc_ptr;
+  gnu_sc_ptr != sve_sc_ptr;
+  gnu_sc_ptr < sve_sc_ptr;
+  gnu_sc_ptr <= sve_sc_ptr;
+  gnu_sc_ptr > sve_sc_ptr;
+  gnu_sc_ptr >= sve_sc_ptr;
+  sve_sc_ptr == gnu_sc_ptr;
+  sve_sc_ptr != gnu_sc_ptr;
+  sve_sc_ptr < gnu_sc_ptr;
+  sve_sc_ptr <= gnu_sc_ptr;
+  sve_sc_ptr > gnu_sc_ptr;
+  sve_sc_ptr >= gnu_sc_ptr;
+
+  // New and delete.
+
+  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
+  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
+  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
+
+  // Conditional expressions.
+
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
+  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
+  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc_ptr : sve_sc_ptr;
+  0 ? sve_sc_ptr : gnu_sc_ptr;
+  0 ? gnu_sc_ptr : sve_sc_ptr;
+
+  // Function arguments.
+
+  ext_consume_sve_sc (sve_sc1);
+  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
+  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
+  ext_consume_varargs (1, sve_sc1);
+
+  // Function returns.
+
+  ext_produce_sve_sc ();
+  sve_sc1 = ext_produce_sve_sc ();
+  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
+
+  // Auto
+
+#if __cplusplus >= 201103L
+  auto auto_sve_sc1 = sve_sc1;
+  auto auto_sve_sc1_return = ext_produce_sve_sc ();
+#endif
+
+  // Varargs processing.
+
+  __builtin_va_list valist;
+  __builtin_va_arg (valist, svint8_t);
+
+  // Other built-ins
+
+  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
+  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
+
+  // Lambdas
+
+#if __cplusplus >= 201103L
+  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
+  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
+  [&] () { sve_sc1 = sve_sc2; };
+  [] () { return ext_produce_sve_sc (); } ();
+#endif
+
+  // Exceptions
+
+  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t *x) {}
+#if __cplusplus < 201103L
+  thrower2 ();
+#endif
+
+  // Use in traits.  Doesn't use static_assert so that tests work with
+  // earlier -std=s.
+
+  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
+  { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
+  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
+     for int8x32_t changes then the behavior for svint8_t should change in the same
+     way.  */
+  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+}
+
+// Function parameters in definitions.
+
+void
+unnamed_st1 (svint8_t)
+{
+}
+
+void
+named_st1 (svint8_t param1)
+{
+  svint8_t sve_sc1 = param1;
+}
+
+// Function return values in definitions.
+
+svint8_t
+ret_st1 (svint8_t param)
+{
+  return param;
+}
+
+svint8_t
+bad_ret_st1 (svint16_t param)
+{
+  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
+}
+
+#if __cplusplus >= 201103L
+template<typename T>
+void
+const_to_sve_sc (T i)
+{
+  constexpr svint8_t a = (svint8_t) i;
+}
+#endif
+
+template<typename T>
+int
+get_x (T *a)
+{
+  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
+}
+template int get_x<svint8_t>(svint8_t *);
+
+#if __cplusplus < 201103L
+void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Using "auto" as a return type.
+
+#if __cplusplus >= 201402L
+auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
+const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
+#endif
Jason Merrill Dec. 6, 2019, 5:46 p.m. UTC | #4
On 12/6/19 9:26 AM, Richard Sandiford wrote:
> Jason Merrill <jason@redhat.com> writes:
>> On 12/5/19 1:21 PM, Richard Sandiford wrote:
>>> +  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, type))
>>> +    return false;
>>> +
>>> +  else if (TYPE_REF_P (type)
>>> +	   && !verify_type_context (input_location, TCTX_EXCEPTIONS,
>>> +				    TREE_TYPE (type)))
>>
>> You could use the non_reference function to combine these.
> 
> Thanks.  This patch fixes that and follows Marek's suggestion of using
> location_of in check_array_initializer.  (I wondered whether to check
> for decl == error_mark_node as well, but that can't currently happen.)
> 
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK to install?

OK.

> Richard
> 
> 
> 2019-12-06  Richard Sandiford  <richard.sandiford@arm.com>
> 
> gcc/
> 	* target.h (TCTX_ALLOCATION, TCTX_DEALLOCATION, TCTX_EXCEPTIONS)
> 	(TCTX_CAPTURE_BY_COPY): New type_context_kinds.
> 	* config/aarch64/aarch64-sve-builtins.cc (verify_type_context):
> 	Handle them.
> 
> gcc/cp/
> 	* decl.c (start_decl_1): Use verify_type_context to check whether
> 	the target allows variables of a particular type to have static
> 	or thread-local storage duration.
> 	(check_array_initializer): Use verify_type_context to check whether
> 	the target allows a particular type to be used as an array element.
> 	(create_array_type_for_decl): Likewise.
> 	(cp_finish_decl): Use verify_type_context to check whether
> 	the target allows static member variables of a particular type.
> 	(grokdeclarator): Likewise.  Also use verify_type_context to check
> 	whether the target allows non-static member variables of a particular
> 	type.
> 	* except.c: Include target.h.
> 	(is_admissible_throw_operand_or_catch_parameter): Use
> 	verify_type_context to check whether the target allows particular
> 	types to be thrown and caught.
> 	* typeck2.c (add_exception_specifier): Likewise.
> 	* init.c (build_new_1): Use verify_type_context to check whether
> 	the target allows particular types to be dynamically allocated.
> 	(build_vec_delete_1, build_delete): Use verify_type_context to check
> 	whether the target allows particular types to be deleted.
> 	* lambda.c (add_capture): Use verify_type_context to check
> 	whether the target allows particular types to be captured by copy.
> 	* pt.c: Include target.h.
> 	(instantiate_class_template_1): Use verify_type_context to check
> 	whether the target allows non-static member variables of a particular
> 	type.
> 	* typeck.c (cxx_alignof_expr): Use verify_type_context to check
> 	whether the target allows the alignment of a particular type
> 	to be measured.
> 	(pointer_diff, cp_build_unary_op): Use verify_type_context to check
> 	whether the target allows arithmetic involving pointers to particular
> 	types.
> 
> gcc/testsuite/
> 	* g++.dg/ext/sve-sizeless-1.C: New test.
> 	* g++.dg/ext/sve-sizeless-2.C: Likewise.
> 
> Index: gcc/target.h
> ===================================================================
> --- gcc/target.h	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/target.h	2019-12-06 14:11:28.233552680 +0000
> @@ -249,7 +249,19 @@ enum type_context_kind {
>   
>     /* Adding to or subtracting from a pointer to T, or computing the
>        difference between two pointers when one of them is a pointer to T.  */
> -  TCTX_POINTER_ARITH
> +  TCTX_POINTER_ARITH,
> +
> +  /* Dynamically allocating objects of type T.  */
> +  TCTX_ALLOCATION,
> +
> +  /* Dynamically deallocating objects of type T.  */
> +  TCTX_DEALLOCATION,
> +
> +  /* Throwing or catching an object of type T.  */
> +  TCTX_EXCEPTIONS,
> +
> +  /* Capturing objects of type T by value in a closure.  */
> +  TCTX_CAPTURE_BY_COPY
>   };
>   
>   extern bool verify_type_context (location_t, type_context_kind, const_tree,
> Index: gcc/config/aarch64/aarch64-sve-builtins.cc
> ===================================================================
> --- gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-06 14:11:28.217552787 +0000
> @@ -3352,6 +3352,26 @@ verify_type_context (location_t loc, typ
>         if (!silent_p)
>   	error_at (loc, "array elements cannot have SVE type %qT", type);
>         return false;
> +
> +    case TCTX_ALLOCATION:
> +      if (!silent_p)
> +	error_at (loc, "cannot allocate objects with SVE type %qT", type);
> +      return false;
> +
> +    case TCTX_DEALLOCATION:
> +      if (!silent_p)
> +	error_at (loc, "cannot delete objects with SVE type %qT", type);
> +      return false;
> +
> +    case TCTX_EXCEPTIONS:
> +      if (!silent_p)
> +	error_at (loc, "cannot throw or catch SVE type %qT", type);
> +      return false;
> +
> +    case TCTX_CAPTURE_BY_COPY:
> +      if (!silent_p)
> +	error_at (loc, "capture by copy of SVE type %qT", type);
> +      return false;
>       }
>     gcc_unreachable ();
>   }
> Index: gcc/cp/decl.c
> ===================================================================
> --- gcc/cp/decl.c	2019-12-06 10:31:11.638430940 +0000
> +++ gcc/cp/decl.c	2019-12-06 14:11:28.221552762 +0000
> @@ -5470,6 +5470,13 @@ start_decl_1 (tree decl, bool initialize
>         cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
>       }
>   
> +  if (is_global_var (decl))
> +    {
> +      type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
> +				   ? TCTX_THREAD_STORAGE
> +				   : TCTX_STATIC_STORAGE);
> +      verify_type_context (input_location, context, TREE_TYPE (decl));
> +    }
>     if (initialized)
>       /* Is it valid for this decl to have an initializer at all?  */
>       {
> @@ -6535,6 +6542,11 @@ check_array_initializer (tree decl, tree
>   	error ("elements of array %q#T have incomplete type", type);
>         return true;
>       }
> +
> +  location_t loc = (decl ? location_of (decl) : input_location);
> +  if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, element_type))
> +    return true;
> +
>     /* A compound literal can't have variable size.  */
>     if (init && !decl
>         && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
> @@ -7482,6 +7494,8 @@ cp_finish_decl (tree decl, tree init, bo
>   
>     if (VAR_P (decl)
>         && DECL_CLASS_SCOPE_P (decl)
> +      && verify_type_context (DECL_SOURCE_LOCATION (decl),
> +			      TCTX_STATIC_STORAGE, type)
>         && DECL_INITIALIZED_IN_CLASS_P (decl))
>       check_static_variable_definition (decl, type);
>   
> @@ -10550,6 +10564,10 @@ create_array_type_for_decl (tree name, t
>         break;
>       }
>   
> +  if (!verify_type_context (name ? loc : input_location,
> +			    TCTX_ARRAY_ELEMENT, type))
> +    return error_mark_node;
> +
>     /* [dcl.array]
>   
>        The constant expressions that specify the bounds of the arrays
> @@ -13254,6 +13272,14 @@ grokdeclarator (const cp_declarator *dec
>   		decl = NULL_TREE;
>   	      }
>   	  }
> +	else if (!verify_type_context (input_location,
> +				       staticp
> +				       ? TCTX_STATIC_STORAGE
> +				       : TCTX_FIELD, type))
> +	  {
> +	    type = error_mark_node;
> +	    decl = NULL_TREE;
> +	  }
>   	else
>   	  {
>   	    if (friendp)
> Index: gcc/cp/except.c
> ===================================================================
> --- gcc/cp/except.c	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/cp/except.c	2019-12-06 14:11:28.221552762 +0000
> @@ -29,6 +29,7 @@ the Free Software Foundation; either ver
>   #include "trans-mem.h"
>   #include "attribs.h"
>   #include "tree-iterator.h"
> +#include "target.h"
>   
>   static void push_eh_cleanup (tree);
>   static tree prepare_eh_type (tree);
> @@ -927,6 +928,10 @@ is_admissible_throw_operand_or_catch_par
>     if (!complete_ptr_ref_or_void_ptr_p (type, expr))
>       return false;
>   
> +  tree nonref_type = non_reference (type);
> +  if (!verify_type_context (input_location, TCTX_EXCEPTIONS, nonref_type))
> +    return false;
> +
>     /* 10.4/3 An abstract class shall not be used as a parameter type,
>   	    as a function return type or as type of an explicit
>   	    conversion.  */
> Index: gcc/cp/typeck2.c
> ===================================================================
> --- gcc/cp/typeck2.c	2019-12-05 14:20:16.965063368 +0000
> +++ gcc/cp/typeck2.c	2019-12-06 14:11:28.233552680 +0000
> @@ -33,6 +33,7 @@ the Free Software Foundation; either ver
>   #include "varasm.h"
>   #include "intl.h"
>   #include "gcc-rich-location.h"
> +#include "target.h"
>   
>   static tree
>   process_init_constructor (tree type, tree init, int nested, int flags,
> @@ -2401,6 +2402,9 @@ add_exception_specifier (tree list, tree
>       ok = true;
>     else if (processing_template_decl)
>       ok = true;
> +  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, core,
> +				 !(complain & tf_error)))
> +    return error_mark_node;
>     else
>       {
>         ok = true;
> Index: gcc/cp/init.c
> ===================================================================
> --- gcc/cp/init.c	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/cp/init.c	2019-12-06 14:11:28.221552762 +0000
> @@ -3058,6 +3058,10 @@ build_new_1 (vec<tree, va_gc> **placemen
>   				    complain);
>       }
>   
> +  if (!verify_type_context (input_location, TCTX_ALLOCATION, elt_type,
> +			    !(complain & tf_error)))
> +    return error_mark_node;
> +
>     if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error))
>       {
>         error ("variably modified type not allowed in new-expression");
> @@ -3942,6 +3946,10 @@ build_vec_delete_1 (tree base, tree maxi
>     if (base == error_mark_node || maxindex == error_mark_node)
>       return error_mark_node;
>   
> +  if (!verify_type_context (input_location, TCTX_DEALLOCATION, type,
> +			    !(complain & tf_error)))
> +    return error_mark_node;
> +
>     if (!COMPLETE_TYPE_P (type))
>       {
>         if (complain & tf_warning)
> @@ -4827,6 +4835,11 @@ build_delete (tree otype, tree addr, spe
>         if (!VOID_TYPE_P (type))
>   	{
>   	  complete_type (type);
> +	  if (deleting
> +	      && !verify_type_context (input_location, TCTX_DEALLOCATION, type,
> +				       !(complain & tf_error)))
> +	    return error_mark_node;
> +
>   	  if (!COMPLETE_TYPE_P (type))
>   	    {
>   	      if (complain & tf_warning)
> Index: gcc/cp/lambda.c
> ===================================================================
> --- gcc/cp/lambda.c	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/cp/lambda.c	2019-12-06 14:11:28.225552732 +0000
> @@ -30,6 +30,7 @@
>   #include "tree-iterator.h"
>   #include "toplev.h"
>   #include "gimplify.h"
> +#include "target.h"
>   
>   /* Constructor for a lambda expression.  */
>   
> @@ -579,6 +580,9 @@ add_capture (tree lambda, tree id, tree
>   	      cxx_incomplete_type_inform (type);
>   	      return error_mark_node;
>   	    }
> +	  else if (!verify_type_context (input_location,
> +					 TCTX_CAPTURE_BY_COPY, type))
> +	    return error_mark_node;
>   	}
>       }
>   
> Index: gcc/cp/pt.c
> ===================================================================
> --- gcc/cp/pt.c	2019-12-05 14:20:16.969063342 +0000
> +++ gcc/cp/pt.c	2019-12-06 14:11:28.229552706 +0000
> @@ -42,6 +42,7 @@ the Free Software Foundation; either ver
>   #include "gimplify.h"
>   #include "gcc-rich-location.h"
>   #include "selftest.h"
> +#include "target.h"
>   
>   /* The type of functions taking a tree, and some additional data, and
>      returning an int.  */
> @@ -11815,6 +11816,9 @@ instantiate_class_template_1 (tree type)
>   			      error ("flexible array member %qD in union", r);
>   			      TREE_TYPE (r) = error_mark_node;
>   			    }
> +			  else if (!verify_type_context (input_location,
> +							 TCTX_FIELD, rtype))
> +			    TREE_TYPE (r) = error_mark_node;
>   			}
>   
>   		      /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
> Index: gcc/cp/typeck.c
> ===================================================================
> --- gcc/cp/typeck.c	2019-12-04 13:13:48.000000000 +0000
> +++ gcc/cp/typeck.c	2019-12-06 14:11:28.229552706 +0000
> @@ -1824,7 +1824,14 @@ cxx_alignof_expr (tree e, tsubst_flags_t
>   
>     e = mark_type_use (e);
>   
> -  if (VAR_P (e))
> +  if (!verify_type_context (input_location, TCTX_ALIGNOF, TREE_TYPE (e),
> +			    !(complain & tf_error)))
> +    {
> +      if (!(complain & tf_error))
> +	return error_mark_node;
> +      t = size_one_node;
> +    }
> +  else if (VAR_P (e))
>       t = size_int (DECL_ALIGN_UNIT (e));
>     else if (bitfield_p (e))
>       {
> @@ -5778,6 +5785,13 @@ pointer_diff (location_t loc, tree op0,
>         else
>   	return error_mark_node;
>       }
> +  else if (!verify_type_context (loc, TCTX_POINTER_ARITH,
> +				 TREE_TYPE (TREE_TYPE (op0)),
> +				 !(complain & tf_error))
> +	   || !verify_type_context (loc, TCTX_POINTER_ARITH,
> +				    TREE_TYPE (TREE_TYPE (op1)),
> +				    !(complain & tf_error)))
> +    return error_mark_node;
>   
>     /* Determine integer type result of the subtraction.  This will usually
>        be the same as the result type (ptrdiff_t), but may need to be a wider
> @@ -6572,6 +6586,10 @@ cp_build_unary_op (enum tree_code code,
>                   else
>                     return error_mark_node;
>                 }
> +	    else if (!verify_type_context (location, TCTX_POINTER_ARITH,
> +					   TREE_TYPE (argtype),
> +					   !(complain & tf_error)))
> +	      return error_mark_node;
>   
>   	    inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
>   	  }
> Index: gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
> ===================================================================
> --- /dev/null	2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/g++.dg/ext/sve-sizeless-1.C	2019-12-06 14:11:28.233552680 +0000
> @@ -0,0 +1,420 @@
> +// { dg-do compile { target aarch64*-*-* } }
> +// { dg-options "-Wclass-memaccess" }
> +
> +#pragma GCC target "+sve"
> +
> +typedef __SIZE_TYPE__ size_t;
> +inline void *operator new (size_t, void *__p) throw() { return __p; }
> +
> +#include <arm_sve.h>
> +
> +typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
> +
> +// Sizeless objects with global scope.
> +
> +svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
> +
> +// Sizeless arrays.
> +
> +typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +
> +// Sizeless member variables.
> +
> +struct struct1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +union union1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +#if __cplusplus >= 201103L
> +struct static_sve_sc {
> +  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
> +};
> +#endif
> +
> +// Sizeless member variables in templated structures.
> +
> +template<typename T>
> +struct templated_struct1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +template<typename T>
> +struct templated_struct2 {
> +  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
> +};
> +
> +template class templated_struct2<svint8_t>;
> +
> +template<typename T>
> +struct templated_struct3 {
> +  T &a;
> +};
> +
> +template class templated_struct3<svint8_t>;
> +
> +#if __cplusplus >= 201103L
> +template<typename T>
> +struct templated_struct4 {
> +  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
> +  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
> +};
> +
> +template class templated_struct4<svint8_t>;
> +#endif
> +
> +template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
> +template class templated_struct5<svint8_t>;
> +
> +#if __cplusplus >= 201103L
> +template<int N> using typedef_sizeless1 = svint8_t;
> +template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
> +template<typename T> using array = T[2];
> +#endif
> +
> +// Pointers to sizeless types.
> +
> +svint8_t *global_sve_sc_ptr;
> +
> +// Sizeless arguments and return values.
> +
> +void ext_consume_sve_sc (svint8_t);
> +void ext_consume_const_int_ref (const int &);
> +void ext_consume_varargs (int, ...);
> +svint8_t ext_produce_sve_sc ();
> +
> +// Sizeless types in throw specifications.
> +
> +#if __cplusplus < 201103L
> +void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +#endif
> +
> +// Main tests for statements and expressions.
> +
> +void
> +statements (int n)
> +{
> +  // Local declarations.
> +
> +  svint8_t sve_sc1, sve_sc2;
> +  volatile svint8_t volatile_sve_sc1;
> +  int8x32_t gnu_sc1;
> +  svint16_t sve_sh1;
> +
> +  // Layout queries.
> +
> +  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +
> +#if __cplusplus >= 201103L
> +  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
> +#endif
> +
> +  // Initialization.
> +
> +  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +
> +  svint8_t init_sve_sc1 (sve_sc1);
> +  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  svint8_t init_sve_sc3 = sve_sc1;
> +  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  svint8_t init_sve_sc5 = {};
> +  svint8_t init_sve_sc6 = { sve_sc1 };
> +  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +
> +  // Constructor calls.
> +
> +  (0, svint8_t ());
> +
> +  // Lvalue reference binding
> +
> +  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
> +  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
> +  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
> +
> +  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
> +  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
> +  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
> +
> +  // Compound literals.
> +
> +  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +
> +  // Arrays.
> +
> +  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +
> +  // Assignment.
> +
> +  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
> +
> +  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
> +  sve_sc1 = sve_sc1;
> +  sve_sc1 = gnu_sc1; // { dg-error {cannot convert 'int8x32_t'[^\n]* to 'svint8_t' in assignment} }
> +  gnu_sc1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int8x32_t'} }
> +  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +
> +  // Casting.
> +
> +  (void) sve_sc1;
> +  (void) volatile_sve_sc1;
> +  (void) *&volatile_sve_sc1;
> +
> +  // Addressing and dereferencing.
> +
> +  svint8_t *sve_sc_ptr = &sve_sc1;
> +  int8x32_t *gnu_sc_ptr = &gnu_sc1;
> +  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
> +
> +  // Pointer assignment.
> +
> +  gnu_sc_ptr = sve_sc_ptr; // { dg-error {cannot convert 'svint8_t\*' to 'int8x32_t\*'} }
> +  sve_sc_ptr = gnu_sc_ptr; // { dg-error {cannot convert 'int8x32_t\*'[^\n]* to 'svint8_t\*'} }
> +
> +  // Pointer arithmetic.
> +
> +  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} }
> +  sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} }
> +  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +
> +  // Pointer comparison.
> +
> +  sve_sc_ptr == &sve_sc1;
> +  sve_sc_ptr != &sve_sc1;
> +  sve_sc_ptr < &sve_sc1;
> +  sve_sc_ptr <= &sve_sc1;
> +  sve_sc_ptr > &sve_sc1;
> +  sve_sc_ptr >= &sve_sc1;
> +  gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +  sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
> +
> +  // New and delete.
> +
> +  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +
> +  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +
> +  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
> +  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
> +  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
> +
> +  // Conditional expressions.
> +
> +  0 ? sve_sc1 : sve_sc1;
> +  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
> +  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
> +  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
> +  0 ? sve_sc1 : sve_sc1;
> +  0 ? sve_sc_ptr : sve_sc_ptr;
> +  0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
> +  0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
> +
> +  // Function arguments.
> +
> +  ext_consume_sve_sc (sve_sc1);
> +  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
> +  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
> +  ext_consume_varargs (1, sve_sc1);
> +
> +  // Function returns.
> +
> +  ext_produce_sve_sc ();
> +  sve_sc1 = ext_produce_sve_sc ();
> +  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
> +
> +  // Auto
> +
> +#if __cplusplus >= 201103L
> +  auto auto_sve_sc1 = sve_sc1;
> +  auto auto_sve_sc1_return = ext_produce_sve_sc ();
> +#endif
> +
> +  // Varargs processing.
> +
> +  __builtin_va_list valist;
> +  __builtin_va_arg (valist, svint8_t);
> +
> +  // Other built-ins
> +
> +  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
> +  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
> +
> +  // Lambdas
> +
> +#if __cplusplus >= 201103L
> +  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
> +  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
> +  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
> +  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
> +  [&] () { sve_sc1 = sve_sc2; };
> +  [] () { return ext_produce_sve_sc (); } ();
> +#endif
> +
> +  // Exceptions
> +
> +  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t *x) {}
> +#if __cplusplus < 201103L
> +  thrower2 ();
> +#endif
> +
> +  // Use in traits.  Doesn't use static_assert so that tests work with
> +  // earlier -std=s.
> +
> +  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
> +  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
> +     for int8x32_t changes then the behavior for svint8_t should change in the same
> +     way.  */
> +  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
> +}
> +
> +// Function parameters in definitions.
> +
> +void
> +unnamed_st1 (svint8_t)
> +{
> +}
> +
> +void
> +named_st1 (svint8_t param1)
> +{
> +  svint8_t sve_sc1 = param1;
> +}
> +
> +// Function return values in definitions.
> +
> +svint8_t
> +ret_st1 (svint8_t param)
> +{
> +  return param;
> +}
> +
> +svint8_t
> +bad_ret_st1 (svint16_t param)
> +{
> +  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
> +}
> +
> +#if __cplusplus >= 201103L
> +template<typename T>
> +void
> +const_to_sve_sc (T i)
> +{
> +  constexpr svint8_t a = (svint8_t) i;
> +}
> +#endif
> +
> +template<typename T>
> +int
> +get_x (T *a)
> +{
> +  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
> +}
> +template int get_x<svint8_t>(svint8_t *);
> +
> +#if __cplusplus < 201103L
> +void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +#endif
> +
> +// Using "auto" as a return type.
> +
> +#if __cplusplus >= 201402L
> +auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
> +const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
> +auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
> +auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
> +#endif
> Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
> ===================================================================
> --- /dev/null	2019-09-17 11:41:18.176664108 +0100
> +++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C	2019-12-06 14:11:28.233552680 +0000
> @@ -0,0 +1,420 @@
> +// { dg-do compile { target aarch64*-*-* } }
> +// { dg-options "-Wclass-memaccess -msve-vector-bits=256" }
> +
> +#pragma GCC target "+sve"
> +
> +typedef __SIZE_TYPE__ size_t;
> +inline void *operator new (size_t, void *__p) throw() { return __p; }
> +
> +#include <arm_sve.h>
> +
> +typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
> +
> +// Sizeless objects with global scope.
> +
> +svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
> +
> +// Sizeless arrays.
> +
> +typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +
> +// Sizeless member variables.
> +
> +struct struct1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +union union1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +#if __cplusplus >= 201103L
> +struct static_sve_sc {
> +  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
> +};
> +#endif
> +
> +// Sizeless member variables in templated structures.
> +
> +template<typename T>
> +struct templated_struct1 {
> +  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
> +};
> +
> +template<typename T>
> +struct templated_struct2 {
> +  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
> +};
> +
> +template class templated_struct2<svint8_t>;
> +
> +template<typename T>
> +struct templated_struct3 {
> +  T &a;
> +};
> +
> +template class templated_struct3<svint8_t>;
> +
> +#if __cplusplus >= 201103L
> +template<typename T>
> +struct templated_struct4 {
> +  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
> +  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
> +};
> +
> +template class templated_struct4<svint8_t>;
> +#endif
> +
> +template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
> +template class templated_struct5<svint8_t>;
> +
> +#if __cplusplus >= 201103L
> +template<int N> using typedef_sizeless1 = svint8_t;
> +template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
> +template<typename T> using array = T[2];
> +#endif
> +
> +// Pointers to sizeless types.
> +
> +svint8_t *global_sve_sc_ptr;
> +
> +// Sizeless arguments and return values.
> +
> +void ext_consume_sve_sc (svint8_t);
> +void ext_consume_const_int_ref (const int &);
> +void ext_consume_varargs (int, ...);
> +svint8_t ext_produce_sve_sc ();
> +
> +// Sizeless types in throw specifications.
> +
> +#if __cplusplus < 201103L
> +void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +#endif
> +
> +// Main tests for statements and expressions.
> +
> +void
> +statements (int n)
> +{
> +  // Local declarations.
> +
> +  svint8_t sve_sc1, sve_sc2;
> +  volatile svint8_t volatile_sve_sc1;
> +  int8x32_t gnu_sc1;
> +  svint16_t sve_sh1;
> +
> +  // Layout queries.
> +
> +  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
> +  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
> +
> +#if __cplusplus >= 201103L
> +  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
> +#endif
> +
> +  // Initialization.
> +
> +  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +
> +  svint8_t init_sve_sc1 (sve_sc1);
> +  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  svint8_t init_sve_sc3 = sve_sc1;
> +  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  svint8_t init_sve_sc5 = {};
> +  svint8_t init_sve_sc6 = { sve_sc1 };
> +  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +
> +  // Constructor calls.
> +
> +  (0, svint8_t ());
> +
> +  // Lvalue reference binding
> +
> +  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
> +  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
> +  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
> +
> +  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
> +  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
> +  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
> +
> +  // Compound literals.
> +
> +  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
> +
> +  // Arrays.
> +
> +  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
> +
> +  // Assignment.
> +
> +  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
> +
> +  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
> +  sve_sc1 = sve_sc1;
> +  sve_sc1 = gnu_sc1;
> +  gnu_sc1 = sve_sc1;
> +  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +
> +  // Casting.
> +
> +  (void) sve_sc1;
> +  (void) volatile_sve_sc1;
> +  (void) *&volatile_sve_sc1;
> +
> +  // Addressing and dereferencing.
> +
> +  svint8_t *sve_sc_ptr = &sve_sc1;
> +  int8x32_t *gnu_sc_ptr = &gnu_sc1;
> +  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
> +
> +  // Pointer assignment.
> +
> +  gnu_sc_ptr = sve_sc_ptr;
> +  sve_sc_ptr = gnu_sc_ptr;
> +
> +  // Pointer arithmetic.
> +
> +  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
> +
> +  // Pointer comparison.
> +
> +  sve_sc_ptr == &sve_sc1;
> +  sve_sc_ptr != &sve_sc1;
> +  sve_sc_ptr < &sve_sc1;
> +  sve_sc_ptr <= &sve_sc1;
> +  sve_sc_ptr > &sve_sc1;
> +  sve_sc_ptr >= &sve_sc1;
> +  gnu_sc_ptr == sve_sc_ptr;
> +  gnu_sc_ptr != sve_sc_ptr;
> +  gnu_sc_ptr < sve_sc_ptr;
> +  gnu_sc_ptr <= sve_sc_ptr;
> +  gnu_sc_ptr > sve_sc_ptr;
> +  gnu_sc_ptr >= sve_sc_ptr;
> +  sve_sc_ptr == gnu_sc_ptr;
> +  sve_sc_ptr != gnu_sc_ptr;
> +  sve_sc_ptr < gnu_sc_ptr;
> +  sve_sc_ptr <= gnu_sc_ptr;
> +  sve_sc_ptr > gnu_sc_ptr;
> +  sve_sc_ptr >= gnu_sc_ptr;
> +
> +  // New and delete.
> +
> +  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +
> +  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
> +
> +  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
> +  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
> +  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
> +
> +  // Conditional expressions.
> +
> +  0 ? sve_sc1 : sve_sc1;
> +  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
> +  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
> +  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
> +  0 ? sve_sc1 : sve_sc1;
> +  0 ? sve_sc_ptr : sve_sc_ptr;
> +  0 ? sve_sc_ptr : gnu_sc_ptr;
> +  0 ? gnu_sc_ptr : sve_sc_ptr;
> +
> +  // Function arguments.
> +
> +  ext_consume_sve_sc (sve_sc1);
> +  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
> +  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
> +  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
> +  ext_consume_varargs (1, sve_sc1);
> +
> +  // Function returns.
> +
> +  ext_produce_sve_sc ();
> +  sve_sc1 = ext_produce_sve_sc ();
> +  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
> +
> +  // Auto
> +
> +#if __cplusplus >= 201103L
> +  auto auto_sve_sc1 = sve_sc1;
> +  auto auto_sve_sc1_return = ext_produce_sve_sc ();
> +#endif
> +
> +  // Varargs processing.
> +
> +  __builtin_va_list valist;
> +  __builtin_va_arg (valist, svint8_t);
> +
> +  // Other built-ins
> +
> +  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
> +  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
> +
> +  // Lambdas
> +
> +#if __cplusplus >= 201103L
> +  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
> +  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
> +  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
> +  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
> +  [&] () { sve_sc1 = sve_sc2; };
> +  [] () { return ext_produce_sve_sc (); } ();
> +#endif
> +
> +  // Exceptions
> +
> +  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
> +  try {} catch (svint8_t *x) {}
> +#if __cplusplus < 201103L
> +  thrower2 ();
> +#endif
> +
> +  // Use in traits.  Doesn't use static_assert so that tests work with
> +  // earlier -std=s.
> +
> +  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
> +  { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
> +  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
> +     for int8x32_t changes then the behavior for svint8_t should change in the same
> +     way.  */
> +  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
> +  { typedef int f[__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
> +  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
> +}
> +
> +// Function parameters in definitions.
> +
> +void
> +unnamed_st1 (svint8_t)
> +{
> +}
> +
> +void
> +named_st1 (svint8_t param1)
> +{
> +  svint8_t sve_sc1 = param1;
> +}
> +
> +// Function return values in definitions.
> +
> +svint8_t
> +ret_st1 (svint8_t param)
> +{
> +  return param;
> +}
> +
> +svint8_t
> +bad_ret_st1 (svint16_t param)
> +{
> +  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
> +}
> +
> +#if __cplusplus >= 201103L
> +template<typename T>
> +void
> +const_to_sve_sc (T i)
> +{
> +  constexpr svint8_t a = (svint8_t) i;
> +}
> +#endif
> +
> +template<typename T>
> +int
> +get_x (T *a)
> +{
> +  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
> +}
> +template int get_x<svint8_t>(svint8_t *);
> +
> +#if __cplusplus < 201103L
> +void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
> +#endif
> +
> +// Using "auto" as a return type.
> +
> +#if __cplusplus >= 201402L
> +auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
> +const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
> +auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
> +auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
> +#endif
>

Patch
diff mbox series

Index: gcc/target.h
===================================================================
--- gcc/target.h	2019-12-04 10:58:40.000000000 +0000
+++ gcc/target.h	2019-12-04 10:59:10.223988432 +0000
@@ -249,7 +249,19 @@  enum type_context_kind {
 
   /* Adding to or subtracting from a pointer to T, or computing the
      difference between two pointers when one of them is a pointer to T.  */
-  TCTX_POINTER_ARITH
+  TCTX_POINTER_ARITH,
+
+  /* Dynamically allocating objects of type T.  */
+  TCTX_ALLOCATION,
+
+  /* Dynamically deallocating objects of type T.  */
+  TCTX_DEALLOCATION,
+
+  /* Throwing or catching an object of type T.  */
+  TCTX_EXCEPTIONS,
+
+  /* Capturing objects of type T by value in a closure.  */
+  TCTX_CAPTURE_BY_COPY
 };
 
 extern bool verify_type_context (location_t, type_context_kind, const_tree,
Index: gcc/config/aarch64/aarch64-sve-builtins.cc
===================================================================
--- gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-04 10:58:40.000000000 +0000
+++ gcc/config/aarch64/aarch64-sve-builtins.cc	2019-12-04 10:59:10.211988515 +0000
@@ -3352,6 +3352,26 @@  verify_type_context (location_t loc, typ
       if (!silent_p)
 	error_at (loc, "array elements cannot have SVE type %qT", type);
       return false;
+
+    case TCTX_ALLOCATION:
+      if (!silent_p)
+	error_at (loc, "cannot allocate objects with SVE type %qT", type);
+      return false;
+
+    case TCTX_DEALLOCATION:
+      if (!silent_p)
+	error_at (loc, "cannot delete objects with SVE type %qT", type);
+      return false;
+
+    case TCTX_EXCEPTIONS:
+      if (!silent_p)
+	error_at (loc, "cannot throw or catch SVE type %qT", type);
+      return false;
+
+    case TCTX_CAPTURE_BY_COPY:
+      if (!silent_p)
+	error_at (loc, "capture by copy of SVE type %qT", type);
+      return false;
     }
   gcc_unreachable ();
 }
Index: gcc/cp/decl.c
===================================================================
--- gcc/cp/decl.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/decl.c	2019-12-04 10:59:10.215988487 +0000
@@ -5470,6 +5470,13 @@  start_decl_1 (tree decl, bool initialize
       cp_apply_type_quals_to_decl (cp_type_quals (type), decl);
     }
 
+  if (is_global_var (decl))
+    {
+      type_context_kind context = (DECL_THREAD_LOCAL_P (decl)
+				   ? TCTX_THREAD_STORAGE
+				   : TCTX_STATIC_STORAGE);
+      verify_type_context (input_location, context, TREE_TYPE (decl));
+    }
   if (initialized)
     /* Is it valid for this decl to have an initializer at all?  */
     {
@@ -6527,6 +6534,12 @@  check_array_initializer (tree decl, tree
 	error ("elements of array %q#T have incomplete type", type);
       return true;
     }
+
+  location_t loc = (decl && DECL_P (decl)
+		    ? DECL_SOURCE_LOCATION (decl) : input_location);
+  if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, element_type))
+    return true;
+
   /* A compound literal can't have variable size.  */
   if (init && !decl
       && ((COMPLETE_TYPE_P (type) && !TREE_CONSTANT (TYPE_SIZE (type)))
@@ -7473,6 +7486,8 @@  cp_finish_decl (tree decl, tree init, bo
 
   if (VAR_P (decl)
       && DECL_CLASS_SCOPE_P (decl)
+      && verify_type_context (DECL_SOURCE_LOCATION (decl),
+			      TCTX_STATIC_STORAGE, type)
       && DECL_INITIALIZED_IN_CLASS_P (decl))
     check_static_variable_definition (decl, type);
 
@@ -10541,6 +10556,10 @@  create_array_type_for_decl (tree name, t
       break;
     }
 
+  if (!verify_type_context (name ? loc : input_location,
+			    TCTX_ARRAY_ELEMENT, type))
+    return error_mark_node;
+
   /* [dcl.array]
 
      The constant expressions that specify the bounds of the arrays
@@ -13245,6 +13264,14 @@  grokdeclarator (const cp_declarator *dec
 		decl = NULL_TREE;
 	      }
 	  }
+	else if (!verify_type_context (input_location,
+				       staticp
+				       ? TCTX_STATIC_STORAGE
+				       : TCTX_FIELD, type))
+	  {
+	    type = error_mark_node;
+	    decl = NULL_TREE;
+	  }
 	else
 	  {
 	    if (friendp)
Index: gcc/cp/except.c
===================================================================
--- gcc/cp/except.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/except.c	2019-12-04 10:59:10.215988487 +0000
@@ -29,6 +29,7 @@  the Free Software Foundation; either ver
 #include "trans-mem.h"
 #include "attribs.h"
 #include "tree-iterator.h"
+#include "target.h"
 
 static void push_eh_cleanup (tree);
 static tree prepare_eh_type (tree);
@@ -927,6 +928,14 @@  is_admissible_throw_operand_or_catch_par
   if (!complete_ptr_ref_or_void_ptr_p (type, expr))
     return false;
 
+  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, type))
+    return false;
+
+  else if (TYPE_REF_P (type)
+	   && !verify_type_context (input_location, TCTX_EXCEPTIONS,
+				    TREE_TYPE (type)))
+    return false;
+
   /* 10.4/3 An abstract class shall not be used as a parameter type,
 	    as a function return type or as type of an explicit
 	    conversion.  */
Index: gcc/cp/typeck2.c
===================================================================
--- gcc/cp/typeck2.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/typeck2.c	2019-12-04 10:59:10.223988432 +0000
@@ -33,6 +33,7 @@  the Free Software Foundation; either ver
 #include "varasm.h"
 #include "intl.h"
 #include "gcc-rich-location.h"
+#include "target.h"
 
 static tree
 process_init_constructor (tree type, tree init, int nested, int flags,
@@ -2400,6 +2401,9 @@  add_exception_specifier (tree list, tree
     ok = true;
   else if (processing_template_decl)
     ok = true;
+  else if (!verify_type_context (input_location, TCTX_EXCEPTIONS, core,
+				 !(complain & tf_error)))
+    return error_mark_node;
   else
     {
       ok = true;
Index: gcc/cp/init.c
===================================================================
--- gcc/cp/init.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/init.c	2019-12-04 10:59:10.215988487 +0000
@@ -3058,6 +3058,10 @@  build_new_1 (vec<tree, va_gc> **placemen
 				    complain);
     }
 
+  if (!verify_type_context (input_location, TCTX_ALLOCATION, elt_type,
+			    !(complain & tf_error)))
+    return error_mark_node;
+
   if (variably_modified_type_p (elt_type, NULL_TREE) && (complain & tf_error))
     {
       error ("variably modified type not allowed in new-expression");
@@ -3942,6 +3946,10 @@  build_vec_delete_1 (tree base, tree maxi
   if (base == error_mark_node || maxindex == error_mark_node)
     return error_mark_node;
 
+  if (!verify_type_context (input_location, TCTX_DEALLOCATION, type,
+			    !(complain & tf_error)))
+    return error_mark_node;
+
   if (!COMPLETE_TYPE_P (type))
     {
       if (complain & tf_warning)
@@ -4827,6 +4835,11 @@  build_delete (tree otype, tree addr, spe
       if (!VOID_TYPE_P (type))
 	{
 	  complete_type (type);
+	  if (deleting
+	      && !verify_type_context (input_location, TCTX_DEALLOCATION, type,
+				       !(complain & tf_error)))
+	    return error_mark_node;
+
 	  if (!COMPLETE_TYPE_P (type))
 	    {
 	      if (complain & tf_warning)
Index: gcc/cp/lambda.c
===================================================================
--- gcc/cp/lambda.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/lambda.c	2019-12-04 10:59:10.215988487 +0000
@@ -30,6 +30,7 @@ 
 #include "tree-iterator.h"
 #include "toplev.h"
 #include "gimplify.h"
+#include "target.h"
 
 /* Constructor for a lambda expression.  */
 
@@ -579,6 +580,9 @@  add_capture (tree lambda, tree id, tree
 	      cxx_incomplete_type_inform (type);
 	      return error_mark_node;
 	    }
+	  else if (!verify_type_context (input_location,
+					 TCTX_CAPTURE_BY_COPY, type))
+	    return error_mark_node;
 	}
     }
 
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/pt.c	2019-12-04 10:59:10.223988432 +0000
@@ -42,6 +42,7 @@  the Free Software Foundation; either ver
 #include "gimplify.h"
 #include "gcc-rich-location.h"
 #include "selftest.h"
+#include "target.h"
 
 /* The type of functions taking a tree, and some additional data, and
    returning an int.  */
@@ -11815,6 +11816,9 @@  instantiate_class_template_1 (tree type)
 			      error ("flexible array member %qD in union", r);
 			      TREE_TYPE (r) = error_mark_node;
 			    }
+			  else if (!verify_type_context (input_location,
+							 TCTX_FIELD, rtype))
+			    TREE_TYPE (r) = error_mark_node;
 			}
 
 		      /* If it is a TYPE_DECL for a class-scoped ENUMERAL_TYPE,
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	2019-12-04 10:58:40.000000000 +0000
+++ gcc/cp/typeck.c	2019-12-04 10:59:10.223988432 +0000
@@ -1824,7 +1824,14 @@  cxx_alignof_expr (tree e, tsubst_flags_t
 
   e = mark_type_use (e);
 
-  if (VAR_P (e))
+  if (!verify_type_context (input_location, TCTX_ALIGNOF, TREE_TYPE (e),
+			    !(complain & tf_error)))
+    {
+      if (!(complain & tf_error))
+	return error_mark_node;
+      t = size_one_node;
+    }
+  else if (VAR_P (e))
     t = size_int (DECL_ALIGN_UNIT (e));
   else if (bitfield_p (e))
     {
@@ -5778,6 +5785,13 @@  pointer_diff (location_t loc, tree op0,
       else
 	return error_mark_node;
     }
+  else if (!verify_type_context (loc, TCTX_POINTER_ARITH,
+				 TREE_TYPE (TREE_TYPE (op0)),
+				 !(complain & tf_error))
+	   || !verify_type_context (loc, TCTX_POINTER_ARITH,
+				    TREE_TYPE (TREE_TYPE (op1)),
+				    !(complain & tf_error)))
+    return error_mark_node;
 
   /* Determine integer type result of the subtraction.  This will usually
      be the same as the result type (ptrdiff_t), but may need to be a wider
@@ -6572,6 +6586,10 @@  cp_build_unary_op (enum tree_code code,
                 else
                   return error_mark_node;
               }
+	    else if (!verify_type_context (location, TCTX_POINTER_ARITH,
+					   TREE_TYPE (argtype),
+					   !(complain & tf_error)))
+	      return error_mark_node;
 
 	    inc = cxx_sizeof_nowarn (TREE_TYPE (argtype));
 	  }
Index: gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
===================================================================
--- /dev/null	2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/g++.dg/ext/sve-sizeless-1.C	2019-12-04 10:59:10.223988432 +0000
@@ -0,0 +1,418 @@ 
+// { dg-do compile { target aarch64*-*-* } }
+// { dg-options "-Wclass-memaccess" }
+
+typedef __SIZE_TYPE__ size_t;
+inline void *operator new (size_t, void *__p) throw() { return __p; }
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+// Sizeless objects with global scope.
+
+svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
+
+// Sizeless arrays.
+
+typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+// Sizeless member variables.
+
+struct struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+union union1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+#if __cplusplus >= 201103L
+struct static_sve_sc {
+  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
+};
+#endif
+
+// Sizeless member variables in templated structures.
+
+template<typename T>
+struct templated_struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+template<typename T>
+struct templated_struct2 {
+  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
+};
+
+template class templated_struct2<svint8_t>;
+
+template<typename T>
+struct templated_struct3 {
+  T &a;
+};
+
+template class templated_struct3<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<typename T>
+struct templated_struct4 {
+  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+};
+
+template class templated_struct4<svint8_t>;
+#endif
+
+template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
+template class templated_struct5<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<int N> using typedef_sizeless1 = svint8_t;
+template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
+template<typename T> using array = T[2];
+#endif
+
+// Pointers to sizeless types.
+
+svint8_t *global_sve_sc_ptr;
+
+// Sizeless arguments and return values.
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_const_int_ref (const int &);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+// Sizeless types in throw specifications.
+
+#if __cplusplus < 201103L
+void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Main tests for statements and expressions.
+
+void
+statements (int n)
+{
+  // Local declarations.
+
+  svint8_t sve_sc1, sve_sc2;
+  volatile svint8_t volatile_sve_sc1;
+  int8x32_t gnu_sc1;
+  svint16_t sve_sh1;
+
+  // Layout queries.
+
+  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+
+#if __cplusplus >= 201103L
+  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+#endif
+
+  // Initialization.
+
+  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  svint8_t init_sve_sc1 (sve_sc1);
+  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc3 = sve_sc1;
+  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc5 = {};
+  svint8_t init_sve_sc6 = { sve_sc1 };
+  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Constructor calls.
+
+  (0, svint8_t ());
+
+  // Lvalue reference binding
+
+  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
+  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
+  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
+
+  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
+  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
+  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
+
+  // Compound literals.
+
+  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  // Arrays.
+
+  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+  // Assignment.
+
+  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
+
+  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
+  sve_sc1 = sve_sc1;
+  sve_sc1 = gnu_sc1; // { dg-error {cannot convert 'int8x32_t'[^\n]* to 'svint8_t' in assignment} }
+  gnu_sc1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int8x32_t'} }
+  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Casting.
+
+  (void) sve_sc1;
+  (void) volatile_sve_sc1;
+  (void) *&volatile_sve_sc1;
+
+  // Addressing and dereferencing.
+
+  svint8_t *sve_sc_ptr = &sve_sc1;
+  int8x32_t *gnu_sc_ptr = &gnu_sc1;
+  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
+
+  // Pointer assignment.
+
+  gnu_sc_ptr = sve_sc_ptr; // { dg-error {cannot convert 'svint8_t\*' to 'int8x32_t\*'} }
+  sve_sc_ptr = gnu_sc_ptr; // { dg-error {cannot convert 'int8x32_t\*'[^\n]* to 'svint8_t\*'} }
+
+  // Pointer arithmetic.
+
+  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  gnu_sc_ptr - sve_sc_ptr; // { dg-error {invalid operands of types 'int8x32_t\*'[^\n]* and 'svint8_t\*' to binary 'operator-'} }
+  sve_sc_ptr - gnu_sc_ptr; // { dg-error {invalid operands of types 'svint8_t\*' and 'int8x32_t\*'[^\n]* to binary 'operator-'} }
+  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+
+  // Pointer comparison.
+
+  sve_sc_ptr == &sve_sc1;
+  sve_sc_ptr != &sve_sc1;
+  sve_sc_ptr < &sve_sc1;
+  sve_sc_ptr <= &sve_sc1;
+  sve_sc_ptr > &sve_sc1;
+  sve_sc_ptr >= &sve_sc1;
+  gnu_sc_ptr == sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr != sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr < sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr <= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr > sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  gnu_sc_ptr >= sve_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr == gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr != gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr < gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr <= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr > gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+  sve_sc_ptr >= gnu_sc_ptr; // { dg-error {comparison between distinct pointer types [^\n]*lacks a cast} }
+
+  // New and delete.
+
+  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
+  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
+  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
+
+  // Conditional expressions.
+
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
+  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
+  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc_ptr : sve_sc_ptr;
+  0 ? sve_sc_ptr : gnu_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
+  0 ? gnu_sc_ptr : sve_sc_ptr; // { dg-error {conditional expression between distinct pointer types [^\n]*lacks a cast} }
+
+  // Function arguments.
+
+  ext_consume_sve_sc (sve_sc1);
+  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
+  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
+  ext_consume_varargs (1, sve_sc1);
+
+  // Function returns.
+
+  ext_produce_sve_sc ();
+  sve_sc1 = ext_produce_sve_sc ();
+  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
+
+  // Auto
+
+#if __cplusplus >= 201103L
+  auto auto_sve_sc1 = sve_sc1;
+  auto auto_sve_sc1_return = ext_produce_sve_sc ();
+#endif
+
+  // Varargs processing.
+
+  __builtin_va_list valist;
+  __builtin_va_arg (valist, svint8_t);
+
+  // Other built-ins
+
+  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
+  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
+
+  // Lambdas
+
+#if __cplusplus >= 201103L
+  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
+  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
+  [&] () { sve_sc1 = sve_sc2; };
+  [] () { return ext_produce_sve_sc (); } ();
+#endif
+
+  // Exceptions
+
+  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t *x) {}
+#if __cplusplus < 201103L
+  thrower2 ();
+#endif
+
+  // Use in traits.  Doesn't use static_assert so that tests work with
+  // earlier -std=s.
+
+  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
+  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
+     for int8x32_t changes then the behavior for svint8_t should change in the same
+     way.  */
+  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+}
+
+// Function parameters in definitions.
+
+void
+unnamed_st1 (svint8_t)
+{
+}
+
+void
+named_st1 (svint8_t param1)
+{
+  svint8_t sve_sc1 = param1;
+}
+
+// Function return values in definitions.
+
+svint8_t
+ret_st1 (svint8_t param)
+{
+  return param;
+}
+
+svint8_t
+bad_ret_st1 (svint16_t param)
+{
+  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
+}
+
+#if __cplusplus >= 201103L
+template<typename T>
+void
+const_to_sve_sc (T i)
+{
+  constexpr svint8_t a = (svint8_t) i;
+}
+#endif
+
+template<typename T>
+int
+get_x (T *a)
+{
+  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
+}
+template int get_x<svint8_t>(svint8_t *);
+
+#if __cplusplus < 201103L
+void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Using "auto" as a return type.
+
+#if __cplusplus >= 201402L
+auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
+const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
+#endif
Index: gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
===================================================================
--- /dev/null	2019-09-17 11:41:18.176664108 +0100
+++ gcc/testsuite/g++.dg/ext/sve-sizeless-2.C	2019-12-04 10:59:10.223988432 +0000
@@ -0,0 +1,418 @@ 
+// { dg-do compile { target aarch64*-*-* } }
+// { dg-options "-Wclass-memaccess -msve-vector-bits=256" }
+
+typedef __SIZE_TYPE__ size_t;
+inline void *operator new (size_t, void *__p) throw() { return __p; }
+
+#include <arm_sve.h>
+
+typedef signed char int8x32_t __attribute__((__vector_size__ (32)));
+
+// Sizeless objects with global scope.
+
+svint8_t global_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+static svint8_t local_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+extern svint8_t extern_sve_sc; // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+__thread svint8_t tls_sve_sc; // { dg-error {variables of type 'svint8_t' cannot have thread-local storage duration} }
+
+// Sizeless arrays.
+
+typedef svint8_t array_type[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+extern svint8_t extern_array[]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+// Sizeless member variables.
+
+struct struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+union union1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+#if __cplusplus >= 201103L
+struct static_sve_sc {
+  static svint8_t sve_sc1 = {}; // { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target c++11 } }
+};
+#endif
+
+// Sizeless member variables in templated structures.
+
+template<typename T>
+struct templated_struct1 {
+  svint8_t a; // { dg-error {member variables cannot have SVE type 'svint8_t'} }
+};
+
+template<typename T>
+struct templated_struct2 {
+  T a; // { dg-error {member variables cannot have SVE type '(svint8_t|__SVInt8_t)'} }
+};
+
+template class templated_struct2<svint8_t>;
+
+template<typename T>
+struct templated_struct3 {
+  T &a;
+};
+
+template class templated_struct3<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<typename T>
+struct templated_struct4 {
+  static T a; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+  static T b = {}; // { dg-error {SVE type '(svint8_t|__SVInt8_t)' does not have a fixed size} "" { target c++11 } }
+};
+
+template class templated_struct4<svint8_t>;
+#endif
+
+template<typename T> struct templated_struct5 : T {}; // { dg-error {base type '[^']*' fails to be a struct or class type} }
+template class templated_struct5<svint8_t>;
+
+#if __cplusplus >= 201103L
+template<int N> using typedef_sizeless1 = svint8_t;
+template<int N> using typedef_sizeless1 = svint8_t; // { dg-error {redefinition of 'template<int N> using typedef_sizeless1 = svint8_t'} "" { target c++11 } }
+template<typename T> using array = T[2];
+#endif
+
+// Pointers to sizeless types.
+
+svint8_t *global_sve_sc_ptr;
+
+// Sizeless arguments and return values.
+
+void ext_consume_sve_sc (svint8_t);
+void ext_consume_const_int_ref (const int &);
+void ext_consume_varargs (int, ...);
+svint8_t ext_produce_sve_sc ();
+
+// Sizeless types in throw specifications.
+
+#if __cplusplus < 201103L
+void thrower1 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower2 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+void thrower3 () throw (svint8_t); // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Main tests for statements and expressions.
+
+void
+statements (int n)
+{
+  // Local declarations.
+
+  svint8_t sve_sc1, sve_sc2;
+  volatile svint8_t volatile_sve_sc1;
+  int8x32_t gnu_sc1;
+  svint16_t sve_sh1;
+
+  // Layout queries.
+
+  sizeof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  sizeof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a fixed size} }
+  __alignof (svint8_t); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (sve_sc1); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+  __alignof (ext_produce_sve_sc ()); // { dg-error {SVE type 'svint8_t' does not have a defined alignment} }
+
+#if __cplusplus >= 201103L
+  array<svint8_t> foo = {}; // { dg-error {array elements cannot have SVE type '(svint8_t|__SVInt8_t)'} "" { target c++11 } }
+#endif
+
+  // Initialization.
+
+  int init_int1 = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+  int init_int2 = { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  svint8_t init_sve_sc1 (sve_sc1);
+  svint8_t init_sve_sc2 (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc3 = sve_sc1;
+  svint8_t init_sve_sc4 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  svint8_t init_sve_sc5 = {};
+  svint8_t init_sve_sc6 = { sve_sc1 };
+  svint8_t init_sve_sc7 = { sve_sh1 }; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Constructor calls.
+
+  (0, svint8_t ());
+
+  // Lvalue reference binding
+
+  svint8_t &lvalue_ref_sve_sc1 = sve_sc1;
+  svint8_t &lvalue_ref_sve_sc2 = ext_produce_sve_sc (); // { dg-error {cannot bind non-const lvalue reference of type 'svint8_t&' to an rvalue of type 'svint8_t'} }
+  svint8_t &lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'svint8_t&' from expression of type 'svint16_t'} }
+
+  const svint8_t &const_lvalue_ref_sve_sc1 = sve_sc1;
+  const svint8_t &const_lvalue_ref_sve_sc2 = ext_produce_sve_sc ();
+  const svint8_t &const_lvalue_ref_sve_sc3 = sve_sh1; // { dg-error {invalid initialization of reference of type 'const svint8_t&' from expression of type 'svint16_t'} }
+
+  // Compound literals.
+
+  (int) { sve_sc1 }; // { dg-error {cannot convert 'svint8_t' to 'int' in initialization} }
+
+  // Arrays.
+
+  svint8_t array[2]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t zero_length_array[0]; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+  svint8_t empty_init_array[] = {}; // { dg-error {array elements cannot have SVE type 'svint8_t'} }
+
+  // Assignment.
+
+  n = sve_sc1; // { dg-error {cannot convert 'svint8_t' to 'int' in assignment} }
+
+  sve_sc1 = 0; // { dg-error {cannot convert 'int' to 'svint8_t' in assignment} }
+  sve_sc1 = sve_sc1;
+  sve_sc1 = gnu_sc1;
+  gnu_sc1 = sve_sc1;
+  sve_sc1 = sve_sh1; // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+
+  // Casting.
+
+  (void) sve_sc1;
+  (void) volatile_sve_sc1;
+  (void) *&volatile_sve_sc1;
+
+  // Addressing and dereferencing.
+
+  svint8_t *sve_sc_ptr = &sve_sc1;
+  int8x32_t *gnu_sc_ptr = &gnu_sc1;
+  sve_sc_ptr = (svint16_t *) 0; // { dg-error {cannot convert 'svint16_t\*' to 'svint8_t\*' in assignment} }
+
+  // Pointer assignment.
+
+  gnu_sc_ptr = sve_sc_ptr;
+  sve_sc_ptr = gnu_sc_ptr;
+
+  // Pointer arithmetic.
+
+  ++sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  --sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr++; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr--; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr += 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 0; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr -= 1; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  gnu_sc_ptr - sve_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc_ptr - gnu_sc_ptr; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[0]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+  sve_sc1 = sve_sc_ptr[1]; // { dg-error {arithmetic on pointer to SVE type 'svint8_t'} }
+
+  // Pointer comparison.
+
+  sve_sc_ptr == &sve_sc1;
+  sve_sc_ptr != &sve_sc1;
+  sve_sc_ptr < &sve_sc1;
+  sve_sc_ptr <= &sve_sc1;
+  sve_sc_ptr > &sve_sc1;
+  sve_sc_ptr >= &sve_sc1;
+  gnu_sc_ptr == sve_sc_ptr;
+  gnu_sc_ptr != sve_sc_ptr;
+  gnu_sc_ptr < sve_sc_ptr;
+  gnu_sc_ptr <= sve_sc_ptr;
+  gnu_sc_ptr > sve_sc_ptr;
+  gnu_sc_ptr >= sve_sc_ptr;
+  sve_sc_ptr == gnu_sc_ptr;
+  sve_sc_ptr != gnu_sc_ptr;
+  sve_sc_ptr < gnu_sc_ptr;
+  sve_sc_ptr <= gnu_sc_ptr;
+  sve_sc_ptr > gnu_sc_ptr;
+  sve_sc_ptr >= gnu_sc_ptr;
+
+  // New and delete.
+
+  new svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  new (global_sve_sc_ptr) svint8_t; // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+  new (global_sve_sc_ptr) svint8_t (); // { dg-error {cannot allocate objects with SVE type 'svint8_t'} }
+
+  sve_sc1.~svint8_t(); // { dg-error {expected class-name before '\(' token} }
+  delete sve_sc_ptr; // { dg-error {cannot delete objects with SVE type '(svint8_t|__SVInt8_t)'} }
+  delete[] sve_sc_ptr; // { dg-error {cannot delete objects with SVE type 'svint8_t'} }
+
+  // Conditional expressions.
+
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc1 : sve_sh1; // { dg-error {different types 'svint8_t' and 'svint16_t'} }
+  0 ? sve_sc1 : 0; // { dg-error {different types 'svint8_t' and 'int'} }
+  0 ? 0 : sve_sc1; // { dg-error {different types 'int' and 'svint8_t'} }
+  0 ? sve_sc1 : sve_sc1;
+  0 ? sve_sc_ptr : sve_sc_ptr;
+  0 ? sve_sc_ptr : gnu_sc_ptr;
+  0 ? gnu_sc_ptr : sve_sc_ptr;
+
+  // Function arguments.
+
+  ext_consume_sve_sc (sve_sc1);
+  ext_consume_sve_sc (sve_sh1); // { dg-error {cannot convert 'svint16_t' to 'svint8_t'} }
+  ext_consume_const_int_ref (sve_sc1); // { dg-error {invalid initialization of reference of type 'const int&' from expression of type 'svint8_t'} }
+  ext_consume_varargs (sve_sc1); // { dg-error {cannot convert 'svint8_t' to 'int'} }
+  ext_consume_varargs (1, sve_sc1);
+
+  // Function returns.
+
+  ext_produce_sve_sc ();
+  sve_sc1 = ext_produce_sve_sc ();
+  sve_sh1 = ext_produce_sve_sc (); // { dg-error {cannot convert 'svint8_t' to 'svint16_t' in assignment} }
+
+  // Auto
+
+#if __cplusplus >= 201103L
+  auto auto_sve_sc1 = sve_sc1;
+  auto auto_sve_sc1_return = ext_produce_sve_sc ();
+#endif
+
+  // Varargs processing.
+
+  __builtin_va_list valist;
+  __builtin_va_arg (valist, svint8_t);
+
+  // Other built-ins
+
+  __builtin_launder (sve_sc1); // { dg-error {non-pointer argument to '__builtin_launder'} }
+  __builtin_memcpy (&sve_sc1, &sve_sc2, 2);
+
+  // Lambdas
+
+#if __cplusplus >= 201103L
+  [sve_sc1] () {}; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [=] () { &sve_sc1; }; // { dg-error {capture by copy of SVE type 'svint8_t'} "" { target c++11 } }
+  [&sve_sc1] () { sve_sc1 = sve_sc2; }; // { dg-error {'sve_sc2' is not captured} "" { target c++11 } }
+  [&sve_sc1, &sve_sc2] () { sve_sc1 = sve_sc2; };
+  [&] () { sve_sc1 = sve_sc2; };
+  [] () { return ext_produce_sve_sc (); } ();
+#endif
+
+  // Exceptions
+
+  throw svint8_t (); // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t &x) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} }
+  try {} catch (svint8_t *x) {}
+#if __cplusplus < 201103L
+  thrower2 ();
+#endif
+
+  // Use in traits.  Doesn't use static_assert so that tests work with
+  // earlier -std=s.
+
+  { typedef int f[__has_nothrow_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_assign (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_constructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_nothrow_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_copy (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_trivial_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[__has_unique_object_representations (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__has_virtual_destructor (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_abstract (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_aggregate (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_base_of (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_class (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_empty (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_enum (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_final (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_pod (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_polymorphic (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[__is_same_as (svint8_t *, int8x32_t *) ? 1 : -1]; }
+  { typedef int f[__is_same_as (int8x32_t *, svint8_t *) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_same_as (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivial (svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_union (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_copyable (svint8_t) ? 1 : -1]; }
+  /* The intention is that svint8_t should behave like int8x32_t here.  If the behavior
+     for int8x32_t changes then the behavior for svint8_t should change in the same
+     way.  */
+  { typedef int f[!__is_trivially_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_assignable (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_trivially_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_trivially_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (svint8_t, int8x32_t) ? 1 : -1]; }
+  { typedef int f[__is_constructible (int8x32_t, svint8_t) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, int) ? 1 : -1]; }
+  { typedef int f[!__is_constructible (svint8_t, svint16_t) ? 1 : -1]; }
+}
+
+// Function parameters in definitions.
+
+void
+unnamed_st1 (svint8_t)
+{
+}
+
+void
+named_st1 (svint8_t param1)
+{
+  svint8_t sve_sc1 = param1;
+}
+
+// Function return values in definitions.
+
+svint8_t
+ret_st1 (svint8_t param)
+{
+  return param;
+}
+
+svint8_t
+bad_ret_st1 (svint16_t param)
+{
+  return param; // { dg-error {cannot convert 'svint16_t' to 'svint8_t' in return} }
+}
+
+#if __cplusplus >= 201103L
+template<typename T>
+void
+const_to_sve_sc (T i)
+{
+  constexpr svint8_t a = (svint8_t) i;
+}
+#endif
+
+template<typename T>
+int
+get_x (T *a)
+{
+  return a->a; // { dg-error {request for member 'a' in '\* a', which is of non-class type} }
+}
+template int get_x<svint8_t>(svint8_t *);
+
+#if __cplusplus < 201103L
+void thrower3 () throw (svint8_t) {} // { dg-error {cannot throw or catch SVE type 'svint8_t'} "" { target c++98_only } }
+#endif
+
+// Using "auto" as a return type.
+
+#if __cplusplus >= 201402L
+auto auto_ret_sve_sc (svint8_t *ptr) { return *ptr; }
+const auto &auto_ret_const_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &auto_ret_sve_sc_ref (svint8_t *ptr) { return *ptr; }
+auto &&auto_ret_sve_sc_rvalue_ref (svint8_t *ptr) { return *ptr; }
+#endif