static location_t current_function_prototype_locus;
+/* The argument information structure for the function currently being
+ defined. */
+
+static GTY(()) tree current_function_arg_info;
+
/* The current statement tree. */
static GTY(()) struct stmt_tree_s c_stmt_tree;
suppress further errors about that identifier in the current
function.
+ The ->type field stores the type of the declaration in this scope;
+ if NULL, the type is the type of the ->decl field. This is only of
+ relevance for objects with external or internal linkage which may
+ be redeclared in inner scopes, forming composite types that only
+ persist for the duration of those scopes. In the external scope,
+ this stores the composite of all the types declared for this
+ object, visible or not. The ->inner_comp field (used only at file
+ scope) stores whether an incomplete array type at file scope was
+ completed at an inner scope to an array size other than 1.
+
The depth field is copied from the scope structure that holds this
decl. It is used to preserve the proper ordering of the ->shadowed
field (see bind()) and also for a handful of special-case checks.
struct c_binding GTY((chain_next ("%h.prev")))
{
tree decl; /* the decl bound */
+ tree type; /* the type in this scope */
tree id; /* the identifier it's bound to */
struct c_binding *prev; /* the previous decl in this scope */
struct c_binding *shadowed; /* the innermost decl shadowed by this one */
unsigned int depth : 28; /* depth of this scope */
BOOL_BITFIELD invisible : 1; /* normal lookup should ignore this binding */
BOOL_BITFIELD nested : 1; /* do not set DECL_CONTEXT when popping */
- /* two free bits */
+ BOOL_BITFIELD inner_comp : 1; /* incomplete array completed in inner scope */
+ /* one free bit */
};
#define B_IN_SCOPE(b1, b2) ((b1)->depth == (b2)->depth)
#define B_IN_CURRENT_SCOPE(b) ((b)->depth == current_scope->depth)
b->depth = scope->depth;
b->invisible = invisible;
b->nested = nested;
+ b->inner_comp = 0;
+
+ b->type = 0;
b->prev = scope->bindings;
scope->bindings = b;
&& scope != external_scope)
warning ("%Junused variable `%D'", p, p);
+ if (b->inner_comp)
+ {
+ error ("%Jtype of array %qD completed incompatibly with"
+ " implicit initialization", p, p);
+ }
+
/* Fall through. */
case TYPE_DECL:
case CONST_DECL:
if (I_SYMBOL_BINDING (b->id) != b) abort ();
#endif
I_SYMBOL_BINDING (b->id) = b->shadowed;
+ if (b->shadowed && b->shadowed->type)
+ TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
}
break;
else if (!DECL_FILE_SCOPE_P (newdecl))
{
if (DECL_EXTERNAL (newdecl))
- abort ();
+ {
+ /* Extern with initializer at block scope, which will
+ already have received an error. */
+ }
else if (DECL_EXTERNAL (olddecl))
- error ("%Jdeclaration of '%D' with no linkage follows "
- "extern declaration", newdecl, newdecl);
+ {
+ error ("%Jdeclaration of '%D' with no linkage follows "
+ "extern declaration", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ }
else
- error ("%Jredeclaration of '%D' with no linkage",
- newdecl, newdecl);
+ {
+ error ("%Jredeclaration of '%D' with no linkage",
+ newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ }
- locate_old_decl (olddecl, error);
return false;
}
}
b = I_SYMBOL_BINDING (name);
if (b && B_IN_SCOPE (b, scope))
{
+ if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
+ && COMPLETE_TYPE_P (TREE_TYPE (x)))
+ b->inner_comp = false;
if (duplicate_decls (x, b->decl))
return b->decl;
else
have compatible type; otherwise, the behavior is undefined.) */
if (DECL_EXTERNAL (x) || scope == file_scope)
{
+ tree type = TREE_TYPE (x);
+ tree vistype = 0;
+ tree visdecl = 0;
+ bool type_saved = false;
+ if (b && !B_IN_EXTERNAL_SCOPE (b)
+ && (TREE_CODE (b->decl) == FUNCTION_DECL
+ || TREE_CODE (b->decl) == VAR_DECL)
+ && DECL_FILE_SCOPE_P (b->decl))
+ {
+ visdecl = b->decl;
+ vistype = TREE_TYPE (visdecl);
+ }
if (warn_nested_externs
&& scope != file_scope
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of '%D'", x);
while (b && !B_IN_EXTERNAL_SCOPE (b))
- b = b->shadowed;
+ {
+ /* If this decl might be modified, save its type. This is
+ done here rather than when the decl is first bound
+ because the type may change after first binding, through
+ being completed or through attributes being added. If we
+ encounter multiple such decls, only the first should have
+ its type saved; the others will already have had their
+ proper types saved and the types will not have changed as
+ their scopes will not have been re-entered. */
+ if (DECL_FILE_SCOPE_P (b->decl) && !type_saved)
+ {
+ b->type = TREE_TYPE (b->decl);
+ type_saved = true;
+ }
+ if (B_IN_FILE_SCOPE (b)
+ && TREE_CODE (b->decl) == VAR_DECL
+ && TREE_STATIC (b->decl)
+ && TREE_CODE (TREE_TYPE (b->decl)) == ARRAY_TYPE
+ && !TYPE_DOMAIN (TREE_TYPE (b->decl))
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TYPE_DOMAIN (type)
+ && TYPE_MAX_VALUE (TYPE_DOMAIN (type))
+ && !integer_zerop (TYPE_MAX_VALUE (TYPE_DOMAIN (type))))
+ {
+ /* Array type completed in inner scope, which should be
+ diagnosed if the completion does not have size 1 and
+ it does not get completed in the file scope. */
+ b->inner_comp = true;
+ }
+ b = b->shadowed;
+ }
+
+ /* If a matching external declaration has been found, set its
+ type to the composite of all the types of that declaration.
+ After the consistency checks, it will be reset to the
+ composite of the visible types only. */
+ if (b && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
+ && b->type)
+ TREE_TYPE (b->decl) = b->type;
/* The point of the same_translation_unit_p check here is,
we want to detect a duplicate decl for a construct like
&& (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
&& duplicate_decls (x, b->decl))
{
+ tree thistype;
+ thistype = (vistype ? composite_type (vistype, type) : type);
+ b->type = TREE_TYPE (b->decl);
+ if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES (b->type));
+ TREE_TYPE (b->decl) = thistype;
bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
return b->decl;
}
else if (TREE_PUBLIC (x))
{
- bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
- nested = true;
+ if (visdecl && !b && duplicate_decls (x, visdecl))
+ {
+ /* An external declaration at block scope referring to a
+ visible entity with internal linkage. The composite
+ type will already be correct for this scope, so we
+ just need to fall through to make the declaration in
+ this scope. */
+ nested = true;
+ }
+ else
+ {
+ bind (name, x, external_scope, /*invisible=*/true,
+ /*nested=*/false);
+ nested = true;
+ }
}
}
/* Similarly, a declaration of a function with static linkage at
tree
implicitly_declare (tree functionid)
{
- tree decl = lookup_name_in_scope (functionid, external_scope);
+ struct c_binding *b;
+ tree decl = 0;
+ for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
+ {
+ if (B_IN_SCOPE (b, external_scope))
+ {
+ decl = b->decl;
+ break;
+ }
+ }
if (decl)
{
}
else
{
+ tree newtype = default_function_type;
+ if (b->type)
+ TREE_TYPE (decl) = b->type;
/* Implicit declaration of a function already declared
(somehow) in a different scope, or as a built-in.
If this is the first time this has happened, warn;
- then recycle the old declaration. */
+ then recycle the old declaration but with the new type. */
if (!C_DECL_IMPLICIT (decl))
{
implicit_decl_warning (functionid, decl);
}
if (DECL_BUILT_IN (decl))
{
- if (!comptypes (default_function_type, TREE_TYPE (decl)))
+ newtype = build_type_attribute_variant (newtype,
+ TYPE_ATTRIBUTES
+ (TREE_TYPE (decl)));
+ if (!comptypes (newtype, TREE_TYPE (decl)))
{
warning ("incompatible implicit declaration of built-in"
" function %qD", decl);
+ newtype = TREE_TYPE (decl);
}
}
else
{
- if (!comptypes (default_function_type, TREE_TYPE (decl)))
+ if (!comptypes (newtype, TREE_TYPE (decl)))
{
error ("incompatible implicit declaration of function %qD",
decl);
locate_old_decl (decl, error);
}
}
+ b->type = TREE_TYPE (decl);
+ TREE_TYPE (decl) = newtype;
bind (functionid, decl, current_scope,
/*invisible=*/false, /*nested=*/true);
return decl;
input_location.line = 0;
#endif
- build_common_tree_nodes (flag_signed_char);
+ build_common_tree_nodes (flag_signed_char, false);
c_common_nodes_and_builtins ();
}
}
+/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
+
+tree
+grokparm (tree parm)
+{
+ tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
+ TREE_PURPOSE (TREE_PURPOSE (parm)),
+ PARM, false, NULL);
+
+ decl_attributes (&decl, TREE_VALUE (parm), 0);
+
+ return decl;
+}
+
/* Given a parsed parameter declaration, decode it into a PARM_DECL
and push that on the current scope. */
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
maxindex = build_int_cst (NULL_TREE,
(TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
+ / eltsize) - 1);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
tree elts = CONSTRUCTOR_ELTS (initial_value);
- maxindex = build_int_cst (NULL_TREE, -1, -1);
+ maxindex = build_int_cst (NULL_TREE, -1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
value = 1;
/* Prevent further error messages. */
- maxindex = build_int_cst (NULL_TREE, 0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
}
}
if (!maxindex)
{
if (do_default)
- maxindex = build_int_cst (NULL_TREE, 0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
value = 2;
}
{
error ("width of `%s' exceeds its type", name);
w = max_width;
- *width = build_int_cst (NULL_TREE, w, 0);
+ *width = build_int_cst (NULL_TREE, w);
}
else
w = tree_low_cst (*width, 1);
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
/* For a function definition, record the argument information
- block in DECL_ARGUMENTS where store_parm_decls will look
- for it. */
+ block where store_parm_decls will look for it. */
if (funcdef_flag)
- DECL_ARGUMENTS (decl) = arg_info;
+ current_function_arg_info = arg_info;
if (defaulted_int)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
store_parm_decls (void)
{
tree fndecl = current_function_decl;
+ bool proto;
/* The argument information block for FNDECL. */
- tree arg_info = DECL_ARGUMENTS (fndecl);
+ tree arg_info = current_function_arg_info;
+ current_function_arg_info = 0;
/* True if this definition is written with a prototype. Note:
despite C99 6.7.5.3p14, we can *not* treat an empty argument
list in a function definition as equivalent to (void) -- an
empty argument list specifies the function has no parameters,
but only (void) sets up a prototype for future calls. */
- bool proto = ARG_INFO_TYPES (arg_info) != 0;
+ proto = ARG_INFO_TYPES (arg_info) != 0;
if (proto)
store_parm_decls_newstyle (fndecl, arg_info);
p->x_break_label = c_break_label;
p->x_cont_label = c_cont_label;
p->x_switch_stack = c_switch_stack;
+ p->arg_info = current_function_arg_info;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
c_break_label = p->x_break_label;
c_cont_label = p->x_cont_label;
c_switch_stack = p->x_switch_stack;
+ current_function_arg_info = p->arg_info;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;