diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 15 | ||||
-rw-r--r-- | gcc/c-family/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/c-family/c-common.c | 15 | ||||
-rw-r--r-- | gcc/c/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/c/c-decl.c | 29 | ||||
-rw-r--r-- | gcc/c/c-typeck.c | 8 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-protos.h | 3 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64-sve-builtins.cc | 49 | ||||
-rw-r--r-- | gcc/config/aarch64/aarch64.c | 12 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 13 | ||||
-rw-r--r-- | gcc/doc/tm.texi.in | 2 | ||||
-rw-r--r-- | gcc/target.def | 16 | ||||
-rw-r--r-- | gcc/target.h | 29 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c | 217 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c | 217 | ||||
-rw-r--r-- | gcc/tree.c | 15 |
17 files changed, 664 insertions, 3 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 0bfc239..72c8d2e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,18 @@ +2019-11-30 Richard Sandiford <richard.sandiford@arm.com> + + * target.h (type_context_kind): New enum. + (verify_type_context): Declare. + * target.def (verify_type_context): New target hook. + * doc/tm.texi.in (TARGET_VERIFY_TYPE_CONTEXT): Likewise. + * doc/tm.texi: Regenerate. + * tree.c (verify_type_context): New function. + * config/aarch64/aarch64-protos.h (aarch64_sve::verify_type_context): + Declare. + * config/aarch64/aarch64-sve-builtins.cc (verify_type_context): + New function. + * config/aarch64/aarch64.c (aarch64_verify_type_context): Likewise. + (TARGET_VERIFY_TYPE_CONTEXT): Define. + 2019-11-30 Jan Hubicka <hubicka@ucw.cz> * cgraph.c (cgraph_node::dump): Dump unit_id and merged_extern_inline. diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog index a26b1f2..763e5a2 100644 --- a/gcc/c-family/ChangeLog +++ b/gcc/c-family/ChangeLog @@ -1,3 +1,11 @@ +2019-11-30 Richard Sandiford <richard.sandiford@arm.com> + + * c-common.c (pointer_int_sum): Use verify_type_context to check + whether the target allows pointer arithmetic for the types involved. + (c_sizeof_or_alignof_type, c_alignof_expr): Use verify_type_context + to check whether the target allows sizeof and alignof operations + for the types involved. + 2019-11-27 Jason Merrill <jason@redhat.com> * c-cppbuiltin.c (c_cpp_builtins): Update __cpp_deduction_guides. diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c index 5b9af1a..2f389d2 100644 --- a/gcc/c-family/c-common.c +++ b/gcc/c-family/c-common.c @@ -3146,6 +3146,9 @@ pointer_int_sum (location_t loc, enum tree_code resultcode, return error_mark_node; size_exp = integer_one_node; } + else if (!verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (result_type))) + size_exp = integer_one_node; else size_exp = size_in_bytes_loc (loc, TREE_TYPE (result_type)); @@ -3691,6 +3694,13 @@ c_sizeof_or_alignof_type (location_t loc, "incomplete element type", op_name, type); return error_mark_node; } + else if (!verify_type_context (loc, is_sizeof ? TCTX_SIZEOF : TCTX_ALIGNOF, + type, !complain)) + { + if (!complain) + return error_mark_node; + value = size_one_node; + } else { if (is_sizeof) @@ -3723,7 +3733,10 @@ c_alignof_expr (location_t loc, tree expr) { tree t; - if (VAR_OR_FUNCTION_DECL_P (expr)) + if (!verify_type_context (loc, TCTX_ALIGNOF, TREE_TYPE (expr))) + t = size_one_node; + + else if (VAR_OR_FUNCTION_DECL_P (expr)) t = size_int (DECL_ALIGN_UNIT (expr)); else if (TREE_CODE (expr) == COMPONENT_REF diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index b69e82d..8fee474 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,17 @@ +2019-11-30 Richard Sandiford <richard.sandiford@arm.com> + + * c-decl.c (start_decl): Allow initialization of variables whose + size is a POLY_INT_CST. + (finish_decl): Use verify_type_context to check whether the target + allows variables with a particular type to have static or thread-local + storage duration. Don't raise a second error if such variables do + not have a constant size. + (grokdeclarator): Use verify_type_context to check whether the + target allows fields or array elements to have a particular type. + * c-typeck.c (pointer_diff): Use verify_type_context to test whether + the target allows pointer difference for the types involved. + (build_unary_op): Likewise for pointer increment and decrement. + 2019-11-29 Joseph Myers <joseph@codesourcery.com> * c-parser.c (struct c_parser): Add members raw_tokens and diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c index 292a4cc..fa7dea5 100644 --- a/gcc/c/c-decl.c +++ b/gcc/c/c-decl.c @@ -5021,7 +5021,7 @@ start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs, { /* A complete type is ok if size is fixed. */ - if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST + if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl))) || C_DECL_VARIABLE_SIZE (decl)) { error ("variable-sized object may not be initialized"); @@ -5304,6 +5304,15 @@ finish_decl (tree decl, location_t init_loc, tree init, complete_flexible_array_elts (DECL_INITIAL (decl)); + if (is_global_var (decl)) + { + type_context_kind context = (DECL_THREAD_LOCAL_P (decl) + ? TCTX_THREAD_STORAGE + : TCTX_STATIC_STORAGE); + if (!verify_type_context (input_location, context, TREE_TYPE (decl))) + TREE_TYPE (decl) = error_mark_node; + } + if (DECL_SIZE (decl) == NULL_TREE && TREE_TYPE (decl) != error_mark_node && COMPLETE_TYPE_P (TREE_TYPE (decl))) layout_decl (decl, 0); @@ -5333,7 +5342,9 @@ finish_decl (tree decl, location_t init_loc, tree init, && TREE_STATIC (decl)) incomplete_record_decls.safe_push (decl); - if (is_global_var (decl) && DECL_SIZE (decl) != NULL_TREE) + if (is_global_var (decl) + && DECL_SIZE (decl) != NULL_TREE + && TREE_TYPE (decl) != error_mark_node) { if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST) constant_expression_warning (DECL_SIZE (decl)); @@ -5653,6 +5664,10 @@ build_compound_literal (location_t loc, tree type, tree init, bool non_const, return error_mark_node; } + if (TREE_STATIC (decl) + && !verify_type_context (loc, TCTX_STATIC_STORAGE, type)) + return error_mark_node; + stmt = build_stmt (DECL_SOURCE_LOCATION (decl), DECL_EXPR, decl); complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt); TREE_SIDE_EFFECTS (complit) = 1; @@ -6370,6 +6385,12 @@ grokdeclarator (const struct c_declarator *declarator, if (type == error_mark_node) continue; + if (!verify_type_context (loc, TCTX_ARRAY_ELEMENT, type)) + { + type = error_mark_node; + continue; + } + /* If size was specified, set ITYPE to a range-type for that size. Otherwise, ITYPE remains null. finish_decl may figure it out from an initial value. */ @@ -7217,6 +7238,10 @@ grokdeclarator (const struct c_declarator *declarator, if (orig_qual_indirect == 0) orig_qual_type = NULL_TREE; } + if (type != error_mark_node + && !verify_type_context (loc, TCTX_FIELD, type)) + type = error_mark_node; + type = c_build_qualified_type (type, type_quals, orig_qual_type, orig_qual_indirect); decl = build_decl (declarator->id_loc, diff --git a/gcc/c/c-typeck.c b/gcc/c/c-typeck.c index 5f74a3b..f9ab1e3 100644 --- a/gcc/c/c-typeck.c +++ b/gcc/c/c-typeck.c @@ -3892,6 +3892,7 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0))); addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1))); tree target_type = TREE_TYPE (TREE_TYPE (op0)); + tree orig_op0 = op0; tree orig_op1 = op1; /* If the operands point into different address spaces, we need to @@ -3962,6 +3963,10 @@ pointer_diff (location_t loc, tree op0, tree op1, tree *instrument_expr) /* This generates an error if op1 is pointer to incomplete type. */ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1)))) error_at (loc, "arithmetic on pointer to an incomplete type"); + else if (verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op0)))) + verify_type_context (loc, TCTX_POINTER_ARITH, + TREE_TYPE (TREE_TYPE (orig_op1))); op1 = c_size_in_bytes (target_type); @@ -4614,6 +4619,9 @@ build_unary_op (location_t location, enum tree_code code, tree xarg, pedwarn (location, OPT_Wpointer_arith, "wrong type argument to decrement"); } + else + verify_type_context (location, TCTX_POINTER_ARITH, + TREE_TYPE (argtype)); inc = c_size_in_bytes (TREE_TYPE (argtype)); inc = convert_to_ptrofftype_loc (location, inc); diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 5b1fc7b..c16b936 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -715,6 +715,9 @@ namespace aarch64_sve { tree, unsigned int, tree *); gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *); rtx expand_builtin (unsigned int, tree, rtx); +#ifdef GCC_TARGET_H + bool verify_type_context (location_t, type_context_kind, const_tree, bool); +#endif } extern void aarch64_split_combinev16qi (rtx operands[3]); diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc index 27736b9..5dd7ccb 100644 --- a/gcc/config/aarch64/aarch64-sve-builtins.cc +++ b/gcc/config/aarch64/aarch64-sve-builtins.cc @@ -3296,6 +3296,55 @@ builtin_type_p (const_tree type) return svbool_type_p (type) || nvectors_if_data_type (type) > 0; } +/* Implement TARGET_VERIFY_TYPE_CONTEXT for SVE types. */ +bool +verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + if (!builtin_type_p (type)) + return true; + + switch (context) + { + case TCTX_SIZEOF: + case TCTX_STATIC_STORAGE: + if (!silent_p) + error_at (loc, "SVE type %qT does not have a fixed size", type); + return false; + + case TCTX_ALIGNOF: + if (!silent_p) + error_at (loc, "SVE type %qT does not have a defined alignment", type); + return false; + + case TCTX_THREAD_STORAGE: + if (!silent_p) + error_at (loc, "variables of type %qT cannot have thread-local" + " storage duration", type); + return false; + + case TCTX_POINTER_ARITH: + if (!silent_p) + error_at (loc, "arithmetic on pointer to SVE type %qT", type); + return false; + + case TCTX_FIELD: + if (silent_p) + ; + else if (lang_GNU_CXX ()) + error_at (loc, "member variables cannot have SVE type %qT", type); + else + error_at (loc, "fields cannot have SVE type %qT", type); + return false; + + case TCTX_ARRAY_ELEMENT: + if (!silent_p) + error_at (loc, "array elements cannot have SVE type %qT", type); + return false; + } + gcc_unreachable (); +} + } using namespace aarch64_sve; diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 94e664a..d0cbe13 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -16200,6 +16200,15 @@ aarch64_mangle_type (const_tree type) return NULL; } +/* Implement TARGET_VERIFY_TYPE_CONTEXT. */ + +static bool +aarch64_verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + return aarch64_sve::verify_type_context (loc, context, type, silent_p); +} + /* Find the first rtx_insn before insn that will generate an assembly instruction. */ @@ -21860,6 +21869,9 @@ aarch64_libgcc_floating_mode_supported_p #undef TARGET_MANGLE_TYPE #define TARGET_MANGLE_TYPE aarch64_mangle_type +#undef TARGET_VERIFY_TYPE_CONTEXT +#define TARGET_VERIFY_TYPE_CONTEXT aarch64_verify_type_context + #undef TARGET_MEMORY_MOVE_COST #define TARGET_MEMORY_MOVE_COST aarch64_memory_move_cost diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 7116450..5b8b68b 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -11976,6 +11976,19 @@ conversion rules. This is currently used only by the C and C++ front ends. @end deftypefn +@deftypefn {Target Hook} bool TARGET_VERIFY_TYPE_CONTEXT (location_t @var{loc}, type_context_kind @var{context}, const_tree @var{type}, bool @var{silent_p}) +If defined, this hook returns false if there is a target-specific reason +why type @var{type} cannot be used in the source language context described +by @var{context}. When @var{silent_p} is false, the hook also reports an +error against @var{loc} for invalid uses of @var{type}. + +Calls to this hook should be made through the global function +@code{verify_type_context}, which makes the @var{silent_p} parameter +default to false and also handles @code{error_mark_node}. + +The default implementation always returns true. +@end deftypefn + @defmac OBJC_JBLEN This macro determines the size of the objective C jump buffer for the NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value. diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in index 4034686..1b061d7 100644 --- a/gcc/doc/tm.texi.in +++ b/gcc/doc/tm.texi.in @@ -8087,6 +8087,8 @@ and scanf formatter settings. @hook TARGET_CONVERT_TO_TYPE +@hook TARGET_VERIFY_TYPE_CONTEXT + @defmac OBJC_JBLEN This macro determines the size of the objective C jump buffer for the NeXT runtime. By default, OBJC_JBLEN is defined to an innocuous value. diff --git a/gcc/target.def b/gcc/target.def index cce71cd..e0e8569 100644 --- a/gcc/target.def +++ b/gcc/target.def @@ -5287,6 +5287,22 @@ This is currently used only by the C and C++ front ends.", hook_tree_tree_tree_null) DEFHOOK +(verify_type_context, + "If defined, this hook returns false if there is a target-specific reason\n\ +why type @var{type} cannot be used in the source language context described\n\ +by @var{context}. When @var{silent_p} is false, the hook also reports an\n\ +error against @var{loc} for invalid uses of @var{type}.\n\ +\n\ +Calls to this hook should be made through the global function\n\ +@code{verify_type_context}, which makes the @var{silent_p} parameter\n\ +default to false and also handles @code{error_mark_node}.\n\ +\n\ +The default implementation always returns true.", + bool, (location_t loc, type_context_kind context, const_tree type, + bool silent_p), + NULL) + +DEFHOOK (can_change_mode_class, "This hook returns true if it is possible to bitcast values held in\n\ registers of class @var{rclass} from mode @var{from} to mode @var{to}\n\ diff --git a/gcc/target.h b/gcc/target.h index 2c5b59b..973d743 100644 --- a/gcc/target.h +++ b/gcc/target.h @@ -226,6 +226,35 @@ enum omp_device_kind_arch_isa { will choose the first mode that works. */ const unsigned int VECT_COMPARE_COSTS = 1U << 0; +/* The contexts in which the use of a type T can be checked by + TARGET_VERIFY_TYPE_CONTEXT. */ +enum type_context_kind { + /* Directly measuring the size of T. */ + TCTX_SIZEOF, + + /* Directly measuring the alignment of T. */ + TCTX_ALIGNOF, + + /* Creating objects of type T with static storage duration. */ + TCTX_STATIC_STORAGE, + + /* Creating objects of type T with thread-local storage duration. */ + TCTX_THREAD_STORAGE, + + /* Creating a field of type T. */ + TCTX_FIELD, + + /* Creating an array with elements of type T. */ + TCTX_ARRAY_ELEMENT, + + /* 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 +}; + +extern bool verify_type_context (location_t, type_context_kind, const_tree, + bool = false); + /* The target structure. This holds all the backend hooks. */ #define DEFHOOKPOD(NAME, DOC, TYPE, INIT) TYPE NAME; #define DEFHOOK(NAME, DOC, TYPE, PARAMS, INIT) TYPE (* NAME) PARAMS; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 4595d66..34d5a75 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-11-30 Richard Sandiford <richard.sandiford@arm.com> + + * gcc.target/aarch64/sve/acle/general-c/sizeless-1.c: New test. + * gcc.target/aarch64/sve/acle/general-c/sizeless-2.c: Likewise. + 2019-11-30 Jan Hubicka <hubicka@ucw.cz> * g++.dg/lto/inline-crossmodule-1.h: New testcase. diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c new file mode 100644 index 0000000..ec892a3 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-1.c @@ -0,0 +1,217 @@ +/* { dg-options "-std=gnu99" } */ + +#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} } */ +_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + +/* 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 fields. */ + +struct struct1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +union union1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +/* Pointers to sizeless types. */ + +svint8_t *global_sve_sc_ptr; +svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */ + /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */ + +/* Sizeless arguments and return values. */ + +void ext_consume_sve_sc (svint8_t); +void ext_consume_varargs (int, ...); +svint8_t ext_produce_sve_sc (); + +/* Main tests for statements and expressions. */ + +void +statements (int n) +{ + /* Local declarations. */ + + unsigned char va __attribute__((__vector_size__(2))); + svint8_t sve_sc1, sve_sc2; + _Atomic svint8_t atomic_sve_sc; + int8x32_t gnu_sc1; + svint16_t sve_sh1; + static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + + /* 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} } */ + + /* Initialization. */ + + svint8_t init_sve_sc1 = sve_sc1; + svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ + svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + + int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Compound literals. */ + + (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) { sve_sc1 }; + + (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* 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'} } */ + /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */ + typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + + /* Assignment. */ + + n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */ + + sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */ + sve_sc1 = sve_sc2; + sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */ + + /* Casting. */ + + (void) sve_sc1; + (svint8_t) sve_sc1; + + /* Addressing and dereferencing. */ + + svint8_t *sve_sc_ptr = &sve_sc1; + int8x32_t *gnu_sc_ptr = &gnu_sc1; + sve_sc1 = *sve_sc_ptr; + + /* Pointer assignment. */ + + gnu_sc_ptr = sve_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */ + sve_sc_ptr = gnu_sc_ptr; /* { dg-warning {assignment to [^\n]* from incompatible pointer type} } */ + + /* 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 to binary -} } */ + sve_sc_ptr - gnu_sc_ptr; /* { dg-error {invalid operands to binary -} } */ + 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-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr != sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr < sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr <= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr > sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + gnu_sc_ptr >= sve_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr == gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr != gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr < gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr <= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr > gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + sve_sc_ptr >= gnu_sc_ptr; /* { dg-warning {comparison of distinct pointer types lacks a cast} } */ + + /* Conditional expressions. */ + + 0 ? sve_sc1 : sve_sc1; + 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + 0 ? gnu_sc_ptr : sve_sc_ptr; /* { dg-warning {pointer type mismatch in conditional expression} } */ + + /* Generic associations. */ + + _Generic (sve_sc1, default: 100); + _Generic (1, svint8_t: 10, default: 20); + + /* Function arguments. */ + + ext_consume_sve_sc (sve_sc1); + ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */ + ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */ + 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 {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */ + + /* Varargs processing. */ + + __builtin_va_list valist; + __builtin_va_arg (valist, svint8_t); + + /* Statement expressions. */ + + ({ sve_sc1; }); + ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; }); +} + +/* Function parameters in definitions. */ + +void +old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */ + svint8_t input_sve_sc; +{ + svint8_t sve_sc1 = input_sve_sc; +} + +void +new_style_param (svint8_t input_sve_sc) +{ + svint8_t sve_sc1 = input_sve_sc; +} + +/* Function return values in definitions. */ + +svint8_t +good_return_sve_sc (svint8_t param) +{ + return param; +} + +svint8_t +bad_return_sve_sc (svint16_t param) +{ + return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */ +} diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c new file mode 100644 index 0000000..7174393 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/sizeless-2.c @@ -0,0 +1,217 @@ +/* { dg-options "-std=gnu99 -msve-vector-bits=256" } */ + +#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} } */ +_Atomic svint8_t atomic_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + +/* 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 fields. */ + +struct struct1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +union union1 { + svint8_t a; /* { dg-error {fields cannot have SVE type 'svint8_t'} } */ +}; + +/* Pointers to sizeless types. */ + +svint8_t *global_sve_sc_ptr; +svint8_t *invalid_sve_sc_ptr = &(svint8_t) { *global_sve_sc_ptr }; /* { dg-error {initializer element is not constant} } */ + /* { dg-error {SVE type 'svint8_t' does not have a fixed size} "" { target *-*-* } .-1 } */ + +/* Sizeless arguments and return values. */ + +void ext_consume_sve_sc (svint8_t); +void ext_consume_varargs (int, ...); +svint8_t ext_produce_sve_sc (); + +/* Main tests for statements and expressions. */ + +void +statements (int n) +{ + /* Local declarations. */ + + unsigned char va __attribute__((__vector_size__(2))); + svint8_t sve_sc1, sve_sc2; + _Atomic svint8_t atomic_sve_sc; + int8x32_t gnu_sc1; + svint16_t sve_sh1; + static svint8_t local_static_sve_sc; /* { dg-error {SVE type 'svint8_t' does not have a fixed size} } */ + + /* 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} } */ + + /* Initialization. */ + + svint8_t init_sve_sc1 = sve_sc1; + svint8_t init_sve_sc2 = sve_sh1; /* { dg-error {incompatible types when initializing type 'svint8_t' using type 'svint16_t'} } */ + svint8_t init_sve_sc3 = {}; /* { dg-error {empty scalar initializer} } */ + + int initi_a = sve_sc1; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + int initi_b = { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* Compound literals. */ + + (svint8_t) {}; /* { dg-error {empty scalar initializer} } */ + (svint8_t) { sve_sc1 }; + + (int) { sve_sc1 }; /* { dg-error {incompatible types when initializing type 'int' using type 'svint8_t'} } */ + + /* 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'} } */ + /* { dg-error {empty scalar initializer} "" { target *-*-* } .-1 } */ + typedef svint8_t vla_type[n]; /* { dg-error {array elements cannot have SVE type 'svint8_t'} } */ + + /* Assignment. */ + + n = sve_sc1; /* { dg-error {incompatible types when assigning to type 'int' from type 'svint8_t'} } */ + + sve_sc1 = 0; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */ + sve_sc1 = sve_sc2; + sve_sc1 = sve_sh1; /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'svint16_t'} } */ + + /* Casting. */ + + (void) sve_sc1; + (svint8_t) sve_sc1; + + /* Addressing and dereferencing. */ + + svint8_t *sve_sc_ptr = &sve_sc1; + int8x32_t *gnu_sc_ptr = &gnu_sc1; + sve_sc1 = *sve_sc_ptr; + + /* 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; + + /* Conditional expressions. */ + + 0 ? sve_sc1 : sve_sc1; + 0 ? sve_sc1 : sve_sh1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc1 : 0; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? 0 : sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ?: sve_sc1; /* { dg-error {type mismatch in conditional expression} } */ + 0 ? sve_sc_ptr : sve_sc_ptr; + 0 ? sve_sc_ptr : gnu_sc_ptr; + 0 ? gnu_sc_ptr : sve_sc_ptr; + + /* Generic associations. */ + + _Generic (sve_sc1, default: 100); + _Generic (1, svint8_t: 10, default: 20); + + /* Function arguments. */ + + ext_consume_sve_sc (sve_sc1); + ext_consume_sve_sc (sve_sh1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_sve_sc'} } */ + ext_consume_varargs (sve_sc1); /* { dg-error {incompatible type for argument 1 of 'ext_consume_varargs'} } */ + 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 {incompatible types when assigning to type 'svint16_t' from type 'svint8_t'} } */ + + /* Varargs processing. */ + + __builtin_va_list valist; + __builtin_va_arg (valist, svint8_t); + + /* Statement expressions. */ + + ({ sve_sc1; }); + ({ svint8_t another_sve_sc = *sve_sc_ptr; another_sve_sc; }); +} + +/* Function parameters in definitions. */ + +void +old_style (input_sve_sc) /* { dg-error {SVE type 'svint8_t' cannot be passed to an unprototyped function} } */ + svint8_t input_sve_sc; +{ + svint8_t sve_sc1 = input_sve_sc; +} + +void +new_style_param (svint8_t input_sve_sc) +{ + svint8_t sve_sc1 = input_sve_sc; +} + +/* Function return values in definitions. */ + +svint8_t +good_return_sve_sc (svint8_t param) +{ + return param; +} + +svint8_t +bad_return_sve_sc (svint16_t param) +{ + return param; /* { dg-error {incompatible types when returning type 'svint16_t' but 'svint8_t' was expected} } */ +} @@ -15123,6 +15123,21 @@ max_object_size (void) return TYPE_MAX_VALUE (ptrdiff_type_node); } +/* A wrapper around TARGET_VERIFY_TYPE_CONTEXT that makes the silent_p + parameter default to false and that weeds out error_mark_node. */ + +bool +verify_type_context (location_t loc, type_context_kind context, + const_tree type, bool silent_p) +{ + if (type == error_mark_node) + return true; + + gcc_assert (TYPE_P (type)); + return (!targetm.verify_type_context + || targetm.verify_type_context (loc, context, type, silent_p)); +} + #if CHECKING_P namespace selftest { |