for (;;)
{
- tree oldargtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
- tree newargtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs));
+ tree oldargtype = TREE_VALUE (oldargs);
+ tree newargtype = TREE_VALUE (newargs);
+
+ if (oldargtype == error_mark_node || newargtype == error_mark_node)
+ return false;
+
+ oldargtype = TYPE_MAIN_VARIANT (oldargtype);
+ newargtype = TYPE_MAIN_VARIANT (newargtype);
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
}
/* If this was marked 'used', be sure it will be output. */
- if (lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
+ if (!flag_unit_at_a_time && lookup_attribute ("used", DECL_ATTRIBUTES (decl)))
mark_decl_referenced (decl);
if (TREE_CODE (decl) == TYPE_DECL)
size_varies = 1;
}
}
+ else if (decl_context == TYPENAME)
+ {
+ if (array_parm_vla_unspec_p)
+ {
+ /* The error is printed elsewhere. 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);
+ }
+ }
/* Complain about arrays of incomplete types. */
if (!COMPLETE_TYPE_P (type))
type = error_mark_node;
}
else
+ /* When itype is NULL, a shared incomplete array type is
+ returned for all array of a given type. Elsewhere we
+ make sure we don't complete that type before copying
+ it, but here we want to make sure we don't ever
+ modify the shared type, so we gcc_assert (itype)
+ below. */
type = 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));
zero. */
if (size && integer_zerop (size))
{
+ gcc_assert (itype);
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
}
if (array_parm_vla_unspec_p)
{
+ gcc_assert (itype);
/* The type is complete. C99 6.7.5.2p4 */
TYPE_SIZE (type) = bitsize_zero_node;
TYPE_SIZE_UNIT (type) = size_zero_node;
inner layer of declarator. */
arg_info = declarator->u.arg_info;
arg_types = grokparms (arg_info, really_funcdef);
+ if (really_funcdef)
+ put_pending_sizes (arg_info->pending_sizes);
/* Type qualifiers before the return type of the function
qualify the return type, not the function type. */
type = c_build_qualified_type (type, type_quals);
size_varies = 0;
+ /* When the pointed-to type involves components of variable size,
+ care must be taken to ensure that the size evaluation code is
+ emitted early enough to dominate all the possible later uses
+ and late enough for the variables on which it depends to have
+ been assigned.
+
+ This is expected to happen automatically when the pointed-to
+ type has a name/declaration of it's own, but special attention
+ is required if the type is anonymous.
+
+ We handle the NORMAL and FIELD contexts here by attaching an
+ artificial TYPE_DECL to such pointed-to type. This forces the
+ sizes evaluation at a safe point and ensures it is not deferred
+ until e.g. within a deeper conditional context.
+
+ We expect nothing to be needed here for PARM or TYPENAME.
+ Pushing a TYPE_DECL at this point for TYPENAME would actually
+ be incorrect, as we might be in the middle of an expression
+ with side effects on the pointed-to type size "arguments" prior
+ to the pointer declaration point and the fake TYPE_DECL in the
+ enclosing context would force the size evaluation prior to the
+ side effects. */
+
+ if (!TYPE_NAME (type)
+ && (decl_context == NORMAL || decl_context == FIELD)
+ && variably_modified_type_p (type, NULL_TREE))
+ {
+ tree decl = build_decl (TYPE_DECL, NULL_TREE, type);
+ DECL_ARTIFICIAL (decl) = 1;
+ pushdecl (decl);
+ finish_decl (decl, NULL_TREE, NULL_TREE);
+ TYPE_NAME (type) = decl;
+ }
+
type = build_pointer_type (type);
/* Process type qualifiers (such as const or volatile)
return decl;
}
- /* Detect the case of an array type of unspecified size
- which came, as such, direct from a typedef name.
- We must copy the type, so that each identifier gets
- a distinct type, so that each identifier's size can be
- controlled separately by its own initializer. */
-
- if (type != 0 && typedef_type != 0
- && TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
- && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
- {
- type = build_array_type (TREE_TYPE (type), 0);
- if (size_varies)
- C_TYPE_VARIABLE_SIZE (type) = 1;
- }
-
/* If this is a type name (such as, in a cast or sizeof),
compute the type and return it now. */
}
if (threadp)
- {
- if (targetm.have_tls)
- DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
- else
- /* A mere warning is sure to result in improper semantics
- at runtime. Don't bother to allow this to compile. */
- error ("thread-local storage not supported for this target");
- }
+ DECL_TLS_MODEL (decl) = decl_default_tls_model (decl);
}
if (storage_class == csc_extern
arg_info->tags = 0;
arg_info->types = 0;
arg_info->others = 0;
+ arg_info->pending_sizes = 0;
arg_info->had_vla_unspec = current_scope->had_vla_unspec;
/* The bindings in this scope must not get put into a block.
arg_info->tags = tags;
arg_info->types = types;
arg_info->others = others;
+ arg_info->pending_sizes = get_pending_sizes ();
return arg_info;
}
\f
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
+ if (old_decl && TREE_CODE (old_decl) != FUNCTION_DECL)
+ old_decl = 0;
current_function_prototype_locus = UNKNOWN_LOCATION;
current_function_prototype_built_in = false;
current_function_prototype_arg_types = NULL_TREE;