\f
/* Nonzero if we have seen an invalid cross reference
to a struct, union, or enum, but not yet printed the message. */
-
tree pending_invalid_xref;
+
/* File and line to appear in the eventual error message. */
location_t pending_invalid_xref_location;
+/* True means we've initialized exception handling. */
+bool c_eh_initialized_p;
+
/* While defining an enum type, this is 1 plus the last enumerator
constant value. Note that will do not have to save this or `enum_overflow'
around nested function definition since such a definition could only
static location_t current_function_prototype_locus;
-/* The current statement tree. */
+/* The argument information structure for the function currently being
+ defined. */
-static GTY(()) struct stmt_tree_s c_stmt_tree;
+static GTY(()) tree current_function_arg_info;
-/* The current scope statement stack. */
+/* The current statement tree. */
-static GTY(()) tree c_scope_stmt_stack;
+static GTY(()) struct stmt_tree_s c_stmt_tree;
/* State saving variables. */
-int c_in_iteration_stmt;
-int c_in_case_stmt;
+tree c_break_label;
+tree c_cont_label;
/* Linked list of TRANSLATION_UNIT_DECLS for the translation units
included in this invocation. Note that the current translation
chained together by the ->prev field, which (as the name implies)
runs in reverse order. All the decls in a given namespace bound to
a given identifier are chained by the ->shadowed field, which runs
- from inner to outer scopes. Finally, the ->contour field points
- back to the relevant scope structure; this is mainly used to make
- decls in the externals scope invisible (see below).
+ from inner to outer scopes.
The ->decl field usually points to a DECL node, but there are two
exceptions. In the namespace of type tags, the bound entity is a
RECORD_TYPE, UNION_TYPE, or ENUMERAL_TYPE node. If an undeclared
identifier is encountered, it is bound to error_mark_node to
suppress further errors about that identifier in the current
- function. */
+ 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.
+ Finally, the invisible bit is true for a decl which should be
+ ignored for purposes of normal name lookup, and the nested bit is
+ true for a decl that's been bound a second time in an inner scope;
+ in all such cases, the binding in the outer scope will have its
+ invisible bit true. */
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 */
- struct c_scope *contour; /* the scope in which this decl is bound */
+ 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 */
+ 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)
+#define B_IN_FILE_SCOPE(b) ((b)->depth == 1 /*file_scope->depth*/)
+#define B_IN_EXTERNAL_SCOPE(b) ((b)->depth == 0 /*external_scope->depth*/)
#define I_SYMBOL_BINDING(node) \
(((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->symbol_binding)
/* Functions called automatically at the beginning and end of execution. */
-tree static_ctors, static_dtors;
+static GTY(()) tree static_ctors;
+static GTY(()) tree static_dtors;
/* 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
which may be any of several kinds of DECL or TYPE or error_mark_node,
in the scope SCOPE. */
static void
-bind (tree name, tree decl, struct c_scope *scope)
+bind (tree name, tree decl, struct c_scope *scope, bool invisible, bool nested)
{
struct c_binding *b, **here;
binding_freelist = b->prev;
}
else
- b = ggc_alloc (sizeof (struct c_binding));
+ b = GGC_NEW (struct c_binding);
b->shadowed = 0;
b->decl = decl;
b->id = name;
- b->contour = scope;
+ b->depth = scope->depth;
+ b->invisible = invisible;
+ b->nested = nested;
+ b->inner_comp = 0;
+
+ b->type = 0;
b->prev = scope->bindings;
scope->bindings = b;
/* Locate the appropriate place in the chain of shadowed decls
to insert this binding. Normally, scope == current_scope and
this does nothing. */
- while (*here && (*here)->contour->depth > scope->depth)
+ while (*here && (*here)->depth > scope->depth)
here = &(*here)->shadowed;
b->shadowed = *here;
{
struct c_binding *prev = b->prev;
- b->id = 0;
- b->decl = 0;
- b->contour = 0;
- b->shadowed = 0;
+ memset (b, 0, sizeof (struct c_binding));
b->prev = binding_freelist;
binding_freelist = b;
scope_freelist = scope->outer;
}
else
- scope = ggc_alloc_cleared (sizeof (struct c_scope));
+ scope = GGC_CNEW (struct c_scope);
scope->keep = keep_next_level_flag;
scope->outer = current_scope;
scope->depth--;
sorry ("GCC supports only %u nested scopes\n", scope->depth);
}
-
+
current_scope = scope;
keep_next_level_flag = false;
}
}
+/* Set the TYPE_CONTEXT of all of TYPE's variants to CONTEXT. */
+
+static void
+set_type_context (tree type, tree context)
+{
+ for (type = TYPE_MAIN_VARIANT (type); type;
+ type = TYPE_NEXT_VARIANT (type))
+ TYPE_CONTEXT (type) = context;
+}
+
/* Exit a scope. Restore the state of the identifier-decl mappings
that were in effect when this scope was entered. Return a BLOCK
node containing all the DECLs in this scope that are of interest
/* Labels go in BLOCK_VARS. */
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
-
+
#ifdef ENABLE_CHECKING
if (I_LABEL_BINDING (b->id) != b) abort ();
#endif
case ENUMERAL_TYPE:
case UNION_TYPE:
case RECORD_TYPE:
- TYPE_CONTEXT (p) = context;
+ set_type_context (p, context);
/* Types may not have tag-names, in which case the type
appears in the bindings list with b->id NULL. */
goto common_symbol;
case VAR_DECL:
- /* Warnings for unused variables. Keep this in sync with
- stmt.c:warn_about_unused_variables, which we cannot use
- since it expects a different data structure. */
+ /* Warnings for unused variables. */
if (warn_unused_variable
&& !TREE_USED (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& 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:
common_symbol:
/* All of these go in BLOCK_VARS, but only if this is the
binding in the home scope. */
- if (!C_DECL_IN_EXTERNAL_SCOPE (p) || scope == external_scope)
+ if (!b->nested)
{
TREE_CHAIN (p) = BLOCK_VARS (block);
BLOCK_VARS (block) = p;
}
- /* If this is the file scope, must set DECL_CONTEXT on these. */
- if (!C_DECL_IN_EXTERNAL_SCOPE (p) && scope == file_scope)
- DECL_CONTEXT (p) = context;
+ /* If this is the file scope, and we are processing more
+ than one translation unit in this compilation, set
+ DECL_CONTEXT of each decl to the TRANSLATION_UNIT_DECL.
+ This makes same_translation_unit_p work, and causes
+ static declarations to be given disambiguating suffixes. */
+ if (scope == file_scope && num_in_fnames > 1)
+ {
+ DECL_CONTEXT (p) = context;
+ if (TREE_CODE (p) == TYPE_DECL)
+ set_type_context (TREE_TYPE (p), context);
+ }
/* Fall through. */
/* Parameters go in DECL_ARGUMENTS, not BLOCK_VARS, and have
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;
}
}
-
+
/* Dispose of the block that we just made inside some higher level. */
if ((scope->function_body || scope == file_scope) && context)
{
{
tree decl;
+ if (file_scope)
+ return;
+
push_scope ();
file_scope = current_scope;
start_fname_decls ();
for (decl = visible_builtins; decl; decl = TREE_CHAIN (decl))
- bind (DECL_NAME (decl), decl, file_scope);
+ bind (DECL_NAME (decl), decl, file_scope,
+ /*invisible=*/false, /*nested=*/true);
}
void
still works without it. */
finish_fname_decls ();
- /* Kludge: don't actually pop the file scope if generating a
- precompiled header, so that macros and local symbols are still
- visible to the PCH generator. */
+ /* This is the point to write out a PCH if we're doing that.
+ In that case we do not want to do anything else. */
if (pch_file)
- return;
+ {
+ c_common_write_pch ();
+ return;
+ }
- /* And pop off the file scope. */
+ /* Pop off the file scope and close this translation unit. */
pop_scope ();
file_scope = 0;
-
- cpp_undef_all (parse_in);
+ cgraph_finalize_compilation_unit ();
}
/* Insert BLOCK at the end of the list of subblocks of the current
/* Record the identifier as the type's name if it has none. */
if (name && !TYPE_NAME (type))
TYPE_NAME (type) = name;
- bind (name, type, current_scope);
+ bind (name, type, current_scope, /*invisible=*/false, /*nested=*/false);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
tagged type we just added to the current scope. This fake
tree t;
if (TREE_CODE (olddecl) != FUNCTION_DECL
- || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype), COMPARE_STRICT)
+ || !comptypes (TREE_TYPE (oldtype), TREE_TYPE (newtype))
|| !((TYPE_ARG_TYPES (oldtype) == 0 && DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0 && DECL_INITIAL (newdecl) == 0)))
/* Type for passing arg must be consistent with that declared
for the arg. */
- else if (! comptypes (oldargtype, newargtype, COMPARE_STRICT))
+ else if (! comptypes (oldargtype, newargtype))
{
error ("%Jprototype for '%D' declares arg %d with incompatible type",
newdecl, newdecl, i);
return false;
}
- if (!comptypes (oldtype, newtype, COMPARE_STRICT))
+ if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_BUILT_IN (olddecl) && !C_DECL_DECLARED_BUILTIN (olddecl))
This is for the ffs and fprintf builtins. */
tree trytype = match_builtin_function_types (newtype, oldtype);
- if (trytype && comptypes (newtype, trytype, COMPARE_STRICT))
+ if (trytype && comptypes (newtype, trytype))
*oldtypep = oldtype = trytype;
else
{
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
+ && DECL_IS_BUILTIN (olddecl))
{
/* A conflicting function declaration for a predeclared
function that isn't actually built in. Objective C uses
}
else
{
- error ("%Jconflicting types for '%D'", newdecl, newdecl);
+ if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
+ error ("%J conflicting type qualifiers for '%D'", newdecl, newdecl);
+ else
+ error ("%Jconflicting types for '%D'", newdecl, newdecl);
diagnose_arglist_conflict (newdecl, olddecl, newtype, oldtype);
locate_old_decl (olddecl, error);
return false;
{
if (DECL_IN_SYSTEM_HEADER (newdecl) || DECL_IN_SYSTEM_HEADER (olddecl))
return true; /* Allow OLDDECL to continue in use. */
-
+
error ("%Jredefinition of typedef '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
/* Discard the old built-in function. */
return false;
}
-
+
if (DECL_INITIAL (newdecl))
{
if (DECL_INITIAL (olddecl)
&& !(DECL_DECLARED_INLINE_P (olddecl)
&& DECL_EXTERNAL (olddecl)
&& !(DECL_DECLARED_INLINE_P (newdecl)
- && DECL_EXTERNAL (newdecl))))
+ && DECL_EXTERNAL (newdecl)
+ && same_translation_unit_p (olddecl, newdecl))))
{
error ("%Jredefinition of '%D'", newdecl, newdecl);
locate_old_decl (olddecl, error);
locate_old_decl (olddecl, error);
return false;
}
- /* Mismatched non-static and static is considered poor style.
- We only diagnose static then non-static if -Wtraditional,
- because it is the most convenient way to get some effects
- (see e.g. what unwind-dw2-fde-glibc.c does to the definition
- of _Unwind_Find_FDE in unwind-dw2-fde.c). Revisit? */
+ /* A non-static declaration (even an "extern") followed by a
+ static declaration is undefined behavior per C99 6.2.2p3-5,7.
+ The same is true for a static forward declaration at block
+ scope followed by a non-static declaration/definition at file
+ scope. Static followed by non-static at the same scope is
+ not undefined behavior, and is the most convenient way to get
+ some effects (see e.g. what unwind-dw2-fde-glibc.c does to
+ the definition of _Unwind_Find_FDE in unwind-dw2-fde.c), but
+ we do diagnose it if -Wtraditional. */
if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
{
- /* A static function declaration for a predeclared function
- that isn't actually built in, silently overrides the
- default. Objective C uses these. See also above.
- FIXME: Make Objective C use normal builtins. */
- if (TREE_CODE (olddecl) == FUNCTION_DECL
- && DECL_SOURCE_LINE (olddecl) == 0)
- return false;
- else
+ /* Two exceptions to the rule. If olddecl is an extern
+ inline, or a predeclared function that isn't actually
+ built in, newdecl silently overrides olddecl. The latter
+ occur only in Objective C; see also above. (FIXME: Make
+ Objective C use normal builtins.) */
+ if (!DECL_IS_BUILTIN (olddecl)
+ && !(DECL_EXTERNAL (olddecl)
+ && DECL_DECLARED_INLINE_P (olddecl)))
{
- warning ("%Jstatic declaration of '%D' follows "
- "non-static declaration", newdecl, newdecl);
- warned = true;
+ error ("%Jstatic declaration of '%D' follows "
+ "non-static declaration", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
}
+ return false;
}
- else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl)
- && warn_traditional)
+ else if (TREE_PUBLIC (newdecl) && !TREE_PUBLIC (olddecl))
{
- warning ("%Jnon-static declaration of '%D' follows "
- "static declaration", newdecl, newdecl);
- warned = true;
+ if (DECL_CONTEXT (olddecl))
+ {
+ error ("%Jnon-static declaration of '%D' follows "
+ "static declaration", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ else if (warn_traditional)
+ {
+ warning ("%Jnon-static declaration of '%D' follows "
+ "static declaration", newdecl, newdecl);
+ warned = true;
+ }
}
}
else if (TREE_CODE (newdecl) == VAR_DECL)
return false;
}
- /* Objects declared at file scope: if at least one is 'extern',
- it's fine (6.2.2p4); otherwise the linkage must agree (6.2.2p7). */
- if (DECL_FILE_SCOPE_P (newdecl))
+ /* Objects declared at file scope: if the first declaration had
+ external linkage (even if it was an external reference) the
+ second must have external linkage as well, or the behavior is
+ undefined. If the first declaration had internal linkage, then
+ the second must too, or else be an external reference (in which
+ case the composite declaration still has internal linkage).
+ As for function declarations, we warn about the static-then-
+ extern case only for -Wtraditional. See generally 6.2.2p3-5,7. */
+ if (DECL_FILE_SCOPE_P (newdecl)
+ && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
{
- if (!DECL_EXTERNAL (newdecl)
- && !DECL_EXTERNAL (olddecl)
- && TREE_PUBLIC (newdecl) != TREE_PUBLIC (olddecl))
+ if (DECL_EXTERNAL (newdecl))
+ {
+ if (!DECL_FILE_SCOPE_P (olddecl))
+ {
+ error ("%Jextern declaration of %qD follows "
+ "declaration with no linkage", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ else if (warn_traditional)
+ {
+ warning ("%Jnon-static declaration of '%D' follows "
+ "static declaration", newdecl, newdecl);
+ warned = true;
+ }
+ }
+ else
{
if (TREE_PUBLIC (newdecl))
error ("%Jnon-static declaration of '%D' follows "
}
/* Two objects with the same name declared at the same block
scope must both be external references (6.7p3). */
- else if (DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl)
- && (!DECL_EXTERNAL (newdecl) || !DECL_EXTERNAL (olddecl)))
+ else if (!DECL_FILE_SCOPE_P (newdecl))
{
if (DECL_EXTERNAL (newdecl))
- error ("%Jextern declaration of '%D' follows "
- "declaration with no linkage", newdecl, newdecl);
+ {
+ /* 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;
}
}
/* warnings */
- /* All decls must agree on a non-default visibility. */
- if (DECL_VISIBILITY (newdecl) != VISIBILITY_DEFAULT
- && DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT
+ /* All decls must agree on a visibility. */
+ if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
warning ("%Jredeclaration of '%D' with different visibility "
/* Inline declaration after use or definition.
??? Should we still warn about this now we have unit-at-a-time
- mode and can get it right? */
- if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl))
+ mode and can get it right?
+ Definitely don't complain if the decls are in different translation
+ units. */
+ if (DECL_DECLARED_INLINE_P (newdecl) && !DECL_DECLARED_INLINE_P (olddecl)
+ && same_translation_unit_p (olddecl, newdecl))
{
if (TREE_USED (olddecl))
{
locate_old_decl (olddecl, error);
return false;
}
-
- /* These bits are only type qualifiers when applied to objects. */
- if (TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl))
- {
- if (TREE_THIS_VOLATILE (newdecl))
- pedwarn ("%Jvolatile declaration of '%D' follows "
- "non-volatile declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-volatile declaration of '%D' follows "
- "volatile declaration", newdecl, newdecl);
- pedwarned = true;
- }
- if (TREE_READONLY (newdecl) != TREE_READONLY (olddecl))
- {
- if (TREE_READONLY (newdecl))
- pedwarn ("%Jconst declaration of '%D' follows "
- "non-const declaration", newdecl, newdecl);
- else
- pedwarn ("%Jnon-const declaration of '%D' follows "
- "const declaration", newdecl, newdecl);
- pedwarned = true;
- }
}
/* Optional warning for completely redundant decls. */
definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
+ /* Don't warn about redundant redeclarations of builtins. */
+ && !(TREE_CODE (newdecl) == FUNCTION_DECL
+ && !DECL_BUILT_IN (newdecl)
+ && DECL_BUILT_IN (olddecl)
+ && !C_DECL_DECLARED_BUILTIN (olddecl))
/* Don't warn about an extern followed by a definition. */
&& !(DECL_EXTERNAL (olddecl) && !DECL_EXTERNAL (newdecl))
/* Don't warn about forward parameter decls. */
Currently, it can only be defined in the prototype. */
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
- /* If either declaration has a nondefault visibility, use it. */
- if (DECL_VISIBILITY (olddecl) != VISIBILITY_DEFAULT)
- DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ /* Use visibility of whichever declaration had it specified */
+ if (DECL_VISIBILITY_SPECIFIED (olddecl))
+ {
+ DECL_VISIBILITY (newdecl) = DECL_VISIBILITY (olddecl);
+ DECL_VISIBILITY_SPECIFIED (newdecl) = 1;
+ }
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
}
}
- /* This bit must not get wiped out. */
- C_DECL_IN_EXTERNAL_SCOPE (newdecl) |= C_DECL_IN_EXTERNAL_SCOPE (olddecl);
-
/* Copy most of the decl-specific fields of NEWDECL into OLDDECL.
- But preserve OLDDECL's DECL_UID. */
+ But preserve OLDDECL's DECL_UID and DECL_CONTEXT. */
{
unsigned olddecl_uid = DECL_UID (olddecl);
+ tree olddecl_context = DECL_CONTEXT (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common));
DECL_UID (olddecl) = olddecl_uid;
+ DECL_CONTEXT (olddecl) = olddecl_context;
}
/* If OLDDECL had its DECL_RTL instantiated, re-invoke make_decl_rtl
&& (TREE_CODE (olddecl) == FUNCTION_DECL
|| (TREE_CODE (olddecl) == VAR_DECL
&& TREE_STATIC (olddecl))))
- make_decl_rtl (olddecl, NULL);
+ make_decl_rtl (olddecl);
}
/* Handle when a new declaration NEWDECL has the same name as an old
merge_decls (newdecl, olddecl, newtype, oldtype);
return true;
}
-
+
\f
-/* Check whether decl-node NEW shadows an existing declaration. */
+/* Check whether decl-node NEW_DECL shadows an existing declaration. */
static void
-warn_if_shadowing (tree new)
+warn_if_shadowing (tree new_decl)
{
struct c_binding *b;
/* Shadow warnings wanted? */
if (!warn_shadow
/* No shadow warnings for internally generated vars. */
- || DECL_SOURCE_LINE (new) == 0
+ || DECL_IS_BUILTIN (new_decl)
/* No shadow warnings for vars made for inlining. */
- || DECL_FROM_INLINE (new)
+ || DECL_FROM_INLINE (new_decl)
/* Don't warn about the parm names in function declarator
within a function declarator. It would be nice to avoid
warning in any function declarator in a declaration, as
opposed to a definition, but there is no way to tell
it's not a definition at this point. */
- || (TREE_CODE (new) == PARM_DECL && current_scope->outer->parm_flag))
+ || (TREE_CODE (new_decl) == PARM_DECL && current_scope->outer->parm_flag))
return;
- /* Is anything being shadowed? Do not be confused by a second binding
- to the same decl in the externals scope. */
- for (b = I_SYMBOL_BINDING (DECL_NAME (new)); b; b = b->shadowed)
- if (b->decl && b->decl != new && b->contour != external_scope)
+ /* Is anything being shadowed? Invisible decls do not count. */
+ for (b = I_SYMBOL_BINDING (DECL_NAME (new_decl)); b; b = b->shadowed)
+ if (b->decl && b->decl != new_decl && !b->invisible)
{
- tree old = b->decl;
+ tree old_decl = b->decl;
- if (TREE_CODE (old) == PARM_DECL)
- warning ("%Jdeclaration of '%D' shadows a parameter", new, new);
- else if (DECL_FILE_SCOPE_P (old))
+ if (TREE_CODE (old_decl) == PARM_DECL)
+ warning ("%Jdeclaration of '%D' shadows a parameter",
+ new_decl, new_decl);
+ else if (DECL_FILE_SCOPE_P (old_decl))
warning ("%Jdeclaration of '%D' shadows a global declaration",
- new, new);
- else if (TREE_CODE (old) == FUNCTION_DECL && DECL_BUILT_IN (old))
+ new_decl, new_decl);
+ else if (TREE_CODE (old_decl) == FUNCTION_DECL
+ && DECL_BUILT_IN (old_decl))
warning ("%Jdeclaration of '%D' shadows a built-in function",
- new, new);
+ new_decl, new_decl);
else
- warning ("%Jdeclaration of '%D' shadows a previous local", new, new);
+ warning ("%Jdeclaration of '%D' shadows a previous local",
+ new_decl, new_decl);
- if (TREE_CODE (old) != FUNCTION_DECL || !DECL_BUILT_IN (old))
- warning ("%Jshadowed declaration is here", old);
+ if (TREE_CODE (old_decl) != FUNCTION_DECL
+ || ! DECL_BUILT_IN (old_decl))
+ warning ("%Jshadowed declaration is here", old_decl);
break;
}
static void
clone_underlying_type (tree x)
{
- if (DECL_SOURCE_LINE (x) == 0)
+ if (DECL_IS_BUILTIN (x))
{
if (TYPE_NAME (TREE_TYPE (x)) == 0)
TYPE_NAME (TREE_TYPE (x)) = x;
{
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;
tree name = DECL_NAME (x);
struct c_scope *scope = current_scope;
struct c_binding *b;
+ bool nested = false;
/* Functions need the lang_decl data. */
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
- DECL_LANG_SPECIFIC (x) = ggc_alloc_cleared (sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
/* Must set DECL_CONTEXT for everything not at file scope or
DECL_FILE_SCOPE_P won't work. Local externs don't count
/* Anonymous decls are just inserted in the scope. */
if (!name)
{
- bind (name, x, scope);
+ bind (name, x, scope, /*invisible=*/false, /*nested=*/false);
return x;
}
diagnostics). In particular, we should not consider possible
duplicates in the external scope, or shadowing. */
b = I_SYMBOL_BINDING (name);
- if (b && b->contour == scope)
+ 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 `%s'",
- IDENTIFIER_POINTER (name));
+ warning ("nested extern declaration of '%D'", x);
- while (b && b->contour != external_scope)
- b = b->shadowed;
+ while (b && !B_IN_EXTERNAL_SCOPE (b))
+ {
+ /* 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
they are in different translation units. In any case,
the static does not go in the externals scope. */
if (b
- && (DECL_EXTERNAL (x) || TREE_PUBLIC (x)
- || same_translation_unit_p (x, b->decl))
+ && (TREE_PUBLIC (x) || same_translation_unit_p (x, b->decl))
&& duplicate_decls (x, b->decl))
{
- bind (name, b->decl, scope);
+ 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 (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+ else if (TREE_PUBLIC (x))
{
- C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
- bind (name, x, external_scope);
+ 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
+ block scope must be checked against any existing declaration
+ of that function at file scope. */
+ else if (TREE_CODE (x) == FUNCTION_DECL && scope != file_scope
+ && !TREE_PUBLIC (x) && !DECL_INITIAL (x))
+ {
+ if (warn_nested_externs && !DECL_IN_SYSTEM_HEADER (x))
+ warning ("nested static declaration of '%D'", x);
+
+ while (b && !B_IN_FILE_SCOPE (b))
+ b = b->shadowed;
+
+ if (b && same_translation_unit_p (x, b->decl)
+ && duplicate_decls (x, b->decl))
+ {
+ bind (name, b->decl, scope, /*invisible=*/false, /*nested=*/true);
+ return b->decl;
+ }
+ else
+ {
+ bind (name, x, file_scope, /*invisible=*/true, /*nested=*/false);
+ nested = true;
}
}
if (TREE_CODE (x) == TYPE_DECL)
clone_underlying_type (x);
- bind (name, x, scope);
+ bind (name, x, scope, /*invisible=*/false, nested);
/* If x's type is incomplete because it's based on a
structure or union which has not yet been fully declared,
pushdecl_top_level (tree x)
{
tree name;
+ bool nested = false;
if (TREE_CODE (x) != VAR_DECL)
abort ();
if (I_SYMBOL_BINDING (name))
abort ();
- if (DECL_EXTERNAL (x) || TREE_PUBLIC (x))
+ if (TREE_PUBLIC (x))
{
- C_DECL_IN_EXTERNAL_SCOPE (x) = 1;
- bind (name, x, external_scope);
+ bind (name, x, external_scope, /*invisible=*/true, /*nested=*/false);
+ nested = true;
}
if (file_scope)
- bind (name, x, file_scope);
+ bind (name, x, file_scope, /*invisible=*/false, nested);
return x;
}
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)
{
in the external scope because they're pushed before the file
scope gets created. Catch this here and rebind them into the
file scope. */
- if (!DECL_BUILT_IN (decl) && DECL_SOURCE_LINE (decl) == 0)
+ if (!DECL_BUILT_IN (decl) && DECL_IS_BUILTIN (decl))
{
- bind (functionid, decl, file_scope);
+ bind (functionid, decl, file_scope,
+ /*invisible=*/false, /*nested=*/true);
return 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);
C_DECL_IMPLICIT (decl) = 1;
}
- bind (functionid, decl, current_scope);
+ if (DECL_BUILT_IN (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 (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;
}
}
decl = pushdecl (decl);
/* No need to call objc_check_decl here - it's a function type. */
- rest_of_decl_compilation (decl, NULL, 0, 0);
+ rest_of_decl_compilation (decl, 0, 0);
/* Write a record describing this implicit function declaration
to the prototypes file (if requested). */
will be nonnull but current_function_scope will be null. */
scope = current_function_scope ? current_function_scope : current_scope;
}
- bind (id, error_mark_node, scope);
+ bind (id, error_mark_node, scope, /*invisible=*/false, /*nested=*/false);
}
\f
/* Subroutine of lookup_label, declare_label, define_label: construct a
label = make_label (name, input_location);
/* Ordinary labels go in the current function scope. */
- bind (name, label, current_function_scope);
+ bind (name, label, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
return label;
}
/* Check to make sure that the label hasn't already been declared
at this scope */
- if (b && b->contour == current_scope)
+ if (b && B_IN_CURRENT_SCOPE (b))
{
error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
locate_old_decl (b->decl, error);
C_DECLARED_LABEL_FLAG (label) = 1;
/* Declared labels go in the current scope. */
- bind (name, label, current_scope);
+ bind (name, label, current_scope,
+ /*invisible=*/false, /*nested=*/false);
return label;
}
label = make_label (name, location);
/* Ordinary labels go in the current function scope. */
- bind (name, label, current_function_scope);
+ bind (name, label, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
}
if (warn_traditional && !in_system_header && lookup_name (name))
/* For our purposes, a tag in the external scope is the same as
a tag in the file scope. (Primarily relevant to Objective-C
and its builtin structure tags, which get pushed before the
- file scope is created.) */
- if (b->contour == current_scope
- || (current_scope == file_scope && b->contour == external_scope))
+ file scope is created.) */
+ if (B_IN_CURRENT_SCOPE (b)
+ || (current_scope == file_scope && B_IN_EXTERNAL_SCOPE (b)))
thislevel = 1;
}
lookup_name (tree name)
{
struct c_binding *b = I_SYMBOL_BINDING (name);
- if (b && (b->contour != external_scope || TREE_CODE (b->decl) == TYPE_DECL))
+ if (b && !b->invisible)
return b->decl;
return 0;
}
struct c_binding *b;
for (b = I_SYMBOL_BINDING (name); b; b = b->shadowed)
- if (b->contour == scope)
+ if (B_IN_SCOPE (b, scope))
return b->decl;
return 0;
}
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
- input_location.file = "<internal>";
+#ifdef USE_MAPPED_LOCATION
+ input_location = BUILTINS_LOCATION;
+#else
+ input_location.file = "<built-in>";
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 ();
if (current_function_decl)
{
DECL_CONTEXT (decl) = current_function_decl;
- bind (id, decl, current_function_scope);
+ bind (id, decl, current_function_scope,
+ /*invisible=*/false, /*nested=*/false);
}
finish_decl (decl, init, NULL_TREE);
tree
builtin_function (const char *name, tree type, int function_code,
- enum built_in_class class, const char *library_name,
+ enum built_in_class cl, const char *library_name,
tree attrs)
{
tree id = get_identifier (name);
tree decl = build_decl (FUNCTION_DECL, id, type);
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
- DECL_LANG_SPECIFIC (decl) = ggc_alloc_cleared (sizeof (struct lang_decl));
- DECL_BUILT_IN_CLASS (decl) = class;
+ DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
+ DECL_BUILT_IN_CLASS (decl) = cl;
DECL_FUNCTION_CODE (decl) = function_code;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
- make_decl_rtl (decl, NULL);
/* Should never be called on a symbol with a preexisting meaning. */
if (I_SYMBOL_BINDING (id))
abort ();
- C_DECL_IN_EXTERNAL_SCOPE (decl) = 1;
- bind (id, decl, external_scope);
+ bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
/* Builtins in the implementation namespace are made visible without
needing to be explicitly declared. See push_file_scope. */
shadow_tag_warned (declspecs, 0);
}
+/* WARNED is 1 if we have done a pedwarn, 2 if we have done a warning,
+ but no pedwarn. */
void
shadow_tag_warned (tree declspecs, int warned)
-
-
- /* 1 => we have done a pedwarn. 2 => we have done a warning, but
- no pedwarn. */
{
int found_tag = 0;
tree link;
/* 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);
+ decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
TREE_TYPE (decl) = quals;
TREE_STATIC (decl) = (static_p ? 1 : 0);
if (pedantic && !flag_isoc99)
/* 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)))
return decl;
}
\f
+/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
+ lists. SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
+
+ The head of the declspec list is stored in DECLSPECS.
+ The head of the attribute list is stored in PREFIX_ATTRIBUTES.
+
+ Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
+ the list elements. We drop the containing TREE_LIST nodes and link the
+ resulting attributes together the way decl_attributes expects them. */
+
+void
+split_specs_attrs (tree specs_attrs, tree *declspecs, tree *prefix_attributes)
+{
+ tree t, s, a, next, specs, attrs;
+
+ /* This can happen after an __extension__ in pedantic mode. */
+ if (specs_attrs != NULL_TREE
+ && TREE_CODE (specs_attrs) == INTEGER_CST)
+ {
+ *declspecs = NULL_TREE;
+ *prefix_attributes = NULL_TREE;
+ return;
+ }
+
+ /* This can happen in c++ (eg: decl: typespec initdecls ';'). */
+ if (specs_attrs != NULL_TREE
+ && TREE_CODE (specs_attrs) != TREE_LIST)
+ {
+ *declspecs = specs_attrs;
+ *prefix_attributes = NULL_TREE;
+ return;
+ }
+
+ /* Remember to keep the lists in the same order, element-wise. */
+
+ specs = s = NULL_TREE;
+ attrs = a = NULL_TREE;
+ for (t = specs_attrs; t; t = next)
+ {
+ next = TREE_CHAIN (t);
+ /* Declspecs have a non-NULL TREE_VALUE. */
+ if (TREE_VALUE (t) != NULL_TREE)
+ {
+ if (specs == NULL_TREE)
+ specs = s = t;
+ else
+ {
+ TREE_CHAIN (s) = t;
+ s = t;
+ }
+ }
+ /* The TREE_PURPOSE may also be empty in the case of
+ __attribute__(()). */
+ else if (TREE_PURPOSE (t) != NULL_TREE)
+ {
+ if (attrs == NULL_TREE)
+ attrs = a = TREE_PURPOSE (t);
+ else
+ {
+ TREE_CHAIN (a) = TREE_PURPOSE (t);
+ a = TREE_PURPOSE (t);
+ }
+ /* More attrs can be linked here, move A to the end. */
+ while (TREE_CHAIN (a) != NULL_TREE)
+ a = TREE_CHAIN (a);
+ }
+ }
+
+ /* Terminate the lists. */
+ if (s != NULL_TREE)
+ TREE_CHAIN (s) = NULL_TREE;
+ if (a != NULL_TREE)
+ TREE_CHAIN (a) = NULL_TREE;
+
+ /* All done. */
+ *declspecs = specs;
+ *prefix_attributes = attrs;
+}
+
/* Decode a "typename", such as "int **", returning a ..._TYPE node. */
tree
-groktypename (tree typename)
+groktypename (tree type_name)
{
tree specs, attrs;
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
+ if (TREE_CODE (type_name) != TREE_LIST)
+ return type_name;
- split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
+ split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
- typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0,
+ type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
NULL);
/* Apply attributes. */
- decl_attributes (&typename, attrs, 0);
+ decl_attributes (&type_name, attrs, 0);
- return typename;
+ return type_name;
}
/* Return a PARM_DECL node for a given pair of specs and declarator. */
tree
-groktypename_in_parm_context (tree typename)
+groktypename_in_parm_context (tree type_name)
{
- if (TREE_CODE (typename) != TREE_LIST)
- return typename;
- return grokdeclarator (TREE_VALUE (typename),
- TREE_PURPOSE (typename),
- PARM, 0, NULL);
+ if (TREE_CODE (type_name) != TREE_LIST)
+ return type_name;
+ return grokdeclarator (TREE_VALUE (type_name),
+ TREE_PURPOSE (type_name),
+ 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;
if (initialized)
{
- DECL_EXTERNAL (decl) = 0;
if (current_scope == file_scope)
TREE_STATIC (decl) = 1;
for (; args; args = TREE_CHAIN (args))
{
tree type = TREE_TYPE (args);
- if (INTEGRAL_TYPE_P (type)
+ if (type && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (args) = integer_type_node;
}
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
+ if (initialized)
+ DECL_EXTERNAL (tem) = 0;
+
return tem;
}
store_init_value (decl, init);
if (c_dialect_objc () && (TREE_CODE (decl) == VAR_DECL
- || TREE_CODE (decl) == FUNCTION_DECL
- || TREE_CODE (decl) == FIELD_DECL))
+ || TREE_CODE (decl) == FUNCTION_DECL
+ || TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
/* Deduce size of array from initialization, if not already known. */
in the array, because we start counting at zero. Therefore,
warn only if the value is less than zero. */
else if (pedantic && TYPE_DOMAIN (type) != 0
- && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
+ && tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
error ("%Jzero or negative size array '%D'", decl, decl);
layout_decl (decl, 0);
/* Don't give an error if we already gave one earlier. */
&& TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
- ?
- /* A static variable with an incomplete type
- is an error if it is initialized.
- Also if it is not file scope.
- Otherwise, let it through, but if it is not `extern'
- then it may cause an error message later. */
- (DECL_INITIAL (decl) != 0
+ /* A static variable with an incomplete type
+ is an error if it is initialized.
+ Also if it is not file scope.
+ Otherwise, let it through, but if it is not `extern'
+ then it may cause an error message later. */
+ ? (DECL_INITIAL (decl) != 0
|| !DECL_FILE_SCOPE_P (decl))
- :
- /* An automatic variable with an incomplete type
- is an error. */
- !DECL_EXTERNAL (decl)))
- {
- error ("%Jstorage size of '%D' isn't known", decl, decl);
- TREE_TYPE (decl) = error_mark_node;
- }
+ /* An automatic variable with an incomplete type
+ is an error. */
+ : !DECL_EXTERNAL (decl)))
+ {
+ error ("%Jstorage size of '%D' isn't known", decl, decl);
+ TREE_TYPE (decl) = error_mark_node;
+ }
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != 0)
was a normal built-in. */
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
- /* ASMSPEC is given, and not the name of a register. Mark the
- name with a star so assemble_name won't munge it. */
- char *starred = alloca (strlen (asmspec) + 2);
- starred[0] = '*';
- strcpy (starred + 1, asmspec);
-
if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
{
tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- SET_DECL_RTL (builtin, NULL_RTX);
- change_decl_assembler_name (builtin, get_identifier (starred));
-#ifdef TARGET_MEM_FUNCTIONS
- if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
- init_block_move_fn (starred);
- else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
- init_block_clear_fn (starred);
-#else
- if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BCOPY)
- init_block_move_fn (starred);
- else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_BZERO)
- init_block_clear_fn (starred);
-#endif
- }
- SET_DECL_RTL (decl, NULL_RTX);
- change_decl_assembler_name (decl, get_identifier (starred));
+ set_user_assembler_name (builtin, asmspec);
+ if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+ init_block_move_fn (asmspec);
+ else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+ init_block_clear_fn (asmspec);
+ }
+ set_user_assembler_name (decl, asmspec);
}
/* If #pragma weak was used, mark the decl weak now. */
if (current_scope == file_scope)
maybe_apply_pragma_weak (decl);
+ /* If this is a variable definition, determine its ELF visibility. */
+ if (TREE_CODE (decl) == VAR_DECL
+ && TREE_STATIC (decl)
+ && !DECL_EXTERNAL (decl))
+ c_determine_visibility (decl);
+
/* Output the assembler code and/or RTL code for variables and functions,
unless the type is an undefined structure or union.
If not, it will get done when the type is completed. */
if (c_dialect_objc ())
objc_check_decl (decl);
+ if (asmspec)
+ {
+ /* If this is not a static variable, issue a warning.
+ It doesn't make any sense to give an ASMSPEC for an
+ ordinary, non-register local variable. Historically,
+ GCC has accepted -- but ignored -- the ASMSPEC in
+ this case. */
+ if (! DECL_FILE_SCOPE_P (decl)
+ && TREE_CODE (decl) == VAR_DECL
+ && !C_DECL_REGISTER (decl)
+ && !TREE_STATIC (decl))
+ warning ("%Jignoring asm-specifier for non-static local "
+ "variable '%D'", decl, decl);
+ else if (C_DECL_REGISTER (decl))
+ change_decl_assembler_name (decl, get_identifier (asmspec));
+ else
+ set_user_assembler_name (decl, asmspec);
+ }
+
if (DECL_FILE_SCOPE_P (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
when a tentative file-scope definition is seen.
But at end of compilation, do output code for them. */
DECL_DEFER_OUTPUT (decl) = 1;
- rest_of_decl_compilation (decl, asmspec, true, 0);
+ rest_of_decl_compilation (decl, true, 0);
}
else
{
- /* This is a local variable. If there is an ASMSPEC, the
- user has requested that we handle it specially. */
- if (asmspec)
+ /* In conjunction with an ASMSPEC, the `register'
+ keyword indicates that we should place the variable
+ in a particular register. */
+ if (asmspec && C_DECL_REGISTER (decl))
{
- /* In conjunction with an ASMSPEC, the `register'
- keyword indicates that we should place the variable
- in a particular register. */
- if (C_DECL_REGISTER (decl))
- {
- DECL_HARD_REGISTER (decl) = 1;
- /* This cannot be done for a structure with volatile
- fields, on which DECL_REGISTER will have been
- reset. */
- if (!DECL_REGISTER (decl))
- error ("cannot put object with volatile field into register");
- }
-
- /* If this is not a static variable, issue a warning.
- It doesn't make any sense to give an ASMSPEC for an
- ordinary, non-register local variable. Historically,
- GCC has accepted -- but ignored -- the ASMSPEC in
- this case. */
- if (TREE_CODE (decl) == VAR_DECL
- && !C_DECL_REGISTER (decl)
- && !TREE_STATIC (decl))
- warning ("%Jignoring asm-specifier for non-static local "
- "variable '%D'", decl, decl);
- else
- change_decl_assembler_name (decl, get_identifier (asmspec));
+ DECL_HARD_REGISTER (decl) = 1;
+ /* This cannot be done for a structure with volatile
+ fields, on which DECL_REGISTER will have been
+ reset. */
+ if (!DECL_REGISTER (decl))
+ error ("cannot put object with volatile field into register");
}
if (TREE_CODE (decl) != FUNCTION_DECL)
- add_decl_stmt (decl);
+ {
+ /* If we're building a variable sized type, and we might be
+ reachable other than via the top of the current binding
+ level, then create a new BIND_EXPR so that we deallocate
+ the object at the right time. */
+ /* Note that DECL_SIZE can be null due to errors. */
+ if (DECL_SIZE (decl)
+ && !TREE_CONSTANT (DECL_SIZE (decl))
+ && STATEMENT_LIST_HAS_LABEL (cur_stmt_list))
+ {
+ tree bind;
+ bind = build3 (BIND_EXPR, void_type_node, NULL, NULL, NULL);
+ TREE_SIDE_EFFECTS (bind) = 1;
+ add_stmt (bind);
+ BIND_EXPR_BODY (bind) = push_stmt_list ();
+ }
+ add_stmt (build_stmt (DECL_EXPR, decl));
+ }
}
+
if (!DECL_FILE_SCOPE_P (decl))
{
if (TREE_CODE (decl) == TYPE_DECL)
{
if (!DECL_FILE_SCOPE_P (decl)
- && variably_modified_type_p (TREE_TYPE (decl)))
- add_decl_stmt (decl);
+ && variably_modified_type_p (TREE_TYPE (decl), NULL_TREE))
+ add_stmt (build_stmt (DECL_EXPR, decl));
- rest_of_decl_compilation (decl, NULL, DECL_FILE_SCOPE_P (decl), 0);
+ rest_of_decl_compilation (decl, DECL_FILE_SCOPE_P (decl), 0);
}
/* At the end of a declaration, throw away any variable type sizes
tree attr = lookup_attribute ("cleanup", DECL_ATTRIBUTES (decl));
if (attr)
{
- static bool eh_initialized_p;
-
tree cleanup_id = TREE_VALUE (TREE_VALUE (attr));
tree cleanup_decl = lookup_name (cleanup_id);
tree cleanup;
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
+ TREE_USED (cleanup_decl) = 1;
/* Initialize EH, if we've been told to do so. */
- if (flag_exceptions && !eh_initialized_p)
+ if (flag_exceptions && !c_eh_initialized_p)
{
- eh_initialized_p = true;
+ c_eh_initialized_p = true;
eh_personality_libfunc
= init_one_libfunc (USING_SJLJ_EXCEPTIONS
? "__gcc_personality_sj0"
using_eh_for_cleanups ();
}
- add_stmt (build_stmt (CLEANUP_STMT, decl, cleanup));
+ push_cleanup (decl, cleanup, false);
}
}
}
+/* 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. */
{
tree decl;
- /* Don't attempt to expand sizes while parsing this decl.
- (We can get here with i_s_e 1 somehow from Objective-C.) */
- int save_immediate_size_expand = immediate_size_expand;
- immediate_size_expand = 0;
-
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);
finish_decl (decl, NULL_TREE, NULL_TREE);
-
- immediate_size_expand = save_immediate_size_expand;
}
/* Mark all the parameter declarations to date as forward decls.
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
- the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_STMT. */
+ the COMPOUND_LITERAL_EXPR rather than added elsewhere as a DECL_EXPR. */
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
tree complit;
tree stmt;
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
- stmt = build_stmt (DECL_STMT, decl);
+ stmt = build_stmt (DECL_EXPR, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
TREE_SIDE_EFFECTS (complit) = 1;
DECL_COMDAT (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
- rest_of_decl_compilation (decl, NULL, 1, 0);
+ rest_of_decl_compilation (decl, 1, 0);
}
return complit;
{
int eltsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
- / eltsize) - 1, 0);
+ maxindex = build_int_cst (NULL_TREE,
+ (TREE_STRING_LENGTH (initial_value)
+ / eltsize) - 1);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
tree elts = CONSTRUCTOR_ELTS (initial_value);
- maxindex = build_int_2 (-1, -1);
+ maxindex = build_int_cst (NULL_TREE, -1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
- maxindex = fold (build (PLUS_EXPR, integer_type_node,
- maxindex, integer_one_node));
+ maxindex = fold (build2 (PLUS_EXPR, integer_type_node,
+ maxindex, integer_one_node));
}
- maxindex = copy_node (maxindex);
}
else
{
value = 1;
/* Prevent further error messages. */
- maxindex = build_int_2 (0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
}
}
if (!maxindex)
{
if (do_default)
- maxindex = build_int_2 (0, 0);
+ maxindex = build_int_cst (NULL_TREE, 0);
value = 2;
}
{
TYPE_DOMAIN (type) = build_index_type (maxindex);
if (!TREE_TYPE (maxindex))
- TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
+ abort ();
}
/* Lay out the type now that we can get the real answer. */
{
error ("width of `%s' exceeds its type", name);
w = max_width;
- *width = build_int_2 (w, 0);
+ *width = build_int_cst (NULL_TREE, w);
}
else
w = tree_low_cst (*width, 1);
if (TREE_CODE (*type) == ENUMERAL_TYPE)
{
struct lang_type *lt = TYPE_LANG_SPECIFIC (*type);
- if (!lt
+ if (!lt
|| w < min_precision (lt->enum_min, TYPE_UNSIGNED (*type))
|| w < min_precision (lt->enum_max, TYPE_UNSIGNED (*type)))
warning ("`%s' is narrower than values of its type", name);
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;
Do the calculation in index_type, so that if it is
a variable the computations will be done in the
proper mode. */
- itype = fold (build (MINUS_EXPR, index_type,
- convert (index_type, size),
- convert (index_type, size_one_node)));
+ itype = fold (build2 (MINUS_EXPR, index_type,
+ convert (index_type, size),
+ convert (index_type, size_one_node)));
/* If that overflowed, the array is too big.
??? While a size of INT_MAX+1 technically shouldn't
}
if (size_varies)
- {
- /* We must be able to distinguish the
- SAVE_EXPR_CONTEXT for the variably-sized type
- so that we can set it correctly in
- set_save_expr_context. The convention is
- that all SAVE_EXPRs that need to be reset
- have NULL_TREE for their SAVE_EXPR_CONTEXT. */
- tree cfd = current_function_decl;
- if (decl_context == PARM)
- current_function_decl = NULL_TREE;
- itype = variable_size (itype);
- if (decl_context == PARM)
- current_function_decl = cfd;
- }
+ itype = variable_size (itype);
itype = build_index_type (itype);
}
}
}
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. */
qualify the return type, not the function type. */
if (type_quals)
{
- /* Type qualifiers on a function return type are normally
- permitted by the standard but have no effect, so give a
- warning at -Wextra. Qualifiers on a void return type have
- meaning as a GNU extension, and are banned on function
- definitions in ISO C. FIXME: strictly we shouldn't
- pedwarn for qualified void return types except on function
- definitions, but not doing so could lead to the undesirable
- state of a "volatile void" function return type not being
- warned about, and a use of the function being compiled
- with GNU semantics, with no diagnostics under -pedantic. */
- if (VOID_TYPE_P (type) && pedantic && !in_system_header)
- pedwarn ("ISO C forbids qualified void function return type");
- else if (extra_warnings
- && !(VOID_TYPE_P (type)
- && type_quals == TYPE_QUAL_VOLATILE))
+ /* Type qualifiers on a function return type are
+ normally permitted by the standard but have no
+ effect, so give a warning at -Wreturn-type.
+ Qualifiers on a void return type are banned on
+ function definitions in ISO C; GCC used to used them
+ for noreturn functions. */
+ if (VOID_TYPE_P (type) && really_funcdef)
+ pedwarn ("function definition has qualified void return type");
+ else if (warn_return_type)
warning ("type qualifiers ignored on function return type");
type = c_build_qualified_type (type, type_quals);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- /* Every function declaration is "external"
- except for those which are inside a function body
- in which `auto' is used.
- That is a case not specified by ANSI C,
- and we use it for forward declarations for nested functions. */
- int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_scope == file_scope);
-
- if (specbits & (1 << (int) RID_AUTO)
- && (pedantic || current_scope == file_scope))
- pedwarn ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_REGISTER))
+ if (specbits & (1 << (int) RID_REGISTER)
+ || specbits & (1 << (int) RID_THREAD))
error ("invalid storage class for function `%s'", name);
- if (specbits & (1 << (int) RID_THREAD))
- error ("invalid storage class for function `%s'", name);
- /* Function declaration not at file scope.
- Storage classes other than `extern' are not allowed
- and `extern' makes no difference. */
- if (current_scope != file_scope
- && (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
- && pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
+ else if (current_scope != file_scope)
+ {
+ /* Function declaration not at file scope. Storage
+ classes other than `extern' are not allowed, C99
+ 6.7.1p5, and `extern' makes no difference. However,
+ GCC allows 'auto', perhaps with 'inline', to support
+ nested functions. */
+ if (specbits & (1 << (int) RID_AUTO))
+ {
+ if (pedantic)
+ pedwarn ("invalid storage class for function `%s'", name);
+ }
+ if (specbits & (1 << (int) RID_STATIC))
+ error ("invalid storage class for function `%s'", name);
+ }
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_attr);
- DECL_LANG_SPECIFIC (decl)
- = ggc_alloc_cleared (sizeof (struct lang_decl));
+ DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
- /* GNU C interprets a `volatile void' return type to indicate
+ /* GNU C interprets a volatile-qualified function type to indicate
that the function does not return. */
if ((type_quals & TYPE_QUAL_VOLATILE)
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
warning ("`noreturn' function returns non-void value");
- if (extern_ref)
+ /* Every function declaration is an external reference
+ (DECL_EXTERNAL) except for those which are not at file
+ scope and are explicitly declared "auto". This is
+ forbidden by standard C (C99 6.7.1p5) and is interpreted by
+ GCC to signify a forward declaration of a nested function. */
+ if ((specbits & (1 << RID_AUTO)) && current_scope != file_scope)
+ DECL_EXTERNAL (decl) = 0;
+ else
DECL_EXTERNAL (decl) = 1;
+
/* Record absence of global scope for `static' or `auto'. */
TREE_PUBLIC (decl)
= !(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;
if (inlinep)
pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
- DECL_EXTERNAL (decl) = extern_ref;
+ /* At file scope, an initialized extern declaration may follow
+ a static declaration. In that case, DECL_EXTERNAL will be
+ reset later in start_decl. */
+ DECL_EXTERNAL (decl) = !!(specbits & (1 << (int) RID_EXTERN));
/* At file scope, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
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);
/* The %s will be one of 'struct', 'union', or 'enum'. */
warning ("anonymous %s declared inside parameter list",
keyword);
-
+
if (! explained_incomplete_types)
{
warning ("its scope is only this definition or declaration,"
}
}
- value = grokdeclarator (declarator, declspecs, FIELD, 0,
+ value = grokdeclarator (declarator, declspecs, FIELD, false,
width ? &width : NULL);
finish_decl (value, NULL_TREE, NULL_TREE);
}
/* Install struct as DECL_CONTEXT of each field decl.
- Also process specified field sizes,m which is found in the DECL_INITIAL.
- Store 0 there, except for ": 0" fields (so we can find them
- and delete them, below). */
+ Also process specified field sizes, found in the DECL_INITIAL,
+ storing 0 there after the type has been changed to precision equal
+ to its width, rather than the precision of the specified standard
+ type. (Correct layout requires the original type to have been preserved
+ until now.) */
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
SET_DECL_C_BIT_FIELD (x);
}
- DECL_INITIAL (x) = 0;
-
/* Detect flexible array member in an invalid context. */
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
layout_type (t);
- /* Delete all zero-width bit-fields from the fieldlist. */
+ /* Give bit-fields their proper types. */
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
- if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
- *fieldlistp = TREE_CHAIN (*fieldlistp);
+ if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp)
+ && TREE_TYPE (*fieldlistp) != error_mark_node)
+ {
+ unsigned HOST_WIDE_INT width
+ = tree_low_cst (DECL_INITIAL (*fieldlistp), 1);
+ tree type = TREE_TYPE (*fieldlistp);
+ if (width != TYPE_PRECISION (type))
+ TREE_TYPE (*fieldlistp)
+ = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+ DECL_INITIAL (*fieldlistp) = 0;
+ }
else
fieldlistp = &TREE_CHAIN (*fieldlistp);
}
ensure that this lives as long as the rest of the struct decl.
All decls in an inline function need to be saved. */
- space = ggc_alloc_cleared (sizeof (struct lang_type));
- space2 = ggc_alloc (sizeof (struct sorted_fields_type) + len * sizeof (tree));
+ space = GGC_CNEW (struct lang_type);
+ space2 = GGC_NEWVAR (struct sorted_fields_type,
+ sizeof (struct sorted_fields_type) + len * sizeof (tree));
len = 0;
space->s = space2;
layout_decl (decl, 0);
if (c_dialect_objc ())
objc_check_decl (decl);
- rest_of_decl_compilation (decl, NULL, toplevel, 0);
+ rest_of_decl_compilation (decl, toplevel, 0);
if (! toplevel)
expand_decl (decl);
}
/* Record the min/max values so that we can warn about bit-field
enumerations that are too small for the values. */
- lt = ggc_alloc_cleared (sizeof (struct lang_type));
+ lt = GGC_CNEW (struct lang_type);
lt->enum_min = minnode;
lt->enum_max = maxnode;
TYPE_LANG_SPECIFIC (enumtype) = lt;
start_function (tree declspecs, tree declarator, tree attributes)
{
tree decl1, old_decl;
- tree restype;
- int old_immediate_size_expand = immediate_size_expand;
+ tree restype, resdecl;
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
- c_in_iteration_stmt = 0;
- c_in_case_stmt = 0;
+ c_switch_stack = NULL;
- /* Don't expand any sizes in the return type of the function. */
- immediate_size_expand = 0;
+ /* Indicate no valid break/continue context by setting these variables
+ to some non-null, non-label value. We'll notice and emit the proper
+ 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. */
if (decl1 == 0)
- {
- immediate_size_expand = old_immediate_size_expand;
- return 0;
- }
+ return 0;
decl_attributes (&decl1, attributes, 0);
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& !DECL_BUILT_IN (old_decl)
- && (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
- == TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
+ && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (TREE_TYPE (old_decl)))
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
{
- TREE_TYPE (decl1) = TREE_TYPE (old_decl);
+ TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
+ TREE_TYPE (decl1));
current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
}
push_scope ();
declare_parm_level ();
- make_decl_rtl (current_function_decl, NULL);
-
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
/* Promote the value to int before returning it. */
if (c_promoting_integer_type_p (restype))
else
restype = integer_type_node;
}
- DECL_RESULT (current_function_decl)
- = build_decl (RESULT_DECL, NULL_TREE, restype);
- /* If this fcn was already referenced via a block-scope `extern' decl
- (or an implicit decl), propagate certain information about the usage. */
- if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
- TREE_ADDRESSABLE (current_function_decl) = 1;
-
- immediate_size_expand = old_immediate_size_expand;
+ resdecl = build_decl (RESULT_DECL, NULL_TREE, restype);
+ DECL_ARTIFICIAL (resdecl) = 1;
+ DECL_IGNORED_P (resdecl) = 1;
+ DECL_RESULT (current_function_decl) = resdecl;
start_fname_decls ();
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
- bind (DECL_NAME (decl), decl, current_scope);
+ bind (DECL_NAME (decl), decl, current_scope,
+ /*invisible=*/false, /*nested=*/false);
else
error ("%Jparameter name omitted", decl);
}
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
- bind (DECL_NAME (decl), decl, current_scope);
+ bind (DECL_NAME (decl), decl, current_scope,
+ /*invisible=*/false, /*nested=*/false);
}
/* And all the tag declarations. */
for (decl = tags; decl; decl = TREE_CHAIN (decl))
if (TREE_PURPOSE (decl))
- bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope);
+ bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
+ /*invisible=*/false, /*nested=*/false);
}
/* Subroutine of store_parm_decls which handles old-style function
}
b = I_SYMBOL_BINDING (TREE_VALUE (parm));
- if (b && b->contour == current_scope)
+ if (b && B_IN_CURRENT_SCOPE (b))
{
decl = b->decl;
/* If we got something other than a PARM_DECL it is an error. */
declared for the arg. ISO C says we take the unqualified
type for parameters declared with qualified type. */
if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type)),
- COMPARE_STRICT))
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
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;
}
}
-/* A subroutine of store_parm_decls called via walk_tree. Mark all
- decls non-local. */
-
-static tree
-set_decl_nonlocal (tree *tp, int *walk_subtrees, void *data ATTRIBUTE_UNUSED)
-{
- tree t = *tp;
-
- if (DECL_P (t))
- {
- DECL_NONLOCAL (t) = 1;
- *walk_subtrees = 0;
- }
- else if (TYPE_P (t))
- *walk_subtrees = 0;
-
- return NULL;
-}
-
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
store_parm_decls (void)
{
tree fndecl = current_function_decl;
-
- /* The function containing FNDECL, if any. */
- tree context = decl_function_context (fndecl);
+ 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);
allocate_struct_function (fndecl);
/* Begin the statement tree for this function. */
- begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = push_stmt_list ();
- /* If this is a nested function, save away the sizes of any
- variable-size types so that we can expand them when generating
- RTL. */
- if (context)
- {
- tree t;
-
- DECL_LANG_SPECIFIC (fndecl)->pending_sizes
- = nreverse (get_pending_sizes ());
- for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
- t;
- t = TREE_CHAIN (t))
- {
- /* We will have a nonlocal use of whatever variables are
- buried inside here. */
- walk_tree (&TREE_OPERAND (TREE_VALUE (t), 0),
- set_decl_nonlocal, NULL, NULL);
-
- SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
- }
- }
-
- /* This function is being processed in whole-function mode. */
- cfun->x_whole_function_mode_p = 1;
+ /* ??? Insert the contents of the pending sizes list into the function
+ to be evaluated. This just changes mis-behaviour until assign_parms
+ phase ordering problems are resolved. */
+ {
+ tree t;
+ for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
+ add_stmt (TREE_VALUE (t));
+ }
/* Even though we're inside a function body, we still don't want to
call expand_expr to calculate the size of a variable-sized array.
We haven't necessarily assigned RTL to all variables yet, so it's
not safe to try to expand expressions involving them. */
- immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
}
\f
{
tree fndecl = current_function_decl;
- /* When a function declaration is totally empty, e.g.
- void foo(void) { }
- (the argument list is irrelevant) the compstmt rule will not
- bother calling push_scope/pop_scope, which means we get here with
- the scope stack out of sync. Detect this situation by noticing
- that current_scope is still as store_parm_decls left it, and do
- a dummy push/pop to get back to consistency.
- Note that the call to push_scope does not actually push another
- scope - see there for details. */
-
- if (current_scope->parm_flag && next_is_function_body)
- {
- push_scope ();
- pop_scope ();
- }
-
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
}
else
{
-#ifdef DEFAULT_MAIN_RETURN
- /* Make it so that `main' always returns success by default. */
- DEFAULT_MAIN_RETURN;
-#else
if (flag_isoc99)
- c_expand_return (integer_zero_node);
-#endif
+ c_finish_return (integer_zero_node);
}
}
- finish_fname_decls ();
-
/* Tie off the statement tree for this function. */
- finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
+ DECL_SAVED_TREE (fndecl) = pop_stmt_list (DECL_SAVED_TREE (fndecl));
+
+ finish_fname_decls ();
/* Complain if there's just no return statement. */
if (warn_return_type
&& !targetm.have_ctors_dtors)
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
+ /* Finalize the ELF visibility for the function. */
+ c_determine_visibility (fndecl);
+
/* Genericize before inlining. Delay genericizing nested functions
until their parent function is genericized. Since finalizing
requires GENERIC, delay that as well. */
-
+
if (DECL_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node)
{
if (!decl_function_context (fndecl))
c_push_function_context (struct function *f)
{
struct language_function *p;
- p = ggc_alloc (sizeof (struct language_function));
+ p = GGC_NEW (struct language_function);
f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
- p->base.x_scope_stmt_stack = c_scope_stmt_stack;
- p->x_in_iteration_stmt = c_in_iteration_stmt;
- p->x_in_case_stmt = c_in_case_stmt;
+ 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_stmt_tree = p->base.x_stmt_tree;
- c_scope_stmt_stack = p->base.x_scope_stmt_stack;
- c_in_iteration_stmt = p->x_in_iteration_stmt;
- c_in_case_stmt = p->x_in_case_stmt;
+ 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;
if (!DECL_LANG_SPECIFIC (decl))
return;
- ld = ggc_alloc (sizeof (struct lang_decl));
+ ld = GGC_NEW (struct lang_decl);
memcpy (ld, DECL_LANG_SPECIFIC (decl), sizeof (struct lang_decl));
DECL_LANG_SPECIFIC (decl) = ld;
}
return &c_stmt_tree;
}
-/* Returns the stack of SCOPE_STMTs for the current function. */
-
-tree *
-current_scope_stmt_stack (void)
-{
- return &c_scope_stmt_stack;
-}
-
/* Nonzero if TYPE is an anonymous union or struct type. Always 0 in
C. */
int
-anon_aggr_type_p (tree node ATTRIBUTE_UNUSED)
+anon_aggr_type_p (tree ARG_UNUSED (node))
{
return 0;
}
{
}
-/* Return a new COMPOUND_STMT, after adding it to the current
- statement tree. */
-
-tree
-c_begin_compound_stmt (void)
-{
- tree stmt;
-
- /* Create the COMPOUND_STMT. */
- stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
-
- return stmt;
-}
-
/* Return the global value of T as a symbol. */
tree
struct c_binding *b;
for (b = I_SYMBOL_BINDING (t); b; b = b->shadowed)
- if (b->contour == file_scope || b->contour == external_scope)
+ if (B_IN_FILE_SCOPE (b) || B_IN_EXTERNAL_SCOPE (b))
return b->decl;
return 0;
void
record_builtin_type (enum rid rid_index, const char *name, tree type)
{
- tree id;
+ tree id, decl;
if (name == 0)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
- pushdecl (build_decl (TYPE_DECL, id, type));
+ decl = build_decl (TYPE_DECL, id, type);
+ pushdecl (decl);
+ if (debug_hooks->type_decl)
+ debug_hooks->type_decl (decl, false);
}
/* Build the void_list_node (void_type_node having been created). */
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);
}
-/* A wrapper around lhd_set_decl_assembler_name that gives static
- variables their C names if they are at file scope and only one
- translation unit is being compiled, for backwards compatibility
- with certain bizarre assembler hacks (like crtstuff.c). */
-
-void
-c_static_assembler_name (tree decl)
+/* Synthesize a function which calls all the global ctors or global
+ dtors in this file. This is only used for targets which do not
+ support .ctors/.dtors sections. FIXME: Migrate into cgraph. */
+static void
+build_cdtor (int method_type, tree cdtors)
{
- if (num_in_fnames == 1
- && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl)
- && TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL)
- SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
- else
- lhd_set_decl_assembler_name (decl);
+ tree body = 0;
+
+ if (!cdtors)
+ return;
+
+ for (; cdtors; cdtors = TREE_CHAIN (cdtors))
+ append_to_statement_list (build_function_call (TREE_VALUE (cdtors), 0),
+ &body);
+
+ cgraph_build_static_cdtor (method_type, body, DEFAULT_INIT_PRIORITY);
}
-/* Perform final processing on file-scope data. */
+/* Perform final processing on one file scope's declarations (or the
+ external scope's declarations), GLOBALS. */
static void
c_write_global_declarations_1 (tree globals)
{
size_t len = list_length (globals);
- tree *vec = xmalloc (sizeof (tree) * len);
+ tree *vec = XNEWVEC (tree, len);
size_t i;
tree decl;
-
+
/* Process the decls in the order they were written. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[i] = decl;
wrapup_global_declarations (vec, len);
check_global_declarations (vec, len);
-
+
free (vec);
}
void
c_write_global_declarations (void)
{
- tree t;
+ tree ext_block, t;
/* We don't want to do this if generating a PCH. */
if (pch_file)
return;
- /* Process all file scopes in this compilation. */
+ /* Don't waste time on further processing if -fsyntax-only or we've
+ encountered errors. */
+ if (flag_syntax_only || errorcount || sorrycount || cpp_errors (parse_in))
+ return;
+
+ /* Close the external scope. */
+ ext_block = pop_scope ();
+ external_scope = 0;
+ if (current_scope)
+ abort ();
+
+ /* Process all file scopes in this compilation, and the external_scope,
+ through wrapup_global_declarations and check_global_declarations. */
for (t = all_translation_units; t; t = TREE_CHAIN (t))
c_write_global_declarations_1 (BLOCK_VARS (DECL_INITIAL (t)));
-
- /* Now do the same for the externals scope. */
- t = pop_scope ();
- if (t)
- c_write_global_declarations_1 (BLOCK_VARS (t));
+ c_write_global_declarations_1 (BLOCK_VARS (ext_block));
+
+ /* Generate functions to call static constructors and destructors
+ for targets that do not support .ctors/.dtors sections. These
+ functions have magic names which are detected by collect2. */
+ build_cdtor ('I', static_ctors); static_ctors = 0;
+ build_cdtor ('D', static_dtors); static_dtors = 0;
+
+ /* We're done parsing; proceed to optimize and emit assembly.
+ FIXME: shouldn't be the front end's responsibility to call this. */
+ cgraph_optimize ();
+
+ /* Presently this has to happen after cgraph_optimize.
+ FIXME: shouldn't be the front end's responsibility to call this. */
+ if (flag_mudflap)
+ mudflap_finish_file ();
}
#include "gt-c-decl.h"