static int current_extern_inline;
+/* Nonzero when the current toplevel function contains a declaration
+ of a nested function which is never defined. */
+
+static bool undef_nested_function;
+
/* True means global_bindings_p should return false even if the scope stack
says we are in file scope. */
bool c_override_global_bindings_to_false;
&& DECL_ABSTRACT_ORIGIN (p) != 0
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
+ if (!DECL_EXTERNAL (p)
+ && DECL_INITIAL (p) == 0)
+ {
+ error ("%Jnested function %qD declared but never defined", p, p);
+ undef_nested_function = true;
+ }
goto common_symbol;
case VAR_DECL:
tree newtype, oldtype;
bool pedwarned = false;
bool warned = false;
+ bool retval = true;
/* If we have error_mark_node for either decl or type, just discard
the previous decl - we're in an error cascade already. */
if (DECL_INITIAL (newdecl))
{
- if (DECL_INITIAL (olddecl)
- && !(DECL_DECLARED_INLINE_P (olddecl)
- && DECL_EXTERNAL (olddecl)
- && !(DECL_DECLARED_INLINE_P (newdecl)
- && DECL_EXTERNAL (newdecl)
- && same_translation_unit_p (olddecl, newdecl))))
+ if (DECL_INITIAL (olddecl))
{
- error ("%Jredefinition of %qD", newdecl, newdecl);
- locate_old_decl (olddecl, error);
- return false;
- }
+ /* If both decls have extern inline and are in the same TU,
+ reject the new decl. */
+ if (DECL_DECLARED_INLINE_P (olddecl)
+ && DECL_EXTERNAL (olddecl)
+ && DECL_DECLARED_INLINE_P (newdecl)
+ && DECL_EXTERNAL (newdecl)
+ && same_translation_unit_p (newdecl, olddecl))
+ {
+ error ("%Jredefinition of %qD", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ /* If both decls have not extern inline, reject the new decl. */
+ if (!DECL_DECLARED_INLINE_P (olddecl)
+ && !DECL_EXTERNAL (olddecl)
+ && !DECL_DECLARED_INLINE_P (newdecl)
+ && !DECL_EXTERNAL (newdecl))
+ {
+ error ("%Jredefinition of %qD", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ /* If the new decl is declared as extern inline, error if they are
+ in the same TU, otherwise retain the old decl. */
+ if (!DECL_DECLARED_INLINE_P (olddecl)
+ && !DECL_EXTERNAL (olddecl)
+ && DECL_DECLARED_INLINE_P (newdecl)
+ && DECL_EXTERNAL (newdecl))
+ {
+ if (same_translation_unit_p (newdecl, olddecl))
+ {
+ error ("%Jredefinition of %qD", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+ else
+ retval = false;
+ }
+ }
}
/* If we have a prototype after an old-style function definition,
the argument types must be checked specially. */
if (warned || pedwarned)
locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
- return true;
+ return retval;
}
/* Subroutine of duplicate_decls. NEWDECL has been found to be
{
tree old_decl = b->decl;
- if (TREE_CODE (old_decl) == PARM_DECL)
+ if (old_decl == error_mark_node)
+ {
+ warning ("%Jdeclaration of %qD shadows previous non-variable",
+ new_decl, new_decl);
+ break;
+ }
+ else if (TREE_CODE (old_decl) == PARM_DECL)
warning ("%Jdeclaration of %qD shadows a parameter",
new_decl, new_decl);
else if (DECL_FILE_SCOPE_P (old_decl))
new_decl, new_decl);
else if (TREE_CODE (old_decl) == FUNCTION_DECL
&& DECL_BUILT_IN (old_decl))
- warning ("%Jdeclaration of %qD shadows a built-in function",
- new_decl, new_decl);
+ {
+ warning ("%Jdeclaration of %qD shadows a built-in function",
+ new_decl, new_decl);
+ break;
+ }
else
warning ("%Jdeclaration of %qD shadows a previous local",
new_decl, new_decl);
- if (TREE_CODE (old_decl) != FUNCTION_DECL
- || !DECL_BUILT_IN (old_decl))
- warning ("%Jshadowed declaration is here", old_decl);
+ warning ("%Jshadowed declaration is here", old_decl);
break;
}
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)
+ if (DECL_P (b->decl) && DECL_FILE_SCOPE_P (b->decl) && !type_saved)
{
b->type = TREE_TYPE (b->decl);
type_saved = true;
if (decl)
{
+ if (decl == error_mark_node)
+ return decl;
+
/* FIXME: Objective-C has weird not-really-builtin functions
which are supposed to be visible automatically. They wind up
in the external scope because they're pushed before the file
tree decl, type, init;
size_t length = strlen (name);
- type = build_array_type
- (build_qualified_type (char_type_node, TYPE_QUAL_CONST),
- build_index_type (size_int (length)));
+ type = build_array_type (char_type_node,
+ build_index_type (size_int (length)));
+ type = c_build_qualified_type (type, TYPE_QUAL_CONST);
decl = build_decl (VAR_DECL, id, type);
error ("variable %qD has initializer but incomplete type", decl);
initialized = 0;
}
- else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
- {
- error ("elements of array %qD have incomplete type", decl);
- initialized = 0;
- }
else if (C_DECL_VARIABLE_SIZE (decl))
{
/* Although C99 is unclear about whether incomplete arrays
if (volatilep > 1)
pedwarn ("duplicate %<volatile%>");
}
- if (!flag_gen_aux_info && (TYPE_QUALS (type)))
+ if (!flag_gen_aux_info && (TYPE_QUALS (element_type)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
/* Now figure out the structure of the declarator proper.
Descend through it, creating more complex types, until we reach
- the declared identifier (or NULL_TREE, in an absolute declarator). */
+ the declared identifier (or NULL_TREE, in an absolute declarator).
+ At each stage we maintain an unqualified version of the type
+ together with any qualifiers that should be applied to it with
+ c_build_qualified_type; this way, array types including
+ multidimensional array types are first built up in unqualified
+ form and then the qualified form is created with
+ TYPE_MAIN_VARIANT pointing to the unqualified form. */
while (declarator && declarator->kind != cdk_id)
{
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
}
- /* If pedantic, complain about arrays of incomplete types. */
- if (pedantic && !COMPLETE_TYPE_P (type))
- pedwarn ("array type has incomplete element type");
-
- /* Build the array type itself, then merge any constancy
- or volatility into the target type. We must do it in
- this order to ensure that the TYPE_MAIN_VARIANT field
- of the array type is set correctly. */
- type = build_array_type (type, itype);
- if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ /* Complain about arrays of incomplete types. */
+ if (!COMPLETE_TYPE_P (type))
+ {
+ error ("array type has incomplete element type");
+ type = error_mark_node;
+ }
+ else
+ type = build_array_type (type, itype);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
}
}
- /* Now TYPE has the actual type. */
+ /* Now TYPE has the actual type, apart from any qualifiers in
+ TYPE_QUALS. */
/* Check the type and width of a bit-field. */
if (bitfield)
error ("field %qs has incomplete type", name);
type = error_mark_node;
}
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
+ type = c_build_qualified_type (type, type_quals);
decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
/* An uninitialized decl with `extern' is a reference. */
int extern_ref = !initialized && storage_class == csc_extern;
- /* Move type qualifiers down to element of an array. */
- if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- {
- int saved_align = TYPE_ALIGN(type);
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
- TYPE_ALIGN (type) = saved_align;
- }
- else if (type_quals)
- type = c_build_qualified_type (type, type_quals);
+ type = c_build_qualified_type (type, type_quals);
/* C99 6.2.2p7: It is invalid (compile-time undefined
behavior) to create an 'extern' declaration for a
= 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));
+ {
+ TREE_TYPE (*fieldlistp)
+ = build_nonstandard_integer_type (width, TYPE_UNSIGNED (type));
+ DECL_MODE (*fieldlistp) = TYPE_MODE (TREE_TYPE (*fieldlistp));
+ }
DECL_INITIAL (*fieldlistp) = 0;
}
else
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_INITIAL (fndecl) && DECL_INITIAL (fndecl) != error_mark_node
+ && !undef_nested_function)
{
if (!decl_function_context (fndecl))
{
}
}
+ if (!decl_function_context (fndecl))
+ undef_nested_function = false;
+
/* We're leaving the context of this function, so zap cfun.
It's still in DECL_STRUCT_FUNCTION, and we'll restore it in
tree_rest_of_compilation. */