mirror of
https://github.com/gcc-mirror/gcc.git
synced 2024-11-21 13:40:47 +00:00
c: minor fixes related to arrays of unspecified size
The patch for PR117145 and PR117245 also fixed PR100420 and PR116284 which are bugs related to arrays of unspecified size. Those are now represented as variable size arrays with size (0, 0). There are still some loose ends, which are resolved here by 1. adding a testcase for PR116284, 2. moving code related to creation and detection of arrays of unspecified sizes in their own functions, 3. preferring a specified size over an unspecified size when forming a composite type as required by C99 (PR118391) 4. removing useless code in comptypes_internal and composite_type_internal. PR c/116284 PR c/117391 gcc/c/ChangeLog: * c-tree.h (c_type_unspecified_p): New inline function. * c-typeck.cc (c_build_array_type_unspecified): New function. (comptypes_interal): Remove useless code. (composite_type_internal): Update. * c-decl.cc (grokdeclarator): Revise. gcc/testsuite/ChangeLog: * gcc.dg/pr116284.c: New test. * gcc.dg/pr117391.c: New test.
This commit is contained in:
parent
9c8f3d5e7d
commit
114abf075c
@ -7501,10 +7501,6 @@ grokdeclarator (const struct c_declarator *declarator,
|
||||
/* 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;
|
||||
}
|
||||
|
||||
@ -7540,7 +7536,10 @@ grokdeclarator (const struct c_declarator *declarator,
|
||||
if (!ADDR_SPACE_GENERIC_P (as) && as != TYPE_ADDR_SPACE (type))
|
||||
type = c_build_qualified_type (type,
|
||||
ENCODE_QUAL_ADDR_SPACE (as));
|
||||
type = c_build_array_type (type, itype);
|
||||
if (array_parm_vla_unspec_p)
|
||||
type = c_build_array_type_unspecified (type);
|
||||
else
|
||||
type = c_build_array_type (type, itype);
|
||||
}
|
||||
|
||||
if (type != error_mark_node)
|
||||
|
@ -776,12 +776,22 @@ extern struct c_switch *c_switch_stack;
|
||||
extern bool null_pointer_constant_p (const_tree);
|
||||
|
||||
|
||||
inline
|
||||
bool c_type_variably_modified_p (tree t)
|
||||
inline bool
|
||||
c_type_variably_modified_p (tree t)
|
||||
{
|
||||
return error_mark_node != t && C_TYPE_VARIABLY_MODIFIED (t);
|
||||
}
|
||||
|
||||
inline bool
|
||||
c_type_unspecified_p (tree t)
|
||||
{
|
||||
return error_mark_node != t
|
||||
&& C_TYPE_VARIABLE_SIZE (t) && TREE_CODE (t) == ARRAY_TYPE
|
||||
&& TYPE_DOMAIN (t) && TYPE_MAX_VALUE (TYPE_DOMAIN (t))
|
||||
&& TREE_CODE (TYPE_MAX_VALUE (TYPE_DOMAIN (t))) == COMPOUND_EXPR
|
||||
&& integer_zerop (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 0))
|
||||
&& integer_zerop (TREE_OPERAND (TYPE_MAX_VALUE (TYPE_DOMAIN (t)), 1));
|
||||
}
|
||||
|
||||
extern bool char_type_p (tree);
|
||||
extern tree c_objc_common_truthvalue_conversion (location_t, tree,
|
||||
@ -883,10 +893,10 @@ 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_array_type_unspecified (tree type);
|
||||
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. */
|
||||
|
||||
|
@ -358,7 +358,7 @@ qualify_type (tree type, tree like)
|
||||
}
|
||||
|
||||
|
||||
/* Check consistency of type TYP.E For derived types, we test that
|
||||
/* Check consistency of type TYPE. 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
|
||||
@ -490,6 +490,17 @@ c_build_array_type (tree type, tree domain)
|
||||
return c_set_type_bits (ret, type);
|
||||
}
|
||||
|
||||
|
||||
/* Build an array type of unspecified size. */
|
||||
tree
|
||||
c_build_array_type_unspecified (tree type)
|
||||
{
|
||||
tree upper = build2 (COMPOUND_EXPR, TREE_TYPE (size_zero_node),
|
||||
integer_zero_node, size_zero_node);
|
||||
return c_build_array_type (type, build_index_type (upper));
|
||||
}
|
||||
|
||||
|
||||
tree
|
||||
c_build_type_attribute_qual_variant (tree type, tree attrs, int quals)
|
||||
{
|
||||
@ -660,15 +671,23 @@ composite_type_internal (tree t1, tree t2, struct composite_cache* cache)
|
||||
d2_variable = (!d2_zero
|
||||
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|
||||
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
|
||||
d1_variable = d1_variable || (d1_zero && C_TYPE_VARIABLE_SIZE (t1));
|
||||
d2_variable = d2_variable || (d2_zero && C_TYPE_VARIABLE_SIZE (t2));
|
||||
|
||||
bool use1 = TYPE_DOMAIN (t1)
|
||||
&& (d2_variable || d2_zero || !d1_variable);
|
||||
bool use2 = TYPE_DOMAIN (t2)
|
||||
&& (d1_variable || d1_zero || !d2_variable);
|
||||
|
||||
/* If the first is an unspecified size pick the other one. */
|
||||
if (d2_variable && c_type_unspecified_p (t1))
|
||||
{
|
||||
gcc_assert (use1 && use2);
|
||||
use1 = false;
|
||||
}
|
||||
|
||||
/* 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))
|
||||
if (elt == TREE_TYPE (t1) && use1)
|
||||
return c_build_type_attribute_variant (t1, attributes);
|
||||
if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)
|
||||
&& (d1_variable || d1_zero || !d2_variable))
|
||||
if (elt == TREE_TYPE (t2) && use2)
|
||||
return c_build_type_attribute_variant (t2, attributes);
|
||||
|
||||
if (elt == TREE_TYPE (t1) && !TYPE_DOMAIN (t2) && !TYPE_DOMAIN (t1))
|
||||
@ -683,13 +702,7 @@ 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 = c_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 (use1 ? t1 : t2));
|
||||
|
||||
/* Check that a type which has a varying outermost dimension
|
||||
got marked has having a variable size. */
|
||||
@ -1658,8 +1671,6 @@ comptypes_internal (const_tree type1, const_tree type2,
|
||||
d2_variable = (!d2_zero
|
||||
&& (TREE_CODE (TYPE_MIN_VALUE (d2)) != INTEGER_CST
|
||||
|| TREE_CODE (TYPE_MAX_VALUE (d2)) != INTEGER_CST));
|
||||
d1_variable = d1_variable || (d1_zero && C_TYPE_VARIABLE_SIZE (t1));
|
||||
d2_variable = d2_variable || (d2_zero && C_TYPE_VARIABLE_SIZE (t2));
|
||||
|
||||
if (d1_variable != d2_variable)
|
||||
data->different_types_p = true;
|
||||
|
14
gcc/testsuite/gcc.dg/pr116284.c
Normal file
14
gcc/testsuite/gcc.dg/pr116284.c
Normal file
@ -0,0 +1,14 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=gnu23" } */
|
||||
|
||||
// There should be no warning about variably-modified types
|
||||
|
||||
static int a[0];
|
||||
static int b[sizeof a];
|
||||
|
||||
void foo(int (*x)[*]);
|
||||
|
||||
static int c[0];
|
||||
static int d[sizeof c];
|
||||
|
||||
|
14
gcc/testsuite/gcc.dg/pr117391.c
Normal file
14
gcc/testsuite/gcc.dg/pr117391.c
Normal file
@ -0,0 +1,14 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-std=c99" } */
|
||||
|
||||
int foo(int n, char (*buf)[*]);
|
||||
int bar(int n, char (*buf)[n]);
|
||||
|
||||
void test()
|
||||
{
|
||||
(1 ? foo : bar)(0); /* { dg-error "too few arguments to function '\\\(int \\\(\\\*\\\)\\\(int, char \\\(\\\*\\\)\\\[n]\\\)\\\)&foo'" } */
|
||||
(0 ? bar : foo)(0); /* { dg-error "too few arguments to function '\\\(int \\\(\\\*\\\)\\\(int, char \\\(\\\*\\\)\\\[n]\\\)\\\)&foo'" } */
|
||||
(0 ? foo : bar)(0); /* { dg-error "too few arguments to function 'bar'" } */
|
||||
(1 ? bar : foo)(0); /* { dg-error "too few arguments to function 'bar'" } */
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user