Claudio Bantaloukas <claudio.bantalou...@arm.com> writes:
> The ACLE defines a new scalar type, __mfp8. This is an opaque 8bit types that
> can only be used by fp8 intrinsics. Additionally, the mfloat8_t type is made
> available in arm_neon.h and arm_sve.h as an alias of the same.
>
> This implementation uses an INTEGER_TYPE, with precision 8 to represent
> __mfp8. Conversions to int and other types are disabled via the
> TARGET_INVALID_CONVERSION hook.
> Additionally, operations that are typically available to integer types are
> disabled via TARGET_INVALID_UNARY_OP and TARGET_INVALID_BINARY_OP hooks.
>
> gcc/ChangeLog:
>
>       * config/aarch64/aarch64-builtins.cc (aarch64_mfp8_type_node): Add node
>       for __mfp8 type.
>       (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type.
>       (aarch64_init_fp8_types): New function to initialise fp8 types and
>       register with language backends.
>       * config/aarch64/aarch64.cc (aarch64_invalid_conversion): Add function
>       implementing TARGET_INVALID_CONVERSION hook that blocks conversion to
>       and from __mfp8 type.
>       (aarch64_invalid_unary_op): Add function implementing TARGET_UNARY_OP
>       hook that blocks operations on __mfp8 other than &.
>       (aarch64_invalid_binary_op): Extend TARGET_BINARY_OP hook to disallow
>       operations on __mfp8 type.
>       (TARGET_INVALID_CONVERSION): Add define.
>       (TARGET_INVALID_UNARY_OP): Likewise.
>       * config/aarch64/aarch64.h (aarch64_mfp8_type_node): Add node for __mfp8
>       type.
>       (aarch64_mfp8_ptr_type_node): Add node for __mfp8 pointer type.
>       * config/aarch64/arm_neon.h (mfloat8_t): Add typedef.
>       * config/aarch64/arm_sve.h (mfloat8_t): Likewise.
>
> gcc/testsuite/ChangeLog:
>
>       * gcc.target/aarch64/fp8_scalar_1.c: New tests in C.
>       * gcc.target/aarch64/fp8_scalar_typecheck_1.c: Likewise.
>       * gcc.target/aarch64/fp8_scalar_typecheck_2.C: New tests in C++.

C++ tests should go in g++.target instead.

I think the new type needs to be mangled explicitly, so that the
overloads in:

  int foo(__mfp8) { return 1; }
  int foo(unsigned char) { return 2; }
  int bar(__mfp8 x) { return foo(x); }

are distinct.  It'd also be good to have a constexpr version of foo
in the tests, to make sure that the right overload is chosen.

> ---
>
> Hi, 
> Is this ok for master? I do not have commit rights yet, if ok, can someone 
> commit it on my behalf?
>
> Regression tested with aarch64-unknown-linux-gnu.
>
> Thanks,
> Claudio Bantaloukas
>
>  gcc/config/aarch64/aarch64-builtins.cc        |  23 ++
>  gcc/config/aarch64/aarch64.cc                 |  60 +++
>  gcc/config/aarch64/aarch64.h                  |   5 +
>  gcc/config/aarch64/arm_neon.h                 |   2 +
>  gcc/config/aarch64/arm_sve.h                  |   1 +
>  .../gcc.target/aarch64/fp8_scalar_1.c         | 108 ++++++
>  .../aarch64/fp8_scalar_typecheck_1.c          | 329 ++++++++++++++++
>  .../aarch64/fp8_scalar_typecheck_2.C          | 354 ++++++++++++++++++
>  8 files changed, 882 insertions(+)
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
>  create mode 100644 gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C
>
> [...]
> @@ -1721,6 +1726,22 @@ aarch64_init_builtin_rsqrt (void)
>    }
>  }
>  
> +static void
> +aarch64_init_fp8_types (void)

The function should have a comment before it.

> +{
> +  aarch64_mfp8_type_node = make_node (INTEGER_TYPE);
> +  TYPE_PRECISION (aarch64_mfp8_type_node) = 8;
> +  TYPE_MIN_VALUE (aarch64_mfp8_type_node)
> +      = TYPE_MIN_VALUE (unsigned_char_type_node);
> +  TYPE_MAX_VALUE (aarch64_mfp8_type_node)
> +      = TYPE_MAX_VALUE (unsigned_char_type_node);

If we're using the unsigned range, we should also set TYPE_UNSIGNED.
That said...

> +  layout_type (aarch64_mfp8_type_node);

...it looks like the code above could be replaced by:

  aarch64_mfp8_type_node = make_unsigned_type (8);

which would also give TYPE_MIN_VALUE and TYPE_MAX_VALUE the "right" types.

I was surprised that the tests worked so well with just a standard
integer type, without having to use build_distinct_type_copy.
But since they do, I agree we shouldn't use build_distinct_type_copy
unless a specific reason comes up.

> +  SET_TYPE_MODE (aarch64_mfp8_type_node, QImode);
> +
> +  lang_hooks.types.register_builtin_type (aarch64_mfp8_type_node, "__mfp8");
> +  aarch64_mfp8_ptr_type_node = build_pointer_type (aarch64_mfp8_type_node);
> +}
> +
>  /* Initialize the backend types that support the user-visible __fp16
>     type, also initialize a pointer to that type, to be used when
>     forming HFAs.  */
> @@ -2128,6 +2149,8 @@ aarch64_general_init_builtins (void)
>  {
>    aarch64_init_fpsr_fpcr_builtins ();
>  
> +  aarch64_init_fp8_types ();
> +
>    aarch64_init_fp16_types ();
>  
>    aarch64_init_bf16_types ();
> diff --git a/gcc/config/aarch64/aarch64.cc b/gcc/config/aarch64/aarch64.cc
> index 9810f2c0390..e774b95e430 100644
> --- a/gcc/config/aarch64/aarch64.cc
> +++ b/gcc/config/aarch64/aarch64.cc
> @@ -22450,6 +22450,35 @@ aarch64_mangle_type (const_tree type)
>    return NULL;
>  }
>  
> +/* Implement TARGET_INVALID_CONVERSION.
> +
> +Return the diagnostic message when it is invalid to convert from fromtype to
> +totype, or NULL if validity should be determined by the front end. */

The usual style is not to reiterate the hook description, since when
that's happened in the past, the comments have become out of date
wrt the documentation.  So just:

/* Implement TARGET_INVALID_CONVERSION.  */

should be good enough.

> +
> +static const char *
> +aarch64_invalid_conversion (const_tree fromtype, const_tree totype)
> +{
> +  /* Do not allow conversions to/from FP8.  */
> +  bool fromtype_is_fp8
> +      = ((fromtype) && (TYPE_MODE (fromtype) == QImode)
> +      && (TYPE_MAIN_VARIANT (fromtype) == aarch64_mfp8_type_node));
> +  bool totype_is_fp8
> +      = ((totype)
> +      && (TYPE_MODE (totype) == QImode
> +          && TYPE_MAIN_VARIANT (totype) == aarch64_mfp8_type_node));

Did you see null fromtypes and totypes?  It doesn't look like the other
targets have needed to handle them, and it's not clear what the correct
behaviour would be in that case.

The QImode tests also look redundant.

Trying it locally, things seemed to work for me with:

  bool fromtype_is_fp8
    = TYPE_MAIN_VARIANT (fromtype) == aarch64_mfp8_type_node;
  bool totype_is_fp8
    = TYPE_MAIN_VARIANT (totype) == aarch64_mfp8_type_node;

> +
> +  /* But do allow conversions between volatile and const __mfp8 */
> +  if (fromtype_is_fp8 && totype_is_fp8)
> +    return NULL;
> +
> +  if (fromtype_is_fp8)
> +    return N_ ("invalid conversion from type %<mfloat8_t%>");
> +  if (totype_is_fp8)
> +    return N_ ("invalid conversion to type %<mfloat8_t%>");
> +  /* Conversion allowed.  */
> +  return NULL;
> +}
> +
>  /* Implement TARGET_VERIFY_TYPE_CONTEXT.  */
>  
>  static bool
> @@ -28967,6 +28996,24 @@ aarch64_stack_protect_guard (void)
>    return NULL_TREE;
>  }
>  
> +/* Implement TARGET_INVALID_UNARY_OP.
> +
> +   Return the diagnostic message string if the unary operation OP is
> +   not permitted on TYPE, NULL otherwise.  */

Similar comment about the comment here.

> +
> +static const char *
> +aarch64_invalid_unary_op (int op, const_tree type)
> +{
> +  /* Reject all single-operand operations on __mfp8 except for &.  */
> +  if ((TYPE_MODE (type) == QImode)
> +      && (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node)
> +      && (op != ADDR_EXPR))

Just:

  if (TYPE_MAIN_VARIANT (type) == aarch64_mfp8_type_node
      && op != ADDR_EXPR)

should be enough.  (GCC style is not to add brackets around individual
comparisons, unless they're needed or span multiple lines.)

> +    return N_ ("operation not permitted on type %<mfloat8_t%>");
> +
> +  /* Operation allowed.  */
> +  return NULL;
> +}
> +
>  /* Return the diagnostic message string if the binary operation OP is
>     not permitted on TYPE1 and TYPE2, NULL otherwise.  */
>  
> @@ -28982,6 +29029,13 @@ aarch64_invalid_binary_op (int op ATTRIBUTE_UNUSED, 
> const_tree type1,
>         != aarch64_sve::builtin_type_p (type2)))
>      return N_("cannot combine GNU and SVE vectors in a binary operation");
>  
> +  /* Reject all 2-operand operations on __mfp8.  */
> +  if (((TYPE_MODE (type1) == QImode)
> +       && (TYPE_MAIN_VARIANT (type1) == aarch64_mfp8_type_node))
> +      || ((TYPE_MODE (type2) == QImode)
> +          && (TYPE_MAIN_VARIANT (type2) == aarch64_mfp8_type_node)))

Similarly here.

> +    return N_ ("operation not permitted on type %<mfloat8_t%>");
> +
>    /* Operation allowed.  */
>    return NULL;
>  }
> [...]
> diff --git a/gcc/config/aarch64/arm_neon.h b/gcc/config/aarch64/arm_neon.h
> index e376685489d..0092314cf75 100644
> --- a/gcc/config/aarch64/arm_neon.h
> +++ b/gcc/config/aarch64/arm_neon.h
> @@ -72,6 +72,8 @@ typedef __Poly16_t poly16_t;
>  typedef __Poly64_t poly64_t;
>  typedef __Poly128_t poly128_t;
>  
> +typedef __mfp8 mfloat8_t;
> +
>  typedef __fp16 float16_t;
>  typedef float float32_t;
>  typedef double float64_t;
> diff --git a/gcc/config/aarch64/arm_sve.h b/gcc/config/aarch64/arm_sve.h
> index aa0bd9909f9..61c440fef56 100644
> --- a/gcc/config/aarch64/arm_sve.h
> +++ b/gcc/config/aarch64/arm_sve.h
> @@ -29,6 +29,7 @@
>  #include <arm_private_fp8.h>
>  #include <arm_bf16.h>
>  
> +typedef __mfp8 mfloat8_t;
>  typedef __fp16 float16_t;
>  typedef float float32_t;
>  typedef double float64_t;

Ultran minor nit, but it'd be good to have a consistent separation style
between arm_neon.h and arm_sve.h.  (Don't mind which we use.)

> diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c 
> b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
> new file mode 100644
> index 00000000000..6925653e33c
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_1.c
> @@ -0,0 +1,108 @@
> +/* Test the fp8 ACLE intrinsics family.  */
> +/* { dg-do compile } */
> +/* { dg-options "-O2 -march=armv9.4-a+fp8" } */
> +/* { dg-final { check-function-bodies "**" "" "" } } */
> +
> +#include <arm_neon.h>
> +
> +/*
> +**stacktest1:
> +**   sub     sp, sp, #16
> +**   sxtb    w0, w0

(This would become an AND if we do switch to an unsigned type.)

> +**   strb    w0, \[sp, 15\]
> +**   ldrb    w0, \[sp, 15\]
> +**   add     sp, sp, 16
> +**   ret
> +*/
> +mfloat8_t
> +stacktest1 (mfloat8_t __a)
> +{
> +  volatile mfloat8_t b = __a;
> +  return b;
> +}
> +
> +/*
> +**fp8_mov_ww:
> +**   dup     b1, v2.b\[0\]
> +**   ret
> +*/
> +void
> +fp8_mov_ww (void)
> +{
> +  register mfloat8_t x asm ("h2");
> +  register mfloat8_t y asm ("h1");
> +  asm volatile ("" : "=w"(x));
> +  y = x;
> +  asm volatile ("" ::"w"(y));
> +}
> +
> +/*
> +**fp8_mov_rw:
> +**   dup     v1.8b, w1
> +**   ret
> +*/
> +void
> +fp8_mov_rw (void)
> +{
> +  register mfloat8_t x asm ("w1");
> +  register mfloat8_t y asm ("h1");
> +  asm volatile ("" : "=r"(x));
> +  y = x;
> +  asm volatile ("" ::"w"(y));
> +}
> +
> +/*
> +**fp8_mov_wr:
> +**   umov    w1, v1.b\[0\]
> +**   ret
> +*/
> +void
> +fp8_mov_wr (void)
> +{
> +  register mfloat8_t x asm ("h1");
> +  register mfloat8_t y asm ("w1");
> +  asm volatile ("" : "=w"(x));
> +  y = x;
> +  asm volatile ("" ::"r"(y));
> +}
> +
> +/*
> +**fp8_mov_rr:
> +**   mov     w1, w2
> +**   ret
> +*/
> +void
> +fp8_mov_rr (void)
> +{
> +  register mfloat8_t x asm ("w2");
> +  register mfloat8_t y asm ("w1");
> +  asm volatile ("" : "=r"(x));
> +  y = x;
> +  asm volatile ("" ::"r"(y));
> +}
> +
> +/*
> +**fp8_mov_rm:
> +**   strb    w2, \[x0\]
> +**   ret
> +*/
> +void
> +fp8_mov_rm (mfloat8_t *ptr)
> +{
> +  register mfloat8_t x asm ("w2");
> +  asm volatile ("" : "=r"(x));
> +  *ptr = x;
> +}
> +
> +/*
> +**fp8_mov_mr:
> +**   ldrb    w2, \[x0\]
> +**   ret
> +*/
> +void
> +fp8_mov_mr (mfloat8_t *ptr)
> +{
> +  register mfloat8_t y asm ("w2");
> +  y = *ptr;
> +  asm volatile ("" ::"r"(y));
> +}

Nice tests :-)

It would be good to test loads and stores for FPRs as well,
for completeness.

> diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c 
> b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
> new file mode 100644
> index 00000000000..122dc5aa2b5
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_1.c
> @@ -0,0 +1,329 @@
> +/* Test that there is no conversion between ints and mfloat8_t.  */
> +/* { dg-do assemble } */
> +/* { dg-options "-O1 -march=armv9.4-a+fp8" } */
> +
> +#include <arm_neon.h>
> +#include <stdint.h>
> +
> +mfloat8_t glob_fp8;
> +
> +int is_an_int;
> +uint8_t is_a_uint8;
> +int8_t is_an_int8;
> +short is_a_short_int;
> +float is_a_float;
> +double is_a_double;
> +
> +uint8_t *uint8_ptr;

I think we should also test that:

  mfloat8_t extern_fn1(void);
  unsigned char extern_fn1(void);

  mfloat8_t extern_fn2(void);
  uint8_t extern_fn2(void);

  unsigned char extern_fn3(void);
  mfloat8_t extern_fn3(void);

  uint8_t extern_fn4(void);
  mfloat8_t extern_fn4(void);

give errors on the second definition.  Same for C++.

> +
> +mfloat8_t
> +invalid_from_fp8 (uint16_t __a)
> +{
> +  mfloat8_t b = __a; // { dg-error "invalid conversion to type 'mfloat8_t'" }
> +  return b;
> +}
> +
> +uint16_t
> +invalid_to_fp8 (mfloat8_t __a)
> +{
> +  uint16_t b = __a; // { dg-error "invalid conversion from type 'mfloat8_t'" 
> }
> +  return b;
> +}
> +
> +mfloat8_t
> +foo1 (void)
> +{
> +  return (mfloat8_t)0x1234; // { dg-error {invalid conversion to type 
> 'mfloat8_t'} }
> +}
> +mfloat8_t
> +foo2 (void)
> +{
> +  return (mfloat8_t)(short)0x1234; // { dg-error {invalid conversion to type 
> 'mfloat8_t'} }
> +}
> +
> +mfloat8_t
> +footest (mfloat8_t scalar0)
> +{
> +
> +  /* Initialisation  */
> +
> +  mfloat8_t scalar1_1;
> +  mfloat8_t scalar1_2 = glob_fp8;
> +  mfloat8_t scalar1_3 = 0; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  mfloat8_t scalar1_4
> +      = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar1_5
> +      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_6
> +      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_8
> +      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  mfloat8_t scalar1_9
> +      = is_a_short_int; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  mfloat8_t scalar1_10
> +      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_11
> +      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +
> +  int initi_1_1
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  float initi_1_2
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  short initi_1_4
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  double initi_1_5
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  uint8_t initi_1_6
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  int8_t initi_1_7
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  mfloat8_t scalar2_1 = {};
> +  mfloat8_t scalar2_2 = { glob_fp8 };
> +  mfloat8_t scalar2_3
> +      = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_4
> +      = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_5
> +      = { is_a_float }; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  mfloat8_t scalar2_6
> +      = { is_an_int }; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  mfloat8_t scalar2_8 = {
> +    is_a_double
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_9 = {
> +    is_a_short_int
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_10
> +      = { is_a_uint8 }; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  mfloat8_t scalar2_11
> +      = { is_an_int8 }; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +
> +  int initi_2_1
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  float initi_2_2
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  short initi_2_4
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  double initi_2_5
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  uint8_t initi_2_6
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  int8_t initi_2_7
> +      = { glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +
> +  /* Assignments.  */
> +
> +  glob_fp8 = glob_fp8;
> +  glob_fp8 = 0;        /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  glob_fp8
> +      = is_a_float;  /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  glob_fp8 = is_an_int; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  glob_fp8
> +      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  glob_fp8
> +      = is_a_short_int; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  glob_fp8
> +      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  glob_fp8
> +      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +
> +  is_an_int
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_float
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_double
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_short_int
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_uint8
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_an_int8
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  /* Casting.  */
> +
> +  (void)glob_fp8;
> +  (mfloat8_t) glob_fp8;
> +
> +  (int)glob_fp8;     /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (float)glob_fp8;   /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (double)glob_fp8;  /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (short)glob_fp8;   /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (uint8_t)glob_fp8; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (int8_t)glob_fp8;  /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +
> +  (mfloat8_t) is_an_int;     /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t) is_a_float;    /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t) is_a_double; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t)
> +      is_a_short_int;  /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t) is_a_uint8; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t) is_an_int8; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +
> +  /* Compound literals.  */
> +
> +  (mfloat8_t){};
> +  (mfloat8_t){ glob_fp8 };
> +  (mfloat8_t){ 0 };   /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  (mfloat8_t){ 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  (mfloat8_t){
> +    is_a_float
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t){
> +    is_an_int
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t){
> +    is_a_double
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t){
> +    is_a_short_int
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t){
> +    is_a_uint8
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t){
> +    is_an_int8
> +  }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +
> +  (int){ glob_fp8 }; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (float){
> +    glob_fp8
> +  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  (double){
> +    glob_fp8
> +  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  (short){
> +    glob_fp8
> +  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  (uint8_t){
> +    glob_fp8
> +  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  (int8_t){
> +    glob_fp8
> +  }; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +
> +  /* Arrays and Structs.  */
> +
> +  typedef mfloat8_t array_type[2];
> +  extern mfloat8_t extern_array[];
> +
> +  mfloat8_t array[2];
> +  mfloat8_t zero_length_array[0];
> +  mfloat8_t empty_init_array[] = {};
> +  typedef mfloat8_t some_other_type[is_an_int];
> +
> +  struct struct1
> +  {
> +    mfloat8_t a;
> +  };
> +
> +  union union1
> +  {
> +    mfloat8_t a;
> +  };
> +
> +  /* Addressing and dereferencing.  */
> +
> +  mfloat8_t *fp8_ptr = &scalar0;
> +  scalar0 = *fp8_ptr;
> +
> +  /* Pointer assignment.  */
> +
> +  mfloat8_t *fp8_ptr2 = fp8_ptr;
> +  mfloat8_t *fp8_ptr3 = array;
> +
> +  /* Pointer arithmetic.  */
> +
> +  ++fp8_ptr;
> +  --fp8_ptr;
> +  fp8_ptr++;
> +  fp8_ptr--;
> +  fp8_ptr += 1;
> +  fp8_ptr -= 1;
> +  fp8_ptr - fp8_ptr2;
> +  fp8_ptr = &fp8_ptr3[0];
> +  fp8_ptr = &fp8_ptr3[1];
> +
> +  /* Simple comparison.  */
> +  scalar0 > glob_fp8; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  glob_fp8
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 > is_a_float; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  is_a_float
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 > 0;         /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 == scalar0;        /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  scalar0 > 0.1;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0
> +      > is_an_int; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  is_an_int
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  /* Pointer comparison.  */
> +
> +  fp8_ptr == &scalar0;
> +  fp8_ptr != &scalar0;
> +  fp8_ptr < &scalar0;
> +  fp8_ptr <= &scalar0;
> +  fp8_ptr > &scalar0;
> +  fp8_ptr >= &scalar0;
> +  fp8_ptr == fp8_ptr2;
> +  fp8_ptr != fp8_ptr2;
> +  fp8_ptr < fp8_ptr2;
> +  fp8_ptr <= fp8_ptr2;
> +  fp8_ptr > fp8_ptr2;
> +  fp8_ptr >= fp8_ptr2;
> +
> +  /* Conditional expressions.  */
> +
> +  0 ? scalar0 : scalar0; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? scalar0
> +    : is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  0 ? is_a_float
> +    : scalar0;            /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? scalar0 : 0;   /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? 0 : scalar0;   /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? 0.1 : scalar0; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? scalar0 : 0.1; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? fp8_ptr : fp8_ptr2;
> +  0 ? fp8_ptr : uint8_ptr; /* { dg-error {pointer type mismatch in 
> conditional expression} } */
> +  0 ? uint8_ptr : fp8_ptr; /* { dg-error {pointer type mismatch in 
> conditional expression} } */
> +
> +  scalar0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +       : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 ? is_a_float /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +       : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 ? scalar0 : is_a_float; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +  scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +
> +  /* Unary operators.  */
> +
> +  +scalar0;    /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  -scalar0;    /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  ~scalar0;    /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  !scalar0;    /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  *scalar0;    /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  __real scalar0; /* { dg-error {operation not permitted on type 
> 'mfloat8_t'} } */
> +  __imag scalar0; /* { dg-error {operation not permitted on type 
> 'mfloat8_t'} } */
> +  ++scalar0;   /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  --scalar0;   /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  scalar0++;   /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +  scalar0--;   /* { dg-error {operation not permitted on type 'mfloat8_t'} } 
> */
> +
> +  /* Binary arithmetic operations.  */
> +
> +  scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +  scalar0 = glob_fp8 + *fp8_ptr; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  scalar0 = glob_fp8
> +         + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  scalar0
> +      = glob_fp8 + 0; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  scalar0
> +      = glob_fp8
> +     + is_a_float; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */

Hmm, so all the errors for binary operations come from the usual
integer conversions, rather than from the binary operation itself.
That makes sense.

Could you also test fp8 op fp8 only for the other binary operations,
including && and ||?

For C++, it would be good to test:

  #include <type_traits>

  static_assert(!std::is_integral<__mfp8>(), "not integral");
  static_assert(!std::is_signed<__mfp8>(), "not signed");
  static_assert(!std::is_unsigned<__mfp8>(), "not unsigned");

to make sure that we maintain the abstraction.  Was kind-of surprised
that this Just Works -- didn't look into the mechanics of how it does.

Thanks,
Richard

> +
> +  return scalar0;
> +}
> diff --git a/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C 
> b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C
> new file mode 100644
> index 00000000000..f0a3c756c84
> --- /dev/null
> +++ b/gcc/testsuite/gcc.target/aarch64/fp8_scalar_typecheck_2.C
> @@ -0,0 +1,354 @@
> +/* Test that mfloat8_t is only usable with intrinsics, thus not convertible. 
>  */
> +/* { dg-do assemble } */
> +/* { dg-options "-O1 -march=armv9.4-a+fp8 -Wno-narrowing" } */
> +
> +#include <arm_neon.h>
> +#include <stdint.h>
> +
> +mfloat8_t glob_fp8;
> +
> +int is_an_int;
> +uint8_t is_a_uint8;
> +int8_t is_an_int8;
> +short is_a_short_int;
> +float is_a_float;
> +double is_a_double;
> +
> +uint8_t *uint8_ptr;
> +
> +mfloat8_t
> +invalid_from_fp8 (uint16_t __a)
> +{
> +  mfloat8_t b = __a; /* { dg-error "invalid conversion to type 'mfloat8_t'" 
> } */
> +  return b;
> +}
> +
> +uint16_t
> +invalid_to_fp8 (mfloat8_t __a)
> +{
> +  uint16_t b = __a; /*{ dg-error "invalid conversion from type 'mfloat8_t'" 
> } */
> +  return b;
> +}
> +
> +mfloat8_t
> +foo1 (void)
> +{
> +  return (mfloat8_t)0x1234; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +}
> +
> +mfloat8_t
> +foo2 (void)
> +{
> +  return (mfloat8_t)(short)0x1234; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +}
> +
> +mfloat8_t
> +footest (mfloat8_t scalar0)
> +{
> +
> +  /* Initialisation  */
> +
> +  mfloat8_t scalar1_1;
> +  mfloat8_t scalar1_2 = glob_fp8;
> +  mfloat8_t scalar1_3
> +      = 0; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar1_4
> +      = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar1_5
> +      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_6
> +      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_8
> +      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  mfloat8_t scalar1_9 = is_a_short_int; /* { dg-error {invalid conversion to 
> type 'mfloat8_t'} } */
> +  mfloat8_t scalar1_10
> +      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  mfloat8_t scalar1_11
> +      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +
> +  int initi_1_1
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  float initi_1_2
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  short initi_1_4
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  double initi_1_5
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  uint8_t initi_1_6
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  int8_t initi_1_7
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  mfloat8_t scalar2_1 = {};
> +  mfloat8_t scalar2_2 = { glob_fp8 };
> +  mfloat8_t scalar2_3
> +      = { 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_4
> +      = { 0.1 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  mfloat8_t scalar2_5 = {
> +    is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  mfloat8_t scalar2_6 = {
> +    is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  mfloat8_t scalar2_8 = {
> +    is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  mfloat8_t scalar2_9 = {
> +    is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  };
> +  mfloat8_t scalar2_10 = {
> +    is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  mfloat8_t scalar2_11 = {
> +    is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +
> +  int initi_2_1 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  float initi_2_2 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  short initi_2_4 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  double initi_2_5 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  uint8_t initi_2_6 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  int8_t initi_2_7 = {
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +
> +  /* Assignments.  */
> +
> +  glob_fp8 = glob_fp8;
> +  glob_fp8 = 0;        /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  glob_fp8 = 0.1; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  glob_fp8
> +      = is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  glob_fp8
> +      = is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  glob_fp8
> +      = is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} 
> } */
> +  glob_fp8 = is_a_short_int; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  glob_fp8
> +      = is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  glob_fp8
> +      = is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +
> +  is_an_int
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_float
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_double
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_short_int
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_a_uint8
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  is_an_int8
> +      = glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  /* Casting.  */
> +
> +  (void)glob_fp8;
> +  (mfloat8_t) glob_fp8;
> +
> +  (int)glob_fp8;   /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  (float)glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  (double)
> +      glob_fp8;         /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  (short)glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  (uint8_t)
> +      glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  (int8_t)
> +      glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +
> +  (mfloat8_t)
> +      is_an_int; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t)
> +      is_a_float; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t)
> +      is_a_double; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  (mfloat8_t) is_a_short_int; /* { dg-error {invalid conversion to type 
> 'mfloat8_t'} } */
> +  (mfloat8_t)
> +      is_a_uint8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  (mfloat8_t)
> +      is_an_int8; /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +
> +  /* Compound literals.  */
> +
> +  (mfloat8_t){};
> +  (mfloat8_t){ glob_fp8 };
> +  (mfloat8_t){ 0 }; /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  (mfloat8_t){
> +    0.1 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  }; 
> +  (mfloat8_t){
> +    is_a_float /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  (mfloat8_t){
> +    is_an_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  (mfloat8_t){
> +    is_a_double /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  (mfloat8_t){
> +    is_a_short_int /* { dg-error {invalid conversion to type 'mfloat8_t'} } 
> */
> +  };
> +  (mfloat8_t){
> +    is_a_uint8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +  (mfloat8_t){
> +    is_an_int8 /* { dg-error {invalid conversion to type 'mfloat8_t'} } */
> +  };
> +
> +  (int){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  (float){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  (double){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  (short){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  (uint8_t){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +  (int8_t){
> +    glob_fp8 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  };
> +
> +  /* Arrays and Structs.  */
> +
> +  typedef mfloat8_t array_type[2];
> +  extern mfloat8_t extern_array[];
> +
> +  mfloat8_t array[2];
> +  mfloat8_t zero_length_array[0];
> +  mfloat8_t empty_init_array[] = {};
> +  typedef mfloat8_t some_other_type[is_an_int];
> +
> +  struct struct1
> +  {
> +    mfloat8_t a;
> +  };
> +
> +  union union1
> +  {
> +    mfloat8_t a;
> +  };
> +
> +  /* Addressing and dereferencing.  */
> +
> +  mfloat8_t *fp8_ptr = &scalar0;
> +  scalar0 = *fp8_ptr;
> +
> +  /* Pointer assignment.  */
> +
> +  mfloat8_t *fp8_ptr2 = fp8_ptr;
> +  mfloat8_t *fp8_ptr3 = array;
> +
> +  /* Pointer arithmetic.  */
> +
> +  ++fp8_ptr;
> +  --fp8_ptr;
> +  fp8_ptr++;
> +  fp8_ptr--;
> +  fp8_ptr += 1;
> +  fp8_ptr -= 1;
> +  fp8_ptr - fp8_ptr2;
> +  fp8_ptr = &fp8_ptr3[0];
> +  fp8_ptr = &fp8_ptr3[1];
> +
> +  /* Simple comparison.  */
> +  scalar0
> +      > glob_fp8; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  glob_fp8
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 > is_a_float; /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  is_a_float
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0 > 0;         /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 == scalar0;        /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  scalar0 > 0.1;  /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  0.1 == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +  scalar0
> +      > is_an_int; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  is_an_int
> +      == scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } 
> */
> +
> +  /* Pointer comparison.  */
> +
> +  fp8_ptr == &scalar0;
> +  fp8_ptr != &scalar0;
> +  fp8_ptr < &scalar0;
> +  fp8_ptr <= &scalar0;
> +  fp8_ptr > &scalar0;
> +  fp8_ptr >= &scalar0;
> +  fp8_ptr == fp8_ptr2;
> +  fp8_ptr != fp8_ptr2;
> +  fp8_ptr < fp8_ptr2;
> +  fp8_ptr <= fp8_ptr2;
> +  fp8_ptr > fp8_ptr2;
> +  fp8_ptr >= fp8_ptr2;
> +
> +  /* Conditional expressions.  */
> +
> +  0 ? scalar0 : scalar0;
> +  0 ? scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +    : is_a_float;
> +  0 ? is_a_float
> +    : scalar0;          /* { dg-error {invalid conversion from type 
> 'mfloat8_t'} } */
> +  0 ? scalar0 : 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  0 ? 0 : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} 
> } */
> +  0 ? 0.1
> +    : scalar0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  0 ? scalar0  /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +    : 0.1;
> +  0 ? fp8_ptr : fp8_ptr2;
> +  0 ? fp8_ptr : uint8_ptr; /* { dg-error {conditional expression between 
> distinct pointer types} } */
> +  0 ? uint8_ptr : fp8_ptr; /* { dg-error {conditional expression between 
> distinct pointer types} } */
> +
> +  scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +      ? scalar0
> +      : scalar0;
> +  scalar0 /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +      ? is_a_float
> +      : scalar0;
> +  scalar0 ? scalar0 : is_a_float;    /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +  scalar0 ? is_a_float : is_a_float; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +
> +  /* Unary operators.  */
> +
> +  +scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  -scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  ~scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  !scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  *scalar0; /* { dg-error {invalid type argument of unary} } */
> +  __real scalar0; /* { dg-error {operation not permitted on type 
> 'mfloat8_t'} } */
> +  __imag scalar0; /* { dg-error {operation not permitted on type 
> 'mfloat8_t'} } */
> +  ++scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  --scalar0; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  scalar0++; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +  scalar0--; /* { dg-error {operation not permitted on type 'mfloat8_t'} } */
> +
> +  /* Binary arithmetic operations.  */
> +
> +  scalar0 = glob_fp8 + scalar1_2; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +  scalar0 = glob_fp8 + *fp8_ptr;  /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +  scalar0 = glob_fp8
> +         + 0.1; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  scalar0 = glob_fp8
> +         + 0; /* { dg-error {invalid conversion from type 'mfloat8_t'} } */
> +  scalar0 = glob_fp8 + is_a_float; /* { dg-error {invalid conversion from 
> type 'mfloat8_t'} } */
> +
> +  return scalar0;
> +}

Reply via email to