@@ -688,7 +688,11 @@ c_pretty_printer::direct_abstract_declarator (tree t)
maxval = TREE_OPERAND (maxval, 0);
}
- expression (maxval);
+ /* This covers unspecified bounds. */
+ if (TREE_CODE (maxval) == COMPOUND_EXPR)
+ pp_string (this, "*");
+ else
+ expression (maxval);
}
}
else if (TYPE_SIZE (t))
@@ -714,22 +714,9 @@ add_stmt (tree t)
return t;
}
-
-/* Build a pointer type using the default pointer mode. */
-static tree
-c_build_pointer_type (tree to_type)
-{
- addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
- : TYPE_ADDR_SPACE (to_type);
- machine_mode pointer_mode;
- if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
- pointer_mode = targetm.addr_space.pointer_mode (as);
- else
- pointer_mode = c_default_pointer_mode;
- return build_pointer_type_for_mode (to_type, pointer_mode, false);
-}
+
/* Return true if we will want to say something if a goto statement
@@ -1921,7 +1908,7 @@ match_builtin_function_types (tree newtype, tree oldtype,
newargs = TREE_CHAIN (newargs);
}
- tree trytype = build_function_type (newrettype, tryargs);
+ tree trytype = c_build_function_type (newrettype, tryargs);
/* Allow declaration to change transaction_safe attribute. */
tree oldattrs = TYPE_ATTRIBUTES (oldtype);
@@ -1934,7 +1921,7 @@ match_builtin_function_types (tree newtype, tree oldtype,
oldattrs = tree_cons (get_identifier ("transaction_safe"),
NULL_TREE, oldattrs);
- return build_type_attribute_variant (trytype, oldattrs);
+ return c_build_type_attribute_variant (trytype, oldattrs);
}
/* Subroutine of diagnose_mismatched_decls. Check for function type
@@ -3395,9 +3382,9 @@ pushdecl (tree x)
if (TREE_CODE (b_use->decl) == FUNCTION_DECL
&& fndecl_built_in_p (b_use->decl))
thistype
- = build_type_attribute_variant (thistype,
- TYPE_ATTRIBUTES
- (b_use->u.type));
+ = c_build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES
+ (b_use->u.type));
TREE_TYPE (b_use->decl) = thistype;
}
return b_use->decl;
@@ -3495,8 +3482,8 @@ pushdecl (tree x)
b->u.type = TREE_TYPE (b->decl);
/* Propagate the type attributes to the decl. */
thistype
- = build_type_attribute_variant (thistype,
- TYPE_ATTRIBUTES (b->u.type));
+ = c_build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->u.type));
TREE_TYPE (b->decl) = thistype;
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true,
locus);
@@ -3894,9 +3881,9 @@ implicitly_declare (location_t loc, tree functionid)
}
if (fndecl_built_in_p (decl))
{
- newtype = build_type_attribute_variant (newtype,
- TYPE_ATTRIBUTES
- (TREE_TYPE (decl)));
+ newtype = c_build_type_attribute_variant (newtype,
+ TYPE_ATTRIBUTES
+ (TREE_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
auto_diagnostic_group d;
@@ -4836,8 +4823,8 @@ c_make_fname_decl (location_t loc, tree id, int type_dep)
tree decl, type, init;
size_t length = strlen (name);
- type = build_array_type (char_type_node,
- build_index_type (size_int (length)));
+ type = c_build_array_type (char_type_node,
+ build_index_type (size_int (length)));
type = c_build_qualified_type (type, TYPE_QUAL_CONST);
decl = build_decl (loc, VAR_DECL, id, type);
@@ -7222,8 +7209,6 @@ grokdeclarator (const struct c_declarator *declarator,
array_parm_static = false;
}
- bool varmod = C_TYPE_VARIABLY_MODIFIED (type);
-
switch (declarator->kind)
{
case cdk_attrs:
@@ -7505,31 +7490,20 @@ grokdeclarator (const struct c_declarator *declarator,
/* ISO C99 Flexible array members are effectively
identical to GCC's zero-length array extension. */
- if (flexible_array_member || array_parm_vla_unspec_p)
- itype = build_range_type (sizetype, size_zero_node,
- NULL_TREE);
+ if (flexible_array_member)
+ itype = build_index_type (NULL_TREE);
}
- else if (decl_context == PARM)
+
+ if (array_parm_vla_unspec_p)
{
- if (array_parm_vla_unspec_p)
- {
- itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- size_varies = true;
- }
- }
- else if (decl_context == TYPENAME)
- {
- if (array_parm_vla_unspec_p)
- {
- /* C99 6.7.5.2p4 */
- warning (0, "%<[*]%> not in a declaration");
- /* We use this to avoid messing up with incomplete
- array types of the same type, that would
- otherwise be modified below. */
- itype = build_range_type (sizetype, size_zero_node,
- NULL_TREE);
- size_varies = true;
- }
+ /* C99 6.7.5.2p4 */
+ if (decl_context == TYPENAME)
+ warning (0, "%<[*]%> not in a declaration");
+ /* Array of unspecified size. */
+ tree upper = build2 (COMPOUND_EXPR, TREE_TYPE (size_zero_node),
+ integer_zero_node, size_zero_node);
+ itype = build_index_type (upper);
+ size_varies = true;
}
/* Complain about arrays of incomplete types. */
@@ -7560,34 +7534,15 @@ grokdeclarator (const struct c_declarator *declarator,
modify the shared type, so we gcc_assert (itype)
below. */
{
- /* Identify typeless storage as introduced in C2Y
- and supported also in earlier language modes. */
- bool typeless = (char_type_p (type)
- && !(type_quals & TYPE_QUAL_ATOMIC))
- || (AGGREGATE_TYPE_P (type)
- && TYPE_TYPELESS_STORAGE (type));
-
addr_space_t as = DECODE_QUAL_ADDR_SPACE (type_quals);
if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
- type = build_qualified_type (type,
- ENCODE_QUAL_ADDR_SPACE (as));
- type = build_array_type (type, itype, typeless);
+ type = c_build_qualified_type (type,
+ ENCODE_QUAL_ADDR_SPACE (as));
+ type = c_build_array_type (type, itype);
}
if (type != error_mark_node)
{
- if (size_varies)
- {
- /* It is ok to modify type here even if itype is
- NULL: if size_varies, we're in a
- multi-dimensional array and the inner type has
- variable size, so the enclosing shared array type
- must too. */
- if (size && TREE_CODE (size) == INTEGER_CST)
- type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
- C_TYPE_VARIABLE_SIZE (type) = 1;
- }
-
/* The GCC extension for zero-length arrays differs from
ISO flexible array members in that sizeof yields
zero. */
@@ -7599,15 +7554,6 @@ grokdeclarator (const struct c_declarator *declarator,
TYPE_SIZE_UNIT (type) = size_zero_node;
SET_TYPE_STRUCTURAL_EQUALITY (type);
}
- if (array_parm_vla_unspec_p)
- {
- gcc_assert (itype);
- /* The type is complete. C99 6.7.5.2p4 */
- type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
- TYPE_SIZE (type) = bitsize_zero_node;
- TYPE_SIZE_UNIT (type) = size_zero_node;
- SET_TYPE_STRUCTURAL_EQUALITY (type);
- }
if (!valid_array_size_p (loc, type, name))
type = error_mark_node;
@@ -7730,8 +7676,8 @@ grokdeclarator (const struct c_declarator *declarator,
}
type_quals = TYPE_UNQUALIFIED;
- type = build_function_type (type, arg_types,
- arg_info->no_named_args_stdarg_p);
+ type = c_build_function_type (type, arg_types,
+ arg_info->no_named_args_stdarg_p);
declarator = declarator->declarator;
/* Set the TYPE_CONTEXTs for each tagged type which is local to
@@ -7796,8 +7742,6 @@ grokdeclarator (const struct c_declarator *declarator,
default:
gcc_unreachable ();
}
- if (type != error_mark_node)
- C_TYPE_VARIABLY_MODIFIED (type) = varmod || size_varies;
}
*decl_attrs = chainon (returned_attrs, *decl_attrs);
*decl_attrs = chainon (decl_id_attrs, *decl_attrs);
@@ -8120,7 +8064,7 @@ grokdeclarator (const struct c_declarator *declarator,
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error_at (loc, "field %qE declared as a function", name);
- type = build_pointer_type (type);
+ type = c_build_pointer_type (type);
}
else if (TREE_CODE (type) != ERROR_MARK
&& !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
@@ -9444,7 +9388,7 @@ c_update_type_canonical (tree t)
else
{
tree
- c = build_qualified_type (TYPE_CANONICAL (t), TYPE_QUALS (x));
+ c = c_build_qualified_type (TYPE_CANONICAL (t), TYPE_QUALS (x));
if (TYPE_STRUCTURAL_EQUALITY_P (c))
{
gcc_checking_assert (TYPE_CANONICAL (t) == t);
@@ -9479,8 +9423,8 @@ c_update_type_canonical (tree t)
continue;
if (TYPE_CANONICAL (x) != x || TYPE_REF_CAN_ALIAS_ALL (p))
TYPE_CANONICAL (p)
- = build_pointer_type_for_mode (TYPE_CANONICAL (x), TYPE_MODE (p),
- false);
+ = c_build_pointer_type_for_mode (TYPE_CANONICAL (x), TYPE_MODE (p),
+ false);
else
TYPE_CANONICAL (p) = p;
c_update_type_canonical (p);
@@ -10709,9 +10653,9 @@ start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
error_at (loc, "return type is an incomplete type");
/* Make it return void instead. */
TREE_TYPE (decl1)
- = build_function_type (void_type_node,
- TYPE_ARG_TYPES (TREE_TYPE (decl1)),
- TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (decl1)));
+ = c_build_function_type (void_type_node,
+ TYPE_ARG_TYPES (TREE_TYPE (decl1)),
+ TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (decl1)));
}
if (warn_about_return_type)
@@ -74,6 +74,8 @@ extern void c_register_features ();
#define LANG_HOOKS_EMITS_BEGIN_STMT true
#undef LANG_HOOKS_FINALIZE_EARLY_DEBUG
#define LANG_HOOKS_FINALIZE_EARLY_DEBUG c_common_finalize_early_debug
+#undef LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE
+#define LANG_HOOKS_RECONSTRUCT_COMPLEX_TYPE c_reconstruct_complex_type
static const scoped_attribute_specs *const c_objc_attribute_table[] =
{
@@ -4415,7 +4415,7 @@ c_parser_typeof_specifier (c_parser *parser)
else if (FUNCTION_POINTER_TYPE_P (ret.spec)
&& TYPE_QUALS (TREE_TYPE (ret.spec)) != TYPE_UNQUALIFIED)
ret.spec
- = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
+ = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (ret.spec)));
}
}
return ret;
@@ -10708,7 +10708,7 @@ c_parser_generic_selection (c_parser *parser)
if (FUNCTION_POINTER_TYPE_P (selector_type)
&& TYPE_QUALS (TREE_TYPE (selector_type)) != TYPE_UNQUALIFIED)
selector_type
- = build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
+ = c_build_pointer_type (TYPE_MAIN_VARIANT (TREE_TYPE (selector_type)));
}
if (!c_parser_require (parser, CPP_COMMA, "expected %<,%>"))
@@ -875,6 +875,13 @@ extern tree c_build_function_call_vec (location_t, const vec<location_t>&,
tree, vec<tree, va_gc> *,
vec<tree, va_gc> *);
extern tree c_omp_clause_copy_ctor (tree, tree, tree);
+extern tree c_reconstruct_complex_type (tree, tree);
+extern tree c_build_type_attribute_variant (tree ntype, tree attrs);
+extern tree c_build_pointer_type (tree type);
+extern tree c_build_array_type (tree type, tree domain);
+extern tree c_build_function_type (tree type, tree args, bool no = false);
+extern tree c_build_pointer_type_for_mode (tree type, machine_mode mode, bool m);
+
/* Set to 0 at beginning of a function definition, set to 1 if
a return statement that specifies a return value is seen. */
@@ -356,6 +356,193 @@ qualify_type (tree type, tree like)
| ENCODE_QUAL_ADDR_SPACE (as_common));
}
+
+/* Check consistency of type TYP.E For derived types, we test that
+ C_TYPE_VARIABLE_SIZE and C_TYPE_VARIABLY_MODIFIED are consistent with
+ the requirements of the base type. We also check that arrays with a
+ non-constant length are marked with C_TYPE_VARIABLE_SIZE. If any
+ inconsistency is detected false is returned and true otherwise. */
+
+static bool
+c_verify_type (tree type)
+{
+ switch (TREE_CODE (type))
+ {
+ case POINTER_TYPE:
+ case FUNCTION_TYPE:
+ /* Pointer and funcions can not have variable size. */
+ if (C_TYPE_VARIABLE_SIZE (type))
+ return false;
+ /* Pointer and funcions are variably modified if and only if the
+ return / target type is variably modified. */
+ if (C_TYPE_VARIABLY_MODIFIED (type)
+ != C_TYPE_VARIABLY_MODIFIED (TREE_TYPE (type)))
+ return false;
+ break;
+ case ARRAY_TYPE:
+ /* An array has variable size if and only if it has a non-constant
+ dimensions or its element type has variable size. */
+ if ((C_TYPE_VARIABLE_SIZE (TREE_TYPE (type))
+ || (TYPE_DOMAIN (type) && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
+ != INTEGER_CST))
+ != C_TYPE_VARIABLE_SIZE (type))
+ return false;
+ /* If the element type or the array has variable size, then the
+ array has variable size and is variably modified. */
+ if (C_TYPE_VARIABLE_SIZE (TREE_TYPE (type))
+ || C_TYPE_VARIABLE_SIZE (type))
+ {
+ if (!C_TYPE_VARIABLE_SIZE (type))
+ return false;
+ if (!C_TYPE_VARIABLY_MODIFIED (type))
+ return false;
+ }
+ /* If the element type is variably modified, then also the array. */
+ if (C_TYPE_VARIABLY_MODIFIED (TREE_TYPE (type))
+ && !C_TYPE_VARIABLY_MODIFIED (type))
+ return false;
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+/* Propagate C_TYPE_VARIABLY_MODIFIED and C_TYPE_VARIABLE_SIZE
+ from a base type to a newly built derived or qualified type. */
+
+static tree
+c_set_type_bits (tree new_type, tree old_type)
+{
+ gcc_checking_assert (c_verify_type (old_type));
+
+ if (C_TYPE_VARIABLY_MODIFIED (old_type))
+ C_TYPE_VARIABLY_MODIFIED (new_type) = true;
+
+ if (TREE_CODE (new_type) == ARRAY_TYPE && C_TYPE_VARIABLE_SIZE (old_type))
+ {
+ C_TYPE_VARIABLY_MODIFIED (new_type) = true;
+ C_TYPE_VARIABLE_SIZE (new_type) = true;
+ }
+ return new_type;
+}
+
+/* Build a pointer type using the default pointer mode. */
+
+tree
+c_build_pointer_type (tree to_type)
+{
+ addr_space_t as = to_type == error_mark_node? ADDR_SPACE_GENERIC
+ : TYPE_ADDR_SPACE (to_type);
+ machine_mode pointer_mode;
+
+ if (as != ADDR_SPACE_GENERIC || c_default_pointer_mode == VOIDmode)
+ pointer_mode = targetm.addr_space.pointer_mode (as);
+ else
+ pointer_mode = c_default_pointer_mode;
+
+ return c_build_pointer_type_for_mode (to_type, pointer_mode, false);
+}
+
+/* Build a pointer type using the given mode. */
+
+tree
+c_build_pointer_type_for_mode (tree type, machine_mode mode, bool m)
+{
+ tree ret = build_pointer_type_for_mode (type, mode, m);
+ return c_set_type_bits (ret, type);
+}
+
+/* Build a function type. */
+
+tree
+c_build_function_type (tree type, tree args, bool no)
+{
+ tree ret = build_function_type (type, args, no);
+ return c_set_type_bits (ret, type);
+}
+
+/* Build an array type. This sets typeless storage as required
+ by C23 and C_TYPE_VARIABLY_MODIFIED and C_TYPE_VARIABLE_SIZE
+ based on the element type and domain. */
+
+tree
+c_build_array_type (tree type, tree domain)
+{
+ int type_quals = TYPE_QUALS (type);
+
+ /* Identify typeless storage as introduced in C2Y
+ and supported also in earlier language modes. */
+ bool typeless = (char_type_p (type) && !(type_quals & TYPE_QUAL_ATOMIC))
+ || (AGGREGATE_TYPE_P (type) && TYPE_TYPELESS_STORAGE (type));
+
+ tree ret = build_array_type (type, domain, typeless);
+
+ if (domain && TYPE_MAX_VALUE (domain)
+ && TREE_CODE (TYPE_MAX_VALUE (domain)) != INTEGER_CST)
+ {
+ C_TYPE_VARIABLE_SIZE (ret) = 1;
+ C_TYPE_VARIABLY_MODIFIED (ret) = 1;
+ }
+
+ return c_set_type_bits (ret, type);
+}
+
+tree
+c_build_type_attribute_qual_variant (tree type, tree attrs, int quals)
+{
+ tree ret = build_type_attribute_qual_variant (type, attrs, quals);
+ return c_set_type_bits (ret, type);
+}
+
+tree
+c_build_type_attribute_variant (tree type, tree attrs)
+{
+ return c_build_type_attribute_qual_variant (type, attrs, TYPE_QUALS (type));
+}
+
+/* Reconstruct a complex derived type. This is used to re-construct types
+ with the vector attribute. It is called via a langhook. */
+
+tree
+c_reconstruct_complex_type (tree type, tree bottom)
+{
+ tree inner, outer;
+
+ if (TREE_CODE (type) == POINTER_TYPE)
+ {
+ inner = c_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = c_build_pointer_type_for_mode (inner, TYPE_MODE (type),
+ TYPE_REF_CAN_ALIAS_ALL (type));
+ }
+ else if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ inner = c_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = c_build_array_type (inner, TYPE_DOMAIN (type));
+
+ gcc_checking_assert (C_TYPE_VARIABLE_SIZE (type)
+ == C_TYPE_VARIABLE_SIZE (outer));
+ gcc_checking_assert (C_TYPE_VARIABLY_MODIFIED (outer)
+ == C_TYPE_VARIABLY_MODIFIED (type));
+ }
+ else if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ inner = c_reconstruct_complex_type (TREE_TYPE (type), bottom);
+ outer = c_build_function_type (inner, TYPE_ARG_TYPES (type),
+ TYPE_NO_NAMED_ARGS_STDARG_P (type));
+ }
+ else if (TREE_CODE (type) == REFERENCE_TYPE
+ || TREE_CODE (type) == OFFSET_TYPE)
+ {
+ gcc_assert (0);
+ }
+ else
+ return bottom;
+
+ return c_build_type_attribute_qual_variant (outer, TYPE_ATTRIBUTES (type),
+ TYPE_QUALS (type));
+}
/* If NTYPE is a type of a non-variadic function with a prototype
and OTYPE is a type of a function without a prototype and ATTRS
@@ -364,7 +551,7 @@ qualify_type (tree type, tree like)
the (possibly) modified ATTRS. */
static tree
-build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
+c_build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
{
if (!prototype_p (otype)
&& prototype_p (ntype)
@@ -375,9 +562,11 @@ build_functype_attribute_variant (tree ntype, tree otype, tree attrs)
"does not take variable arguments", "format");
attrs = remove_attribute ("format", attrs);
}
- return build_type_attribute_variant (ntype, attrs);
+ return c_build_type_attribute_variant (ntype, attrs);
}
+
+
/* Return the composite type of two compatible types.
We assume that comptypes has already been done and returned
@@ -439,8 +628,8 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
tree pointed_to_2 = TREE_TYPE (t2);
tree target = composite_type_internal (pointed_to_1,
pointed_to_2, cache);
- t1 = build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
- t1 = build_type_attribute_variant (t1, attributes);
+ t1 = c_build_pointer_type_for_mode (target, TYPE_MODE (t1), false);
+ t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
@@ -478,15 +667,15 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Save space: see if the result is identical to one of the args. */
if (elt == TREE_TYPE (t1) && TYPE_DOMAIN (t1)
&& (d2_variable || d2_zero || !d1_variable))
- return build_type_attribute_variant (t1, attributes);
+ return c_build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
&& (d1_variable || d1_zero || !d2_variable))
- return build_type_attribute_variant (t2, attributes);
+ return c_build_type_attribute_variant (t2, attributes);
if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return build_type_attribute_variant (t1, attributes);
+ return c_build_type_attribute_variant (t1, attributes);
if (elt == TREE_TYPE (t2) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
- return build_type_attribute_variant (t2, attributes);
+ return c_build_type_attribute_variant (t2, attributes);
/* Merge the element types, and have a size if either arg has
one. We may have qualifiers on the element types. To set
@@ -495,13 +684,21 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
back at the end. */
quals = TYPE_QUALS (strip_array_types (elt));
unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
- t1 = build_array_type (unqual_elt,
- TYPE_DOMAIN ((TYPE_DOMAIN (t1)
- && (d2_variable
- || d2_zero
- || !d1_variable))
- ? t1
- : t2));
+ t1 = c_build_array_type (unqual_elt,
+ TYPE_DOMAIN ((TYPE_DOMAIN (t1)
+ && (d2_variable
+ || d2_zero
+ || !d1_variable))
+ ? t1
+ : t2));
+
+ /* Check that a type which has a varying outermost dimension
+ got marked has having a variable size. */
+ bool varsize = (d1_variable && d2_variable)
+ || (d1_variable && !t2_complete)
+ || (d2_variable && !t1_complete);
+ gcc_checking_assert (!varsize || C_TYPE_VARIABLE_SIZE (t1));
+
/* Ensure a composite type involving a zero-length array type
is a zero-length type not an incomplete type. */
if (d1_zero && d2_zero
@@ -512,7 +709,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
TYPE_SIZE_UNIT (t1) = size_zero_node;
}
t1 = c_build_qualified_type (t1, quals);
- return build_type_attribute_variant (t1, attributes);
+ return c_build_type_attribute_variant (t1, attributes);
}
case RECORD_TYPE:
@@ -611,7 +808,7 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
if (attribute_list_equal (TYPE_ATTRIBUTES (t2), attributes))
return t2;
}
- return build_type_attribute_variant (t1, attributes);
+ return c_build_type_attribute_variant (t1, attributes);
case FUNCTION_TYPE:
/* Function types: prefer the one that specified arg types.
@@ -627,23 +824,23 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && !TYPE_ARG_TYPES (t2))
- return build_functype_attribute_variant (t1, t2, attributes);
+ return c_build_functype_attribute_variant (t1, t2, attributes);
if (valtype == TREE_TYPE (t2) && !TYPE_ARG_TYPES (t1))
- return build_functype_attribute_variant (t2, t1, attributes);
+ return c_build_functype_attribute_variant (t2, t1, attributes);
/* Simple way if one arg fails to specify argument types. */
if (TYPE_ARG_TYPES (t1) == NULL_TREE)
{
- t1 = build_function_type (valtype, TYPE_ARG_TYPES (t2),
- TYPE_NO_NAMED_ARGS_STDARG_P (t2));
- t1 = build_type_attribute_variant (t1, attributes);
+ t1 = c_build_function_type (valtype, TYPE_ARG_TYPES (t2),
+ TYPE_NO_NAMED_ARGS_STDARG_P (t2));
+ t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
if (TYPE_ARG_TYPES (t2) == NULL_TREE)
{
- t1 = build_function_type (valtype, TYPE_ARG_TYPES (t1),
- TYPE_NO_NAMED_ARGS_STDARG_P (t1));
- t1 = build_type_attribute_variant (t1, attributes);
+ t1 = c_build_function_type (valtype, TYPE_ARG_TYPES (t1),
+ TYPE_NO_NAMED_ARGS_STDARG_P (t1));
+ t1 = c_build_type_attribute_variant (t1, attributes);
return qualify_type (t1, t2);
}
@@ -738,13 +935,13 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
parm_done: ;
}
- t1 = build_function_type (valtype, newargs);
+ t1 = c_build_function_type (valtype, newargs);
t1 = qualify_type (t1, t2);
}
/* FALLTHRU */
default:
- return build_type_attribute_variant (t1, attributes);
+ return c_build_type_attribute_variant (t1, attributes);
}
}
@@ -821,8 +1018,8 @@ common_pointer_type (tree t1, tree t2)
target_quals |= ENCODE_QUAL_ADDR_SPACE (as_common);
- t1 = build_pointer_type (c_build_qualified_type (target, target_quals));
- return build_type_attribute_variant (t1, attributes);
+ t1 = c_build_pointer_type (c_build_qualified_type (target, target_quals));
+ return c_build_type_attribute_variant (t1, attributes);
}
/* Return the common type for two arithmetic types under the usual
@@ -854,13 +1051,13 @@ c_common_type (tree t1, tree t2)
if (TYPE_ATTRIBUTES (t1) != NULL_TREE)
{
tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t1));
- t1 = build_type_attribute_variant (t1, attrs);
+ t1 = c_build_type_attribute_variant (t1, attrs);
}
if (TYPE_ATTRIBUTES (t2) != NULL_TREE)
{
tree attrs = affects_type_identity_attributes (TYPE_ATTRIBUTES (t2));
- t2 = build_type_attribute_variant (t2, attrs);
+ t2 = c_build_type_attribute_variant (t2, attrs);
}
/* Save time if the two types are the same. */
@@ -1180,6 +1377,9 @@ comptypes_verify (tree type1, tree type2)
|| TREE_CODE (type1) == ERROR_MARK || TREE_CODE (type2) == ERROR_MARK)
return true;
+ gcc_checking_assert (c_verify_type (type1));
+ gcc_checking_assert (c_verify_type (type2));
+
if (TYPE_CANONICAL (type1) != TYPE_CANONICAL (type2)
&& !TYPE_STRUCTURAL_EQUALITY_P (type1)
&& !TYPE_STRUCTURAL_EQUALITY_P (type2))
@@ -2001,11 +2201,7 @@ array_to_pointer_conversion (location_t loc, tree exp)
copy_warning (exp, orig_exp);
- bool varmod = C_TYPE_VARIABLY_MODIFIED (restype);
-
- ptrtype = build_pointer_type (restype);
-
- C_TYPE_VARIABLY_MODIFIED (ptrtype) = varmod;
+ ptrtype = c_build_pointer_type (restype);
if (INDIRECT_REF_P (exp))
return convert (ptrtype, TREE_OPERAND (exp, 0));
@@ -2749,7 +2945,7 @@ build_access_with_size_for_counted_by (location_t loc, tree ref,
{
gcc_assert (c_flexible_array_member_type_p (TREE_TYPE (ref)));
/* The result type of the call is a pointer to the flexible array type. */
- tree result_type = build_pointer_type (TREE_TYPE (ref));
+ tree result_type = c_build_pointer_type (TREE_TYPE (ref));
tree call
= build_call_expr_internal_loc (loc, IFN_ACCESS_WITH_SIZE,
@@ -3208,7 +3404,7 @@ build_omp_array_section (location_t loc, tree array, tree index, tree length)
gcc_assert (!error_operand_p (idxtype));
- sectype = build_array_type (eltype, idxtype);
+ sectype = c_build_array_type (eltype, idxtype);
}
return build3_loc (loc, OMP_ARRAY_SECTION, sectype, array, index, length);
@@ -4886,7 +5082,6 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
tree eptype = NULL_TREE;
const char *invalid_op_diag;
bool int_operands;
- bool varmod;
int_operands = EXPR_INT_CONST_OPERANDS (xarg);
if (int_operands)
@@ -5375,11 +5570,7 @@ build_unary_op (location_t location, enum tree_code code, tree xarg,
gcc_assert (TREE_CODE (arg) != COMPONENT_REF
|| !DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)));
- varmod = C_TYPE_VARIABLY_MODIFIED (argtype);
-
- argtype = build_pointer_type (argtype);
-
- C_TYPE_VARIABLY_MODIFIED (argtype) = varmod;
+ argtype = c_build_pointer_type (argtype);
/* ??? Cope with user tricks that amount to offsetof. Delete this
when we have proper support for integer constant expressions. */
@@ -5658,7 +5849,7 @@ type_or_builtin_type (tree expr, tree *bltin = NULL)
return type;
if ((*bltin = builtin_decl_implicit (code)))
- type = build_pointer_type (TREE_TYPE (*bltin));
+ type = c_build_pointer_type (TREE_TYPE (*bltin));
return type;
}
@@ -5943,7 +6134,7 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
/* for array, use qualifiers of element type */
if (flag_isoc23)
t2 = t2_stripped;
- result_type = build_pointer_type (qualify_type (t1, t2));
+ result_type = c_build_pointer_type (qualify_type (t1, t2));
}
/* Objective-C pointer comparisons are a bit more lenient. */
else if (objc_have_common_type (type1, type2, -3, NULL_TREE))
@@ -5966,8 +6157,8 @@ build_conditional_expr (location_t colon_loc, tree ifexp, bool ifexp_bcp,
inform (op1_loc, "first expression has type %qT", type1);
inform (op2_loc, "second expression has type %qT", type2);
}
- result_type = build_pointer_type
- (build_qualified_type (void_type_node, qual));
+ result_type = c_build_pointer_type
+ (c_build_qualified_type (void_type_node, qual));
}
}
else if (code1 == POINTER_TYPE
@@ -6921,8 +7112,8 @@ build_modify_expr (location_t location, tree lhs, tree lhs_origtype,
}
/* Remove qualifiers. */
- lhstype = build_qualified_type (lhstype, TYPE_UNQUALIFIED);
- olhstype = build_qualified_type (olhstype, TYPE_UNQUALIFIED);
+ lhstype = c_build_qualified_type (lhstype, TYPE_UNQUALIFIED);
+ olhstype = c_build_qualified_type (olhstype, TYPE_UNQUALIFIED);
/* Convert new value to destination type. Fold it first, then
restore any excess precision information, for the sake of
@@ -7572,11 +7763,11 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type,
}
if (!c_mark_addressable (rhs))
return error_mark_node;
- rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
+ rhs = build1 (ADDR_EXPR, c_build_pointer_type (TREE_TYPE (rhs)), rhs);
SET_EXPR_LOCATION (rhs, location);
rhs = convert_for_assignment (location, expr_loc,
- build_pointer_type (TREE_TYPE (type)),
+ c_build_pointer_type (TREE_TYPE (type)),
rhs, origtype, errtype,
null_pointer_constant, fundecl, function,
parmnum, warnopt);
@@ -13646,8 +13837,8 @@ build_binary_op (location_t location, enum tree_code code,
if (result_type == NULL_TREE)
{
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
- result_type = build_pointer_type
- (build_qualified_type (void_type_node, qual));
+ result_type = c_build_pointer_type
+ (c_build_qualified_type (void_type_node, qual));
}
}
else if (code0 == POINTER_TYPE
@@ -13679,10 +13870,10 @@ build_binary_op (location_t location, enum tree_code code,
create a pointer type from its type. */
else if (code0 == NULLPTR_TYPE && null_pointer_constant_p (orig_op1))
result_type = (INTEGRAL_TYPE_P (type1)
- ? build_pointer_type (type1) : type1);
+ ? c_build_pointer_type (type1) : type1);
else if (code1 == NULLPTR_TYPE && null_pointer_constant_p (orig_op0))
result_type = (INTEGRAL_TYPE_P (type0)
- ? build_pointer_type (type0) : type0);
+ ? c_build_pointer_type (type0) : type0);
if ((C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op0))
|| truth_value_p (TREE_CODE (orig_op0)))
^ (C_BOOLEAN_TYPE_P (TREE_TYPE (orig_op1))
@@ -13780,8 +13971,8 @@ build_binary_op (location_t location, enum tree_code code,
else
{
int qual = ENCODE_QUAL_ADDR_SPACE (as_common);
- result_type = build_pointer_type
- (build_qualified_type (void_type_node, qual));
+ result_type = c_build_pointer_type
+ (c_build_qualified_type (void_type_node, qual));
pedwarn (location, OPT_Wcompare_distinct_pointer_types,
"comparison of distinct pointer types lacks a cast");
}
@@ -15046,8 +15237,8 @@ handle_omp_array_sections (tree &c, enum c_omp_region_type ort)
tree eltype = TREE_TYPE (first);
while (TREE_CODE (eltype) == ARRAY_TYPE)
eltype = TREE_TYPE (eltype);
- tree type = build_array_type (eltype, index_type);
- tree ptype = build_pointer_type (eltype);
+ tree type = c_build_array_type (eltype, index_type);
+ tree ptype = c_build_pointer_type (eltype);
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
t = build_fold_addr_expr (t);
tree t2 = build_fold_addr_expr (first);
@@ -15517,10 +15708,10 @@ c_finish_omp_clauses (tree clauses, enum c_omp_region_type ort)
size = size_binop (MINUS_EXPR, size, size_one_node);
size = save_expr (size);
tree index_type = build_index_type (size);
- tree atype = build_array_type (TYPE_MAIN_VARIANT (type),
- index_type);
+ tree atype = c_build_array_type (TYPE_MAIN_VARIANT (type),
+ index_type);
atype = c_build_qualified_type (atype, TYPE_QUALS (type));
- tree ptype = build_pointer_type (type);
+ tree ptype = c_build_pointer_type (type);
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
t = build_fold_addr_expr (t);
t = build2 (MEM_REF, atype, t, build_int_cst (ptype, 0));
@@ -17176,17 +17367,17 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type,
|| (domain && TYPE_CANONICAL (domain) != domain))
{
tree unqualified_canon
- = build_array_type (TYPE_CANONICAL (element_type),
- domain? TYPE_CANONICAL (domain)
- : NULL_TREE);
+ = c_build_array_type (TYPE_CANONICAL (element_type),
+ domain ? TYPE_CANONICAL (domain)
+ : NULL_TREE);
if (TYPE_REVERSE_STORAGE_ORDER (type))
{
unqualified_canon
- = build_distinct_type_copy (unqualified_canon);
+ = build_distinct_type_copy (unqualified_canon);
TYPE_REVERSE_STORAGE_ORDER (unqualified_canon) = 1;
}
TYPE_CANONICAL (t)
- = c_build_qualified_type (unqualified_canon, type_quals);
+ = c_build_qualified_type (unqualified_canon, type_quals);
}
else
TYPE_CANONICAL (t) = t;
@@ -17208,6 +17399,12 @@ c_build_qualified_type (tree type, int type_quals, tree orig_qual_type,
tree var_type = (orig_qual_type && orig_qual_indirect == 0
? orig_qual_type
: build_qualified_type (type, type_quals));
+
+ gcc_checking_assert (C_TYPE_VARIABLE_SIZE (var_type)
+ == C_TYPE_VARIABLE_SIZE (type));
+ gcc_checking_assert (C_TYPE_VARIABLY_MODIFIED (var_type)
+ == C_TYPE_VARIABLY_MODIFIED (type));
+
/* A variant type does not inherit the list of incomplete vars from the
type main variant. */
if ((RECORD_OR_UNION_TYPE_P (var_type)
@@ -104,11 +104,9 @@ void ffpa7_n1 (void (* (* (* [8])[n1])(void))(void));
// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[n1]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-1 }
void ffpa9_x (void (* (* (* [9])[*])(void))(void));
-// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[9]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "pr?????" { xfail *-*-* } .-1 }
-// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[9]\\\)\\\[0]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "" { target *-*-* } .-2 }
+// { dg-message "previously declared as 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[9]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)'" "pr?????" { target *-*-* } .-1 }
void ffpa9_x (void (* (* (* [8])[*])(void))(void));
-// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "pr?????" { xfail *-*-* } .-1 }
-// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[0]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "" { target *-*-* } .-2 }
+// { dg-warning "argument 1 of type 'void \\\(\\\* ?\\\(\\\* ?\\\(\\\*\\\[8]\\\)\\\[\\\*]\\\)\\\(void\\\)\\\)\\\(void\\\)' with mismatched bound" "pr?????" { target *-*-* } .-1 }
/* Verify a three-dimensional array of pointers to two-dimensional arrays
of pointers to function pointers. */
@@ -37,14 +37,10 @@ void f (int[n1][2][n3][4][n5][6][n7][8][n9]);
/* Due to a limitation and because [*] is represented the same as [0]
only the most significant array bound is rendered as [*]; the others
are rendered as [0]. */
-void f (int[n1][2][n3][4][n5][6][n7][8][*]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[\\\*]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { xfail *-*-* } }
-// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[0]' declared with 1 unspecified variable bound" "pr100420" { target *-*-* } .-1 }
-void f (int[n1][2][n3][4][n5][6][*][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[\\\*]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { xfail *-*-* } }
-// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[0]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr100420" { target *-*-* } .-1 }
-void f (int[n1][2][n3][4][*][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[\\\*]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { xfail *-*-*} }
-// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[0]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr100420" { target *-*-* } .-1 }
-void f (int[n1][2][*][4][n5][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[\\\*]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { xfail *-*-* } }
-// { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[0]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable bound" "pr100420" { target *-*-* } .-1 }
+void f (int[n1][2][n3][4][n5][6][n7][8][*]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[\\\*]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { target *-*-* } }
+void f (int[n1][2][n3][4][n5][6][*][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[\\\*]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { target *-*-* } }
+void f (int[n1][2][n3][4][*][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[n3]\\\[4]\\\[\\\*]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { target *-*-*} }
+void f (int[n1][2][*][4][n5][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[2]\\\[\\\*]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" "pr100420 (expected)" { target *-*-* } }
void f (int[*][2][n3][4][n5][6][n7][8][n9]); // { dg-warning "argument 1 of type 'int\\\[\\\*]\\\[2]\\\[n3]\\\[4]\\\[n5]\\\[6]\\\[n7]\\\[8]\\\[n9]' declared with 1 unspecified variable
bound" }
void f (int[n1][n2][n3][n4][n5][n6][n7][n8][n9]); // { dg-warning "argument 1 of type 'int\\\[n1]\\\[n2]\\\[n3]\\\[n4]\\\[n5]\\\[n6]\\\[n7]\\\[n8]\\\[n9]' declared with 9 variable bounds"
}
@@ -23,21 +23,16 @@ void pa1 (int (*)[n + 1]); // { dg-warning "mismatch in bound 1 of
void ppax (int (**)[*]); // { dg-message "previously declared as 'int \\\(\\\*\\\*\\\)\\\[.]'" "note" }
void ppax (int (**)[n]); // { dg-warning "\\\[-Wvla-parameter" }
-/* A VLA with an unspecified bound is represented the same as [0] so
- so the pretty printer can't differentiate between the two forms. */
-void ppax (int (**)[1]); // { dg-bogus "\\\[-Warray-parameter" "pr100420 (expected)" { xfail *-*-* } }
- // { dg-warning "\\\[-Wvla-parameter" "pr100420 (expected)" { xfail *-*-* } .-1 }
+void ppax (int (**)[1]); // { dg-warning "\\\[-Wvla-parameter" "pr100420 (expected)" }
void ppax (int (**)[n + 1]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int *\\\(\\\*\\\*\\\)\\\[n \\\+ 1\\\]'" }
void pa1_n (int (*)[1][n]);
void pa1_n (int (*)[1][n]);
-void pa1_n (int (*)[*][n]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[\\\*]\\\[n]'" "pr100420 (expected)" { xfail *-*-*} }
- // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[0]\\\[n]'" "pr100420" { target *-*-* } .-1 }
+void pa1_n (int (*)[*][n]); // { dg-warning "mismatch in bound 1 of argument 1 declared as 'int \\\(\\\*\\\)\\\[\\\*]\\\[n]'" "pr100420 (expected)" { target *-*-*} }
void pa1_n_2 (int (*)[1][n][2]);
-void pa1_n_2 (int (*)[1][n][*]); // { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[\\\*]'" "pr100420 (expected)" { xfail *-*-* } }
- // { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[0]'" "pr100420" { target *-*-* } .-1 }
+void pa1_n_2 (int (*)[1][n][*]); // { dg-warning "mismatch in bound 3 of argument 1 declared as 'int \\\(\\\*\\\)\\\[1]\\\[n]\\\[\\\*]'" "pr100420 (expected)" { target *-*-* } }
void pa1_n_2_a1_n_2 (int (*)[1][n][2], int (*)[1][n][2]);
new file mode 100644
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+void f(int n, int m)
+{
+ typedef struct fo { int a; } aaa[n];
+ {
+ typedef struct fo { int a; } bbb[m];
+
+ goto foo; /* { dg-error "jump" } */
+ typeof((1 ? (aaa*)0 : (bbb*)0)) x;
+ foo:
+ }
+}
+
+void g(int n, int m)
+{
+ typedef struct fo { int a; } aaa[n];
+ {
+ typedef struct fo { int a; } bbb[];
+
+ goto foo; /* { dg-error "jump" } */
+ typeof((1 ? (aaa*)0 : (bbb*)0)) x;
+ foo:
+ }
+}
+
new file mode 100644
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c23" } */
+
+void b();
+int e(int c, struct d { [[gnu::vector_size(4)]] char an[c]; } *)
+{
+ (void)sizeof(struct d);
+ return 0;
+}
+void f() {
+ if (e(0, 0))
+ b();
+}
+
new file mode 100644
@@ -0,0 +1,10 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void e(int c)
+{
+ goto foo; /* { dg-error "jump into scope" } */
+ [[maybe_unused]] struct d { [[gnu::vector_size(4)]] char an[c]; } q;
+foo:
+}
+
new file mode 100644
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+void a() {
+ int b;
+ struct {
+ char c[b];
+ } bar() {
+ }
+ struct bar {
+ __attribute__((vector_size(4))) char c[b];
+ } (*d)();
+ struct bar e() { struct bar f; }
+ d = e;
+ sizeof(d());
+}
+