1614 lines
85 KiB
Diff
1614 lines
85 KiB
Diff
|
|
This backport contains 5 patchs from gcc main stream tree.
|
||
|
|
The commit id of these patchs list as following in the order of time.
|
||
|
|
|
||
|
|
0001-re-PR-target-88838-SVE-Use-32-bit-WHILELO-in-LP64-mo.patch
|
||
|
|
9b884225bfc609606f9b169b021c4da93feba48e
|
||
|
|
|
||
|
|
0002-C-Avoid-aka-types-that-just-add-tags.patch
|
||
|
|
558798156b41fcbe5ba68b75171708cad135b041
|
||
|
|
|
||
|
|
0003-g-.dg-tree-ssa-pr61034.C-Add-param-max-inline-insns-.patch
|
||
|
|
cfcf3551c432da3a8154ef11a26a4d75655deb3d
|
||
|
|
|
||
|
|
0004-C-Avoid-exposing-internal-details-in-aka-types.patch
|
||
|
|
56898e437a538c7edc0724a3650f5cb81c9d5721
|
||
|
|
|
||
|
|
0005-C-Avoid-exposing-internal-details-in-aka-types.patch
|
||
|
|
10bce48f104de56503b17954ed79f019df3252e3
|
||
|
|
|
||
|
|
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
|
||
|
|
index bf3db074a..2c10743b9 100644
|
||
|
|
--- a/gcc/c-family/c-common.c
|
||
|
|
+++ b/gcc/c-family/c-common.c
|
||
|
|
@@ -48,6 +48,7 @@ along with GCC; see the file COPYING3. If not see
|
||
|
|
#include "gimplify.h"
|
||
|
|
#include "substring-locations.h"
|
||
|
|
#include "spellcheck.h"
|
||
|
|
+#include "c-spellcheck.h"
|
||
|
|
#include "selftest.h"
|
||
|
|
|
||
|
|
cpp_reader *parse_in; /* Declared in c-pragma.h. */
|
||
|
|
@@ -7685,6 +7686,52 @@ set_underlying_type (tree x)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Return true if it is worth exposing the DECL_ORIGINAL_TYPE of TYPE to
|
||
|
|
+ the user in diagnostics, false if it would be better to use TYPE itself.
|
||
|
|
+ TYPE is known to satisfy typedef_variant_p. */
|
||
|
|
+
|
||
|
|
+bool
|
||
|
|
+user_facing_original_type_p (const_tree type)
|
||
|
|
+{
|
||
|
|
+ gcc_assert (typedef_variant_p (type));
|
||
|
|
+ tree decl = TYPE_NAME (type);
|
||
|
|
+
|
||
|
|
+ /* Look through any typedef in "user" code. */
|
||
|
|
+ if (!DECL_IN_SYSTEM_HEADER (decl) && !DECL_IS_BUILTIN (decl))
|
||
|
|
+ return true;
|
||
|
|
+
|
||
|
|
+ /* If the original type is also named and is in the user namespace,
|
||
|
|
+ assume it too is a user-facing type. */
|
||
|
|
+ tree orig_type = DECL_ORIGINAL_TYPE (decl);
|
||
|
|
+ if (tree orig_id = TYPE_IDENTIFIER (orig_type))
|
||
|
|
+ if (!name_reserved_for_implementation_p (IDENTIFIER_POINTER (orig_id)))
|
||
|
|
+ return true;
|
||
|
|
+
|
||
|
|
+ switch (TREE_CODE (orig_type))
|
||
|
|
+ {
|
||
|
|
+ /* Don't look through to an anonymous vector type, since the syntax
|
||
|
|
+ we use for them in diagnostics isn't real C or C++ syntax.
|
||
|
|
+ And if ORIG_TYPE is named but in the implementation namespace,
|
||
|
|
+ TYPE is likely to be more meaningful to the user. */
|
||
|
|
+ case VECTOR_TYPE:
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ /* Don't expose anonymous tag types that are presumably meant to be
|
||
|
|
+ known by their typedef name. Also don't expose tags that are in
|
||
|
|
+ the implementation namespace, such as:
|
||
|
|
+
|
||
|
|
+ typedef struct __foo foo; */
|
||
|
|
+ case RECORD_TYPE:
|
||
|
|
+ case UNION_TYPE:
|
||
|
|
+ case ENUMERAL_TYPE:
|
||
|
|
+ return false;
|
||
|
|
+
|
||
|
|
+ /* Look through to anything else. */
|
||
|
|
+ default:
|
||
|
|
+ return true;
|
||
|
|
+ }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Record the types used by the current global variable declaration
|
||
|
|
being parsed, so that we can decide later to emit their debug info.
|
||
|
|
Those types are in types_used_by_cur_var_decl, and we are going to
|
||
|
|
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
|
||
|
|
index 46b8d265a..73ce7c5df 100644
|
||
|
|
--- a/gcc/c-family/c-common.h
|
||
|
|
+++ b/gcc/c-family/c-common.h
|
||
|
|
@@ -1063,6 +1063,7 @@ extern tree builtin_type_for_size (int, bool);
|
||
|
|
extern void c_common_mark_addressable_vec (tree);
|
||
|
|
|
||
|
|
extern void set_underlying_type (tree);
|
||
|
|
+extern bool user_facing_original_type_p (const_tree);
|
||
|
|
extern void record_types_used_by_current_var_decl (tree);
|
||
|
|
extern vec<tree, va_gc> *make_tree_vector (void);
|
||
|
|
extern void release_tree_vector (vec<tree, va_gc> *);
|
||
|
|
diff --git a/gcc/c/c-objc-common.c b/gcc/c/c-objc-common.c
|
||
|
|
index 2b76737a7..10d72c57d 100644
|
||
|
|
--- a/gcc/c/c-objc-common.c
|
||
|
|
+++ b/gcc/c/c-objc-common.c
|
||
|
|
@@ -28,6 +28,8 @@ along with GCC; see the file COPYING3. If not see
|
||
|
|
#include "langhooks.h"
|
||
|
|
#include "c-objc-common.h"
|
||
|
|
#include "gcc-rich-location.h"
|
||
|
|
+#include "stringpool.h"
|
||
|
|
+#include "attribs.h"
|
||
|
|
|
||
|
|
static bool c_tree_printer (pretty_printer *, text_info *, const char *,
|
||
|
|
int, bool, bool, bool, bool *, const char **);
|
||
|
|
@@ -62,6 +64,122 @@ c_objc_common_init (void)
|
||
|
|
return c_common_init ();
|
||
|
|
}
|
||
|
|
|
||
|
|
+/* Decide whether it's worth saying that TYPE is also known as some other
|
||
|
|
+ type. Return the other type if so, otherwise return TYPE. */
|
||
|
|
+
|
||
|
|
+static tree
|
||
|
|
+get_aka_type (tree type)
|
||
|
|
+{
|
||
|
|
+ if (type == error_mark_node)
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ tree result;
|
||
|
|
+ if (typedef_variant_p (type))
|
||
|
|
+ {
|
||
|
|
+ /* Saying that "foo" is also known as "struct foo" or
|
||
|
|
+ "struct <anonymous>" is unlikely to be useful, since users of
|
||
|
|
+ structure-like types would already know that they're structures.
|
||
|
|
+ The same applies to unions and enums; in general, printing the
|
||
|
|
+ tag is only useful if it has a different name. */
|
||
|
|
+ tree orig_type = DECL_ORIGINAL_TYPE (TYPE_NAME (type));
|
||
|
|
+ tree_code code = TREE_CODE (orig_type);
|
||
|
|
+ tree orig_id = TYPE_IDENTIFIER (orig_type);
|
||
|
|
+ if ((code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
|
||
|
|
+ && (!orig_id || TYPE_IDENTIFIER (type) == orig_id))
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ if (!user_facing_original_type_p (type))
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ result = get_aka_type (orig_type);
|
||
|
|
+ }
|
||
|
|
+ else
|
||
|
|
+ {
|
||
|
|
+ tree canonical = TYPE_CANONICAL (type);
|
||
|
|
+ if (canonical && TREE_CODE (type) != TREE_CODE (canonical))
|
||
|
|
+ return canonical;
|
||
|
|
+
|
||
|
|
+ /* Recursive calls might choose a middle ground between TYPE
|
||
|
|
+ (which has no typedefs stripped) and CANONICAL (which has
|
||
|
|
+ all typedefs stripped). So try to reuse TYPE or CANONICAL if
|
||
|
|
+ convenient, but be prepared to create a new type if necessary. */
|
||
|
|
+ switch (TREE_CODE (type))
|
||
|
|
+ {
|
||
|
|
+ case POINTER_TYPE:
|
||
|
|
+ case REFERENCE_TYPE:
|
||
|
|
+ {
|
||
|
|
+ tree target_type = get_aka_type (TREE_TYPE (type));
|
||
|
|
+
|
||
|
|
+ if (target_type == TREE_TYPE (type))
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ if (canonical && target_type == TREE_TYPE (canonical))
|
||
|
|
+ return canonical;
|
||
|
|
+
|
||
|
|
+ result = (TREE_CODE (type) == POINTER_TYPE
|
||
|
|
+ ? build_pointer_type (target_type)
|
||
|
|
+ : build_reference_type (target_type));
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ case ARRAY_TYPE:
|
||
|
|
+ {
|
||
|
|
+ tree element_type = get_aka_type (TREE_TYPE (type));
|
||
|
|
+ tree index_type = (TYPE_DOMAIN (type)
|
||
|
|
+ ? get_aka_type (TYPE_DOMAIN (type))
|
||
|
|
+ : NULL_TREE);
|
||
|
|
+
|
||
|
|
+ if (element_type == TREE_TYPE (type)
|
||
|
|
+ && index_type == TYPE_DOMAIN (type))
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ if (canonical
|
||
|
|
+ && element_type == TREE_TYPE (canonical)
|
||
|
|
+ && index_type == TYPE_DOMAIN (canonical))
|
||
|
|
+ return canonical;
|
||
|
|
+
|
||
|
|
+ result = build_array_type (element_type, index_type,
|
||
|
|
+ TYPE_TYPELESS_STORAGE (type));
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ case FUNCTION_TYPE:
|
||
|
|
+ {
|
||
|
|
+ tree return_type = get_aka_type (TREE_TYPE (type));
|
||
|
|
+
|
||
|
|
+ tree args = TYPE_ARG_TYPES (type);
|
||
|
|
+ if (args == error_mark_node)
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ auto_vec<tree, 32> arg_types;
|
||
|
|
+ bool type_ok_p = true;
|
||
|
|
+ while (args && args != void_list_node)
|
||
|
|
+ {
|
||
|
|
+ tree arg_type = get_aka_type (TREE_VALUE (args));
|
||
|
|
+ arg_types.safe_push (arg_type);
|
||
|
|
+ type_ok_p &= (arg_type == TREE_VALUE (args));
|
||
|
|
+ args = TREE_CHAIN (args);
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ if (type_ok_p && return_type == TREE_TYPE (type))
|
||
|
|
+ return type;
|
||
|
|
+
|
||
|
|
+ unsigned int i;
|
||
|
|
+ tree arg_type;
|
||
|
|
+ FOR_EACH_VEC_ELT_REVERSE (arg_types, i, arg_type)
|
||
|
|
+ args = tree_cons (NULL_TREE, arg_type, args);
|
||
|
|
+ result = build_function_type (return_type, args);
|
||
|
|
+ break;
|
||
|
|
+ }
|
||
|
|
+
|
||
|
|
+ default:
|
||
|
|
+ return canonical ? canonical : type;
|
||
|
|
+ }
|
||
|
|
+ }
|
||
|
|
+ return build_type_attribute_qual_variant (result, TYPE_ATTRIBUTES (type),
|
||
|
|
+ TYPE_QUALS (type));
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
/* Print T to CPP. */
|
||
|
|
|
||
|
|
static void
|
||
|
|
@@ -83,11 +201,12 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
|
||
|
|
stripped version. But sometimes the stripped version looks
|
||
|
|
exactly the same, so we don't want it after all. To avoid
|
||
|
|
printing it in that case, we play ugly obstack games. */
|
||
|
|
- if (TYPE_CANONICAL (t) && t != TYPE_CANONICAL (t))
|
||
|
|
+ tree aka_type = get_aka_type (t);
|
||
|
|
+ if (aka_type != t)
|
||
|
|
{
|
||
|
|
c_pretty_printer cpp2;
|
||
|
|
/* Print the stripped version into a temporary printer. */
|
||
|
|
- cpp2.type_id (TYPE_CANONICAL (t));
|
||
|
|
+ cpp2.type_id (aka_type);
|
||
|
|
struct obstack *ob2 = cpp2.buffer->obstack;
|
||
|
|
/* Get the stripped version from the temporary printer. */
|
||
|
|
const char *aka = (char *) obstack_base (ob2);
|
||
|
|
@@ -107,7 +226,7 @@ print_type (c_pretty_printer *cpp, tree t, bool *quoted)
|
||
|
|
pp_c_whitespace (cpp);
|
||
|
|
if (*quoted)
|
||
|
|
pp_begin_quote (cpp, pp_show_color (cpp));
|
||
|
|
- cpp->type_id (TYPE_CANONICAL (t));
|
||
|
|
+ cpp->type_id (aka_type);
|
||
|
|
if (*quoted)
|
||
|
|
pp_end_quote (cpp, pp_show_color (cpp));
|
||
|
|
pp_right_brace (cpp);
|
||
|
|
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
|
||
|
|
index 4bba1887f..e802dcbeb 100644
|
||
|
|
--- a/gcc/cp/cp-tree.h
|
||
|
|
+++ b/gcc/cp/cp-tree.h
|
||
|
|
@@ -5662,6 +5662,13 @@ enum auto_deduction_context
|
||
|
|
#define TFF_NO_TEMPLATE_BINDINGS (1 << 13)
|
||
|
|
#define TFF_POINTER (1 << 14)
|
||
|
|
|
||
|
|
+/* These constants can be used as bit flags to control strip_typedefs.
|
||
|
|
+
|
||
|
|
+ STF_USER_VISIBLE: use heuristics to try to avoid stripping user-facing
|
||
|
|
+ aliases of internal details. This is intended for diagnostics,
|
||
|
|
+ where it should (for example) give more useful "aka" types. */
|
||
|
|
+const unsigned int STF_USER_VISIBLE = 1U;
|
||
|
|
+
|
||
|
|
/* Returns the TEMPLATE_DECL associated to a TEMPLATE_TEMPLATE_PARM
|
||
|
|
node. */
|
||
|
|
#define TEMPLATE_TEMPLATE_PARM_TEMPLATE_DECL(NODE) \
|
||
|
|
@@ -7221,8 +7228,10 @@ extern int zero_init_p (const_tree);
|
||
|
|
extern bool check_abi_tag_redeclaration (const_tree, const_tree,
|
||
|
|
const_tree);
|
||
|
|
extern bool check_abi_tag_args (tree, tree);
|
||
|
|
-extern tree strip_typedefs (tree, bool * = NULL);
|
||
|
|
-extern tree strip_typedefs_expr (tree, bool * = NULL);
|
||
|
|
+extern tree strip_typedefs (tree, bool * = NULL,
|
||
|
|
+ unsigned int = 0);
|
||
|
|
+extern tree strip_typedefs_expr (tree, bool * = NULL,
|
||
|
|
+ unsigned int = 0);
|
||
|
|
extern tree copy_binfo (tree, tree, tree,
|
||
|
|
tree *, int);
|
||
|
|
extern int member_p (const_tree);
|
||
|
|
diff --git a/gcc/cp/error.c b/gcc/cp/error.c
|
||
|
|
index 4a0aed2b7..5beaf2dc1 100644
|
||
|
|
--- a/gcc/cp/error.c
|
||
|
|
+++ b/gcc/cp/error.c
|
||
|
|
@@ -408,7 +408,7 @@ dump_template_bindings (cxx_pretty_printer *pp, tree parms, tree args,
|
||
|
|
pop_deferring_access_checks ();
|
||
|
|
/* Strip typedefs. We can't just use TFF_CHASE_TYPEDEF because
|
||
|
|
pp_simple_type_specifier doesn't know about it. */
|
||
|
|
- t = strip_typedefs (t);
|
||
|
|
+ t = strip_typedefs (t, NULL, STF_USER_VISIBLE);
|
||
|
|
dump_type (pp, t, TFF_PLAIN_IDENTIFIER);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
@@ -447,7 +447,11 @@ dump_type (cxx_pretty_printer *pp, tree t, int flags)
|
||
|
|
|| DECL_SELF_REFERENCE_P (decl)
|
||
|
|
|| (!flag_pretty_templates
|
||
|
|
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)))
|
||
|
|
- t = strip_typedefs (t);
|
||
|
|
+ {
|
||
|
|
+ unsigned int stf_flags = (!(pp->flags & pp_c_flag_gnu_v3)
|
||
|
|
+ ? STF_USER_VISIBLE : 0);
|
||
|
|
+ t = strip_typedefs (t, NULL, stf_flags);
|
||
|
|
+ }
|
||
|
|
else if (alias_template_specialization_p (t))
|
||
|
|
{
|
||
|
|
dump_alias_template_specialization (pp, t, flags);
|
||
|
|
@@ -3193,7 +3197,7 @@ type_to_string (tree typ, int verbose, bool postprocessed, bool *quote,
|
||
|
|
&& !uses_template_parms (typ))
|
||
|
|
{
|
||
|
|
int aka_start, aka_len; char *p;
|
||
|
|
- tree aka = strip_typedefs (typ);
|
||
|
|
+ tree aka = strip_typedefs (typ, NULL, STF_USER_VISIBLE);
|
||
|
|
if (quote && *quote)
|
||
|
|
pp_end_quote (cxx_pp, show_color);
|
||
|
|
pp_string (cxx_pp, " {aka");
|
||
|
|
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
|
||
|
|
index 3f3583c82..6a1f760ba 100644
|
||
|
|
--- a/gcc/cp/tree.c
|
||
|
|
+++ b/gcc/cp/tree.c
|
||
|
|
@@ -1421,7 +1421,10 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
|
||
|
|
return cp_build_type_attribute_variant (result, new_attribs);
|
||
|
|
}
|
||
|
|
|
||
|
|
-/* Builds a qualified variant of T that is not a typedef variant.
|
||
|
|
+/* Builds a qualified variant of T that is either not a typedef variant
|
||
|
|
+ (the default behavior) or not a typedef variant of a user-facing type
|
||
|
|
+ (if FLAGS contains STF_USER_FACING).
|
||
|
|
+
|
||
|
|
E.g. consider the following declarations:
|
||
|
|
typedef const int ConstInt;
|
||
|
|
typedef ConstInt* PtrConstInt;
|
||
|
|
@@ -1446,7 +1449,7 @@ apply_identity_attributes (tree result, tree attribs, bool *remove_attributes)
|
||
|
|
stripped. */
|
||
|
|
|
||
|
|
tree
|
||
|
|
-strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
+strip_typedefs (tree t, bool *remove_attributes, unsigned int flags)
|
||
|
|
{
|
||
|
|
tree result = NULL, type = NULL, t0 = NULL;
|
||
|
|
|
||
|
|
@@ -1461,7 +1464,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
for (; t; t = TREE_CHAIN (t))
|
||
|
|
{
|
||
|
|
gcc_assert (!TREE_PURPOSE (t));
|
||
|
|
- tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes);
|
||
|
|
+ tree elt = strip_typedefs (TREE_VALUE (t), remove_attributes, flags);
|
||
|
|
if (elt != TREE_VALUE (t))
|
||
|
|
changed = true;
|
||
|
|
vec_safe_push (vec, elt);
|
||
|
|
@@ -1485,28 +1488,29 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
switch (TREE_CODE (t))
|
||
|
|
{
|
||
|
|
case POINTER_TYPE:
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
result = build_pointer_type (type);
|
||
|
|
break;
|
||
|
|
case REFERENCE_TYPE:
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
result = cp_build_reference_type (type, TYPE_REF_IS_RVALUE (t));
|
||
|
|
break;
|
||
|
|
case OFFSET_TYPE:
|
||
|
|
- t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes);
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
+ t0 = strip_typedefs (TYPE_OFFSET_BASETYPE (t), remove_attributes, flags);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
result = build_offset_type (t0, type);
|
||
|
|
break;
|
||
|
|
case RECORD_TYPE:
|
||
|
|
if (TYPE_PTRMEMFUNC_P (t))
|
||
|
|
{
|
||
|
|
- t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t), remove_attributes);
|
||
|
|
+ t0 = strip_typedefs (TYPE_PTRMEMFUNC_FN_TYPE (t),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
result = build_ptrmemfunc_type (t0);
|
||
|
|
}
|
||
|
|
break;
|
||
|
|
case ARRAY_TYPE:
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
- t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
+ t0 = strip_typedefs (TYPE_DOMAIN (t), remove_attributes, flags);
|
||
|
|
result = build_cplus_array_type (type, t0);
|
||
|
|
break;
|
||
|
|
case FUNCTION_TYPE:
|
||
|
|
@@ -1525,7 +1529,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
&& (TYPE_ATTRIBUTES (t) || TYPE_USER_ALIGN (t)))
|
||
|
|
is_variant = true;
|
||
|
|
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
tree canon_spec = (flag_noexcept_type
|
||
|
|
? canonical_eh_spec (TYPE_RAISES_EXCEPTIONS (t))
|
||
|
|
: NULL_TREE);
|
||
|
|
@@ -1539,7 +1543,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
if (arg_node == void_list_node)
|
||
|
|
break;
|
||
|
|
arg_type = strip_typedefs (TREE_VALUE (arg_node),
|
||
|
|
- remove_attributes);
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
gcc_assert (arg_type);
|
||
|
|
if (arg_type == TREE_VALUE (arg_node) && !changed)
|
||
|
|
continue;
|
||
|
|
@@ -1603,9 +1607,10 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
tree arg = TREE_VEC_ELT (args, i);
|
||
|
|
tree strip_arg;
|
||
|
|
if (TYPE_P (arg))
|
||
|
|
- strip_arg = strip_typedefs (arg, remove_attributes);
|
||
|
|
+ strip_arg = strip_typedefs (arg, remove_attributes, flags);
|
||
|
|
else
|
||
|
|
- strip_arg = strip_typedefs_expr (arg, remove_attributes);
|
||
|
|
+ strip_arg = strip_typedefs_expr (arg, remove_attributes,
|
||
|
|
+ flags);
|
||
|
|
TREE_VEC_ELT (new_args, i) = strip_arg;
|
||
|
|
if (strip_arg != arg)
|
||
|
|
changed = true;
|
||
|
|
@@ -1621,7 +1626,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
else
|
||
|
|
ggc_free (new_args);
|
||
|
|
}
|
||
|
|
- tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes);
|
||
|
|
+ tree ctx = strip_typedefs (TYPE_CONTEXT (t), remove_attributes, flags);
|
||
|
|
if (!changed && ctx == TYPE_CONTEXT (t) && !typedef_variant_p (t))
|
||
|
|
return t;
|
||
|
|
tree name = fullname;
|
||
|
|
@@ -1634,7 +1639,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
break;
|
||
|
|
case DECLTYPE_TYPE:
|
||
|
|
result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t),
|
||
|
|
- remove_attributes);
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
if (result == DECLTYPE_TYPE_EXPR (t))
|
||
|
|
result = NULL_TREE;
|
||
|
|
else
|
||
|
|
@@ -1644,7 +1649,8 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
tf_none));
|
||
|
|
break;
|
||
|
|
case UNDERLYING_TYPE:
|
||
|
|
- type = strip_typedefs (UNDERLYING_TYPE_TYPE (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (UNDERLYING_TYPE_TYPE (t),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
result = finish_underlying_type (type);
|
||
|
|
break;
|
||
|
|
default:
|
||
|
|
@@ -1655,15 +1661,18 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
{
|
||
|
|
if (typedef_variant_p (t))
|
||
|
|
{
|
||
|
|
- /* Explicitly get the underlying type, as TYPE_MAIN_VARIANT doesn't
|
||
|
|
- strip typedefs with attributes. */
|
||
|
|
- result = TYPE_MAIN_VARIANT (DECL_ORIGINAL_TYPE (TYPE_NAME (t)));
|
||
|
|
- result = strip_typedefs (result);
|
||
|
|
+ if ((flags & STF_USER_VISIBLE)
|
||
|
|
+ && !user_facing_original_type_p (t))
|
||
|
|
+ return t;
|
||
|
|
+ result = strip_typedefs (DECL_ORIGINAL_TYPE (TYPE_NAME (t)),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
}
|
||
|
|
else
|
||
|
|
result = TYPE_MAIN_VARIANT (t);
|
||
|
|
}
|
||
|
|
- gcc_assert (!typedef_variant_p (result));
|
||
|
|
+ gcc_assert (!typedef_variant_p (result)
|
||
|
|
+ || ((flags & STF_USER_VISIBLE)
|
||
|
|
+ && !user_facing_original_type_p (result)));
|
||
|
|
|
||
|
|
if (COMPLETE_TYPE_P (result) && !COMPLETE_TYPE_P (t))
|
||
|
|
/* If RESULT is complete and T isn't, it's likely the case that T
|
||
|
|
@@ -1712,7 +1721,7 @@ strip_typedefs (tree t, bool *remove_attributes)
|
||
|
|
sizeof(TT) is replaced by sizeof(T). */
|
||
|
|
|
||
|
|
tree
|
||
|
|
-strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
+strip_typedefs_expr (tree t, bool *remove_attributes, unsigned int flags)
|
||
|
|
{
|
||
|
|
unsigned i,n;
|
||
|
|
tree r, type, *ops;
|
||
|
|
@@ -1729,7 +1738,7 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
/* Some expressions have type operands, so let's handle types here rather
|
||
|
|
than check TYPE_P in multiple places below. */
|
||
|
|
if (TYPE_P (t))
|
||
|
|
- return strip_typedefs (t, remove_attributes);
|
||
|
|
+ return strip_typedefs (t, remove_attributes, flags);
|
||
|
|
|
||
|
|
code = TREE_CODE (t);
|
||
|
|
switch (code)
|
||
|
|
@@ -1743,8 +1752,10 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
|
||
|
|
case TRAIT_EXPR:
|
||
|
|
{
|
||
|
|
- tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t), remove_attributes);
|
||
|
|
- tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t), remove_attributes);
|
||
|
|
+ tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
+ tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
if (type1 == TRAIT_EXPR_TYPE1 (t)
|
||
|
|
&& type2 == TRAIT_EXPR_TYPE2 (t))
|
||
|
|
return t;
|
||
|
|
@@ -1761,7 +1772,8 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
tree it;
|
||
|
|
for (it = t; it; it = TREE_CHAIN (it))
|
||
|
|
{
|
||
|
|
- tree val = strip_typedefs_expr (TREE_VALUE (it), remove_attributes);
|
||
|
|
+ tree val = strip_typedefs_expr (TREE_VALUE (it),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
vec_safe_push (vec, val);
|
||
|
|
if (val != TREE_VALUE (it))
|
||
|
|
changed = true;
|
||
|
|
@@ -1788,7 +1800,7 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
for (i = 0; i < n; ++i)
|
||
|
|
{
|
||
|
|
tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i),
|
||
|
|
- remove_attributes);
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
vec->quick_push (op);
|
||
|
|
if (op != TREE_VEC_ELT (t, i))
|
||
|
|
changed = true;
|
||
|
|
@@ -1813,18 +1825,19 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
vec<constructor_elt, va_gc> *vec
|
||
|
|
= vec_safe_copy (CONSTRUCTOR_ELTS (t));
|
||
|
|
n = CONSTRUCTOR_NELTS (t);
|
||
|
|
- type = strip_typedefs (TREE_TYPE (t), remove_attributes);
|
||
|
|
+ type = strip_typedefs (TREE_TYPE (t), remove_attributes, flags);
|
||
|
|
for (i = 0; i < n; ++i)
|
||
|
|
{
|
||
|
|
constructor_elt *e = &(*vec)[i];
|
||
|
|
- tree op = strip_typedefs_expr (e->value, remove_attributes);
|
||
|
|
+ tree op = strip_typedefs_expr (e->value, remove_attributes, flags);
|
||
|
|
if (op != e->value)
|
||
|
|
{
|
||
|
|
changed = true;
|
||
|
|
e->value = op;
|
||
|
|
}
|
||
|
|
gcc_checking_assert
|
||
|
|
- (e->index == strip_typedefs_expr (e->index, remove_attributes));
|
||
|
|
+ (e->index == strip_typedefs_expr (e->index, remove_attributes,
|
||
|
|
+ flags));
|
||
|
|
}
|
||
|
|
|
||
|
|
if (!changed && type == TREE_TYPE (t))
|
||
|
|
@@ -1868,12 +1881,13 @@ strip_typedefs_expr (tree t, bool *remove_attributes)
|
||
|
|
case REINTERPRET_CAST_EXPR:
|
||
|
|
case CAST_EXPR:
|
||
|
|
case NEW_EXPR:
|
||
|
|
- type = strip_typedefs (type, remove_attributes);
|
||
|
|
+ type = strip_typedefs (type, remove_attributes, flags);
|
||
|
|
/* fallthrough */
|
||
|
|
|
||
|
|
default:
|
||
|
|
for (i = 0; i < n; ++i)
|
||
|
|
- ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i), remove_attributes);
|
||
|
|
+ ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i),
|
||
|
|
+ remove_attributes, flags);
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
|
||
|
|
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5.h b/gcc/testsuite/g++.dg/diagnostic/aka5.h
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..0c7404d76
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/g++.dg/diagnostic/aka5.h
|
||
|
|
@@ -0,0 +1,22 @@
|
||
|
|
+#ifdef IS_SYSTEM_HEADER
|
||
|
|
+#pragma GCC system_header
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
+typedef enum __internal_enum { A, B } user_enum;
|
||
|
|
+typedef user_enum *user_enum_ptr;
|
||
|
|
+
|
||
|
|
+typedef struct __internal_struct { int i; } user_struct;
|
||
|
|
+typedef user_struct user_struct_copy;
|
||
|
|
+typedef user_struct *user_struct_ptr;
|
||
|
|
+
|
||
|
|
+typedef union __internal_union { int i; } user_union;
|
||
|
|
+typedef user_union user_union_copy;
|
||
|
|
+typedef user_union *user_union_ptr;
|
||
|
|
+
|
||
|
|
+typedef unsigned int user_vector __attribute__((__vector_size__(16)));
|
||
|
|
+typedef user_vector user_vector_copy;
|
||
|
|
+typedef user_vector *user_vector_ptr;
|
||
|
|
+
|
||
|
|
+typedef int user_int;
|
||
|
|
+typedef user_int user_int_copy;
|
||
|
|
+typedef user_int *user_int_ptr;
|
||
|
|
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5a.C b/gcc/testsuite/g++.dg/diagnostic/aka5a.C
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..e9d4c02f6
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/g++.dg/diagnostic/aka5a.C
|
||
|
|
@@ -0,0 +1,127 @@
|
||
|
|
+#define IS_SYSTEM_HEADER
|
||
|
|
+#include "aka5.h"
|
||
|
|
+
|
||
|
|
+typedef user_enum user_enum_copy;
|
||
|
|
+
|
||
|
|
+struct s { int i; };
|
||
|
|
+
|
||
|
|
+user_enum ue1;
|
||
|
|
+user_enum_copy ue2;
|
||
|
|
+user_enum_ptr ue_ptr1;
|
||
|
|
+user_enum *ue_ptr2;
|
||
|
|
+const user_enum *const_ue_ptr1;
|
||
|
|
+const user_enum_copy *const_ue_ptr2;
|
||
|
|
+volatile user_enum *volatile_ue_ptr1;
|
||
|
|
+volatile user_enum_copy *volatile_ue_ptr2;
|
||
|
|
+user_enum (*ue_array_ptr1)[10];
|
||
|
|
+user_enum_copy (*ue_array_ptr2)[10];
|
||
|
|
+user_enum (*ue_fn_ptr1) (void);
|
||
|
|
+void (*ue_fn_ptr2) (user_enum);
|
||
|
|
+void (*ue_fn_ptr3) (user_enum, ...);
|
||
|
|
+user_enum_copy (*ue_fn_ptr4) (void);
|
||
|
|
+void (*ue_fn_ptr5) (user_enum_copy);
|
||
|
|
+void (*ue_fn_ptr6) (user_enum_copy, ...);
|
||
|
|
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
|
||
|
|
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+user_struct us1;
|
||
|
|
+user_struct_copy us2;
|
||
|
|
+user_struct_ptr us_ptr1;
|
||
|
|
+user_struct *us_ptr2;
|
||
|
|
+const user_struct *const_us_ptr1;
|
||
|
|
+const user_struct_copy *const_us_ptr2;
|
||
|
|
+
|
||
|
|
+user_union uu1;
|
||
|
|
+user_union_copy uu2;
|
||
|
|
+user_union_ptr uu_ptr1;
|
||
|
|
+user_union *uu_ptr2;
|
||
|
|
+const user_union *const_uu_ptr1;
|
||
|
|
+const user_union_copy *const_uu_ptr2;
|
||
|
|
+
|
||
|
|
+user_vector uv1;
|
||
|
|
+user_vector_copy uv2;
|
||
|
|
+user_vector_ptr uv_ptr1;
|
||
|
|
+user_vector *uv_ptr2;
|
||
|
|
+const user_vector *const_uv_ptr1;
|
||
|
|
+const user_vector_copy *const_uv_ptr2;
|
||
|
|
+
|
||
|
|
+user_int ui1;
|
||
|
|
+user_int_copy ui2;
|
||
|
|
+user_int_ptr ui_ptr1;
|
||
|
|
+user_int *ui_ptr2;
|
||
|
|
+const user_int *const_ui_ptr1;
|
||
|
|
+const user_int_copy *const_ui_ptr2;
|
||
|
|
+volatile user_int *volatile_ui_ptr1;
|
||
|
|
+volatile user_int_copy *volatile_ui_ptr2;
|
||
|
|
+user_int (*ui_array_ptr1)[10];
|
||
|
|
+user_int_copy (*ui_array_ptr2)[10];
|
||
|
|
+user_int (*ui_fn_ptr1) (void);
|
||
|
|
+void (*ui_fn_ptr2) (user_int);
|
||
|
|
+void (*ui_fn_ptr3) (user_int, ...);
|
||
|
|
+user_int_copy (*ui_fn_ptr4) (void);
|
||
|
|
+void (*ui_fn_ptr5) (user_int_copy);
|
||
|
|
+void (*ui_fn_ptr6) (user_int_copy, ...);
|
||
|
|
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
|
||
|
|
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+void f (s s1)
|
||
|
|
+{
|
||
|
|
+ ue1 = s1; // { dg-error {cannot convert 's' to 'user_enum' in assignment} }
|
||
|
|
+ ue2 = s1; // { dg-error {cannot convert 's' to 'user_enum_copy' {aka 'user_enum'} in assignment} }
|
||
|
|
+ ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_ptr' {aka 'user_enum\*'} in assignment} }
|
||
|
|
+ ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum\*' in assignment} }
|
||
|
|
+ const_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_enum\*' in assignment} }
|
||
|
|
+ const_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_enum_copy\*' {aka 'const user_enum\*'} in assignment} }
|
||
|
|
+ volatile_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_enum\*' in assignment} }
|
||
|
|
+ volatile_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_enum_copy\*' {aka 'volatile user_enum\*'} in assignment} }
|
||
|
|
+ ue_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(\*\)\[10\]' in assignment} }
|
||
|
|
+ ue_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(\*\)\[10\]' {aka 'user_enum \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(\*\)\(\)' in assignment} }
|
||
|
|
+ ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum\)' in assignment} }
|
||
|
|
+ ue_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum, \.\.\.\)' in assignment} }
|
||
|
|
+ ue_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(\*\)\(\)' {aka 'user_enum \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(user_enum\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(user_enum, \.\.\.\)'} in assignment} }
|
||
|
|
+ unsafe_ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' in assignment} }
|
||
|
|
+ unsafe_ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+
|
||
|
|
+ us1 = s1; // { dg-error {no match for 'operator=' in 'us1 = s1' \(operand types are 'user_struct' and 's'\)} }
|
||
|
|
+ us2 = s1; // { dg-error {no match for 'operator=' in 'us2 = s1' \(operand types are 'user_struct_copy' {aka 'user_struct'} and 's'\)} }
|
||
|
|
+ us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct_ptr' {aka 'user_struct\*'} in assignment} }
|
||
|
|
+ us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct\*' in assignment} }
|
||
|
|
+ const_us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_struct\*' in assignment} }
|
||
|
|
+ const_us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_struct_copy\*' {aka 'const user_struct\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ uu1 = s1; // { dg-error {no match for 'operator=' in 'uu1 = s1' \(operand types are 'user_union' and 's'\)} }
|
||
|
|
+ uu2 = s1; // { dg-error {no match for 'operator=' in 'uu2 = s1' \(operand types are 'user_union_copy' {aka 'user_union'} and 's'\)} }
|
||
|
|
+ uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_union_ptr' {aka 'user_union\*'} in assignment} }
|
||
|
|
+ uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_union\*' in assignment} }
|
||
|
|
+ const_uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_union\*' in assignment} }
|
||
|
|
+ const_uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_union_copy\*' {aka 'const user_union\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ uv1 = s1; // { dg-error {cannot convert 's' to 'user_vector' in assignment} }
|
||
|
|
+ uv2 = s1; // { dg-error {cannot convert 's' to 'user_vector_copy' {aka 'user_vector'} in assignment} }
|
||
|
|
+ uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector_ptr' {aka 'user_vector\*'} in assignment} }
|
||
|
|
+ uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector\*' in assignment} }
|
||
|
|
+ const_uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_vector\*' in assignment} }
|
||
|
|
+ const_uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_vector_copy\*' {aka 'const user_vector\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ ui1 = s1; // { dg-error {cannot convert 's' to 'user_int' {aka 'int'} in assignment} }
|
||
|
|
+ ui2 = s1; // { dg-error {cannot convert 's' to 'user_int_copy' {aka 'int'} in assignment} }
|
||
|
|
+ ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_ptr' {aka 'int\*'} in assignment} }
|
||
|
|
+ ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int\*' {aka 'int\*'} in assignment} }
|
||
|
|
+ const_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_int\*' {aka 'const int\*'} in assignment} }
|
||
|
|
+ const_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_int_copy\*' {aka 'const int\*'} in assignment} }
|
||
|
|
+ volatile_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_int\*' {aka 'volatile int\*'} in assignment} }
|
||
|
|
+ volatile_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_int_copy\*' {aka 'volatile int\*'} in assignment} }
|
||
|
|
+ ui_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ui_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} }
|
||
|
|
+ unsafe_ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+ unsafe_ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/g++.dg/diagnostic/aka5b.C b/gcc/testsuite/g++.dg/diagnostic/aka5b.C
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..6942be3ee
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/g++.dg/diagnostic/aka5b.C
|
||
|
|
@@ -0,0 +1,127 @@
|
||
|
|
+#include "aka5.h"
|
||
|
|
+
|
||
|
|
+typedef user_enum user_enum_copy;
|
||
|
|
+
|
||
|
|
+struct s { int i; };
|
||
|
|
+
|
||
|
|
+user_enum ue1;
|
||
|
|
+user_enum_copy ue2;
|
||
|
|
+user_enum_ptr ue_ptr1;
|
||
|
|
+user_enum *ue_ptr2;
|
||
|
|
+const user_enum *const_ue_ptr1;
|
||
|
|
+const user_enum_copy *const_ue_ptr2;
|
||
|
|
+volatile user_enum *volatile_ue_ptr1;
|
||
|
|
+volatile user_enum_copy *volatile_ue_ptr2;
|
||
|
|
+user_enum (*ue_array_ptr1)[10];
|
||
|
|
+user_enum_copy (*ue_array_ptr2)[10];
|
||
|
|
+user_enum (*ue_fn_ptr1) (void);
|
||
|
|
+void (*ue_fn_ptr2) (user_enum);
|
||
|
|
+void (*ue_fn_ptr3) (user_enum, ...);
|
||
|
|
+user_enum_copy (*ue_fn_ptr4) (void);
|
||
|
|
+void (*ue_fn_ptr5) (user_enum_copy);
|
||
|
|
+void (*ue_fn_ptr6) (user_enum_copy, ...);
|
||
|
|
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
|
||
|
|
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+user_struct us1;
|
||
|
|
+user_struct_copy us2;
|
||
|
|
+user_struct_ptr us_ptr1;
|
||
|
|
+user_struct *us_ptr2;
|
||
|
|
+const user_struct *const_us_ptr1;
|
||
|
|
+const user_struct_copy *const_us_ptr2;
|
||
|
|
+
|
||
|
|
+user_union uu1;
|
||
|
|
+user_union_copy uu2;
|
||
|
|
+user_union_ptr uu_ptr1;
|
||
|
|
+user_union *uu_ptr2;
|
||
|
|
+const user_union *const_uu_ptr1;
|
||
|
|
+const user_union_copy *const_uu_ptr2;
|
||
|
|
+
|
||
|
|
+user_vector uv1;
|
||
|
|
+user_vector_copy uv2;
|
||
|
|
+user_vector_ptr uv_ptr1;
|
||
|
|
+user_vector *uv_ptr2;
|
||
|
|
+const user_vector *const_uv_ptr1;
|
||
|
|
+const user_vector_copy *const_uv_ptr2;
|
||
|
|
+
|
||
|
|
+user_int ui1;
|
||
|
|
+user_int_copy ui2;
|
||
|
|
+user_int_ptr ui_ptr1;
|
||
|
|
+user_int *ui_ptr2;
|
||
|
|
+const user_int *const_ui_ptr1;
|
||
|
|
+const user_int_copy *const_ui_ptr2;
|
||
|
|
+volatile user_int *volatile_ui_ptr1;
|
||
|
|
+volatile user_int_copy *volatile_ui_ptr2;
|
||
|
|
+user_int (*ui_array_ptr1)[10];
|
||
|
|
+user_int_copy (*ui_array_ptr2)[10];
|
||
|
|
+user_int (*ui_fn_ptr1) (void);
|
||
|
|
+void (*ui_fn_ptr2) (user_int);
|
||
|
|
+void (*ui_fn_ptr3) (user_int, ...);
|
||
|
|
+user_int_copy (*ui_fn_ptr4) (void);
|
||
|
|
+void (*ui_fn_ptr5) (user_int_copy);
|
||
|
|
+void (*ui_fn_ptr6) (user_int_copy, ...);
|
||
|
|
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
|
||
|
|
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+void f (s s1)
|
||
|
|
+{
|
||
|
|
+ ue1 = s1; // { dg-error {cannot convert 's' to 'user_enum' {aka '__internal_enum'} in assignment} }
|
||
|
|
+ ue2 = s1; // { dg-error {cannot convert 's' to 'user_enum_copy' {aka '__internal_enum'} in assignment} }
|
||
|
|
+ ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_ptr' {aka '__internal_enum\*'} in assignment} }
|
||
|
|
+ ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum\*' {aka '__internal_enum\*'} in assignment} }
|
||
|
|
+ const_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_enum\*' {aka 'const __internal_enum\*'} in assignment} }
|
||
|
|
+ const_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_enum_copy\*' {aka 'const __internal_enum\*'} in assignment} }
|
||
|
|
+ volatile_ue_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_enum\*' {aka 'volatile __internal_enum\*'} in assignment} }
|
||
|
|
+ volatile_ue_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_enum_copy\*' {aka 'volatile __internal_enum\*'} in assignment} }
|
||
|
|
+ ue_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(\*\)\[10\]' {aka '__internal_enum \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ue_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(\*\)\[10\]' {aka '__internal_enum \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(\*\)\(\)' {aka '__internal_enum \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum\)' {aka 'void \(\*\)\(__internal_enum\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum, \.\.\.\)' {aka 'void \(\*\)\(__internal_enum, \.\.\.\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(\*\)\(\)' {aka '__internal_enum \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(__internal_enum\)'} in assignment} }
|
||
|
|
+ ue_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(__internal_enum, \.\.\.\)'} in assignment} }
|
||
|
|
+ unsafe_ue_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka '__internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+ unsafe_ue_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka '__internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+
|
||
|
|
+ us1 = s1; // { dg-error {no match for 'operator=' in 'us1 = s1' \(operand types are 'user_struct' {aka '__internal_struct'} and 's'\)} }
|
||
|
|
+ us2 = s1; // { dg-error {no match for 'operator=' in 'us2 = s1' \(operand types are 'user_struct_copy' {aka '__internal_struct'} and 's'\)} }
|
||
|
|
+ us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct_ptr' {aka '__internal_struct\*'} in assignment} }
|
||
|
|
+ us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_struct\*' {aka '__internal_struct\*'} in assignment} }
|
||
|
|
+ const_us_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_struct\*' {aka 'const __internal_struct\*'} in assignment} }
|
||
|
|
+ const_us_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_struct_copy\*' {aka 'const __internal_struct\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ uu1 = s1; // { dg-error {no match for 'operator=' in 'uu1 = s1' \(operand types are 'user_union' {aka '__internal_union'} and 's'\)} }
|
||
|
|
+ uu2 = s1; // { dg-error {no match for 'operator=' in 'uu2 = s1' \(operand types are 'user_union_copy' {aka '__internal_union'} and 's'\)} }
|
||
|
|
+ uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_union_ptr' {aka '__internal_union\*'} in assignment} }
|
||
|
|
+ uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_union\*' {aka '__internal_union\*'} in assignment} }
|
||
|
|
+ const_uu_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_union\*' {aka 'const __internal_union\*'} in assignment} }
|
||
|
|
+ const_uu_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_union_copy\*' {aka 'const __internal_union\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ uv1 = s1; // { dg-error {cannot convert 's' to 'user_vector' {aka '__vector\([48]\) unsigned int'} in assignment} }
|
||
|
|
+ uv2 = s1; // { dg-error {cannot convert 's' to 'user_vector_copy' {aka '__vector\([48]\) unsigned int'} in assignment} }
|
||
|
|
+ uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector_ptr' {aka '__vector\([48]\) unsigned int\*'} in assignment} }
|
||
|
|
+ uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_vector\*' {aka '__vector\([48]\) unsigned int\*'} in assignment} }
|
||
|
|
+ const_uv_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_vector\*' {aka 'const __vector\([48]\) unsigned int\*'} in assignment} }
|
||
|
|
+ const_uv_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_vector_copy\*' {aka 'const __vector\([48]\) unsigned int\*'} in assignment} }
|
||
|
|
+
|
||
|
|
+ ui1 = s1; // { dg-error {cannot convert 's' to 'user_int' {aka 'int'} in assignment} }
|
||
|
|
+ ui2 = s1; // { dg-error {cannot convert 's' to 'user_int_copy' {aka 'int'} in assignment} }
|
||
|
|
+ ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_ptr' {aka 'int\*'} in assignment} }
|
||
|
|
+ ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int\*' {aka 'int\*'} in assignment} }
|
||
|
|
+ const_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'const user_int\*' {aka 'const int\*'} in assignment} }
|
||
|
|
+ const_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'const user_int_copy\*' {aka 'const int\*'} in assignment} }
|
||
|
|
+ volatile_ui_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_int\*' {aka 'volatile int\*'} in assignment} }
|
||
|
|
+ volatile_ui_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'volatile user_int_copy\*' {aka 'volatile int\*'} in assignment} }
|
||
|
|
+ ui_array_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ui_array_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} in assignment} }
|
||
|
|
+ ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr3 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr4 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(\*\)\(\)' {aka 'int \(\*\)\(\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr5 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} in assignment} }
|
||
|
|
+ ui_fn_ptr6 = &s1; // { dg-error {cannot convert 's\*' to 'void \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} in assignment} }
|
||
|
|
+ unsafe_ui_fn_ptr1 = &s1; // { dg-error {cannot convert 's\*' to 'user_int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+ unsafe_ui_fn_ptr2 = &s1; // { dg-error {cannot convert 's\*' to 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(\)'} in assignment} }
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
diff --git a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
|
||
|
|
index 2e3dfecac..6a76adb5b 100644
|
||
|
|
--- a/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
|
||
|
|
+++ b/gcc/testsuite/g++.dg/tree-ssa/pr61034.C
|
||
|
|
@@ -1,5 +1,5 @@
|
||
|
|
// { dg-do compile }
|
||
|
|
-// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14" }
|
||
|
|
+// { dg-options "-O2 -fdump-tree-fre3 -fdump-tree-optimized -fdelete-null-pointer-checks --param early-inlining-insns-O2=14 --param max-inline-insns-single-O2=200" }
|
||
|
|
|
||
|
|
#define assume(x) if(!(x))__builtin_unreachable()
|
||
|
|
|
||
|
|
diff --git a/gcc/testsuite/g++.target/aarch64/diag_aka_1.C b/gcc/testsuite/g++.target/aarch64/diag_aka_1.C
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..6b489981f
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/g++.target/aarch64/diag_aka_1.C
|
||
|
|
@@ -0,0 +1,13 @@
|
||
|
|
+#include <arm_neon.h>
|
||
|
|
+
|
||
|
|
+typedef int16x4_t myvec;
|
||
|
|
+
|
||
|
|
+void f (float x)
|
||
|
|
+{
|
||
|
|
+ __Int8x8_t y1 = x; // { dg-error {cannot convert 'float' to '__Int8x8_t' in initialization} }
|
||
|
|
+ __Int8x8_t *ptr1 = &x; // { dg-error {cannot convert 'float\*' to '__Int8x8_t\*' in initialization} }
|
||
|
|
+ int8x8_t y2 = x; // { dg-error {cannot convert 'float' to 'int8x8_t' in initialization} }
|
||
|
|
+ int8x8_t *ptr2 = &x; // { dg-error {cannot convert 'float\*' to 'int8x8_t\*' in initialization} }
|
||
|
|
+ myvec y3 = x; // { dg-error {cannot convert 'float' to 'myvec' {aka 'int16x4_t'} in initialization} }
|
||
|
|
+ myvec *ptr3 = &x; // { dg-error {cannot convert 'float\*' to 'myvec\*' {aka 'int16x4_t\*'} in initialization} }
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/diag-aka-1.c b/gcc/testsuite/gcc.dg/diag-aka-1.c
|
||
|
|
index fde4ca7c7..3383c1c26 100644
|
||
|
|
--- a/gcc/testsuite/gcc.dg/diag-aka-1.c
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/diag-aka-1.c
|
||
|
|
@@ -2,7 +2,7 @@
|
||
|
|
/* { dg-options "-Wc++-compat" } */
|
||
|
|
|
||
|
|
typedef struct A { int i; } B;
|
||
|
|
-typedef struct T { int i; } T;
|
||
|
|
+typedef struct T { int i; } *T; /* { dg-warning "using 'T' as both a typedef and a tag is invalid" } */
|
||
|
|
typedef const float TFA;
|
||
|
|
typedef TFA TFB;
|
||
|
|
typedef TFB TFC;
|
||
|
|
@@ -24,6 +24,6 @@ bar (B *b, int *i)
|
||
|
|
int
|
||
|
|
foo (void *a)
|
||
|
|
{
|
||
|
|
- T *t = a; /* { dg-warning "request for implicit conversion from 'void \\*' to 'T \\*' {aka 'struct T \\*'} not" } */
|
||
|
|
+ T t = a; /* { dg-warning "request for implicit conversion from 'void \\*' to 'T' {aka 'struct T \\*'} not" } */
|
||
|
|
return t->i;
|
||
|
|
}
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/diag-aka-4.c b/gcc/testsuite/gcc.dg/diag-aka-4.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..cf98dd96a
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/diag-aka-4.c
|
||
|
|
@@ -0,0 +1,72 @@
|
||
|
|
+typedef struct struct_wrapper { int i; } struct_wrapper;
|
||
|
|
+typedef struct { int i; } anon_struct_wrapper;
|
||
|
|
+
|
||
|
|
+typedef union union_wrapper { int i; } union_wrapper;
|
||
|
|
+typedef union { int i; } anon_union_wrapper;
|
||
|
|
+
|
||
|
|
+typedef enum enum_wrapper { A, B } enum_wrapper;
|
||
|
|
+typedef enum { C, D } anon_enum_wrapper;
|
||
|
|
+
|
||
|
|
+void test_struct_wrapper (struct_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ struct_wrapper *ptr = &x; /* { dg-error {initialization of 'struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const struct_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile struct_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ struct_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'struct_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ struct_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'struct_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(struct_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(struct_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ y = x; /* { dg-error {incompatible types when assigning to type 'struct_wrapper' from type 'int'} } */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void test_anon_struct_wrapper (anon_struct_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ anon_struct_wrapper *ptr = &x; /* { dg-error {initialization of 'anon_struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const anon_struct_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const anon_struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile anon_struct_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile anon_struct_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_struct_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'anon_struct_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_struct_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'anon_struct_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(anon_struct_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(anon_struct_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ y = x; /* { dg-error {incompatible types when assigning to type 'anon_struct_wrapper' from type 'int'} } */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void test_union_wrapper (union_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ union_wrapper *ptr = &x; /* { dg-error {initialization of 'union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const union_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile union_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ union_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'union_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ union_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'union_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(union_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(union_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ y = x; /* { dg-error {incompatible types when assigning to type 'union_wrapper' from type 'int'} } */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void test_anon_union_wrapper (anon_union_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ anon_union_wrapper *ptr = &x; /* { dg-error {initialization of 'anon_union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const anon_union_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const anon_union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile anon_union_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile anon_union_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_union_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'anon_union_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_union_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'anon_union_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(anon_union_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(anon_union_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ y = x; /* { dg-error {incompatible types when assigning to type 'anon_union_wrapper' from type 'int'} } */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void test_enum_wrapper (enum_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ enum_wrapper *ptr = &x; /* { dg-error {initialization of 'enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const enum_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile enum_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ enum_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'enum_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ enum_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'enum_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(enum_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(enum_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+void test_anon_enum_wrapper (anon_enum_wrapper y, int x)
|
||
|
|
+{
|
||
|
|
+ anon_enum_wrapper *ptr = &x; /* { dg-error {initialization of 'anon_enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ const anon_enum_wrapper *const_ptr = &x; /* { dg-error {initialization of 'const anon_enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ volatile anon_enum_wrapper *volatile_ptr = &x; /* { dg-error {initialization of 'volatile anon_enum_wrapper \*' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_enum_wrapper (*aptr)[10] = &x; /* { dg-error {initialization of 'anon_enum_wrapper \(\*\)\[10\]' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ anon_enum_wrapper (*f1)(int) = &x; /* { dg-error {initialization of 'anon_enum_wrapper \(\*\)\(int\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+ int (*f2)(anon_enum_wrapper) = &x; /* { dg-error {initialization of 'int \(\*\)\(anon_enum_wrapper\)' from incompatible pointer type 'int \*'} } */
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/diag-aka-5.h b/gcc/testsuite/gcc.dg/diag-aka-5.h
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..0c7404d76
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/diag-aka-5.h
|
||
|
|
@@ -0,0 +1,22 @@
|
||
|
|
+#ifdef IS_SYSTEM_HEADER
|
||
|
|
+#pragma GCC system_header
|
||
|
|
+#endif
|
||
|
|
+
|
||
|
|
+typedef enum __internal_enum { A, B } user_enum;
|
||
|
|
+typedef user_enum *user_enum_ptr;
|
||
|
|
+
|
||
|
|
+typedef struct __internal_struct { int i; } user_struct;
|
||
|
|
+typedef user_struct user_struct_copy;
|
||
|
|
+typedef user_struct *user_struct_ptr;
|
||
|
|
+
|
||
|
|
+typedef union __internal_union { int i; } user_union;
|
||
|
|
+typedef user_union user_union_copy;
|
||
|
|
+typedef user_union *user_union_ptr;
|
||
|
|
+
|
||
|
|
+typedef unsigned int user_vector __attribute__((__vector_size__(16)));
|
||
|
|
+typedef user_vector user_vector_copy;
|
||
|
|
+typedef user_vector *user_vector_ptr;
|
||
|
|
+
|
||
|
|
+typedef int user_int;
|
||
|
|
+typedef user_int user_int_copy;
|
||
|
|
+typedef user_int *user_int_ptr;
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/diag-aka-5a.c b/gcc/testsuite/gcc.dg/diag-aka-5a.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..573020659
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/diag-aka-5a.c
|
||
|
|
@@ -0,0 +1,135 @@
|
||
|
|
+#define IS_SYSTEM_HEADER
|
||
|
|
+#include "diag-aka-5.h"
|
||
|
|
+
|
||
|
|
+typedef user_enum user_enum_copy;
|
||
|
|
+
|
||
|
|
+struct s { int i; };
|
||
|
|
+
|
||
|
|
+user_enum ue1;
|
||
|
|
+user_enum_copy ue2;
|
||
|
|
+user_enum_ptr ue_ptr1;
|
||
|
|
+user_enum *ue_ptr2;
|
||
|
|
+const user_enum *const_ue_ptr1;
|
||
|
|
+const user_enum_copy *const_ue_ptr2;
|
||
|
|
+volatile user_enum *volatile_ue_ptr1;
|
||
|
|
+volatile user_enum_copy *volatile_ue_ptr2;
|
||
|
|
+__extension__ _Atomic user_enum *atomic_ue_ptr1;
|
||
|
|
+__extension__ _Atomic user_enum_copy *atomic_ue_ptr2;
|
||
|
|
+user_enum (*ue_array_ptr1)[10];
|
||
|
|
+user_enum_copy (*ue_array_ptr2)[10];
|
||
|
|
+user_enum (*ue_fn_ptr1) (void);
|
||
|
|
+void (*ue_fn_ptr2) (user_enum);
|
||
|
|
+void (*ue_fn_ptr3) (user_enum, ...);
|
||
|
|
+user_enum_copy (*ue_fn_ptr4) (void);
|
||
|
|
+void (*ue_fn_ptr5) (user_enum_copy);
|
||
|
|
+void (*ue_fn_ptr6) (user_enum_copy, ...);
|
||
|
|
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
|
||
|
|
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+user_struct us1;
|
||
|
|
+user_struct_copy us2;
|
||
|
|
+user_struct_ptr us_ptr1;
|
||
|
|
+user_struct *us_ptr2;
|
||
|
|
+const user_struct *const_us_ptr1;
|
||
|
|
+const user_struct_copy *const_us_ptr2;
|
||
|
|
+
|
||
|
|
+user_union uu1;
|
||
|
|
+user_union_copy uu2;
|
||
|
|
+user_union_ptr uu_ptr1;
|
||
|
|
+user_union *uu_ptr2;
|
||
|
|
+const user_union *const_uu_ptr1;
|
||
|
|
+const user_union_copy *const_uu_ptr2;
|
||
|
|
+
|
||
|
|
+user_vector uv1;
|
||
|
|
+user_vector_copy uv2;
|
||
|
|
+user_vector_ptr uv_ptr1;
|
||
|
|
+user_vector *uv_ptr2;
|
||
|
|
+const user_vector *const_uv_ptr1;
|
||
|
|
+const user_vector_copy *const_uv_ptr2;
|
||
|
|
+
|
||
|
|
+user_int ui1;
|
||
|
|
+user_int_copy ui2;
|
||
|
|
+user_int_ptr ui_ptr1;
|
||
|
|
+user_int *ui_ptr2;
|
||
|
|
+const user_int *const_ui_ptr1;
|
||
|
|
+const user_int_copy *const_ui_ptr2;
|
||
|
|
+volatile user_int *volatile_ui_ptr1;
|
||
|
|
+volatile user_int_copy *volatile_ui_ptr2;
|
||
|
|
+__extension__ _Atomic user_int *atomic_ui_ptr1;
|
||
|
|
+__extension__ _Atomic user_int_copy *atomic_ui_ptr2;
|
||
|
|
+user_int (*ui_array_ptr1)[10];
|
||
|
|
+user_int_copy (*ui_array_ptr2)[10];
|
||
|
|
+user_int (*ui_fn_ptr1) (void);
|
||
|
|
+void (*ui_fn_ptr2) (user_int);
|
||
|
|
+void (*ui_fn_ptr3) (user_int, ...);
|
||
|
|
+user_int_copy (*ui_fn_ptr4) (void);
|
||
|
|
+void (*ui_fn_ptr5) (user_int_copy);
|
||
|
|
+void (*ui_fn_ptr6) (user_int_copy, ...);
|
||
|
|
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
|
||
|
|
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+void f (struct s s)
|
||
|
|
+{
|
||
|
|
+ ue1 = s; /* { dg-error {assigning to type 'user_enum' from type 'struct s'} } */
|
||
|
|
+ ue2 = s; /* { dg-error {assigning to type 'user_enum_copy' {aka 'user_enum'} from type 'struct s'} } */
|
||
|
|
+ ue_ptr1 = &s; /* { dg-error {assignment to 'user_enum_ptr' {aka 'user_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_ptr2 = &s; /* { dg-error {assignment to 'user_enum \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ue_ptr1 = &s; /* { dg-error {assignment to 'const user_enum \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ue_ptr2 = &s; /* { dg-error {assignment to 'const user_enum_copy \*' {aka 'const user_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ue_ptr1 = &s; /* { dg-error {assignment to 'volatile user_enum \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ue_ptr2 = &s; /* { dg-error {assignment to 'volatile user_enum_copy \*' {aka 'volatile user_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ue_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_enum \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ue_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_enum_copy \*' {aka '_Atomic user_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_array_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\[10\]' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_array_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy \(\*\)\[10\]' {aka 'user_enum \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\(void\)' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum\)' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum, \.\.\.\)' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr4 = &s; /* { dg-error {assignment to 'user_enum_copy \(\*\)\(void\)' {aka 'user_enum \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(user_enum\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(user_enum, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ue_fn_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ us1 = s; /* { dg-error {assigning to type 'user_struct' from type 'struct s'} } */
|
||
|
|
+ us2 = s; /* { dg-error {assigning to type 'user_struct_copy' {aka 'user_struct'} from type 'struct s'} } */
|
||
|
|
+ us_ptr1 = &s; /* { dg-error {assignment to 'user_struct_ptr' {aka 'user_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ us_ptr2 = &s; /* { dg-error {assignment to 'user_struct \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_us_ptr1 = &s; /* { dg-error {assignment to 'const user_struct \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_us_ptr2 = &s; /* { dg-error {assignment to 'const user_struct_copy \*' {aka 'const user_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ uu1 = s; /* { dg-error {assigning to type 'user_union' from type 'struct s'} } */
|
||
|
|
+ uu2 = s; /* { dg-error {assigning to type 'user_union_copy' {aka 'user_union'} from type 'struct s'} } */
|
||
|
|
+ uu_ptr1 = &s; /* { dg-error {assignment to 'user_union_ptr' {aka 'user_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ uu_ptr2 = &s; /* { dg-error {assignment to 'user_union \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uu_ptr1 = &s; /* { dg-error {assignment to 'const user_union \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uu_ptr2 = &s; /* { dg-error {assignment to 'const user_union_copy \*' {aka 'const user_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ uv1 = s; /* { dg-error {assigning to type 'user_vector' from type 'struct s'} } */
|
||
|
|
+ uv2 = s; /* { dg-error {assigning to type 'user_vector_copy' {aka 'user_vector'} from type 'struct s'} } */
|
||
|
|
+ uv_ptr1 = &s; /* { dg-error {assignment to 'user_vector_ptr' {aka 'user_vector \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ uv_ptr2 = &s; /* { dg-error {assignment to 'user_vector \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uv_ptr1 = &s; /* { dg-error {assignment to 'const user_vector \*' from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uv_ptr2 = &s; /* { dg-error {assignment to 'const user_vector_copy \*' {aka 'const user_vector \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ ui1 = s; /* { dg-error {assigning to type 'user_int' {aka 'int'} from type 'struct s'} } */
|
||
|
|
+ ui2 = s; /* { dg-error {assigning to type 'user_int_copy' {aka 'int'} from type 'struct s'} } */
|
||
|
|
+ ui_ptr1 = &s; /* { dg-error {assignment to 'user_int_ptr' {aka 'int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_ptr2 = &s; /* { dg-error {assignment to 'user_int \*' {aka 'int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ui_ptr1 = &s; /* { dg-error {assignment to 'const user_int \*' {aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ui_ptr2 = &s; /* { dg-error {assignment to 'const user_int_copy \*' {aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ui_ptr1 = &s; /* { dg-error {assignment to 'volatile user_int \*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ui_ptr2 = &s; /* { dg-error {assignment to 'volatile user_int_copy \*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ui_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_int \*' {aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ui_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_int_copy \*' {aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_array_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_array_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\(void\)' {aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr4 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\(void\)' {aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ui_fn_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gcc.dg/diag-aka-5b.c b/gcc/testsuite/gcc.dg/diag-aka-5b.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..f510d0d40
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.dg/diag-aka-5b.c
|
||
|
|
@@ -0,0 +1,134 @@
|
||
|
|
+#include "diag-aka-5.h"
|
||
|
|
+
|
||
|
|
+typedef user_enum user_enum_copy;
|
||
|
|
+
|
||
|
|
+struct s { int i; };
|
||
|
|
+
|
||
|
|
+user_enum ue1;
|
||
|
|
+user_enum_copy ue2;
|
||
|
|
+user_enum_ptr ue_ptr1;
|
||
|
|
+user_enum *ue_ptr2;
|
||
|
|
+const user_enum *const_ue_ptr1;
|
||
|
|
+const user_enum_copy *const_ue_ptr2;
|
||
|
|
+volatile user_enum *volatile_ue_ptr1;
|
||
|
|
+volatile user_enum_copy *volatile_ue_ptr2;
|
||
|
|
+__extension__ _Atomic user_enum *atomic_ue_ptr1;
|
||
|
|
+__extension__ _Atomic user_enum_copy *atomic_ue_ptr2;
|
||
|
|
+user_enum (*ue_array_ptr1)[10];
|
||
|
|
+user_enum_copy (*ue_array_ptr2)[10];
|
||
|
|
+user_enum (*ue_fn_ptr1) (void);
|
||
|
|
+void (*ue_fn_ptr2) (user_enum);
|
||
|
|
+void (*ue_fn_ptr3) (user_enum, ...);
|
||
|
|
+user_enum_copy (*ue_fn_ptr4) (void);
|
||
|
|
+void (*ue_fn_ptr5) (user_enum_copy);
|
||
|
|
+void (*ue_fn_ptr6) (user_enum_copy, ...);
|
||
|
|
+user_enum (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr1) (void);
|
||
|
|
+user_enum_copy (*__attribute__((__transaction_unsafe__)) unsafe_ue_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+user_struct us1;
|
||
|
|
+user_struct_copy us2;
|
||
|
|
+user_struct_ptr us_ptr1;
|
||
|
|
+user_struct *us_ptr2;
|
||
|
|
+const user_struct *const_us_ptr1;
|
||
|
|
+const user_struct_copy *const_us_ptr2;
|
||
|
|
+
|
||
|
|
+user_union uu1;
|
||
|
|
+user_union_copy uu2;
|
||
|
|
+user_union_ptr uu_ptr1;
|
||
|
|
+user_union *uu_ptr2;
|
||
|
|
+const user_union *const_uu_ptr1;
|
||
|
|
+const user_union_copy *const_uu_ptr2;
|
||
|
|
+
|
||
|
|
+user_vector uv1;
|
||
|
|
+user_vector_copy uv2;
|
||
|
|
+user_vector_ptr uv_ptr1;
|
||
|
|
+user_vector *uv_ptr2;
|
||
|
|
+const user_vector *const_uv_ptr1;
|
||
|
|
+const user_vector_copy *const_uv_ptr2;
|
||
|
|
+
|
||
|
|
+user_int ui1;
|
||
|
|
+user_int_copy ui2;
|
||
|
|
+user_int_ptr ui_ptr1;
|
||
|
|
+user_int *ui_ptr2;
|
||
|
|
+const user_int *const_ui_ptr1;
|
||
|
|
+const user_int_copy *const_ui_ptr2;
|
||
|
|
+volatile user_int *volatile_ui_ptr1;
|
||
|
|
+volatile user_int_copy *volatile_ui_ptr2;
|
||
|
|
+__extension__ _Atomic user_int *atomic_ui_ptr1;
|
||
|
|
+__extension__ _Atomic user_int_copy *atomic_ui_ptr2;
|
||
|
|
+user_int (*ui_array_ptr1)[10];
|
||
|
|
+user_int_copy (*ui_array_ptr2)[10];
|
||
|
|
+user_int (*ui_fn_ptr1) (void);
|
||
|
|
+void (*ui_fn_ptr2) (user_int);
|
||
|
|
+void (*ui_fn_ptr3) (user_int, ...);
|
||
|
|
+user_int_copy (*ui_fn_ptr4) (void);
|
||
|
|
+void (*ui_fn_ptr5) (user_int_copy);
|
||
|
|
+void (*ui_fn_ptr6) (user_int_copy, ...);
|
||
|
|
+user_int (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr1) (void);
|
||
|
|
+user_int_copy (*__attribute__((__transaction_unsafe__)) unsafe_ui_fn_ptr2) (void);
|
||
|
|
+
|
||
|
|
+void f (struct s s)
|
||
|
|
+{
|
||
|
|
+ ue1 = s; /* { dg-error {assigning to type 'user_enum' {aka 'enum __internal_enum'} from type 'struct s'} } */
|
||
|
|
+ ue2 = s; /* { dg-error {assigning to type 'user_enum_copy' {aka 'enum __internal_enum'} from type 'struct s'} } */
|
||
|
|
+ ue_ptr1 = &s; /* { dg-error {assignment to 'user_enum_ptr' {aka 'enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_ptr2 = &s; /* { dg-error {assignment to 'user_enum \*' {aka 'enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ue_ptr1 = &s; /* { dg-error {assignment to 'const user_enum \*' {aka 'const enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ue_ptr2 = &s; /* { dg-error {assignment to 'const user_enum_copy \*' {aka 'const enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ue_ptr1 = &s; /* { dg-error {assignment to 'volatile user_enum \*' {aka 'volatile enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ue_ptr2 = &s; /* { dg-error {assignment to 'volatile user_enum_copy \*' {aka 'volatile enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ue_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_enum \*' {aka '_Atomic enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ue_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_enum_copy \*' {aka '_Atomic enum __internal_enum \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_array_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\[10\]' {aka 'enum __internal_enum \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_array_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy \(\*\)\[10\]' {aka 'enum __internal_enum \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(\*\)\(void\)' {aka 'enum __internal_enum \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum\)' {aka 'void \(\*\)\(enum __internal_enum\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum, \.\.\.\)' {aka 'void \(\*\)\(enum __internal_enum, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr4 = &s; /* { dg-error {assignment to 'user_enum_copy \(\*\)\(void\)' {aka 'enum __internal_enum \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy\)' {aka 'void \(\*\)\(enum __internal_enum\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ue_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_enum_copy, \.\.\.\)' {aka 'void \(\*\)\(enum __internal_enum, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ue_fn_ptr1 = &s; /* { dg-error {assignment to 'user_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'enum __internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ue_fn_ptr2 = &s; /* { dg-error {assignment to 'user_enum_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'enum __internal_enum \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ us1 = s; /* { dg-error {assigning to type 'user_struct' {aka 'struct __internal_struct'} from type 'struct s'} } */
|
||
|
|
+ us2 = s; /* { dg-error {assigning to type 'user_struct_copy' {aka 'struct __internal_struct'} from type 'struct s'} } */
|
||
|
|
+ us_ptr1 = &s; /* { dg-error {assignment to 'user_struct_ptr' {aka 'struct __internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ us_ptr2 = &s; /* { dg-error {assignment to 'user_struct \*' {aka 'struct __internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_us_ptr1 = &s; /* { dg-error {assignment to 'const user_struct \*' {aka 'const struct __internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_us_ptr2 = &s; /* { dg-error {assignment to 'const user_struct_copy \*' {aka 'const struct __internal_struct \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ uu1 = s; /* { dg-error {assigning to type 'user_union' {aka 'union __internal_union'} from type 'struct s'} } */
|
||
|
|
+ uu2 = s; /* { dg-error {assigning to type 'user_union_copy' {aka 'union __internal_union'} from type 'struct s'} } */
|
||
|
|
+ uu_ptr1 = &s; /* { dg-error {assignment to 'user_union_ptr' {aka 'union __internal_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ uu_ptr2 = &s; /* { dg-error {assignment to 'user_union \*' {aka 'union __internal_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uu_ptr1 = &s; /* { dg-error {assignment to 'const user_union \*' {aka 'const union __internal_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uu_ptr2 = &s; /* { dg-error {assignment to 'const user_union_copy \*' {aka 'const union __internal_union \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ uv1 = s; /* { dg-error {assigning to type 'user_vector' {aka '__vector\([48]\) unsigned int'} from type 'struct s'} } */
|
||
|
|
+ uv2 = s; /* { dg-error {assigning to type 'user_vector_copy' {aka '__vector\([48]\) unsigned int'} from type 'struct s'} } */
|
||
|
|
+ uv_ptr1 = &s; /* { dg-error {assignment to 'user_vector_ptr' {aka '__vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ uv_ptr2 = &s; /* { dg-error {assignment to 'user_vector \*' {aka '__vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uv_ptr1 = &s; /* { dg-error {assignment to 'const user_vector \*' {aka 'const __vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_uv_ptr2 = &s; /* { dg-error {assignment to 'const user_vector_copy \*' {aka 'const __vector\([48]\) unsigned int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+
|
||
|
|
+ ui1 = s; /* { dg-error {assigning to type 'user_int' {aka 'int'} from type 'struct s'} } */
|
||
|
|
+ ui2 = s; /* { dg-error {assigning to type 'user_int_copy' {aka 'int'} from type 'struct s'} } */
|
||
|
|
+ ui_ptr1 = &s; /* { dg-error {assignment to 'user_int_ptr' {aka 'int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_ptr2 = &s; /* { dg-error {assignment to 'user_int \*' {aka 'int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ui_ptr1 = &s; /* { dg-error {assignment to 'const user_int \*' {aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ const_ui_ptr2 = &s; /* { dg-error {assignment to 'const user_int_copy \*' {aka 'const int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ui_ptr1 = &s; /* { dg-error {assignment to 'volatile user_int \*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ volatile_ui_ptr2 = &s; /* { dg-error {assignment to 'volatile user_int_copy \*' {aka 'volatile int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ui_ptr1 = &s; /* { dg-error {assignment to '_Atomic user_int \*' {aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ atomic_ui_ptr2 = &s; /* { dg-error {assignment to '_Atomic user_int_copy \*' {aka '_Atomic int \*'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_array_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_array_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\[10\]' {aka 'int \(\*\)\[10\]'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(\*\)\(void\)' {aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr2 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int\)' {aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr3 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr4 = &s; /* { dg-error {assignment to 'user_int_copy \(\*\)\(void\)' {aka 'int \(\*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr5 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy\)' {aka 'void \(\*\)\(int\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ ui_fn_ptr6 = &s; /* { dg-error {assignment to 'void \(\*\)\(user_int_copy, \.\.\.\)' {aka 'void \(\*\)\(int, \.\.\.\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ui_fn_ptr1 = &s; /* { dg-error {assignment to 'user_int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+ unsafe_ui_fn_ptr2 = &s; /* { dg-error {assignment to 'user_int_copy \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)' {aka 'int \(__attribute__\(\(transaction_unsafe\)\) \*\)\(void\)'} from incompatible pointer type 'struct s \*'} } */
|
||
|
|
+}
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c b/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c
|
||
|
|
index 59e24f48b..98dffead6 100644
|
||
|
|
--- a/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c
|
||
|
|
+++ b/gcc/testsuite/gcc.target/aarch64/diag_aka_1.c
|
||
|
|
@@ -8,7 +8,6 @@ void f (float x)
|
||
|
|
__Int8x8_t *ptr1 = &x; /* { dg-error {initialization of '__Int8x8_t \*' from incompatible pointer type 'float \*'} } */
|
||
|
|
int8x8_t y2 = x; /* { dg-error {incompatible types when initializing type 'int8x8_t' using type 'float'} } */
|
||
|
|
int8x8_t *ptr2 = &x; /* { dg-error {initialization of 'int8x8_t \*' from incompatible pointer type 'float \*'} } */
|
||
|
|
- /* ??? For these it would be better to print an aka for 'int16x4_t'. */
|
||
|
|
- myvec y3 = x; /* { dg-error {incompatible types when initializing type 'myvec' using type 'float'} } */
|
||
|
|
- myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' from incompatible pointer type 'float \*'} } */
|
||
|
|
+ myvec y3 = x; /* { dg-error {incompatible types when initializing type 'myvec' {aka 'int16x4_t'} using type 'float'} } */
|
||
|
|
+ myvec *ptr3 = &x; /* { dg-error {initialization of 'myvec \*' {aka 'int16x4_t \*'} from incompatible pointer type 'float \*'} } */
|
||
|
|
}
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/aarch64/pr88838.c b/gcc/testsuite/gcc.target/aarch64/pr88838.c
|
||
|
|
new file mode 100644
|
||
|
|
index 000000000..d7db84758
|
||
|
|
--- /dev/null
|
||
|
|
+++ b/gcc/testsuite/gcc.target/aarch64/pr88838.c
|
||
|
|
@@ -0,0 +1,11 @@
|
||
|
|
+/* { dg-do compile } */
|
||
|
|
+/* { dg-options "-S -O3 -march=armv8.2-a+sve" } */
|
||
|
|
+
|
||
|
|
+void
|
||
|
|
+f (int *restrict x, int *restrict y, int *restrict z, int n)
|
||
|
|
+{
|
||
|
|
+ for (int i = 0; i < n; i += 1)
|
||
|
|
+ x[i] = y[i] + z[i];
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
+/* { dg-final { scan-assembler-not "sxtw" } } */
|
||
|
|
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/while_1.c b/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
|
||
|
|
index 2655c4242..2cfb3f697 100644
|
||
|
|
--- a/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
|
||
|
|
+++ b/gcc/testsuite/gcc.target/aarch64/sve/while_1.c
|
||
|
|
@@ -26,14 +26,14 @@
|
||
|
|
TEST_ALL (ADD_LOOP)
|
||
|
|
|
||
|
|
/* { dg-final { scan-assembler-not {\tuqdec} } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, xzr,} 2 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, x[0-9]+,} 2 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, xzr,} 2 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, x[0-9]+,} 2 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, xzr,} 3 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, x[0-9]+,} 3 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, xzr,} 3 } } */
|
||
|
|
-/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, x[0-9]+,} 3 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, wzr,} 2 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.b, w[0-9]+,} 2 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, wzr,} 2 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.h, w[0-9]+,} 2 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, wzr,} 3 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.s, w[0-9]+,} 3 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, wzr,} 3 } } */
|
||
|
|
+/* { dg-final { scan-assembler-times {\twhilelo\tp[0-7]\.d, w[0-9]+,} 3 } } */
|
||
|
|
/* { dg-final { scan-assembler-times {\tld1b\tz[0-9]+\.b, p[0-7]/z, \[x0, x[0-9]+\]\n} 2 } } */
|
||
|
|
/* { dg-final { scan-assembler-times {\tst1b\tz[0-9]+\.b, p[0-7], \[x0, x[0-9]+\]\n} 2 } } */
|
||
|
|
/* { dg-final { scan-assembler-times {\tld1h\tz[0-9]+\.h, p[0-7]/z, \[x0, x[0-9]+, lsl 1\]\n} 2 } } */
|
||
|
|
diff --git a/gcc/tree-vect-loop-manip.c b/gcc/tree-vect-loop-manip.c
|
||
|
|
index d38b298aa..e51b95593 100644
|
||
|
|
--- a/gcc/tree-vect-loop-manip.c
|
||
|
|
+++ b/gcc/tree-vect-loop-manip.c
|
||
|
|
@@ -423,6 +423,7 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
bool might_wrap_p)
|
||
|
|
{
|
||
|
|
tree compare_type = LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo);
|
||
|
|
+ tree iv_type = LOOP_VINFO_MASK_IV_TYPE (loop_vinfo);
|
||
|
|
tree mask_type = rgm->mask_type;
|
||
|
|
unsigned int nscalars_per_iter = rgm->max_nscalars_per_iter;
|
||
|
|
poly_uint64 nscalars_per_mask = TYPE_VECTOR_SUBPARTS (mask_type);
|
||
|
|
@@ -453,11 +454,16 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
tree index_before_incr, index_after_incr;
|
||
|
|
gimple_stmt_iterator incr_gsi;
|
||
|
|
bool insert_after;
|
||
|
|
- tree zero_index = build_int_cst (compare_type, 0);
|
||
|
|
standard_iv_increment_position (loop, &incr_gsi, &insert_after);
|
||
|
|
- create_iv (zero_index, nscalars_step, NULL_TREE, loop, &incr_gsi,
|
||
|
|
+
|
||
|
|
+ tree zero_index = build_int_cst (iv_type, 0);
|
||
|
|
+ tree step = build_int_cst (iv_type,
|
||
|
|
+ LOOP_VINFO_VECT_FACTOR (loop_vinfo));
|
||
|
|
+ /* Create IV of iv_type. */
|
||
|
|
+ create_iv (zero_index, step, NULL_TREE, loop, &incr_gsi,
|
||
|
|
insert_after, &index_before_incr, &index_after_incr);
|
||
|
|
|
||
|
|
+ zero_index = build_int_cst (compare_type, 0);
|
||
|
|
tree test_index, test_limit, first_limit;
|
||
|
|
gimple_stmt_iterator *test_gsi;
|
||
|
|
if (might_wrap_p)
|
||
|
|
@@ -537,6 +543,10 @@ vect_set_loop_masks_directly (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
tree next_mask = NULL_TREE;
|
||
|
|
tree mask;
|
||
|
|
unsigned int i;
|
||
|
|
+ gimple_seq test_seq = NULL;
|
||
|
|
+ test_index = gimple_convert (&test_seq, compare_type, test_index);
|
||
|
|
+ gsi_insert_seq_before (test_gsi, test_seq, GSI_SAME_STMT);
|
||
|
|
+
|
||
|
|
FOR_EACH_VEC_ELT_REVERSE (rgm->masks, i, mask)
|
||
|
|
{
|
||
|
|
/* Previous masks will cover BIAS scalars. This mask covers the
|
||
|
|
@@ -645,12 +655,12 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
|
||
|
|
tree compare_type = LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo);
|
||
|
|
unsigned int compare_precision = TYPE_PRECISION (compare_type);
|
||
|
|
- unsigned HOST_WIDE_INT max_vf = vect_max_vf (loop_vinfo);
|
||
|
|
tree orig_niters = niters;
|
||
|
|
|
||
|
|
/* Type of the initial value of NITERS. */
|
||
|
|
tree ni_actual_type = TREE_TYPE (niters);
|
||
|
|
unsigned int ni_actual_precision = TYPE_PRECISION (ni_actual_type);
|
||
|
|
+ tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
|
||
|
|
|
||
|
|
/* Convert NITERS to the same size as the compare. */
|
||
|
|
if (compare_precision > ni_actual_precision
|
||
|
|
@@ -669,33 +679,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
else
|
||
|
|
niters = gimple_convert (&preheader_seq, compare_type, niters);
|
||
|
|
|
||
|
|
- /* Convert skip_niters to the right type. */
|
||
|
|
- tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
|
||
|
|
-
|
||
|
|
- /* Now calculate the value that the induction variable must be able
|
||
|
|
- to hit in order to ensure that we end the loop with an all-false mask.
|
||
|
|
- This involves adding the maximum number of inactive trailing scalar
|
||
|
|
- iterations. */
|
||
|
|
- widest_int iv_limit;
|
||
|
|
- bool known_max_iters = max_loop_iterations (loop, &iv_limit);
|
||
|
|
- if (known_max_iters)
|
||
|
|
- {
|
||
|
|
- if (niters_skip)
|
||
|
|
- {
|
||
|
|
- /* Add the maximum number of skipped iterations to the
|
||
|
|
- maximum iteration count. */
|
||
|
|
- if (TREE_CODE (niters_skip) == INTEGER_CST)
|
||
|
|
- iv_limit += wi::to_widest (niters_skip);
|
||
|
|
- else
|
||
|
|
- iv_limit += max_vf - 1;
|
||
|
|
- }
|
||
|
|
- /* IV_LIMIT is the maximum number of latch iterations, which is also
|
||
|
|
- the maximum in-range IV value. Round this value down to the previous
|
||
|
|
- vector alignment boundary and then add an extra full iteration. */
|
||
|
|
- poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
|
||
|
|
- iv_limit = (iv_limit & -(int) known_alignment (vf)) + max_vf;
|
||
|
|
- }
|
||
|
|
-
|
||
|
|
+ widest_int iv_limit = vect_iv_limit_for_full_masking (loop_vinfo);
|
||
|
|
/* Get the vectorization factor in tree form. */
|
||
|
|
tree vf = build_int_cst (compare_type,
|
||
|
|
LOOP_VINFO_VECT_FACTOR (loop_vinfo));
|
||
|
|
@@ -725,7 +709,7 @@ vect_set_loop_condition_masked (struct loop *loop, loop_vec_info loop_vinfo,
|
||
|
|
/* See whether zero-based IV would ever generate all-false masks
|
||
|
|
before wrapping around. */
|
||
|
|
bool might_wrap_p
|
||
|
|
- = (!known_max_iters
|
||
|
|
+ = (iv_limit == -1
|
||
|
|
|| (wi::min_precision (iv_limit * rgm->max_nscalars_per_iter,
|
||
|
|
UNSIGNED)
|
||
|
|
> compare_precision));
|
||
|
|
diff --git a/gcc/tree-vect-loop.c b/gcc/tree-vect-loop.c
|
||
|
|
index 16d7d7788..e98bf2c15 100644
|
||
|
|
--- a/gcc/tree-vect-loop.c
|
||
|
|
+++ b/gcc/tree-vect-loop.c
|
||
|
|
@@ -1038,6 +1038,8 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
{
|
||
|
|
struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
|
||
|
|
unsigned int min_ni_width;
|
||
|
|
+ unsigned int max_nscalars_per_iter
|
||
|
|
+ = vect_get_max_nscalars_per_iter (loop_vinfo);
|
||
|
|
|
||
|
|
/* Use a normal loop if there are no statements that need masking.
|
||
|
|
This only happens in rare degenerate cases: it means that the loop
|
||
|
|
@@ -1056,7 +1058,7 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
max_ni = wi::smin (max_ni, max_back_edges + 1);
|
||
|
|
|
||
|
|
/* Account for rgroup masks, in which each bit is replicated N times. */
|
||
|
|
- max_ni *= vect_get_max_nscalars_per_iter (loop_vinfo);
|
||
|
|
+ max_ni *= max_nscalars_per_iter;
|
||
|
|
|
||
|
|
/* Work out how many bits we need to represent the limit. */
|
||
|
|
min_ni_width = wi::min_precision (max_ni, UNSIGNED);
|
||
|
|
@@ -1064,6 +1066,14 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
/* Find a scalar mode for which WHILE_ULT is supported. */
|
||
|
|
opt_scalar_int_mode cmp_mode_iter;
|
||
|
|
tree cmp_type = NULL_TREE;
|
||
|
|
+ tree iv_type = NULL_TREE;
|
||
|
|
+ widest_int iv_limit = vect_iv_limit_for_full_masking (loop_vinfo);
|
||
|
|
+ widest_int iv_precision = UINT_MAX;
|
||
|
|
+
|
||
|
|
+ if (iv_limit != -1)
|
||
|
|
+ iv_precision = wi::min_precision (iv_limit * max_nscalars_per_iter,
|
||
|
|
+ UNSIGNED);
|
||
|
|
+
|
||
|
|
FOR_EACH_MODE_IN_CLASS (cmp_mode_iter, MODE_INT)
|
||
|
|
{
|
||
|
|
unsigned int cmp_bits = GET_MODE_BITSIZE (cmp_mode_iter.require ());
|
||
|
|
@@ -1075,10 +1085,32 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
&& can_produce_all_loop_masks_p (loop_vinfo, this_type))
|
||
|
|
{
|
||
|
|
/* Although we could stop as soon as we find a valid mode,
|
||
|
|
- it's often better to continue until we hit Pmode, since the
|
||
|
|
- operands to the WHILE are more likely to be reusable in
|
||
|
|
- address calculations. */
|
||
|
|
- cmp_type = this_type;
|
||
|
|
+ there are at least two reasons why that's not always the
|
||
|
|
+ best choice:
|
||
|
|
+
|
||
|
|
+ - An IV that's Pmode or wider is more likely to be reusable
|
||
|
|
+ in address calculations than an IV that's narrower than
|
||
|
|
+ Pmode.
|
||
|
|
+
|
||
|
|
+ - Doing the comparison in IV_PRECISION or wider allows
|
||
|
|
+ a natural 0-based IV, whereas using a narrower comparison
|
||
|
|
+ type requires mitigations against wrap-around.
|
||
|
|
+
|
||
|
|
+ Conversely, if the IV limit is variable, doing the comparison
|
||
|
|
+ in a wider type than the original type can introduce
|
||
|
|
+ unnecessary extensions, so picking the widest valid mode
|
||
|
|
+ is not always a good choice either.
|
||
|
|
+
|
||
|
|
+ Here we prefer the first IV type that's Pmode or wider,
|
||
|
|
+ and the first comparison type that's IV_PRECISION or wider.
|
||
|
|
+ (The comparison type must be no wider than the IV type,
|
||
|
|
+ to avoid extensions in the vector loop.)
|
||
|
|
+
|
||
|
|
+ ??? We might want to try continuing beyond Pmode for ILP32
|
||
|
|
+ targets if CMP_BITS < IV_PRECISION. */
|
||
|
|
+ iv_type = this_type;
|
||
|
|
+ if (!cmp_type || iv_precision > TYPE_PRECISION (cmp_type))
|
||
|
|
+ cmp_type = this_type;
|
||
|
|
if (cmp_bits >= GET_MODE_BITSIZE (Pmode))
|
||
|
|
break;
|
||
|
|
}
|
||
|
|
@@ -1089,6 +1121,7 @@ vect_verify_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
return false;
|
||
|
|
|
||
|
|
LOOP_VINFO_MASK_COMPARE_TYPE (loop_vinfo) = cmp_type;
|
||
|
|
+ LOOP_VINFO_MASK_IV_TYPE (loop_vinfo) = iv_type;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
@@ -9080,3 +9113,45 @@ optimize_mask_stores (struct loop *loop)
|
||
|
|
add_phi_arg (phi, gimple_vuse (last_store), e, UNKNOWN_LOCATION);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
+
|
||
|
|
+/* Decide whether it is possible to use a zero-based induction variable
|
||
|
|
+ when vectorizing LOOP_VINFO with a fully-masked loop. If it is,
|
||
|
|
+ return the value that the induction variable must be able to hold
|
||
|
|
+ in order to ensure that the loop ends with an all-false mask.
|
||
|
|
+ Return -1 otherwise. */
|
||
|
|
+widest_int
|
||
|
|
+vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo)
|
||
|
|
+{
|
||
|
|
+ tree niters_skip = LOOP_VINFO_MASK_SKIP_NITERS (loop_vinfo);
|
||
|
|
+ struct loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
|
||
|
|
+ unsigned HOST_WIDE_INT max_vf = vect_max_vf (loop_vinfo);
|
||
|
|
+
|
||
|
|
+ /* Calculate the value that the induction variable must be able
|
||
|
|
+ to hit in order to ensure that we end the loop with an all-false mask.
|
||
|
|
+ This involves adding the maximum number of inactive trailing scalar
|
||
|
|
+ iterations. */
|
||
|
|
+ widest_int iv_limit = -1;
|
||
|
|
+ if (max_loop_iterations (loop, &iv_limit))
|
||
|
|
+ {
|
||
|
|
+ if (niters_skip)
|
||
|
|
+ {
|
||
|
|
+ /* Add the maximum number of skipped iterations to the
|
||
|
|
+ maximum iteration count. */
|
||
|
|
+ if (TREE_CODE (niters_skip) == INTEGER_CST)
|
||
|
|
+ iv_limit += wi::to_widest (niters_skip);
|
||
|
|
+ else
|
||
|
|
+ iv_limit += max_vf - 1;
|
||
|
|
+ }
|
||
|
|
+ else if (LOOP_VINFO_PEELING_FOR_ALIGNMENT (loop_vinfo))
|
||
|
|
+ /* Make a conservatively-correct assumption. */
|
||
|
|
+ iv_limit += max_vf - 1;
|
||
|
|
+
|
||
|
|
+ /* IV_LIMIT is the maximum number of latch iterations, which is also
|
||
|
|
+ the maximum in-range IV value. Round this value down to the previous
|
||
|
|
+ vector alignment boundary and then add an extra full iteration. */
|
||
|
|
+ poly_uint64 vf = LOOP_VINFO_VECT_FACTOR (loop_vinfo);
|
||
|
|
+ iv_limit = (iv_limit & -(int) known_alignment (vf)) + max_vf;
|
||
|
|
+ }
|
||
|
|
+ return iv_limit;
|
||
|
|
+}
|
||
|
|
+
|
||
|
|
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
|
||
|
|
index 34ba49f4d..fae4df52d 100644
|
||
|
|
--- a/gcc/tree-vectorizer.h
|
||
|
|
+++ b/gcc/tree-vectorizer.h
|
||
|
|
@@ -529,6 +529,10 @@ typedef struct _loop_vec_info : public vec_info {
|
||
|
|
is false and vectorized loop otherwise. */
|
||
|
|
tree simd_if_cond;
|
||
|
|
|
||
|
|
+ /* Type of the IV to use in the WHILE_ULT call for fully-masked
|
||
|
|
+ loops. */
|
||
|
|
+ tree iv_type;
|
||
|
|
+
|
||
|
|
/* Unknown DRs according to which loop was peeled. */
|
||
|
|
struct dr_vec_info *unaligned_dr;
|
||
|
|
|
||
|
|
@@ -675,6 +679,7 @@ typedef struct _loop_vec_info : public vec_info {
|
||
|
|
#define LOOP_VINFO_MASKS(L) (L)->masks
|
||
|
|
#define LOOP_VINFO_MASK_SKIP_NITERS(L) (L)->mask_skip_niters
|
||
|
|
#define LOOP_VINFO_MASK_COMPARE_TYPE(L) (L)->mask_compare_type
|
||
|
|
+#define LOOP_VINFO_MASK_IV_TYPE(L) (L)->iv_type
|
||
|
|
#define LOOP_VINFO_PTR_MASK(L) (L)->ptr_mask
|
||
|
|
#define LOOP_VINFO_LOOP_NEST(L) (L)->shared->loop_nest
|
||
|
|
#define LOOP_VINFO_DATAREFS(L) (L)->shared->datarefs
|
||
|
|
@@ -1720,6 +1725,7 @@ extern tree vect_create_addr_base_for_vector_ref (stmt_vec_info, gimple_seq *,
|
||
|
|
/* In tree-vect-loop.c. */
|
||
|
|
/* Used in tree-vect-loop-manip.c */
|
||
|
|
extern void determine_peel_for_niter (loop_vec_info);
|
||
|
|
+extern widest_int vect_iv_limit_for_full_masking (loop_vec_info loop_vinfo);
|
||
|
|
/* Used in gimple-loop-interchange.c and tree-parloops.c. */
|
||
|
|
extern bool check_reduction_path (dump_user_location_t, loop_p, gphi *, tree,
|
||
|
|
enum tree_code);
|