/* 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;
}
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)
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,
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. */
}
\f
-/* 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
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)
{
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))
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. */
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;
--- /dev/null
+/* { 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'" } */
+}
+