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)
/* Forward declarations. */
static tree lookup_name_in_scope (tree, struct c_scope *);
static tree c_make_fname_decl (tree, int);
-static tree grokdeclarator (tree, tree, enum decl_context, int, tree *);
-static tree grokparms (tree, int);
+static tree grokdeclarator (tree, tree, enum decl_context, bool, tree *);
+static tree grokparms (tree, bool);
static void layout_array_type (tree);
\f
/* States indicating how grokdeclarator() should handle declspecs marked
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;
}
}
{
tree tt = TREE_TYPE (x);
DECL_ORIGINAL_TYPE (x) = tt;
- tt = build_type_copy (tt);
+ tt = build_variant_type_copy (tt);
TYPE_NAME (tt) = x;
TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
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 ();
/* Construct an array declarator. EXPR is the expression inside [], or
NULL_TREE. QUALS are the type qualifiers inside the [] (to be applied
to the pointer to which a parameter array is converted). STATIC_P is
- nonzero if "static" is inside the [], zero otherwise. VLA_UNSPEC_P
- is nonzero is the array is [*], a VLA of unspecified length which is
+ true if "static" is inside the [], false otherwise. VLA_UNSPEC_P
+ is true if the array is [*], a VLA of unspecified length which is
nevertheless a complete type (not currently implemented by GCC),
- zero otherwise. The declarator is constructed as an ARRAY_REF
+ false otherwise. The declarator is constructed as an ARRAY_REF
(to be decoded by grokdeclarator), whose operand 0 is what's on the
- left of the [] (filled by in set_array_declarator_type) and operand 1
+ left of the [] (filled by in set_array_declarator_inner) and operand 1
is the expression inside; whose TREE_TYPE is the type qualifiers and
which has TREE_STATIC set if "static" is used. */
tree
-build_array_declarator (tree expr, tree quals, int static_p, int vla_unspec_p)
+build_array_declarator (tree expr, tree quals, bool static_p,
+ bool vla_unspec_p)
{
tree decl;
decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
/* Set the type of an array declarator. DECL is the declarator, as
constructed by build_array_declarator; TYPE is what appears on the left
- of the [] and goes in operand 0. ABSTRACT_P is nonzero if it is an
- abstract declarator, zero otherwise; this is used to reject static and
+ of the [] and goes in operand 0. ABSTRACT_P is true if it is an
+ abstract declarator, false otherwise; this is used to reject static and
type qualifiers in abstract declarators, where they are not in the
C99 grammar. */
tree
-set_array_declarator_type (tree decl, tree type, int abstract_p)
+set_array_declarator_inner (tree decl, tree type, bool abstract_p)
{
TREE_OPERAND (decl, 0) = type;
if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
- type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, 0,
+ type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
NULL);
/* Apply attributes. */
return type_name;
return grokdeclarator (TREE_VALUE (type_name),
TREE_PURPOSE (type_name),
- PARM, 0, NULL);
+ PARM, false, NULL);
}
/* Decode a declarator in an ordinary declaration or data definition.
grokfield and not through here. */
tree
-start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
+start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
{
tree decl;
tree tem;
}
}
+/* 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. */
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, 0, NULL);
+ PARM, false, NULL);
decl_attributes (&decl, TREE_VALUE (parm), 0);
decl = pushdecl (decl);
= 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);
TYPENAME if for a typename (in a cast or sizeof).
Don't make a DECL node; just return the ..._TYPE node.
FIELD for a struct or union field; make a FIELD_DECL.
- INITIALIZED is 1 if the decl has an initializer.
+ INITIALIZED is true if the decl has an initializer.
WIDTH is non-NULL for bit-fields, and is a pointer to an INTEGER_CST node
representing the width of the bit-field.
static tree
grokdeclarator (tree declarator, tree declspecs,
- enum decl_context decl_context, int initialized, tree *width)
+ enum decl_context decl_context, bool initialized, tree *width)
{
int specbits = 0;
tree spec;
}
else if (TREE_CODE (declarator) == CALL_EXPR)
{
- /* Say it's a definition only for the CALL_EXPR closest to
- the identifier. */
- bool really_funcdef = (funcdef_flag
- && (TREE_CODE (TREE_OPERAND (declarator, 0))
- == IDENTIFIER_NODE));
+ /* Say it's a definition only for the declarator closest to
+ the identifier, apart possibly from some attributes. */
+ bool really_funcdef = false;
tree arg_types;
+ if (funcdef_flag)
+ {
+ tree t = TREE_OPERAND (declarator, 0);
+ while (TREE_CODE (t) == TREE_LIST)
+ t = TREE_VALUE (t);
+ really_funcdef = (TREE_CODE (t) == IDENTIFIER_NODE);
+ }
/* Declaring a function type.
Make sure we have a valid type for the function to return. */
Return a list of arg types to use in the FUNCTION_TYPE for this function.
- FUNCDEF_FLAG is nonzero for a function definition, 0 for
+ FUNCDEF_FLAG is true for a function definition, false for
a mere declaration. A nonempty identifier-list gets an error message
- when FUNCDEF_FLAG is zero. */
+ when FUNCDEF_FLAG is false. */
static tree
-grokparms (tree arg_info, int funcdef_flag)
+grokparms (tree arg_info, bool funcdef_flag)
{
tree arg_types = ARG_INFO_TYPES (arg_info);
}
}
- value = grokdeclarator (declarator, declspecs, FIELD, 0,
+ value = grokdeclarator (declarator, declspecs, FIELD, false,
width ? &width : NULL);
finish_decl (value, NULL_TREE, NULL_TREE);
error message in c_finish_bc_stmt. */
c_break_label = c_cont_label = size_zero_node;
- decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
+ decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, true, NULL);
/* If the declarator is not suitable for a function definition,
cause a syntax error. */
will be a variant of the main variant of the original function
type. */
- TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
+ TREE_TYPE (fndecl) = build_variant_type_copy (TREE_TYPE (fndecl));
TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
}
return t;
}
+/* Return a structure for a parameter with the given SPECS, ATTRS and
+ DECLARATOR. */
+
+tree
+build_c_parm (tree specs, tree attrs, tree declarator)
+{
+ return build_tree_list (build_tree_list (specs, declarator), attrs);
+}
+
+/* Return a declarator with nested attributes. TARGET is the inner
+ declarator to which these attributes apply. ATTRS are the
+ attributes. */
+
+tree
+build_attrs_declarator (tree attrs, tree target)
+{
+ return tree_cons (attrs, target, NULL_TREE);
+}
+
+/* Return a declarator for a function with arguments specified by ARGS
+ and return type specified by TARGET. */
+
+tree
+build_function_declarator (tree args, tree target)
+{
+ return build_nt (CALL_EXPR, target, args, NULL_TREE);
+}
+
/* Return something to represent absolute declarators containing a *.
TARGET is the absolute declarator that the * contains.
TYPE_QUALS_ATTRS is a list of modifiers such as const or volatile
tree itarget = target;
split_specs_attrs (type_quals_attrs, &quals, &attrs);
if (attrs != NULL_TREE)
- itarget = tree_cons (attrs, target, NULL_TREE);
+ itarget = build_attrs_declarator (attrs, target);
return build1 (INDIRECT_REF, quals, itarget);
}