mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 03:30:29 +08:00
[C++] Pass type uses through the verify_type_context hook
This patch makes the C++ frontend work with the verify_type_context hook. 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. 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. From-SVN: r279058
This commit is contained in:
parent
1e8f5d49d7
commit
02a32ab4a6
@ -1,3 +1,10 @@
|
||||
2019-12-06 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2019-12-06 Andrew Stubbs <ams@codesourcery.com>
|
||||
|
||||
* config/gcn/gcn-valu.md (gather<mode>_insn_1offset<exec>): Use %o
|
||||
|
@ -3352,6 +3352,26 @@ verify_type_context (location_t loc, type_context_kind context,
|
||||
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 ();
|
||||
}
|
||||
|
@ -1,3 +1,38 @@
|
||||
2019-12-06 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* 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.
|
||||
|
||||
2019-12-05 Marek Polacek <polacek@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
|
@ -5470,6 +5470,13 @@ start_decl_1 (tree decl, bool initialized)
|
||||
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 type, tree init)
|
||||
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, bool init_const_expr_p,
|
||||
|
||||
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, tree type, tree size, location_t loc)
|
||||
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 *declarator,
|
||||
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)
|
||||
|
@ -29,6 +29,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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_parameter (tree t, bool is_throw)
|
||||
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. */
|
||||
|
@ -3058,6 +3058,10 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
||||
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 maxindex, tree type,
|
||||
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, special_function_kind auto_delete,
|
||||
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)
|
||||
|
@ -30,6 +30,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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 orig_init, bool by_reference_p,
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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,
|
||||
|
@ -1824,7 +1824,14 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain)
|
||||
|
||||
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, tree op1, tree ptrtype,
|
||||
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, tree xarg, bool noconvert,
|
||||
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));
|
||||
}
|
||||
|
@ -33,6 +33,7 @@ along with GCC; see the file COPYING3. If not see
|
||||
#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 spec, tsubst_flags_t complain)
|
||||
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;
|
||||
|
14
gcc/target.h
14
gcc/target.h
@ -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,
|
||||
|
@ -1,3 +1,8 @@
|
||||
2019-12-06 Richard Sandiford <richard.sandiford@arm.com>
|
||||
|
||||
* g++.dg/ext/sve-sizeless-1.C: New test.
|
||||
* g++.dg/ext/sve-sizeless-2.C: Likewise.
|
||||
|
||||
2019-12-06 Christophe Lyon <christophe.lyon@linaro.org>
|
||||
|
||||
PR c/36941
|
||||
|
420
gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
Normal file
420
gcc/testsuite/g++.dg/ext/sve-sizeless-1.C
Normal file
@ -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
|
420
gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
Normal file
420
gcc/testsuite/g++.dg/ext/sve-sizeless-2.C
Normal file
@ -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
|
Loading…
x
Reference in New Issue
Block a user