/* Process declarations and variables for C compiler.
Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+ 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
+#include "input.h"
#include "tm.h"
#include "intl.h"
#include "tree.h"
static int enum_overflow;
-/* These #defines are for clarity in working with the information block
- returned by get_parm_info. */
-#define ARG_INFO_PARMS(args) TREE_PURPOSE(args)
-#define ARG_INFO_TAGS(args) TREE_VALUE(args)
-#define ARG_INFO_TYPES(args) TREE_CHAIN(args)
-#define ARG_INFO_OTHERS(args) TREE_TYPE(args)
-
/* The file and line that the prototype came from if this is an
old-style definition; used for diagnostics in
store_parm_decls_oldstyle. */
static location_t current_function_prototype_locus;
+/* Whether this prototype was built-in. */
+
+static bool current_function_prototype_built_in;
+
+/* The argument type information of this prototype. */
+
+static tree current_function_prototype_arg_types;
+
/* The argument information structure for the function currently being
defined. */
-static GTY(()) tree current_function_arg_info;
+static struct c_arg_info *current_function_arg_info;
+
+/* The obstack on which parser and related data structures, which are
+ not live beyond their top-level declaration or definition, are
+ allocated. */
+struct obstack parser_obstack;
/* The current statement tree. */
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;
#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)
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->symbol_binding)
#define I_SYMBOL_DECL(node) \
(I_SYMBOL_BINDING(node) ? I_SYMBOL_BINDING(node)->decl : 0)
#define I_TAG_BINDING(node) \
- (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->tag_binding)
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->tag_binding)
#define I_TAG_DECL(node) \
(I_TAG_BINDING(node) ? I_TAG_BINDING(node)->decl : 0)
#define I_LABEL_BINDING(node) \
- (((struct lang_identifier *)IDENTIFIER_NODE_CHECK(node))->label_binding)
+ (((struct lang_identifier *) IDENTIFIER_NODE_CHECK(node))->label_binding)
#define I_LABEL_DECL(node) \
(I_LABEL_BINDING(node) ? I_LABEL_BINDING(node)->decl : 0)
union lang_tree_node
GTY((desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"),
- chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *)TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *)TREE_CHAIN (&%h.generic)")))
+ chain_next ("TREE_CODE (&%h.generic) == INTEGER_TYPE ? (union lang_tree_node *) TYPE_NEXT_VARIANT (&%h.generic) : (union lang_tree_node *) TREE_CHAIN (&%h.generic)")))
{
union tree_node GTY ((tag ("0"),
desc ("tree_node_structure (&%h)")))
/* 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, bool, tree *);
-static tree grokparms (tree, bool);
+static tree grokdeclarator (const struct c_declarator *,
+ struct c_declspecs *,
+ enum decl_context, bool, tree *);
+static tree grokparms (struct c_arg_info *, bool);
static void layout_array_type (tree);
\f
/* States indicating how grokdeclarator() should handle declspecs marked
case ERROR_MARK: here = &I_SYMBOL_BINDING (name); break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Locate the appropriate place in the chain of shadowed decls
tree type = TREE_TYPE (decl);
if (type != error_mark_node
&& TREE_CODE (type) == ARRAY_TYPE
- && ! DECL_EXTERNAL (decl)
+ && !DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
- warning ("%Jarray '%D' assumed to have one element", decl, decl);
+ warning (0, "%Jarray %qD assumed to have one element", decl, decl);
- complete_array_type (type, NULL_TREE, 1);
+ complete_array_type (&TREE_TYPE (decl), NULL_TREE, true);
layout_decl (decl, 0);
}
scope = scope->outer)
{
for (b = scope->bindings; b; b = b->prev)
- {
- if (TREE_CODE (b->decl) == VAR_DECL
- || TREE_CODE (b->decl) == PARM_DECL)
- {
- C_DECL_REGISTER (b->decl) = 0;
- DECL_REGISTER (b->decl) = 0;
- TREE_THIS_VOLATILE (b->decl) = 1;
- }
- }
+ objc_volatilize_decl (b->decl);
/* Do not climb up past the current function. */
if (scope->function_body)
if (current_scope && scope->depth == 0)
{
scope->depth--;
- sorry ("GCC supports only %u nested scopes\n", scope->depth);
+ sorry ("GCC supports only %u nested scopes", scope->depth);
}
current_scope = scope;
bool functionbody = scope->function_body;
bool keep = functionbody || scope->keep || scope->bindings;
+ c_end_vm_scope (scope->depth);
+
/* If appropriate, create a BLOCK to record the decls for the life
of this function. */
block = 0;
/* Warnings for unused labels, errors for undefined labels. */
if (TREE_USED (p) && !DECL_INITIAL (p))
{
- error ("%Jlabel `%D' used but not defined", p, p);
+ error ("%Jlabel %qD used but not defined", p, p);
DECL_INITIAL (p) = error_mark_node;
}
else if (!TREE_USED (p) && warn_unused_label)
{
if (DECL_INITIAL (p))
- warning ("%Jlabel `%D' defined but not used", p, p);
+ warning (0, "%Jlabel %qD defined but not used", p, p);
else
- warning ("%Jlabel `%D' declared but not defined", p, p);
+ warning (0, "%Jlabel %qD declared but not defined", p, p);
}
/* 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
+ gcc_assert (I_LABEL_BINDING (b->id) == b);
I_LABEL_BINDING (b->id) = b->shadowed;
break;
appears in the bindings list with b->id NULL. */
if (b->id)
{
-#ifdef ENABLE_CHECKING
- if (I_TAG_BINDING (b->id) != b) abort ();
-#endif
+ gcc_assert (I_TAG_BINDING (b->id) == b);
I_TAG_BINDING (b->id) = b->shadowed;
}
break;
case FUNCTION_DECL:
/* Propagate TREE_ADDRESSABLE from nested functions to their
containing functions. */
- if (! TREE_ASM_WRITTEN (p)
+ if (!TREE_ASM_WRITTEN (p)
&& DECL_INITIAL (p) != 0
&& TREE_ADDRESSABLE (p)
&& 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:
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
- && (scope != file_scope
- || (TREE_STATIC (p) && !TREE_PUBLIC (p)
- && !TREE_THIS_VOLATILE (p)))
- && scope != external_scope)
- warning ("%Junused variable `%D'", p, p);
+ && scope != file_scope
+ && scope != external_scope)
+ warning (0, "%Junused variable %qD", p, p);
if (b->inner_comp)
{
here with b->id NULL in this case. */
if (b->id)
{
-#ifdef ENABLE_CHECKING
- if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
I_SYMBOL_BINDING (b->id) = b->shadowed;
if (b->shadowed && b->shadowed->type)
TREE_TYPE (b->shadowed->decl) = b->shadowed->type;
break;
default:
- abort ();
+ gcc_unreachable ();
}
}
/* Pop off the file scope and close this translation unit. */
pop_scope ();
file_scope = 0;
+
+ maybe_apply_pending_pragma_weaks ();
cgraph_finalize_compilation_unit ();
}
while (oldargs || newargs)
{
- if (! oldargs
- || ! newargs
- || ! TREE_VALUE (oldargs)
- || ! TREE_VALUE (newargs)
+ if (!oldargs
+ || !newargs
+ || !TREE_VALUE (oldargs)
+ || !TREE_VALUE (newargs)
|| TYPE_MODE (TREE_VALUE (oldargs))
!= TYPE_MODE (TREE_VALUE (newargs)))
return 0;
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
- inform ("a parameter list with an ellipsis can't match "
+ inform ("a parameter list with an ellipsis can%'t match "
"an empty parameter name list declaration");
break;
}
if (c_type_promotes_to (type) != type)
{
- inform ("an argument type that has a default promotion can't match "
+ inform ("an argument type that has a default promotion can%'t match "
"an empty parameter name list declaration");
break;
}
tree newargs, oldargs;
int i;
- /* ??? Elsewhere TYPE_MAIN_VARIANT is not used in this context. */
-#define END_OF_ARGLIST(t) (TYPE_MAIN_VARIANT (t) == void_type_node)
+#define END_OF_ARGLIST(t) ((t) == void_type_node)
oldargs = TYPE_ACTUAL_ARG_TYPES (oldtype);
newargs = TYPE_ARG_TYPES (newtype);
for (;;)
{
- tree oldargtype = TREE_VALUE (oldargs);
- tree newargtype = TREE_VALUE (newargs);
+ tree oldargtype = TYPE_MAIN_VARIANT (TREE_VALUE (oldargs));
+ tree newargtype = TYPE_MAIN_VARIANT (TREE_VALUE (newargs));
if (END_OF_ARGLIST (oldargtype) && END_OF_ARGLIST (newargtype))
break;
agree on the number of arguments. */
if (END_OF_ARGLIST (oldargtype))
{
- error ("%Jprototype for '%D' declares more arguments "
+ error ("%Jprototype for %qD declares more arguments "
"than previous old-style definition", newdecl, newdecl);
return false;
}
else if (END_OF_ARGLIST (newargtype))
{
- error ("%Jprototype for '%D' declares fewer arguments "
+ error ("%Jprototype for %qD declares fewer arguments "
"than previous old-style definition", newdecl, newdecl);
return false;
}
/* Type for passing arg must be consistent with that declared
for the arg. */
- else if (! comptypes (oldargtype, newargtype))
+ else if (!comptypes (oldargtype, newargtype))
{
- error ("%Jprototype for '%D' declares arg %d with incompatible type",
+ error ("%Jprototype for %qD declares argument %d"
+ " with incompatible type",
newdecl, newdecl, i);
return false;
}
/* If we get here, no errors were found, but do issue a warning
for this poor-style construct. */
- warning ("%Jprototype for '%D' follows non-prototype definition",
+ warning (0, "%Jprototype for %qD follows non-prototype definition",
newdecl, newdecl);
return true;
#undef END_OF_ARGLIST
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_BUILT_IN (decl))
;
else if (DECL_INITIAL (decl))
- diag (N_("%Jprevious definition of '%D' was here"), decl, decl);
+ diag (N_("%Jprevious definition of %qD was here"), decl, decl);
else if (C_DECL_IMPLICIT (decl))
- diag (N_("%Jprevious implicit declaration of '%D' was here"), decl, decl);
+ diag (N_("%Jprevious implicit declaration of %qD was here"), decl, decl);
else
- diag (N_("%Jprevious declaration of '%D' was here"), decl, decl);
+ diag (N_("%Jprevious declaration of %qD was here"), decl, decl);
}
/* Subroutine of duplicate_decls. Compare NEWDECL to OLDDECL.
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. */
&& DECL_BUILT_IN (olddecl)
&& !C_DECL_DECLARED_BUILTIN (olddecl)))
{
- error ("%J'%D' redeclared as different kind of symbol",
+ error ("%J%qD redeclared as different kind of symbol",
newdecl, newdecl);
locate_old_decl (olddecl, error);
}
else if (TREE_PUBLIC (newdecl))
- warning ("%Jbuilt-in function '%D' declared as non-function",
+ warning (0, "%Jbuilt-in function %qD declared as non-function",
newdecl, newdecl);
else if (warn_shadow)
- warning ("%Jdeclaration of '%D' shadows a built-in function",
+ warning (0, "%Jdeclaration of %qD shadows a built-in function",
newdecl, newdecl);
return false;
}
+ /* Enumerators have no linkage, so may only be declared once in a
+ given scope. */
+ if (TREE_CODE (olddecl) == CONST_DECL)
+ {
+ error ("%Jredeclaration of enumerator %qD", newdecl, newdecl);
+ locate_old_decl (olddecl, error);
+ return false;
+ }
+
if (!comptypes (oldtype, newtype))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
/* If types don't match for a built-in, throw away the
built-in. No point in calling locate_old_decl here, it
won't print anything. */
- warning ("%Jconflicting types for built-in function '%D'",
+ warning (0, "%Jconflicting types for built-in function %qD",
newdecl, newdecl);
return false;
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl)
&& TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == integer_type_node
- && C_FUNCTION_IMPLICIT_INT (newdecl))
+ && C_FUNCTION_IMPLICIT_INT (newdecl) && !DECL_INITIAL (olddecl))
{
- pedwarn ("%Jconflicting types for '%D'", newdecl, newdecl);
+ pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
/* Make sure we keep void as the return type. */
TREE_TYPE (newdecl) = *newtypep = newtype = oldtype;
C_FUNCTION_IMPLICIT_INT (newdecl) = 0;
pedwarned = true;
}
+ /* Permit void foo (...) to match an earlier call to foo (...) with
+ no declared type (thus, implicitly int). */
+ else if (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_MAIN_VARIANT (TREE_TYPE (newtype)) == void_type_node
+ && TYPE_MAIN_VARIANT (TREE_TYPE (oldtype)) == integer_type_node
+ && C_DECL_IMPLICIT (olddecl) && !DECL_INITIAL (olddecl))
+ {
+ pedwarn ("%Jconflicting types for %qD", newdecl, newdecl);
+ /* Make sure we keep void as the return type. */
+ TREE_TYPE (olddecl) = *oldtypep = oldtype = newtype;
+ pedwarned = true;
+ }
else
{
if (TYPE_QUALS (newtype) != TYPE_QUALS (oldtype))
- error ("%J conflicting type qualifiers for '%D'", newdecl, newdecl);
+ error ("%J conflicting type qualifiers for %qD", newdecl, newdecl);
else
- error ("%Jconflicting types for '%D'", newdecl, newdecl);
+ error ("%Jconflicting types for %qD", 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);
+ error ("%Jredefinition of typedef %qD", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
&& !TYPE_ARG_TYPES (TREE_TYPE (newdecl)))))
{
if (warn_shadow)
- warning ("%Jdeclaration of '%D' shadows a built-in function",
+ warning (0, "%Jdeclaration of %qD shadows a built-in function",
newdecl, newdecl);
/* 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)
- && same_translation_unit_p (olddecl, newdecl))))
+ if (DECL_INITIAL (olddecl))
{
- error ("%Jredefinition of '%D'", 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. */
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. */
+ we do diagnose it if -Wtraditional. */
if (TREE_PUBLIC (olddecl) && !TREE_PUBLIC (newdecl))
{
/* Two exceptions to the rule. If olddecl is an extern
&& !(DECL_EXTERNAL (olddecl)
&& DECL_DECLARED_INLINE_P (olddecl)))
{
- error ("%Jstatic declaration of '%D' follows "
+ error ("%Jstatic declaration of %qD follows "
"non-static declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
}
{
if (DECL_CONTEXT (olddecl))
{
- error ("%Jnon-static declaration of '%D' follows "
+ error ("%Jnon-static declaration of %qD follows "
"static declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
else if (warn_traditional)
{
- warning ("%Jnon-static declaration of '%D' follows "
+ warning (0, "%Jnon-static declaration of %qD follows "
"static declaration", newdecl, newdecl);
warned = true;
}
if (DECL_THREAD_LOCAL (newdecl) != DECL_THREAD_LOCAL (olddecl))
{
if (DECL_THREAD_LOCAL (newdecl))
- error ("%Jthread-local declaration of '%D' follows "
+ error ("%Jthread-local declaration of %qD follows "
"non-thread-local declaration", newdecl, newdecl);
else
- error ("%Jnon-thread-local declaration of '%D' follows "
+ error ("%Jnon-thread-local declaration of %qD follows "
"thread-local declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
/* Multiple initialized definitions are not allowed (6.9p3,5). */
if (DECL_INITIAL (newdecl) && DECL_INITIAL (olddecl))
{
- error ("%Jredefinition of '%D'", newdecl, newdecl);
+ error ("%Jredefinition of %qD", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
}
else if (warn_traditional)
{
- warning ("%Jnon-static declaration of '%D' follows "
+ warning (0, "%Jnon-static declaration of %qD follows "
"static declaration", newdecl, newdecl);
warned = true;
}
else
{
if (TREE_PUBLIC (newdecl))
- error ("%Jnon-static declaration of '%D' follows "
+ error ("%Jnon-static declaration of %qD follows "
"static declaration", newdecl, newdecl);
else
- error ("%Jstatic declaration of '%D' follows "
+ error ("%Jstatic declaration of %qD follows "
"non-static declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
}
else if (DECL_EXTERNAL (olddecl))
{
- error ("%Jdeclaration of '%D' with no linkage follows "
+ error ("%Jdeclaration of %qD with no linkage follows "
"extern declaration", newdecl, newdecl);
locate_old_decl (olddecl, error);
}
else
{
- error ("%Jredeclaration of '%D' with no linkage",
+ error ("%Jredeclaration of %qD with no linkage",
newdecl, newdecl);
locate_old_decl (olddecl, error);
}
if (DECL_VISIBILITY_SPECIFIED (newdecl) && DECL_VISIBILITY_SPECIFIED (olddecl)
&& DECL_VISIBILITY (newdecl) != DECL_VISIBILITY (olddecl))
{
- warning ("%Jredeclaration of '%D' with different visibility "
+ warning (0, "%Jredeclaration of %qD with different visibility "
"(old visibility preserved)", newdecl, newdecl);
warned = true;
}
if (DECL_DECLARED_INLINE_P (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
- warning ("%Jinline declaration of '%D' follows "
+ warning (0, "%Jinline declaration of %qD follows "
"declaration with attribute noinline", newdecl, newdecl);
warned = true;
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
- warning ("%Jdeclaration of '%D' with attribute noinline follows "
+ warning (0, "%Jdeclaration of %qD with attribute noinline follows "
"inline declaration ", newdecl, newdecl);
warned = true;
}
{
if (TREE_USED (olddecl))
{
- warning ("%J'%D' declared inline after being called",
+ warning (0, "%J%qD declared inline after being called",
olddecl, olddecl);
warned = true;
}
else if (DECL_INITIAL (olddecl))
{
- warning ("%J'%D' declared inline after its definition",
+ warning (0, "%J%qD declared inline after its definition",
olddecl, olddecl);
warned = true;
}
if (TREE_CODE (newdecl) == PARM_DECL
&& (!TREE_ASM_WRITTEN (olddecl) || TREE_ASM_WRITTEN (newdecl)))
{
- error ("%Jredefinition of parameter '%D'", newdecl, newdecl);
+ error ("%Jredefinition of parameter %qD", newdecl, newdecl);
locate_old_decl (olddecl, error);
return false;
}
definition. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) && !DECL_INITIAL (olddecl))
- /* Don't warn about redundant redeclarations of builtins. */
+ /* Don't warn about redundant redeclarations of builtins. */
&& !(TREE_CODE (newdecl) == FUNCTION_DECL
&& !DECL_BUILT_IN (newdecl)
&& DECL_BUILT_IN (olddecl)
&& !(TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl)))
{
- warning ("%Jredundant redeclaration of '%D'", newdecl, newdecl);
+ warning (0, "%Jredundant redeclaration of %qD", newdecl, newdecl);
warned = true;
}
/* Report location of previous decl/defn in a consistent manner. */
if (warned || pedwarned)
- locate_old_decl (olddecl, pedwarned ? pedwarn : warning);
+ locate_old_decl (olddecl, pedwarned ? pedwarn : warning0);
- return true;
+ return retval;
}
/* Subroutine of duplicate_decls. NEWDECL has been found to be
{
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
+ int new_is_prototype = (TREE_CODE (newdecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0);
+ int old_is_prototype = (TREE_CODE (olddecl) == FUNCTION_DECL
+ && TYPE_ARG_TYPES (TREE_TYPE (olddecl)) != 0);
/* For real parm decl following a forward decl, rechain the old decl
in its new location and clear TREE_ASM_WRITTEN (it's not a
forward decl anymore). */
if (TREE_CODE (newdecl) == PARM_DECL
- && TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
+ && TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
{
struct c_binding *b, **here;
for (here = ¤t_scope->bindings; *here; here = &(*here)->prev)
if ((*here)->decl == olddecl)
goto found;
- abort ();
+ gcc_unreachable ();
found:
b = *here;
= composite_type (newtype, oldtype);
/* Lay the type out, unless already done. */
- if (oldtype != TREE_TYPE (newdecl))
+ if (!comptypes (oldtype, TREE_TYPE (newdecl)))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
make_var_volatile (newdecl);
}
- /* Keep source location of definition rather than declaration. */
- if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+ /* Merge deprecatedness. */
+ if (TREE_DEPRECATED (newdecl))
+ TREE_DEPRECATED (olddecl) = 1;
+
+ /* Keep source location of definition rather than declaration and of
+ prototype rather than non-prototype unless that prototype is
+ built-in. */
+ if ((DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0)
+ || (old_is_prototype && !new_is_prototype
+ && !C_DECL_BUILTIN_PROTOTYPE (olddecl)))
DECL_SOURCE_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
/* Merge the unused-warning information. */
TREE_READONLY (newdecl) |= TREE_READONLY (olddecl);
DECL_IS_MALLOC (newdecl) |= DECL_IS_MALLOC (olddecl);
DECL_IS_PURE (newdecl) |= DECL_IS_PURE (olddecl);
+ DECL_IS_NOVOPS (newdecl) |= DECL_IS_NOVOPS (olddecl);
}
/* Merge the storage class information. */
copy the attributes of NEWDECL into OLDDECL. */
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
/* If this clears `static', clear it in the identifier too. */
- if (! TREE_PUBLIC (olddecl))
+ if (!TREE_PUBLIC (olddecl))
TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
}
if (DECL_EXTERNAL (newdecl))
/* An extern decl does not override previous storage class. */
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
- if (! DECL_EXTERNAL (newdecl))
+ if (!DECL_EXTERNAL (newdecl))
{
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
C_DECL_DECLARED_BUILTIN (newdecl) = 1;
+ if (new_is_prototype)
+ C_DECL_BUILTIN_PROTOTYPE (newdecl) = 0;
+ else
+ C_DECL_BUILTIN_PROTOTYPE (newdecl)
+ = C_DECL_BUILTIN_PROTOTYPE (olddecl);
}
/* Also preserve various other info from the definition. */
- if (! new_is_definition)
+ if (!new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
/* Set DECL_INLINE on the declaration if we've got a body
from which to instantiate. */
- if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
+ if (DECL_INLINE (olddecl) && !DECL_UNINLINABLE (newdecl))
{
DECL_INLINE (newdecl) = 1;
DECL_ABSTRACT_ORIGIN (newdecl)
/* If a previous declaration said inline, mark the
definition as inlinable. */
if (DECL_DECLARED_INLINE_P (newdecl)
- && ! DECL_UNINLINABLE (newdecl))
+ && !DECL_UNINLINABLE (newdecl))
DECL_INLINE (newdecl) = 1;
}
}
{
tree old_decl = b->decl;
- if (TREE_CODE (old_decl) == PARM_DECL)
- warning ("%Jdeclaration of '%D' shadows a parameter",
+ if (old_decl == error_mark_node)
+ {
+ warning (0, "%Jdeclaration of %qD shadows previous non-variable",
+ new_decl, new_decl);
+ break;
+ }
+ else if (TREE_CODE (old_decl) == PARM_DECL)
+ warning (0, "%Jdeclaration of %qD shadows a parameter",
new_decl, new_decl);
else if (DECL_FILE_SCOPE_P (old_decl))
- warning ("%Jdeclaration of '%D' shadows a global declaration",
+ warning (0, "%Jdeclaration of %qD shadows a global declaration",
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_decl, new_decl);
+ {
+ warning (0, "%Jdeclaration of %qD shadows a built-in function",
+ new_decl, new_decl);
+ break;
+ }
else
- warning ("%Jdeclaration of '%D' shadows a previous local",
+ warning (0, "%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 (0, "%Jshadowed declaration is here", old_decl);
break;
}
bool nested = false;
/* Functions need the lang_decl data. */
- if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
+ if (TREE_CODE (x) == FUNCTION_DECL && !DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = GGC_CNEW (struct lang_decl);
/* Must set DECL_CONTEXT for everything not at file scope or
|| DECL_INITIAL (x) || !DECL_EXTERNAL (x)))
DECL_CONTEXT (x) = current_function_decl;
+ /* If this is of variably modified type, prevent jumping into its
+ scope. */
+ if ((TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == TYPE_DECL)
+ && variably_modified_type_p (TREE_TYPE (x), NULL_TREE))
+ c_begin_vm_scope (scope->depth);
+
/* Anonymous decls are just inserted in the scope. */
if (!name)
{
b = I_SYMBOL_BINDING (name);
if (b && B_IN_SCOPE (b, scope))
{
+ struct c_binding *b_ext, *b_use;
+ tree type = TREE_TYPE (x);
+ tree visdecl = b->decl;
+ tree vistype = TREE_TYPE (visdecl);
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;
+ b_use = b;
+ b_ext = b;
+ /* If this is an external linkage declaration, we should check
+ for compatibility with the type in the external scope before
+ setting the type at this scope based on the visible
+ information only. */
+ if (TREE_PUBLIC (x) && TREE_PUBLIC (visdecl))
+ {
+ while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+ b_ext = b_ext->shadowed;
+ if (b_ext)
+ {
+ b_use = b_ext;
+ if (b_use->type)
+ TREE_TYPE (b_use->decl) = b_use->type;
+ }
+ }
+ if (duplicate_decls (x, b_use->decl))
+ {
+ if (b_use != b)
+ {
+ /* Save the updated type in the external scope and
+ restore the proper type for this scope. */
+ tree thistype;
+ if (comptypes (vistype, type))
+ thistype = composite_type (vistype, type);
+ else
+ thistype = TREE_TYPE (b_use->decl);
+ b_use->type = TREE_TYPE (b_use->decl);
+ if (TREE_CODE (b_use->decl) == FUNCTION_DECL
+ && DECL_BUILT_IN (b_use->decl))
+ thistype
+ = build_type_attribute_variant (thistype,
+ TYPE_ATTRIBUTES
+ (b_use->type));
+ TREE_TYPE (b_use->decl) = thistype;
+ }
+ return b_use->decl;
+ }
else
goto skip_external_and_shadow_checks;
}
if (warn_nested_externs
&& scope != file_scope
&& !DECL_IN_SYSTEM_HEADER (x))
- warning ("nested extern declaration of '%D'", x);
+ warning (0, "nested extern declaration of %qD", x);
while (b && !B_IN_EXTERNAL_SCOPE (b))
{
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;
&& duplicate_decls (x, b->decl))
{
tree thistype;
- thistype = (vistype ? composite_type (vistype, type) : type);
+ if (vistype)
+ {
+ if (comptypes (vistype, type))
+ thistype = composite_type (vistype, type);
+ else
+ thistype = TREE_TYPE (b->decl);
+ }
+ else
+ thistype = type;
b->type = TREE_TYPE (b->decl);
if (TREE_CODE (b->decl) == FUNCTION_DECL && DECL_BUILT_IN (b->decl))
thistype
just need to fall through to make the declaration in
this scope. */
nested = true;
+ x = visdecl;
}
else
{
}
}
}
- /* 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;
- }
- }
warn_if_shadowing (x);
{
tree name;
bool nested = false;
-
- if (TREE_CODE (x) != VAR_DECL)
- abort ();
+ gcc_assert (TREE_CODE (x) == VAR_DECL || TREE_CODE (x) == CONST_DECL);
name = DECL_NAME (x);
- if (I_SYMBOL_BINDING (name))
- abort ();
+ gcc_assert (TREE_CODE (x) == CONST_DECL || !I_SYMBOL_BINDING (name));
if (TREE_PUBLIC (x))
{
switch (mesg_implicit_function_declaration)
{
case 0: return;
- case 1: diag = warning; break;
+ case 1: diag = warning0; break;
case 2: diag = error; break;
- default: abort ();
+ default: gcc_unreachable ();
}
- diag (N_("implicit declaration of function '%E'"), id);
+ diag (N_("implicit declaration of function %qE"), id);
if (olddecl)
locate_old_decl (olddecl, diag);
}
{
struct c_binding *b;
tree decl = 0;
+ tree asmspec_tree;
+
for (b = I_SYMBOL_BINDING (functionid); b; b = b->shadowed)
{
if (B_IN_SCOPE (b, external_scope))
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_TYPE (decl)));
if (!comptypes (newtype, TREE_TYPE (decl)))
{
- warning ("incompatible implicit declaration of built-in"
+ warning (0, "incompatible implicit declaration of built-in"
" function %qD", decl);
newtype = TREE_TYPE (decl);
}
TREE_PUBLIC (decl) = 1;
C_DECL_IMPLICIT (decl) = 1;
implicit_decl_warning (functionid, 0);
+ asmspec_tree = maybe_apply_renaming_pragma (decl, /*asmname=*/NULL);
+ if (asmspec_tree)
+ set_user_assembler_name (decl, TREE_STRING_POINTER (asmspec_tree));
/* C89 says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
ID, including a reference to a builtin outside of function-call
context. Establish a binding of the identifier to error_mark_node
in an appropriate scope, which will suppress further errors for the
- same identifier. */
+ same identifier. The error message should be given location LOC. */
void
-undeclared_variable (tree id)
+undeclared_variable (tree id, location_t loc)
{
static bool already = false;
struct c_scope *scope;
if (current_function_decl == 0)
{
- error ("'%E' undeclared here (not in a function)", id);
+ error ("%H%qE undeclared here (not in a function)", &loc, id);
scope = current_scope;
}
else
{
- error ("'%E' undeclared (first use in this function)", id);
+ error ("%H%qE undeclared (first use in this function)", &loc, id);
- if (! already)
+ if (!already)
{
- error ("(Each undeclared identifier is reported only once");
- error ("for each function it appears in.)");
+ error ("%H(Each undeclared identifier is reported only once", &loc);
+ error ("%Hfor each function it appears in.)", &loc);
already = true;
}
if (current_function_decl == 0)
{
- error ("label %s referenced outside of any function",
- IDENTIFIER_POINTER (name));
+ error ("label %qE referenced outside of any function", name);
return 0;
}
at this scope */
if (b && B_IN_CURRENT_SCOPE (b))
{
- error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
+ error ("duplicate label declaration %qE", name);
locate_old_decl (b->decl, error);
/* Just use the previous declaration. */
if there is a containing function with a declared label with
the same name. */
tree label = I_LABEL_DECL (name);
+ struct c_label_list *nlist_se, *nlist_vm;
if (label
&& ((DECL_CONTEXT (label) == current_function_decl
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
- error ("%Hduplicate label `%D'", &location, label);
+ error ("%Hduplicate label %qD", &location, label);
locate_old_decl (label, error);
return 0;
}
/* The label has been used or declared already in this function,
but not defined. Update its location to point to this
definition. */
+ if (C_DECL_UNDEFINABLE_STMT_EXPR (label))
+ error ("%Jjump into statement expression", label);
+ if (C_DECL_UNDEFINABLE_VM (label))
+ error ("%Jjump into scope of identifier with variably modified type",
+ label);
DECL_SOURCE_LOCATION (label) = location;
}
else
}
if (warn_traditional && !in_system_header && lookup_name (name))
- warning ("%Htraditional C lacks a separate namespace for labels, "
- "identifier `%s' conflicts", &location,
- IDENTIFIER_POINTER (name));
+ warning (0, "%Htraditional C lacks a separate namespace for labels, "
+ "identifier %qE conflicts", &location, name);
+
+ nlist_se = XOBNEW (&parser_obstack, struct c_label_list);
+ nlist_se->next = label_context_stack_se->labels_def;
+ nlist_se->label = label;
+ label_context_stack_se->labels_def = nlist_se;
+
+ nlist_vm = XOBNEW (&parser_obstack, struct c_label_list);
+ nlist_vm->next = label_context_stack_vm->labels_def;
+ nlist_vm->label = label;
+ label_context_stack_vm->labels_def = nlist_vm;
/* Mark label as having been defined. */
DECL_INITIAL (label) = error_mark_node;
pending_xref_error (void)
{
if (pending_invalid_xref != 0)
- error ("%H`%s' defined as wrong kind of tag",
- &pending_invalid_xref_location,
- IDENTIFIER_POINTER (pending_invalid_xref));
+ error ("%H%qE defined as wrong kind of tag",
+ &pending_invalid_xref_location, pending_invalid_xref);
pending_invalid_xref = 0;
}
void
c_init_decl_processing (void)
{
- tree endlink;
- tree ptr_ftype_void, ptr_ftype_ptr;
location_t save_loc = input_location;
- /* Adds some ggc roots, and reserved words for c-parse.in. */
+ /* Initialize reserved words for parser. */
c_parse_init ();
current_function_decl = 0;
+ gcc_obstack_init (&parser_obstack);
+
/* Make the externals scope. */
push_scope ();
external_scope = current_scope;
pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
boolean_type_node));
- endlink = void_list_node;
- ptr_ftype_void = build_function_type (ptr_type_node, endlink);
- ptr_ftype_ptr
- = build_function_type (ptr_type_node,
- tree_cons (NULL_TREE, ptr_type_node, endlink));
-
input_location = save_loc;
pedantic_lvalues = true;
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);
DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
DECL_BUILT_IN_CLASS (decl) = cl;
DECL_FUNCTION_CODE (decl) = function_code;
+ C_DECL_BUILTIN_PROTOTYPE (decl) = (TYPE_ARG_TYPES (type) != 0);
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
/* Should never be called on a symbol with a preexisting meaning. */
- if (I_SYMBOL_BINDING (id))
- abort ();
+ gcc_assert (!I_SYMBOL_BINDING (id));
bind (id, decl, external_scope, /*invisible=*/true, /*nested=*/false);
Otherwise, it is an error. */
void
-shadow_tag (tree declspecs)
+shadow_tag (const struct c_declspecs *declspecs)
{
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)
+shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
{
- int found_tag = 0;
- tree link;
- tree specs, attrs;
-
- pending_invalid_xref = 0;
-
- /* Remove the attributes from declspecs, since they will confuse the
- following code. */
- split_specs_attrs (declspecs, &specs, &attrs);
+ bool found_tag = false;
- for (link = specs; link; link = TREE_CHAIN (link))
+ if (declspecs->type && !declspecs->default_int_p && !declspecs->typedef_p)
{
- tree value = TREE_VALUE (link);
+ tree value = declspecs->type;
enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
tree name = TYPE_NAME (value);
tree t;
- found_tag++;
+ found_tag = true;
if (name == 0)
{
warned = 1;
}
}
+ else if (!declspecs->tag_defined_p
+ && declspecs->storage_class != csc_none)
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with storage class specifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
+ else if (!declspecs->tag_defined_p
+ && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->restrict_p))
+ {
+ if (warned != 1)
+ pedwarn ("empty declaration with type qualifier "
+ "does not redeclare tag");
+ warned = 1;
+ pending_xref_error ();
+ }
else
{
+ pending_invalid_xref = 0;
t = lookup_tag (code, name, 1);
if (t == 0)
}
else
{
- if (!warned && ! in_system_header)
+ if (warned != 1 && !in_system_header)
{
- warning ("useless keyword or type name in empty declaration");
- warned = 2;
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
}
}
}
+ else if (warned != 1 && !in_system_header && declspecs->typedef_p)
+ {
+ pedwarn ("useless type name in empty declaration");
+ warned = 1;
+ }
+
+ pending_invalid_xref = 0;
+
+ if (declspecs->inline_p)
+ {
+ error ("%<inline%> in empty declaration");
+ warned = 1;
+ }
+
+ if (current_scope == file_scope && declspecs->storage_class == csc_auto)
+ {
+ error ("%<auto%> in file-scope empty declaration");
+ warned = 1;
+ }
+
+ if (current_scope == file_scope && declspecs->storage_class == csc_register)
+ {
+ error ("%<register%> in file-scope empty declaration");
+ warned = 1;
+ }
+
+ if (!warned && !in_system_header && declspecs->storage_class != csc_none)
+ {
+ warning (0, "useless storage class specifier in empty declaration");
+ warned = 2;
+ }
- if (found_tag > 1)
- error ("two types specified in one empty declaration");
+ if (!warned && !in_system_header && declspecs->thread_p)
+ {
+ warning (0, "useless %<__thread%> in empty declaration");
+ warned = 2;
+ }
+
+ if (!warned && !in_system_header && (declspecs->const_p
+ || declspecs->volatile_p
+ || declspecs->restrict_p))
+ {
+ warning (0, "useless type qualifier in empty declaration");
+ warned = 2;
+ }
if (warned != 1)
{
- if (found_tag == 0)
+ if (!found_tag)
pedwarn ("empty declaration");
}
}
\f
+
+/* Return the qualifiers from SPECS as a bitwise OR of TYPE_QUAL_*
+ bits. SPECS represents declaration specifiers that the grammar
+ only permits to contain type qualifiers and attributes. */
+
+int
+quals_from_declspecs (const struct c_declspecs *specs)
+{
+ int quals = ((specs->const_p ? TYPE_QUAL_CONST : 0)
+ | (specs->volatile_p ? TYPE_QUAL_VOLATILE : 0)
+ | (specs->restrict_p ? TYPE_QUAL_RESTRICT : 0));
+ gcc_assert (!specs->type
+ && !specs->decl_attr
+ && specs->typespec_word == cts_none
+ && specs->storage_class == csc_none
+ && !specs->typedef_p
+ && !specs->explicit_signed_p
+ && !specs->deprecated_p
+ && !specs->long_p
+ && !specs->long_long_p
+ && !specs->short_p
+ && !specs->signed_p
+ && !specs->unsigned_p
+ && !specs->complex_p
+ && !specs->inline_p
+ && !specs->thread_p);
+ return quals;
+}
+
/* 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
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),
- 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_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. */
+ false otherwise. The field for the contained declarator is left to be
+ filled in by set_array_declarator_inner. */
-tree
-build_array_declarator (tree expr, tree quals, bool static_p,
+struct c_declarator *
+build_array_declarator (tree expr, struct c_declspecs *quals, bool static_p,
bool vla_unspec_p)
{
- tree decl;
- decl = build_nt (ARRAY_REF, NULL_TREE, expr, NULL_TREE, NULL_TREE);
- TREE_TYPE (decl) = quals;
- TREE_STATIC (decl) = (static_p ? 1 : 0);
+ struct c_declarator *declarator = XOBNEW (&parser_obstack,
+ struct c_declarator);
+ declarator->kind = cdk_array;
+ declarator->declarator = 0;
+ declarator->u.array.dimen = expr;
+ if (quals)
+ {
+ declarator->u.array.attrs = quals->attrs;
+ declarator->u.array.quals = quals_from_declspecs (quals);
+ }
+ else
+ {
+ declarator->u.array.attrs = NULL_TREE;
+ declarator->u.array.quals = 0;
+ }
+ declarator->u.array.static_p = static_p;
+ declarator->u.array.vla_unspec_p = vla_unspec_p;
if (pedantic && !flag_isoc99)
{
- if (static_p || quals != NULL_TREE)
- pedwarn ("ISO C90 does not support `static' or type qualifiers in parameter array declarators");
+ if (static_p || quals != NULL)
+ pedwarn ("ISO C90 does not support %<static%> or type "
+ "qualifiers in parameter array declarators");
if (vla_unspec_p)
- pedwarn ("ISO C90 does not support `[*]' array declarators");
+ pedwarn ("ISO C90 does not support %<[*]%> array declarators");
}
if (vla_unspec_p)
- warning ("GCC does not yet properly implement `[*]' array declarators");
- return decl;
+ warning (0, "GCC does not yet properly implement %<[*]%> array declarators");
+ return declarator;
}
-/* 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 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. */
+/* Set the contained declarator of an array declarator. DECL is the
+ declarator, as constructed by build_array_declarator; INNER is what
+ appears on the left of the []. 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 (subject to possible change in DR#289). */
-tree
-set_array_declarator_inner (tree decl, tree type, bool abstract_p)
+struct c_declarator *
+set_array_declarator_inner (struct c_declarator *decl,
+ struct c_declarator *inner, bool abstract_p)
{
- TREE_OPERAND (decl, 0) = type;
- if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+ decl->declarator = inner;
+ if (abstract_p && (decl->u.array.quals != TYPE_UNQUALIFIED
+ || decl->u.array.attrs != NULL_TREE
+ || decl->u.array.static_p))
error ("static or type qualifiers in abstract declarator");
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 type_name)
+groktypename (struct c_type_name *type_name)
{
- tree specs, attrs;
-
- if (TREE_CODE (type_name) != TREE_LIST)
- return type_name;
+ tree type;
+ tree attrs = type_name->specs->attrs;
- split_specs_attrs (TREE_PURPOSE (type_name), &specs, &attrs);
+ type_name->specs->attrs = NULL_TREE;
- type_name = grokdeclarator (TREE_VALUE (type_name), specs, TYPENAME, false,
- NULL);
+ type = grokdeclarator (type_name->declarator, type_name->specs, TYPENAME,
+ false, NULL);
/* Apply attributes. */
- decl_attributes (&type_name, attrs, 0);
+ decl_attributes (&type, attrs, 0);
- return type_name;
-}
-
-/* Return a PARM_DECL node for a given pair of specs and declarator. */
-
-tree
-groktypename_in_parm_context (tree type_name)
-{
- if (TREE_CODE (type_name) != TREE_LIST)
- return type_name;
- return grokdeclarator (TREE_VALUE (type_name),
- TREE_PURPOSE (type_name),
- PARM, false, NULL);
+ return type;
}
/* Decode a declarator in an ordinary declaration or data definition.
grokfield and not through here. */
tree
-start_decl (tree declarator, tree declspecs, bool initialized, tree attributes)
+start_decl (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ bool initialized, tree attributes)
{
tree decl;
tree tem;
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized, NULL);
+ if (!decl)
+ return 0;
deprecated_state = DEPRECATED_NORMAL;
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
- warning ("%J'%D' is usually a function", decl, decl);
+ warning (0, "%J%qD is usually a function", decl, decl);
if (initialized)
/* Is it valid for this decl to have an initializer at all?
switch (TREE_CODE (decl))
{
case TYPE_DECL:
- error ("typedef '%D' is initialized (use __typeof__ instead)", decl);
+ error ("typedef %qD is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
- error ("function '%D' is initialized like a variable", decl);
+ error ("function %qD is initialized like a variable", decl);
initialized = 0;
break;
case PARM_DECL:
/* DECL_INITIAL in a PARM_DECL is really DECL_ARG_TYPE. */
- error ("parameter '%D' is initialized", decl);
+ error ("parameter %qD is initialized", decl);
initialized = 0;
break;
}
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
{
- error ("variable '%D' has initializer but incomplete type", decl);
+ error ("variable %qD has initializer but incomplete type", decl);
initialized = 0;
}
- else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
+ else if (C_DECL_VARIABLE_SIZE (decl))
{
- error ("elements of array '%D' have incomplete type", decl);
+ /* Although C99 is unclear about whether incomplete arrays
+ of VLAs themselves count as VLAs, it does not make
+ sense to permit them to be initialized given that
+ ordinary VLAs may not be initialized. */
+ error ("variable-sized object may not be initialized");
initialized = 0;
}
}
if (TREE_CODE (decl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (decl)))
{
- tree ce = declarator;
+ struct c_declarator *ce = declarator;
- if (TREE_CODE (ce) == INDIRECT_REF)
- ce = TREE_OPERAND (declarator, 0);
- if (TREE_CODE (ce) == CALL_EXPR)
+ if (ce->kind == cdk_pointer)
+ ce = declarator->declarator;
+ if (ce->kind == cdk_function)
{
- tree args = TREE_PURPOSE (TREE_OPERAND (ce, 1));
+ tree args = ce->u.arg_info->parms;
for (; args; args = TREE_CHAIN (args))
{
tree type = TREE_TYPE (args);
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
- warning ("%Jinline function '%D' given attribute noinline", decl, decl);
+ warning (0, "%Jinline function %qD given attribute noinline", decl, decl);
/* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
- if (initialized)
- DECL_EXTERNAL (tem) = 0;
+ if (initialized && DECL_EXTERNAL (tem))
+ {
+ DECL_EXTERNAL (tem) = 0;
+ TREE_STATIC (tem) = 1;
+ }
return tem;
}
const char *asmspec = 0;
/* If a name was specified, get the string. */
- if (current_scope == file_scope)
+ if ((TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == VAR_DECL)
+ && DECL_FILE_SCOPE_P (decl))
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
&& TYPE_DOMAIN (type) == 0
&& TREE_CODE (decl) != TYPE_DECL)
{
- int do_default
+ bool do_default
= (TREE_STATIC (decl)
/* Even if pedantic, an external linkage array
may have incomplete type at first. */
? pedantic && !TREE_PUBLIC (decl)
: !DECL_EXTERNAL (decl));
int failure
- = complete_array_type (type, DECL_INITIAL (decl), do_default);
+ = complete_array_type (&TREE_TYPE (decl), DECL_INITIAL (decl),
+ do_default);
/* Get the completed type made by complete_array_type. */
type = TREE_TYPE (decl);
- if (failure == 1)
- error ("%Jinitializer fails to determine size of '%D'", decl, decl);
-
- else if (failure == 2)
+ switch (failure)
{
+ case 1:
+ error ("%Jinitializer fails to determine size of %qD", decl, decl);
+ break;
+
+ case 2:
if (do_default)
- error ("%Jarray size missing in '%D'", decl, decl);
+ error ("%Jarray size missing in %qD", decl, decl);
/* If a `static' var's size isn't known,
make it extern as well as static, so it does not get
allocated.
If it is not `static', then do not mark extern;
finish_incomplete_decl will give it a default size
and it will get allocated. */
- else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
+ else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
+ break;
+
+ case 3:
+ error ("%Jzero or negative size array %qD", decl, decl);
+ break;
+
+ case 0:
+ /* For global variables, update the copy of the type that
+ exists in the binding. */
+ if (TREE_PUBLIC (decl))
+ {
+ struct c_binding *b_ext = I_SYMBOL_BINDING (DECL_NAME (decl));
+ while (b_ext && !B_IN_EXTERNAL_SCOPE (b_ext))
+ b_ext = b_ext->shadowed;
+ if (b_ext)
+ {
+ if (b_ext->type)
+ b_ext->type = composite_type (b_ext->type, type);
+ else
+ b_ext->type = type;
+ }
+ }
+ break;
+
+ default:
+ gcc_unreachable ();
}
- /* TYPE_MAX_VALUE is always one less than the number of elements
- 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)
- error ("%Jzero or negative size array '%D'", decl, decl);
+ if (DECL_INITIAL (decl))
+ TREE_TYPE (DECL_INITIAL (decl)) = type;
layout_decl (decl, 0);
}
is an error. */
: !DECL_EXTERNAL (decl)))
{
- error ("%Jstorage size of '%D' isn't known", decl, decl);
+ error ("%Jstorage size of %qD isn%'t known", decl, decl);
TREE_TYPE (decl) = error_mark_node;
}
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
- error ("%Jstorage size of '%D' isn't constant", decl, decl);
+ error ("%Jstorage size of %qD isn%'t constant", decl, decl);
}
if (TREE_USED (type))
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
if (DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL)
- {
- tree builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- 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_builtin_user_assembler_name (decl, 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);
+ maybe_apply_pragma_weak (decl);
/* If this is a variable definition, determine its ELF visibility. */
if (TREE_CODE (decl) == VAR_DECL
ordinary, non-register local variable. Historically,
GCC has accepted -- but ignored -- the ASMSPEC in
this case. */
- if (! DECL_FILE_SCOPE_P (decl)
+ 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);
+ warning (0, "%Jignoring asm-specifier for non-static local "
+ "variable %qD", decl, decl);
else if (C_DECL_REGISTER (decl))
change_decl_assembler_name (decl, get_identifier (asmspec));
else
/* Recompute the RTL of a local array now
if it used to be an incomplete type. */
if (was_incomplete
- && ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
+ && !TREE_STATIC (decl) && !DECL_EXTERNAL (decl))
{
/* If we used it already as memory, it must stay in memory. */
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
/* Given a parsed parameter declaration, decode it into a PARM_DECL. */
tree
-grokparm (tree parm)
+grokparm (const struct c_parm *parm)
{
- tree decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, false, NULL);
+ tree decl = grokdeclarator (parm->declarator, parm->specs, PARM, false,
+ NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
+ decl_attributes (&decl, parm->attrs, 0);
return decl;
}
and push that on the current scope. */
void
-push_parm_decl (tree parm)
+push_parm_decl (const struct c_parm *parm)
{
tree decl;
- decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
- TREE_PURPOSE (TREE_PURPOSE (parm)),
- PARM, false, NULL);
- decl_attributes (&decl, TREE_VALUE (parm), 0);
+ decl = grokdeclarator (parm->declarator, parm->specs, PARM, false, NULL);
+ decl_attributes (&decl, parm->attrs, 0);
decl = pushdecl (decl);
/* 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_EXPR. */
- tree decl = build_decl (VAR_DECL, NULL_TREE, type);
+ tree decl;
tree complit;
tree stmt;
+
+ if (type == error_mark_node)
+ return error_mark_node;
+
+ decl = build_decl (VAR_DECL, NULL_TREE, type);
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = (current_scope == file_scope);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
- int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
- if (failure)
- abort ();
+ int failure = complete_array_type (&TREE_TYPE (decl),
+ DECL_INITIAL (decl), true);
+ gcc_assert (!failure);
+
+ type = TREE_TYPE (decl);
+ TREE_TYPE (DECL_INITIAL (decl)) = type;
}
- type = TREE_TYPE (decl);
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
stmt = build_stmt (DECL_EXPR, decl);
- complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
+ complit = build1 (COMPOUND_LITERAL_EXPR, type, stmt);
TREE_SIDE_EFFECTS (complit) = 1;
layout_decl (decl, 0);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
+ DECL_IGNORED_P (decl) = 1;
pushdecl (decl);
rest_of_decl_compilation (decl, 1, 0);
}
return complit;
}
\f
-/* Make TYPE a complete type based on INITIAL_VALUE.
- Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
- 2 if there was no information (in which case assume 1 if DO_DEFAULT). */
-
-int
-complete_array_type (tree type, tree initial_value, int do_default)
-{
- tree maxindex = NULL_TREE;
- int value = 0;
-
- if (initial_value)
- {
- /* Note MAXINDEX is really the maximum index,
- one less than the size. */
- if (TREE_CODE (initial_value) == STRING_CST)
- {
- int eltsize
- = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
- 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_cst (NULL_TREE, -1);
- for (; elts; elts = TREE_CHAIN (elts))
- {
- if (TREE_PURPOSE (elts))
- maxindex = TREE_PURPOSE (elts);
- else
- maxindex = fold (build2 (PLUS_EXPR, integer_type_node,
- maxindex, integer_one_node));
- }
- }
- else
- {
- /* Make an error message unless that happened already. */
- if (initial_value != error_mark_node)
- value = 1;
-
- /* Prevent further error messages. */
- maxindex = build_int_cst (NULL_TREE, 0);
- }
- }
-
- if (!maxindex)
- {
- if (do_default)
- maxindex = build_int_cst (NULL_TREE, 0);
- value = 2;
- }
-
- if (maxindex)
- {
- TYPE_DOMAIN (type) = build_index_type (maxindex);
- if (!TREE_TYPE (maxindex))
- abort ();
- }
-
- /* Lay out the type now that we can get the real answer. */
-
- layout_type (type);
-
- return value;
-}
-\f
/* Determine whether TYPE is a structure with a flexible array member,
or a union containing such a structure (possibly recursively). */
unsigned HOST_WIDE_INT w;
const char *name = orig_name ? orig_name: _("<anonymous>");
- /* Necessary? */
- STRIP_NOPS (*width);
-
/* Detect and ignore out of range field width and process valid
field widths. */
- if (TREE_CODE (*width) != INTEGER_CST)
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (*width))
+ || TREE_CODE (*width) != INTEGER_CST)
{
- error ("bit-field `%s' width not an integer constant", name);
+ error ("bit-field %qs width not an integer constant", name);
*width = integer_one_node;
}
else
constant_expression_warning (*width);
if (tree_int_cst_sgn (*width) < 0)
{
- error ("negative width in bit-field `%s'", name);
+ error ("negative width in bit-field %qs", name);
*width = integer_one_node;
}
else if (integer_zerop (*width) && orig_name)
{
- error ("zero width for bit-field `%s'", name);
+ error ("zero width for bit-field %qs", name);
*width = integer_one_node;
}
}
&& TREE_CODE (*type) != BOOLEAN_TYPE
&& TREE_CODE (*type) != ENUMERAL_TYPE)
{
- error ("bit-field `%s' has invalid type", name);
+ error ("bit-field %qs has invalid type", name);
*type = unsigned_type_node;
}
&& type_mv != integer_type_node
&& type_mv != unsigned_type_node
&& type_mv != boolean_type_node)
- pedwarn ("type of bit-field `%s' is a GCC extension", name);
+ pedwarn ("type of bit-field %qs is a GCC extension", name);
if (type_mv == boolean_type_node)
max_width = CHAR_TYPE_SIZE;
if (0 < compare_tree_int (*width, max_width))
{
- error ("width of `%s' exceeds its type", name);
+ error ("width of %qs exceeds its type", name);
w = max_width;
*width = build_int_cst (NULL_TREE, w);
}
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);
+ warning (0, "%qs is narrower than values of its type", name);
}
}
\f
(In one case we can return a ..._TYPE node instead.
For invalid input we sometimes return 0.)
- DECLSPECS is a chain of tree_list nodes whose value fields
- are the storage classes and type specifiers.
+ DECLSPECS is a c_declspecs structure for the declaration specifiers.
DECL_CONTEXT says which syntactic context this declaration is in:
NORMAL for most contexts. Make a VAR_DECL or FUNCTION_DECL or TYPE_DECL.
and `extern' are interpreted. */
static tree
-grokdeclarator (tree declarator, tree declspecs,
+grokdeclarator (const struct c_declarator *declarator,
+ struct c_declspecs *declspecs,
enum decl_context decl_context, bool initialized, tree *width)
{
- int specbits = 0;
- tree spec;
- tree type = NULL_TREE;
- int longlong = 0;
+ tree type = declspecs->type;
+ bool threadp = declspecs->thread_p;
+ enum c_storage_class storage_class = declspecs->storage_class;
int constp;
int restrictp;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
- int inlinep;
- int explicit_int = 0;
- int explicit_char = 0;
- int defaulted_int = 0;
- tree typedef_decl = 0;
const char *name, *orig_name;
tree typedef_type = 0;
int funcdef_flag = 0;
- enum tree_code innermost_code = ERROR_MARK;
+ bool funcdef_syntax = false;
int size_varies = 0;
- tree decl_attr = NULL_TREE;
- tree array_ptr_quals = NULL_TREE;
+ tree decl_attr = declspecs->decl_attr;
+ int array_ptr_quals = TYPE_UNQUALIFIED;
+ tree array_ptr_attrs = NULL_TREE;
int array_parm_static = 0;
tree returned_attrs = NULL_TREE;
bool bitfield = width != NULL;
tree element_type;
- tree arg_info = NULL_TREE;
+ struct c_arg_info *arg_info = 0;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
/* Look inside a declarator for the name being declared
and get it as a string, for an error message. */
{
- tree decl = declarator;
+ const struct c_declarator *decl = declarator;
name = 0;
while (decl)
- switch (TREE_CODE (decl))
+ switch (decl->kind)
{
- case ARRAY_REF:
- case INDIRECT_REF:
- case CALL_EXPR:
- innermost_code = TREE_CODE (decl);
- decl = TREE_OPERAND (decl, 0);
+ case cdk_function:
+ case cdk_array:
+ case cdk_pointer:
+ funcdef_syntax = (decl->kind == cdk_function);
+ decl = decl->declarator;
break;
- case TREE_LIST:
- decl = TREE_VALUE (decl);
+ case cdk_attrs:
+ decl = decl->declarator;
break;
- case IDENTIFIER_NODE:
- name = IDENTIFIER_POINTER (decl);
+ case cdk_id:
+ if (decl->u.id)
+ name = IDENTIFIER_POINTER (decl->u.id);
decl = 0;
break;
default:
- abort ();
+ gcc_unreachable ();
}
orig_name = name;
if (name == 0)
/* A function definition's declarator must have the form of
a function declarator. */
- if (funcdef_flag && innermost_code != CALL_EXPR)
+ if (funcdef_flag && !funcdef_syntax)
return 0;
/* If this looks like a function definition, make it one,
if (decl_context == NORMAL && !funcdef_flag && current_scope->parm_flag)
decl_context = PARM;
- /* Look through the decl specs and record which ones appear.
- Some typespecs are defined as built-in typenames.
- Others, the ones that are modifiers of other types,
- are represented by bits in SPECBITS: set the bits for
- the modifiers that appear. Storage class keywords are also in SPECBITS.
-
- If there is a typedef name or a type, store the type in TYPE.
- This includes builtin typedefs such as `int'.
+ if (declspecs->deprecated_p && deprecated_state != DEPRECATED_SUPPRESS)
+ warn_deprecated_use (declspecs->type);
- Set EXPLICIT_INT or EXPLICIT_CHAR if the type is `int' or `char'
- and did not come from a user typedef.
+ typedef_type = type;
+ size_varies = C_TYPE_VARIABLE_SIZE (type);
- Set LONGLONG if `long' is mentioned twice. */
+ /* Diagnose defaulting to "int". */
- for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
+ if (declspecs->default_int_p && !in_system_header)
{
- tree id = TREE_VALUE (spec);
-
- /* If the entire declaration is itself tagged as deprecated then
- suppress reports of deprecated items. */
- if (id && TREE_DEPRECATED (id))
- {
- if (deprecated_state != DEPRECATED_SUPPRESS)
- warn_deprecated_use (id);
- }
-
- if (id == ridpointers[(int) RID_INT])
- explicit_int = 1;
- if (id == ridpointers[(int) RID_CHAR])
- explicit_char = 1;
-
- if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
- {
- enum rid i = C_RID_CODE (id);
- if ((int) i <= (int) RID_LAST_MODIFIER)
- {
- if (i == RID_LONG && (specbits & (1 << (int) RID_LONG)))
- {
- if (longlong)
- error ("`long long long' is too long for GCC");
- else
- {
- if (pedantic && !flag_isoc99 && ! in_system_header
- && warn_long_long)
- pedwarn ("ISO C90 does not support `long long'");
- longlong = 1;
- }
- }
- else if (specbits & (1 << (int) i))
- {
- if (i == RID_CONST || i == RID_VOLATILE || i == RID_RESTRICT)
- {
- if (pedantic && !flag_isoc99)
- pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
- else
- error ("duplicate `%s'", IDENTIFIER_POINTER (id));
- }
+ /* Issue a warning if this is an ISO C 99 program or if
+ -Wreturn-type and this is a function, or if -Wimplicit;
+ prefer the former warning since it is more explicit. */
+ if ((warn_implicit_int || warn_return_type || flag_isoc99)
+ && funcdef_flag)
+ warn_about_return_type = 1;
+ else if (warn_implicit_int || flag_isoc99)
+ pedwarn_c99 ("type defaults to %<int%> in declaration of %qs", name);
+ }
- /* Diagnose "__thread extern". Recall that this list
- is in the reverse order seen in the text. */
- if (i == RID_THREAD
- && (specbits & (1 << (int) RID_EXTERN
- | 1 << (int) RID_STATIC)))
- {
- if (specbits & 1 << (int) RID_EXTERN)
- error ("`__thread' before `extern'");
- else
- error ("`__thread' before `static'");
- }
-
- specbits |= 1 << (int) i;
- goto found;
- }
- }
- if (type)
- error ("two or more data types in declaration of `%s'", name);
- /* Actual typedefs come to us as TYPE_DECL nodes. */
- else if (TREE_CODE (id) == TYPE_DECL)
- {
- if (TREE_TYPE (id) == error_mark_node)
- ; /* Allow the type to default to int to avoid cascading errors. */
- else
- {
- type = TREE_TYPE (id);
- decl_attr = DECL_ATTRIBUTES (id);
- typedef_decl = id;
- }
- }
- /* Built-in types come as identifiers. */
- else if (TREE_CODE (id) == IDENTIFIER_NODE)
- {
- tree t = lookup_name (id);
- if (!t || TREE_CODE (t) != TYPE_DECL)
- error ("`%s' fails to be a typedef or built in type",
- IDENTIFIER_POINTER (id));
- else if (TREE_TYPE (t) == error_mark_node)
- ;
- else
- {
- type = TREE_TYPE (t);
- typedef_decl = t;
- }
- }
- else if (TREE_CODE (id) != ERROR_MARK)
- type = id;
-
- found:
- ;
- }
-
- typedef_type = type;
- if (type)
- size_varies = C_TYPE_VARIABLE_SIZE (type);
-
- /* No type at all: default to `int', and set DEFAULTED_INT
- because it was not a user-defined typedef. */
-
- if (type == 0)
- {
- if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED)
- | (1 << (int) RID_COMPLEX))))
- /* Don't warn about typedef foo = bar. */
- && ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
- && ! in_system_header)
- {
- /* Issue a warning if this is an ISO C 99 program or if -Wreturn-type
- and this is a function, or if -Wimplicit; prefer the former
- warning since it is more explicit. */
- if ((warn_implicit_int || warn_return_type || flag_isoc99)
- && funcdef_flag)
- warn_about_return_type = 1;
- else if (warn_implicit_int || flag_isoc99)
- pedwarn_c99 ("type defaults to `int' in declaration of `%s'",
- name);
- }
-
- defaulted_int = 1;
- type = integer_type_node;
- }
-
- /* Now process the modifiers that were specified
- and check for invalid combinations. */
-
- /* Long double is a special combination. */
-
- if ((specbits & 1 << (int) RID_LONG) && ! longlong
- && TYPE_MAIN_VARIANT (type) == double_type_node)
- {
- specbits &= ~(1 << (int) RID_LONG);
- type = long_double_type_node;
- }
-
- /* Check all other uses of type modifiers. */
-
- if (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED)))
- {
- int ok = 0;
-
- if ((specbits & 1 << (int) RID_LONG)
- && (specbits & 1 << (int) RID_SHORT))
- error ("both long and short specified for `%s'", name);
- else if (((specbits & 1 << (int) RID_LONG)
- || (specbits & 1 << (int) RID_SHORT))
- && explicit_char)
- error ("long or short specified with char for `%s'", name);
- else if (((specbits & 1 << (int) RID_LONG)
- || (specbits & 1 << (int) RID_SHORT))
- && TREE_CODE (type) == REAL_TYPE)
- {
- static int already = 0;
-
- error ("long or short specified with floating type for `%s'", name);
- if (! already && ! pedantic)
- {
- error ("the only valid combination is `long double'");
- already = 1;
- }
- }
- else if ((specbits & 1 << (int) RID_SIGNED)
- && (specbits & 1 << (int) RID_UNSIGNED))
- error ("both signed and unsigned specified for `%s'", name);
- else if (TREE_CODE (type) != INTEGER_TYPE)
- error ("long, short, signed or unsigned invalid for `%s'", name);
- else
- {
- ok = 1;
- if (!explicit_int && !defaulted_int && !explicit_char)
- {
- error ("long, short, signed or unsigned used invalidly for `%s'",
- name);
- ok = 0;
- }
- }
-
- /* Discard the type modifiers if they are invalid. */
- if (! ok)
- {
- specbits &= ~((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_UNSIGNED) | (1 << (int) RID_SIGNED));
- longlong = 0;
- }
- }
-
- if ((specbits & (1 << (int) RID_COMPLEX))
- && TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
- {
- error ("complex invalid for `%s'", name);
- specbits &= ~(1 << (int) RID_COMPLEX);
- }
-
- /* Decide whether an integer type is signed or not.
- Optionally treat bit-fields as signed by default. */
- if (specbits & 1 << (int) RID_UNSIGNED
- || (bitfield && ! flag_signed_bitfields
- && (explicit_int || defaulted_int || explicit_char
- /* A typedef for plain `int' without `signed'
- can be controlled just like plain `int'. */
- || ! (typedef_decl != 0
- && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
- && TREE_CODE (type) != ENUMERAL_TYPE
- && !(specbits & 1 << (int) RID_SIGNED)))
- {
- if (longlong)
- type = long_long_unsigned_type_node;
- else if (specbits & 1 << (int) RID_LONG)
- type = long_unsigned_type_node;
- else if (specbits & 1 << (int) RID_SHORT)
- type = short_unsigned_type_node;
- else if (type == char_type_node)
- type = unsigned_char_type_node;
- else if (typedef_decl)
- type = c_common_unsigned_type (type);
- else
- type = unsigned_type_node;
- }
- else if ((specbits & 1 << (int) RID_SIGNED)
- && type == char_type_node)
- type = signed_char_type_node;
- else if (longlong)
- type = long_long_integer_type_node;
- else if (specbits & 1 << (int) RID_LONG)
- type = long_integer_type_node;
- else if (specbits & 1 << (int) RID_SHORT)
- type = short_integer_type_node;
-
- if (specbits & 1 << (int) RID_COMPLEX)
- {
- if (pedantic && !flag_isoc99)
- pedwarn ("ISO C90 does not support complex types");
- /* If we just have "complex", it is equivalent to
- "complex double", but if any modifiers at all are specified it is
- the complex form of TYPE. E.g, "complex short" is
- "complex short int". */
-
- if (defaulted_int && ! longlong
- && ! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
- | (1 << (int) RID_SIGNED)
- | (1 << (int) RID_UNSIGNED))))
- {
- if (pedantic)
- pedwarn ("ISO C does not support plain `complex' meaning `double complex'");
- type = complex_double_type_node;
- }
- else if (type == integer_type_node)
- {
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
- type = complex_integer_type_node;
- }
- else if (type == float_type_node)
- type = complex_float_type_node;
- else if (type == double_type_node)
- type = complex_double_type_node;
- else if (type == long_double_type_node)
- type = complex_long_double_type_node;
- else
- {
- if (pedantic)
- pedwarn ("ISO C does not support complex integer types");
- type = build_complex_type (type);
- }
- }
-
- /* Check the type and width of a bit-field. */
- if (bitfield)
- check_bitfield_type_and_width (&type, width, orig_name);
+ /* Adjust the type if a bit-field is being declared,
+ -funsigned-bitfields applied and the type is not explicitly
+ "signed". */
+ if (bitfield && !flag_signed_bitfields && !declspecs->explicit_signed_p
+ && TREE_CODE (type) == INTEGER_TYPE)
+ type = c_common_unsigned_type (type);
/* Figure out the type qualifiers for the declaration. There are
two ways a declaration can become qualified. One is something
duplicate qualifiers should be diagnosed in this case, but it
seems most appropriate to do so). */
element_type = strip_array_types (type);
- constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (element_type);
- restrictp
- = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (element_type);
- volatilep
- = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (element_type);
- inlinep = !! (specbits & (1 << (int) RID_INLINE));
+ constp = declspecs->const_p + TYPE_READONLY (element_type);
+ restrictp = declspecs->restrict_p + TYPE_RESTRICT (element_type);
+ volatilep = declspecs->volatile_p + TYPE_VOLATILE (element_type);
if (pedantic && !flag_isoc99)
{
if (constp > 1)
- pedwarn ("duplicate `const'");
+ pedwarn ("duplicate %<const%>");
if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
+ pedwarn ("duplicate %<restrict%>");
if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
+ 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)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
- /* Warn if two storage classes are given. Default to `auto'. */
-
- {
- int nclasses = 0;
-
- if (specbits & 1 << (int) RID_AUTO) nclasses++;
- if (specbits & 1 << (int) RID_STATIC) nclasses++;
- if (specbits & 1 << (int) RID_EXTERN) nclasses++;
- if (specbits & 1 << (int) RID_REGISTER) nclasses++;
- if (specbits & 1 << (int) RID_TYPEDEF) nclasses++;
-
- /* "static __thread" and "extern __thread" are allowed. */
- if ((specbits & (1 << (int) RID_THREAD
- | 1 << (int) RID_STATIC
- | 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
- nclasses++;
-
- /* Warn about storage classes that are invalid for certain
- kinds of declarations (parameters, typenames, etc.). */
-
- if (nclasses > 1)
- error ("multiple storage classes in declaration of `%s'", name);
- else if (funcdef_flag
- && (specbits
- & ((1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO)
- | (1 << (int) RID_TYPEDEF)
- | (1 << (int) RID_THREAD))))
- {
- if (specbits & 1 << (int) RID_AUTO
- && (pedantic || current_scope == file_scope))
- pedwarn ("function definition declared `auto'");
- if (specbits & 1 << (int) RID_REGISTER)
- error ("function definition declared `register'");
- if (specbits & 1 << (int) RID_TYPEDEF)
- error ("function definition declared `typedef'");
- if (specbits & 1 << (int) RID_THREAD)
- error ("function definition declared `__thread'");
- specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_THREAD));
- }
- else if (decl_context != NORMAL && nclasses > 0)
- {
- if (decl_context == PARM && specbits & 1 << (int) RID_REGISTER)
- ;
- else
- {
- switch (decl_context)
- {
- case FIELD:
- error ("storage class specified for structure field `%s'",
- name);
- break;
- case PARM:
- error ("storage class specified for parameter `%s'", name);
- break;
- default:
- error ("storage class specified for typename");
- break;
- }
- specbits &= ~((1 << (int) RID_TYPEDEF) | (1 << (int) RID_REGISTER)
- | (1 << (int) RID_AUTO) | (1 << (int) RID_STATIC)
- | (1 << (int) RID_EXTERN) | (1 << (int) RID_THREAD));
- }
- }
- else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
- {
- /* `extern' with initialization is invalid if not at file scope. */
- if (current_scope == file_scope)
- warning ("`%s' initialized and declared `extern'", name);
- else
- error ("`%s' has both `extern' and initializer", name);
- }
- else if (current_scope == file_scope)
- {
- if (specbits & 1 << (int) RID_AUTO)
- error ("file-scope declaration of `%s' specifies `auto'", name);
- }
- else
- {
- if (specbits & 1 << (int) RID_EXTERN && funcdef_flag)
- error ("nested function `%s' declared `extern'", name);
- else if ((specbits & (1 << (int) RID_THREAD
- | 1 << (int) RID_EXTERN
- | 1 << (int) RID_STATIC))
- == (1 << (int) RID_THREAD))
- {
- error ("function-scope `%s' implicitly auto and declared `__thread'",
- name);
- specbits &= ~(1 << (int) RID_THREAD);
- }
- }
- }
+ /* Warn about storage classes that are invalid for certain
+ kinds of declarations (parameters, typenames, etc.). */
+
+ if (funcdef_flag
+ && (threadp
+ || storage_class == csc_auto
+ || storage_class == csc_register
+ || storage_class == csc_typedef))
+ {
+ if (storage_class == csc_auto
+ && (pedantic || current_scope == file_scope))
+ pedwarn ("function definition declared %<auto%>");
+ if (storage_class == csc_register)
+ error ("function definition declared %<register%>");
+ if (storage_class == csc_typedef)
+ error ("function definition declared %<typedef%>");
+ if (threadp)
+ error ("function definition declared %<__thread%>");
+ threadp = false;
+ if (storage_class == csc_auto
+ || storage_class == csc_register
+ || storage_class == csc_typedef)
+ storage_class = csc_none;
+ }
+ else if (decl_context != NORMAL && (storage_class != csc_none || threadp))
+ {
+ if (decl_context == PARM && storage_class == csc_register)
+ ;
+ else
+ {
+ switch (decl_context)
+ {
+ case FIELD:
+ error ("storage class specified for structure field %qs",
+ name);
+ break;
+ case PARM:
+ error ("storage class specified for parameter %qs", name);
+ break;
+ default:
+ error ("storage class specified for typename");
+ break;
+ }
+ storage_class = csc_none;
+ threadp = false;
+ }
+ }
+ else if (storage_class == csc_extern
+ && initialized
+ && !funcdef_flag)
+ {
+ /* 'extern' with initialization is invalid if not at file scope. */
+ if (current_scope == file_scope)
+ warning (0, "%qs initialized and declared %<extern%>", name);
+ else
+ error ("%qs has both %<extern%> and initializer", name);
+ }
+ else if (current_scope == file_scope)
+ {
+ if (storage_class == csc_auto)
+ error ("file-scope declaration of %qs specifies %<auto%>", name);
+ if (pedantic && storage_class == csc_register)
+ pedwarn ("file-scope declaration of %qs specifies %<register%>", name);
+ }
+ else
+ {
+ if (storage_class == csc_extern && funcdef_flag)
+ error ("nested function %qs declared %<extern%>", name);
+ else if (threadp && storage_class == csc_none)
+ {
+ error ("function-scope %qs implicitly auto and declared "
+ "%<__thread%>",
+ name);
+ threadp = false;
+ }
+ }
/* 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 && TREE_CODE (declarator) != IDENTIFIER_NODE)
+ while (declarator && declarator->kind != cdk_id)
{
if (type == error_mark_node)
{
- declarator = TREE_OPERAND (declarator, 0);
+ declarator = declarator->declarator;
continue;
}
- /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
- an INDIRECT_REF (for *...),
- a CALL_EXPR (for ...(...)),
- a TREE_LIST (for nested attributes),
- an identifier (for the name being declared)
- or a null pointer (for the place in an absolute declarator
+ /* Each level of DECLARATOR is either a cdk_array (for ...[..]),
+ a cdk_pointer (for *...),
+ a cdk_function (for ...(...)),
+ a cdk_attrs (for nested attributes),
+ or a cdk_id (for the name being declared
+ or the place in an absolute declarator
where the name was omitted).
- For the last two cases, we have just exited the loop.
+ For the last case, we have just exited the loop.
At this point, TYPE is the type of elements of an array,
or for a function to return, or for a pointer to point to.
array or function or pointer, and DECLARATOR has had its
outermost layer removed. */
- if (array_ptr_quals != NULL_TREE || array_parm_static)
+ if (array_ptr_quals != TYPE_UNQUALIFIED
+ || array_ptr_attrs != NULL_TREE
+ || array_parm_static)
{
/* Only the innermost declarator (making a parameter be of
array type which is converted to pointer type)
may have static or type qualifiers. */
error ("static or type qualifiers in non-parameter array declarator");
- array_ptr_quals = NULL_TREE;
+ array_ptr_quals = TYPE_UNQUALIFIED;
+ array_ptr_attrs = NULL_TREE;
array_parm_static = 0;
}
- if (TREE_CODE (declarator) == TREE_LIST)
+ switch (declarator->kind)
{
- /* We encode a declarator with embedded attributes using
- a TREE_LIST. */
- tree attrs = TREE_PURPOSE (declarator);
- tree inner_decl;
- int attr_flags = 0;
- declarator = TREE_VALUE (declarator);
- inner_decl = declarator;
- while (inner_decl != NULL_TREE
- && TREE_CODE (inner_decl) == TREE_LIST)
- inner_decl = TREE_VALUE (inner_decl);
- if (inner_decl == NULL_TREE
- || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
- attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
- else if (TREE_CODE (inner_decl) == CALL_EXPR)
- attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
- else if (TREE_CODE (inner_decl) == ARRAY_REF)
- attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
- returned_attrs = decl_attributes (&type,
- chainon (returned_attrs, attrs),
- attr_flags);
- }
- else if (TREE_CODE (declarator) == ARRAY_REF)
- {
- tree itype = NULL_TREE;
- tree size = TREE_OPERAND (declarator, 1);
- /* The index is a signed object `sizetype' bits wide. */
- tree index_type = c_common_signed_type (sizetype);
-
- array_ptr_quals = TREE_TYPE (declarator);
- array_parm_static = TREE_STATIC (declarator);
-
- declarator = TREE_OPERAND (declarator, 0);
-
- /* Check for some types that there cannot be arrays of. */
-
- if (VOID_TYPE_P (type))
- {
- error ("declaration of `%s' as array of voids", name);
- type = error_mark_node;
- }
-
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("declaration of `%s' as array of functions", name);
+ case cdk_attrs:
+ {
+ /* A declarator with embedded attributes. */
+ tree attrs = declarator->u.attrs;
+ const struct c_declarator *inner_decl;
+ int attr_flags = 0;
+ declarator = declarator->declarator;
+ inner_decl = declarator;
+ while (inner_decl->kind == cdk_attrs)
+ inner_decl = inner_decl->declarator;
+ if (inner_decl->kind == cdk_id)
+ attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+ else if (inner_decl->kind == cdk_function)
+ attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+ else if (inner_decl->kind == cdk_array)
+ attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+ returned_attrs = decl_attributes (&type,
+ chainon (returned_attrs, attrs),
+ attr_flags);
+ break;
+ }
+ case cdk_array:
+ {
+ tree itype = NULL_TREE;
+ tree size = declarator->u.array.dimen;
+ /* The index is a signed object `sizetype' bits wide. */
+ tree index_type = c_common_signed_type (sizetype);
+
+ array_ptr_quals = declarator->u.array.quals;
+ array_ptr_attrs = declarator->u.array.attrs;
+ array_parm_static = declarator->u.array.static_p;
+
+ declarator = declarator->declarator;
+
+ /* Check for some types that there cannot be arrays of. */
+
+ if (VOID_TYPE_P (type))
+ {
+ error ("declaration of %qs as array of voids", name);
+ type = error_mark_node;
+ }
+
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("declaration of %qs as array of functions", name);
+ type = error_mark_node;
+ }
+
+ if (pedantic && !in_system_header && flexible_array_type_p (type))
+ pedwarn ("invalid use of structure with flexible array member");
+
+ if (size == error_mark_node)
type = error_mark_node;
- }
-
- if (pedantic && !in_system_header && flexible_array_type_p (type))
- pedwarn ("invalid use of structure with flexible array member");
-
- if (size == error_mark_node)
- type = error_mark_node;
-
- if (type == error_mark_node)
- continue;
-
- /* If size was specified, set ITYPE to a range-type for that size.
- Otherwise, ITYPE remains null. finish_decl may figure it out
- from an initial value. */
-
- if (size)
- {
- /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
- STRIP_TYPE_NOPS (size);
-
- if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
- {
- error ("size of array `%s' has non-integer type", name);
- size = integer_one_node;
- }
-
- if (pedantic && integer_zerop (size))
- pedwarn ("ISO C forbids zero-size array `%s'", name);
-
- if (TREE_CODE (size) == INTEGER_CST)
- {
- constant_expression_warning (size);
- if (tree_int_cst_sgn (size) < 0)
- {
- error ("size of array `%s' is negative", name);
- size = integer_one_node;
- }
- }
- else
- {
- /* Make sure the array size remains visibly nonconstant
- even if it is (eg) a const variable with known value. */
- size_varies = 1;
-
- if (!flag_isoc99 && pedantic)
- {
- if (TREE_CONSTANT (size))
- pedwarn ("ISO C90 forbids array `%s' whose size can't be evaluated",
- name);
- else
- pedwarn ("ISO C90 forbids variable-size array `%s'",
- name);
- }
- }
-
- if (integer_zerop (size))
- {
- /* A zero-length array cannot be represented with an
- unsigned index type, which is what we'll get with
- build_index_type. Create an open-ended range instead. */
- itype = build_range_type (sizetype, size, NULL_TREE);
- }
- else
- {
- /* Compute the maximum valid index, that is, size - 1.
- Do the calculation in index_type, so that if it is
- a variable the computations will be done in the
- proper mode. */
- 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
- cause an overflow (because we subtract 1), the overflow
- is recorded during the conversion to index_type, before
- the subtraction. Handling this case seems like an
- unnecessary complication. */
- if (TREE_OVERFLOW (itype))
- {
- error ("size of array `%s' is too large", name);
- type = error_mark_node;
- continue;
- }
-
- if (size_varies)
- itype = variable_size (itype);
- itype = build_index_type (itype);
- }
- }
- else if (decl_context == FIELD)
- {
- if (pedantic && !flag_isoc99 && !in_system_header)
- pedwarn ("ISO C90 does not support flexible array members");
+
+ if (type == error_mark_node)
+ continue;
- /* ISO C99 Flexible array members are effectively identical
- to GCC's zero-length array extension. */
- itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
- }
+ /* If size was specified, set ITYPE to a range-type for
+ that size. Otherwise, ITYPE remains null. finish_decl
+ may figure it out from an initial value. */
- /* If pedantic, complain about arrays of incomplete types. */
+ if (size)
+ {
+ /* Strip NON_LVALUE_EXPRs since we aren't using as an
+ lvalue. */
+ STRIP_TYPE_NOPS (size);
+
+ if (!INTEGRAL_TYPE_P (TREE_TYPE (size)))
+ {
+ error ("size of array %qs has non-integer type", name);
+ size = integer_one_node;
+ }
+
+ if (pedantic && integer_zerop (size))
+ pedwarn ("ISO C forbids zero-size array %qs", name);
+
+ if (TREE_CODE (size) == INTEGER_CST)
+ {
+ constant_expression_warning (size);
+ if (tree_int_cst_sgn (size) < 0)
+ {
+ error ("size of array %qs is negative", name);
+ size = integer_one_node;
+ }
+ }
+ else
+ {
+ /* Make sure the array size remains visibly
+ nonconstant even if it is (eg) a const variable
+ with known value. */
+ size_varies = 1;
+
+ if (!flag_isoc99 && pedantic)
+ {
+ if (TREE_CONSTANT (size))
+ pedwarn ("ISO C90 forbids array %qs whose size "
+ "can%'t be evaluated",
+ name);
+ else
+ pedwarn ("ISO C90 forbids variable-size array %qs",
+ name);
+ }
+ }
- if (pedantic && !COMPLETE_TYPE_P (type))
- pedwarn ("array type has incomplete element type");
+ if (integer_zerop (size))
+ {
+ /* A zero-length array cannot be represented with
+ an unsigned index type, which is what we'll
+ get with build_index_type. Create an
+ open-ended range instead. */
+ itype = build_range_type (sizetype, size, NULL_TREE);
+ }
+ else
+ {
+ /* Arrange for the SAVE_EXPR on the inside of the
+ MINUS_EXPR, which allows the -1 to get folded
+ with the +1 that happens when building TYPE_SIZE. */
+ if (size_varies)
+ size = variable_size (size);
+
+ /* Compute the maximum valid index, that is, size
+ - 1. Do the calculation in index_type, so that
+ if it is a variable the computations will be
+ done in the proper mode. */
+ 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
+ cause an overflow (because we subtract 1), the
+ overflow is recorded during the conversion to
+ index_type, before the subtraction. Handling
+ this case seems like an unnecessary
+ complication. */
+ if (TREE_OVERFLOW (itype))
+ {
+ error ("size of array %qs is too large", name);
+ type = error_mark_node;
+ continue;
+ }
+
+ itype = build_index_type (itype);
+ }
+ }
+ else if (decl_context == FIELD)
+ {
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C90 does not support flexible array members");
- /* 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. */
+ /* ISO C99 Flexible array members are effectively
+ identical to GCC's zero-length array extension. */
+ itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
+ }
- 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;
+ if (size_varies)
+ C_TYPE_VARIABLE_SIZE (type) = 1;
- /* The GCC extension for zero-length arrays differs from
- ISO flexible array members in that sizeof yields zero. */
- if (size && integer_zerop (size))
- {
- layout_type (type);
- TYPE_SIZE (type) = bitsize_zero_node;
- TYPE_SIZE_UNIT (type) = size_zero_node;
- }
- else if (declarator && TREE_CODE (declarator) == INDIRECT_REF)
- /* We can never complete an array type which is the target of a
- pointer, so go ahead and lay it out. */
- layout_type (type);
+ /* The GCC extension for zero-length arrays differs from
+ ISO flexible array members in that sizeof yields
+ zero. */
+ if (size && integer_zerop (size))
+ {
+ TYPE_SIZE (type) = bitsize_zero_node;
+ TYPE_SIZE_UNIT (type) = size_zero_node;
+ }
- if (decl_context != PARM
- && (array_ptr_quals != NULL_TREE || array_parm_static))
- {
- error ("static or type qualifiers in non-parameter array declarator");
- array_ptr_quals = NULL_TREE;
- array_parm_static = 0;
- }
- }
- else if (TREE_CODE (declarator) == CALL_EXPR)
- {
- /* 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);
- }
+ if (decl_context != PARM
+ && (array_ptr_quals != TYPE_UNQUALIFIED
+ || array_ptr_attrs != NULL_TREE
+ || array_parm_static))
+ {
+ error ("static or type qualifiers in non-parameter array declarator");
+ array_ptr_quals = TYPE_UNQUALIFIED;
+ array_ptr_attrs = NULL_TREE;
+ array_parm_static = 0;
+ }
+ break;
+ }
+ case cdk_function:
+ {
+ /* 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)
+ {
+ const struct c_declarator *t = declarator->declarator;
+ while (t->kind == cdk_attrs)
+ t = t->declarator;
+ really_funcdef = (t->kind == cdk_id);
+ }
- /* Declaring a function type.
- Make sure we have a valid type for the function to return. */
- if (type == error_mark_node)
- continue;
+ /* Declaring a function type. Make sure we have a valid
+ type for the function to return. */
+ if (type == error_mark_node)
+ continue;
+
+ size_varies = 0;
- size_varies = 0;
+ /* Warn about some types functions can't return. */
+ if (TREE_CODE (type) == FUNCTION_TYPE)
+ {
+ error ("%qs declared as function returning a function", name);
+ type = integer_type_node;
+ }
+ if (TREE_CODE (type) == ARRAY_TYPE)
+ {
+ error ("%qs declared as function returning an array", name);
+ type = integer_type_node;
+ }
- /* Warn about some types functions can't return. */
+ /* Construct the function type and go to the next
+ inner layer of declarator. */
+ arg_info = declarator->u.arg_info;
+ arg_types = grokparms (arg_info, really_funcdef);
- if (TREE_CODE (type) == FUNCTION_TYPE)
- {
- error ("`%s' declared as function returning a function", name);
- type = integer_type_node;
- }
- if (TREE_CODE (type) == ARRAY_TYPE)
+ /* Type qualifiers before the return type of the function
+ 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 -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 (0, "type qualifiers ignored on function return type");
+
+ type = c_build_qualified_type (type, type_quals);
+ }
+ type_quals = TYPE_UNQUALIFIED;
+
+ type = build_function_type (type, arg_types);
+ declarator = declarator->declarator;
+
+ /* Set the TYPE_CONTEXTs for each tagged type which is local to
+ the formal parameter list of this FUNCTION_TYPE to point to
+ the FUNCTION_TYPE node itself. */
{
- error ("`%s' declared as function returning an array", name);
- type = integer_type_node;
+ tree link;
+
+ for (link = arg_info->tags;
+ link;
+ link = TREE_CHAIN (link))
+ TYPE_CONTEXT (TREE_VALUE (link)) = type;
}
+ break;
+ }
+ case cdk_pointer:
+ {
+ /* Merge any constancy or volatility into the target type
+ for the pointer. */
- /* Construct the function type and go to the next
- inner layer of declarator. */
- arg_info = TREE_OPERAND (declarator, 1);
- arg_types = grokparms (arg_info, really_funcdef);
-
- /* Type qualifiers before the return type of the function
- 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 -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");
-
+ if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
+ && type_quals)
+ pedwarn ("ISO C forbids qualified function types");
+ if (type_quals)
type = c_build_qualified_type (type, type_quals);
- }
- type_quals = TYPE_UNQUALIFIED;
-
- type = build_function_type (type, arg_types);
- declarator = TREE_OPERAND (declarator, 0);
-
- /* Set the TYPE_CONTEXTs for each tagged type which is local to
- the formal parameter list of this FUNCTION_TYPE to point to
- the FUNCTION_TYPE node itself. */
+ size_varies = 0;
- {
- tree link;
+ type = build_pointer_type (type);
+
+ /* Process type qualifiers (such as const or volatile)
+ that were given inside the `*'. */
+ type_quals = declarator->u.pointer_quals;
- for (link = ARG_INFO_TAGS (arg_info);
- link;
- link = TREE_CHAIN (link))
- TYPE_CONTEXT (TREE_VALUE (link)) = type;
+ declarator = declarator->declarator;
+ break;
}
+ default:
+ gcc_unreachable ();
}
- else if (TREE_CODE (declarator) == INDIRECT_REF)
- {
- /* Merge any constancy or volatility into the target type
- for the pointer. */
-
- if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
- && type_quals)
- pedwarn ("ISO C forbids qualified function types");
- if (type_quals)
- type = c_build_qualified_type (type, type_quals);
- type_quals = TYPE_UNQUALIFIED;
- size_varies = 0;
-
- type = build_pointer_type (type);
-
- /* Process a list of type modifier keywords
- (such as const or volatile) that were given inside the `*'. */
-
- if (TREE_TYPE (declarator))
- {
- tree typemodlist;
- int erred = 0;
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
- for (typemodlist = TREE_TYPE (declarator); typemodlist;
- typemodlist = TREE_CHAIN (typemodlist))
- {
- tree qualifier = TREE_VALUE (typemodlist);
-
- if (C_IS_RESERVED_WORD (qualifier))
- {
- if (C_RID_CODE (qualifier) == RID_CONST)
- constp++;
- else if (C_RID_CODE (qualifier) == RID_VOLATILE)
- volatilep++;
- else if (C_RID_CODE (qualifier) == RID_RESTRICT)
- restrictp++;
- else
- erred++;
- }
- else
- erred++;
- }
-
- if (erred)
- error ("invalid type modifier within pointer declarator");
- if (pedantic && !flag_isoc99)
- {
- if (constp > 1)
- pedwarn ("duplicate `const'");
- if (volatilep > 1)
- pedwarn ("duplicate `volatile'");
- if (restrictp > 1)
- pedwarn ("duplicate `restrict'");
- }
-
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- }
-
- declarator = TREE_OPERAND (declarator, 0);
- }
- else
- abort ();
-
}
- /* 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)
+ check_bitfield_type_and_width (&type, width, orig_name);
/* Did array size calculations overflow? */
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
- error ("size of array `%s' is too large", name);
+ error ("size of array %qs is too large", name);
/* If we proceed with the array type as it is, we'll eventually
crash in tree_low_cst(). */
type = error_mark_node;
/* If this is declaring a typedef name, return a TYPE_DECL. */
- if (specbits & (1 << (int) RID_TYPEDEF))
+ if (storage_class == csc_typedef)
{
tree decl;
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters */
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
- decl = build_decl (TYPE_DECL, declarator, type);
- if ((specbits & (1 << (int) RID_SIGNED))
- || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
+ decl = build_decl (TYPE_DECL, declarator->u.id, type);
+ if (declspecs->explicit_signed_p)
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
decl_attributes (&decl, returned_attrs, 0);
+ if (declspecs->inline_p)
+ pedwarn ("%Jtypedef %qD declared %<inline%>", decl, decl);
return decl;
}
if (decl_context == TYPENAME)
{
- /* Note that the grammar rejects storage classes
- in typenames, fields or parameters */
+ /* Note that the grammar rejects storage classes in typenames
+ and fields. */
+ gcc_assert (storage_class == csc_none && !threadp
+ && !declspecs->inline_p);
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids const or volatile function types");
a better error message can be made later. */
if (VOID_TYPE_P (type) && decl_context != PARM
- && ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
- && ((specbits & (1 << (int) RID_EXTERN))
+ && !((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
+ && (storage_class == csc_extern
|| (current_scope == file_scope
- && !(specbits
- & ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
+ && !(storage_class == csc_static
+ || storage_class == csc_register)))))
{
- error ("variable or field `%s' declared void", name);
+ error ("variable or field %qs declared void", name);
type = integer_type_node;
}
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
- type_quals = TYPE_UNQUALIFIED;
- if (array_ptr_quals)
- {
- tree new_ptr_quals, new_ptr_attrs;
- int erred = 0;
- split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
- /* We don't yet implement attributes in this context. */
- if (new_ptr_attrs != NULL_TREE)
- warning ("attributes in parameter array declarator ignored");
-
- constp = 0;
- volatilep = 0;
- restrictp = 0;
- for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
- {
- tree qualifier = TREE_VALUE (new_ptr_quals);
+ type_quals = array_ptr_quals;
- if (C_IS_RESERVED_WORD (qualifier))
- {
- if (C_RID_CODE (qualifier) == RID_CONST)
- constp++;
- else if (C_RID_CODE (qualifier) == RID_VOLATILE)
- volatilep++;
- else if (C_RID_CODE (qualifier) == RID_RESTRICT)
- restrictp++;
- else
- erred++;
- }
- else
- erred++;
- }
-
- if (erred)
- error ("invalid type modifier within array declarator");
+ /* We don't yet implement attributes in this context. */
+ if (array_ptr_attrs != NULL_TREE)
+ warning (0, "attributes in parameter array declarator ignored");
- type_quals = ((constp ? TYPE_QUAL_CONST : 0)
- | (restrictp ? TYPE_QUAL_RESTRICT : 0)
- | (volatilep ? TYPE_QUAL_VOLATILE : 0));
- }
size_varies = 0;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type_as_written = type;
- decl = build_decl (PARM_DECL, declarator, type);
+ decl = build_decl (PARM_DECL, declarator->u.id, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
+ if (declspecs->inline_p)
+ pedwarn ("%Jparameter %qD declared %<inline%>", decl, decl);
}
else if (decl_context == FIELD)
{
+ /* Note that the grammar rejects storage classes in typenames
+ and fields. */
+ gcc_assert (storage_class == csc_none && !threadp
+ && !declspecs->inline_p);
+
/* Structure field. It may not be a function. */
if (TREE_CODE (type) == FUNCTION_TYPE)
{
- error ("field `%s' declared as a function", name);
+ error ("field %qs declared as a function", name);
type = build_pointer_type (type);
}
else if (TREE_CODE (type) != ERROR_MARK
&& !COMPLETE_OR_UNBOUND_ARRAY_TYPE_P (type))
{
- error ("field `%s' has incomplete type", name);
+ 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));
- decl = build_decl (FIELD_DECL, declarator, type);
+ type = c_build_qualified_type (type, type_quals);
+ decl = build_decl (FIELD_DECL, declarator->u.id, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (size_varies)
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
- if (specbits & (1 << (int) RID_REGISTER)
- || specbits & (1 << (int) RID_THREAD))
- error ("invalid storage class for function `%s'", name);
+ if (storage_class == csc_register || threadp)
+ {
+ error ("invalid storage class for function %qs", name);
+ }
else if (current_scope != file_scope)
{
/* Function declaration not at file scope. Storage
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 (storage_class == csc_auto)
{
if (pedantic)
- pedwarn ("invalid storage class for function `%s'", name);
+ pedwarn ("invalid storage class for function %qs", name);
+ }
+ else if (storage_class == csc_static)
+ {
+ error ("invalid storage class for function %qs", name);
+ if (funcdef_flag)
+ storage_class = declspecs->storage_class = csc_none;
+ else
+ return 0;
}
- if (specbits & (1 << (int) RID_STATIC))
- error ("invalid storage class for function `%s'", name);
}
- decl = build_decl (FUNCTION_DECL, declarator, type);
+ decl = build_decl (FUNCTION_DECL, declarator->u.id, type);
decl = build_decl_attribute_variant (decl, decl_attr);
DECL_LANG_SPECIFIC (decl) = GGC_CNEW (struct lang_decl);
- if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
+ if (pedantic && type_quals && !DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
/* 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");
+ warning (0, "%<noreturn%> function returns non-void value");
/* 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)
+ if (storage_class == csc_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)));
+ = !(storage_class == csc_static || storage_class == csc_auto);
/* For a function definition, record the argument information
block where store_parm_decls will look for it. */
if (funcdef_flag)
current_function_arg_info = arg_info;
- if (defaulted_int)
+ if (declspecs->default_int_p)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
/* Record presence of `inline', if it is reasonable. */
- if (MAIN_NAME_P (declarator))
+ if (flag_hosted && MAIN_NAME_P (declarator->u.id))
{
- if (inlinep)
- warning ("cannot inline function `main'");
+ if (declspecs->inline_p)
+ pedwarn ("cannot inline function %<main%>");
}
- else if (inlinep)
+ else if (declspecs->inline_p)
{
/* Record that the function is declared `inline'. */
DECL_DECLARED_INLINE_P (decl) = 1;
if (initialized)
{
DECL_INLINE (decl) = 1;
- if (specbits & (1 << (int) RID_EXTERN))
+ if (storage_class == csc_extern)
current_extern_inline = 1;
}
}
{
/* It's a variable. */
/* An uninitialized decl with `extern' is a reference. */
- int extern_ref = !initialized && (specbits & (1 << (int) RID_EXTERN));
+ 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
the 'extern' declaration is taken to refer to that decl.) */
if (extern_ref && current_scope != file_scope)
{
- tree global_decl = identifier_global_value (declarator);
- tree visible_decl = lookup_name (declarator);
+ tree global_decl = identifier_global_value (declarator->u.id);
+ tree visible_decl = lookup_name (declarator->u.id);
if (global_decl
&& global_decl != visible_decl
&& TREE_CODE (global_decl) == VAR_DECL
&& !TREE_PUBLIC (global_decl))
- error ("variable previously declared 'static' redeclared "
- "'extern'");
+ error ("variable previously declared %<static%> redeclared "
+ "%<extern%>");
}
- decl = build_decl (VAR_DECL, declarator, type);
+ decl = build_decl (VAR_DECL, declarator->u.id, type);
+ DECL_SOURCE_LOCATION (decl) = declarator->id_loc;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
- if (inlinep)
- pedwarn ("%Jvariable '%D' declared `inline'", decl, decl);
+ if (declspecs->inline_p)
+ pedwarn ("%Jvariable %qD declared %<inline%>", decl, decl);
/* 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));
+ DECL_EXTERNAL (decl) = (storage_class == csc_extern);
/* At file scope, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
the absence of both `static' and `register' makes it public. */
if (current_scope == file_scope)
{
- TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
- | (1 << (int) RID_REGISTER)));
+ TREE_PUBLIC (decl) = !(storage_class == csc_static
+ || storage_class == csc_register);
TREE_STATIC (decl) = !extern_ref;
}
/* Not at file scope, only `static' makes a static definition. */
else
{
- TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
+ TREE_STATIC (decl) = (storage_class == csc_static);
TREE_PUBLIC (decl) = extern_ref;
}
- if (specbits & 1 << (int) RID_THREAD)
+ if (threadp)
{
if (targetm.have_tls)
DECL_THREAD_LOCAL (decl) = 1;
/* Record `register' declaration for warnings on &
and in case doing stupid register allocation. */
- if (specbits & (1 << (int) RID_REGISTER))
+ if (storage_class == csc_register)
{
C_DECL_REGISTER (decl) = 1;
DECL_REGISTER (decl) = 1;
C_DECL_REGISTER (decl) = was_reg;
}
-#ifdef ENABLE_CHECKING
/* This is the earliest point at which we might know the assembler
name of a variable. Thus, if it's known before this, die horribly. */
- if (DECL_ASSEMBLER_NAME_SET_P (decl))
- abort ();
-#endif
+ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl));
decl_attributes (&decl, returned_attrs, 0);
when FUNCDEF_FLAG is false. */
static tree
-grokparms (tree arg_info, bool funcdef_flag)
+grokparms (struct c_arg_info *arg_info, bool funcdef_flag)
{
- tree arg_types = ARG_INFO_TYPES (arg_info);
+ tree arg_types = arg_info->types;
if (warn_strict_prototypes && arg_types == 0 && !funcdef_flag
&& !in_system_header)
- warning ("function declaration isn't a prototype");
+ warning (0, "function declaration isn%'t a prototype");
if (arg_types == error_mark_node)
return 0; /* don't set TYPE_ARG_TYPES in this case */
else if (arg_types && TREE_CODE (TREE_VALUE (arg_types)) == IDENTIFIER_NODE)
{
- if (! funcdef_flag)
+ if (!funcdef_flag)
pedwarn ("parameter names (without types) in function declaration");
- ARG_INFO_PARMS (arg_info) = ARG_INFO_TYPES (arg_info);
- ARG_INFO_TYPES (arg_info) = 0;
+ arg_info->parms = arg_info->types;
+ arg_info->types = 0;
return 0;
}
else
tree parm, type, typelt;
unsigned int parmno;
- /* If the arg types are incomplete in a declaration, they must
- include undefined tags. These tags can never be defined in
- the scope of the declaration, so the types can never be
- completed, and no call can be compiled successfully. */
+ /* If there is a parameter of incomplete type in a definition,
+ this is an error. In a declaration this is valid, and a
+ struct or union type may be completed later, before any calls
+ or definition of the function. In the case where the tag was
+ first declared within the parameter list, a warning has
+ already been given. If a parameter has void type, then
+ however the function cannot be defined or called, so
+ warn. */
- for (parm = ARG_INFO_PARMS (arg_info), typelt = arg_types, parmno = 1;
+ for (parm = arg_info->parms, typelt = arg_types, parmno = 1;
parm;
parm = TREE_CHAIN (parm), typelt = TREE_CHAIN (typelt), parmno++)
{
if (funcdef_flag)
{
if (DECL_NAME (parm))
- error ("%Jparameter %u ('%D') has incomplete type",
+ error ("%Jparameter %u (%qD) has incomplete type",
parm, parmno, parm);
else
error ("%Jparameter %u has incomplete type",
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
}
- else
+ else if (VOID_TYPE_P (type))
{
if (DECL_NAME (parm))
- warning ("%Jparameter %u ('%D') has incomplete type",
+ warning (0, "%Jparameter %u (%qD) has void type",
parm, parmno, parm);
else
- warning ("%Jparameter %u has incomplete type",
+ warning (0, "%Jparameter %u has void type",
parm, parmno);
}
}
}
}
-/* Take apart the current scope and return a tree_list node with info
- on a parameter list just parsed. This tree_list node should be
- examined using the ARG_INFO_* macros, defined above:
-
- ARG_INFO_PARMS: a list of parameter decls.
- ARG_INFO_TAGS: a list of structure, union and enum tags defined.
- ARG_INFO_TYPES: a list of argument types to go in the FUNCTION_TYPE.
- ARG_INFO_OTHERS: a list of non-parameter decls (notably enumeration
- constants) defined with the parameters.
+/* Take apart the current scope and return a c_arg_info structure with
+ info on a parameter list just parsed.
- This tree_list node is later fed to 'grokparms' and 'store_parm_decls'.
+ This structure is later fed to 'grokparms' and 'store_parm_decls'.
ELLIPSIS being true means the argument list ended in '...' so don't
append a sentinel (void_list_node) to the end of the type-list. */
-tree
+struct c_arg_info *
get_parm_info (bool ellipsis)
{
struct c_binding *b = current_scope->bindings;
- tree arg_info = make_node (TREE_LIST);
+ struct c_arg_info *arg_info = XOBNEW (&parser_obstack,
+ struct c_arg_info);
tree parms = 0;
tree tags = 0;
tree types = 0;
static bool explained_incomplete_types = false;
bool gave_void_only_once_err = false;
+ arg_info->parms = 0;
+ arg_info->tags = 0;
+ arg_info->types = 0;
+ arg_info->others = 0;
+
/* The bindings in this scope must not get put into a block.
We will take care of deleting the binding nodes. */
current_scope->bindings = 0;
/* This function is only called if there was *something* on the
parameter list. */
-#ifdef ENABLE_CHECKING
- if (b == 0)
- abort ();
-#endif
+ gcc_assert (b);
/* A parameter list consisting solely of 'void' indicates that the
function takes no arguments. But if the 'void' is qualified
if (TREE_THIS_VOLATILE (b->decl)
|| TREE_READONLY (b->decl)
|| C_DECL_REGISTER (b->decl))
- error ("'void' as only parameter may not be qualified");
+ error ("%<void%> as only parameter may not be qualified");
/* There cannot be an ellipsis. */
if (ellipsis)
- error ("'void' must be the only parameter");
+ error ("%<void%> must be the only parameter");
- ARG_INFO_TYPES (arg_info) = void_list_node;
+ arg_info->types = void_list_node;
return arg_info;
}
case PARM_DECL:
if (b->id)
{
-#ifdef ENABLE_CHECKING
- if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
I_SYMBOL_BINDING (b->id) = b->shadowed;
}
/* Check for forward decls that never got their actual decl. */
if (TREE_ASM_WRITTEN (decl))
- error ("%Jparameter '%D' has just a forward declaration",
+ error ("%Jparameter %qD has just a forward declaration",
decl, decl);
/* Check for (..., void, ...) and issue an error. */
else if (VOID_TYPE_P (type) && !DECL_NAME (decl))
{
if (!gave_void_only_once_err)
{
- error ("'void' must be the only parameter");
+ error ("%<void%> must be the only parameter");
gave_void_only_once_err = true;
}
}
appears in the bindings list with b->id NULL. */
if (b->id)
{
-#ifdef ENABLE_CHECKING
- if (I_TAG_BINDING (b->id) != b) abort ();
-#endif
+ gcc_assert (I_TAG_BINDING (b->id) == b);
I_TAG_BINDING (b->id) = b->shadowed;
}
{
if (b->id)
/* The %s will be one of 'struct', 'union', or 'enum'. */
- warning ("'%s %E' declared inside parameter list",
+ warning (0, "%<%s %E%> declared inside parameter list",
keyword, b->id);
else
/* The %s will be one of 'struct', 'union', or 'enum'. */
- warning ("anonymous %s declared inside parameter list",
+ warning (0, "anonymous %s declared inside parameter list",
keyword);
- if (! explained_incomplete_types)
+ if (!explained_incomplete_types)
{
- warning ("its scope is only this definition or declaration,"
+ warning (0, "its scope is only this definition or declaration,"
" which is probably not what you want");
explained_incomplete_types = true;
}
case CONST_DECL:
case TYPE_DECL:
+ case FUNCTION_DECL:
/* CONST_DECLs appear here when we have an embedded enum,
and TYPE_DECLs appear here when we have an embedded struct
or union. No warnings for this - we already warned about the
- type itself. */
+ type itself. FUNCTION_DECLs appear when there is an implicit
+ function declaration in the parameter list. */
+
TREE_CHAIN (decl) = others;
others = decl;
/* fall through */
variable. Just throw it away. */
if (b->id)
{
-#ifdef ENABLE_CHECKING
- if (I_SYMBOL_BINDING (b->id) != b) abort ();
-#endif
+ gcc_assert (I_SYMBOL_BINDING (b->id) == b);
I_SYMBOL_BINDING (b->id) = b->shadowed;
}
break;
/* Other things that might be encountered. */
case LABEL_DECL:
- case FUNCTION_DECL:
case VAR_DECL:
default:
- abort ();
+ gcc_unreachable ();
}
b = free_binding_and_advance (b);
}
- ARG_INFO_PARMS (arg_info) = parms;
- ARG_INFO_TAGS (arg_info) = tags;
- ARG_INFO_TYPES (arg_info) = types;
- ARG_INFO_OTHERS (arg_info) = others;
+ arg_info->parms = parms;
+ arg_info->tags = tags;
+ arg_info->types = types;
+ arg_info->others = others;
return arg_info;
}
\f
/* Get the struct, enum or union (CODE says which) with tag NAME.
- Define the tag as a forward-reference if it is not defined. */
+ Define the tag as a forward-reference if it is not defined.
+ Return a c_typespec structure for the type specifier. */
-tree
-xref_tag (enum tree_code code, tree name)
+struct c_typespec
+parser_xref_tag (enum tree_code code, tree name)
{
+ struct c_typespec ret;
/* If a cross reference is requested, look up the type
already defined for this tag and return it. */
this would not work properly if we return the reference found.
(For example, with "struct foo" in an outer scope, "union foo;"
must shadow that tag with a new one of union type.) */
+ ret.kind = (ref ? ctsk_tagref : ctsk_tagfirstref);
if (ref && TREE_CODE (ref) == code)
- return ref;
+ {
+ ret.spec = ref;
+ return ret;
+ }
/* If no such tag is yet defined, create a forward-reference node
and record it as the "definition".
pushtag (name, ref);
- return ref;
+ ret.spec = ref;
+ return ret;
+}
+
+/* Get the struct, enum or union (CODE says which) with tag NAME.
+ Define the tag as a forward-reference if it is not defined.
+ Return a tree for the type. */
+
+tree
+xref_tag (enum tree_code code, tree name)
+{
+ return parser_xref_tag (code, name).spec;
}
\f
/* Make sure that the tag NAME is defined *in the current scope*
ref = lookup_tag (code, name, 1);
if (ref && TREE_CODE (ref) == code)
{
- if (TYPE_FIELDS (ref))
+ if (TYPE_SIZE (ref))
{
if (code == UNION_TYPE)
- error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
+ error ("redefinition of %<union %E%>", name);
+ else
+ error ("redefinition of %<struct %E%>", name);
+ }
+ else if (C_TYPE_BEING_DEFINED (ref))
+ {
+ if (code == UNION_TYPE)
+ error ("nested redefinition of %<union %E%>", name);
else
- error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
+ error ("nested redefinition of %<struct %E%>", name);
}
}
else
return ref;
}
-/* Process the specs, declarator (NULL if omitted) and width (NULL if omitted)
+/* Process the specs, declarator and width (NULL if omitted)
of a structure component, returning a FIELD_DECL node.
WIDTH is non-NULL for bit-fields only, and is an INTEGER_CST node.
are ultimately passed to `build_struct' to make the RECORD_TYPE node. */
tree
-grokfield (tree declarator, tree declspecs, tree width)
+grokfield (struct c_declarator *declarator, struct c_declspecs *declspecs,
+ tree width)
{
tree value;
- if (declarator == NULL_TREE && width == NULL_TREE)
+ if (declarator->kind == cdk_id && declarator->u.id == NULL_TREE
+ && width == NULL_TREE)
{
/* This is an unnamed decl.
took this from Plan 9 or if it was an accident of implementation
that took root before someone noticed the bug... */
- tree type = TREE_VALUE (declspecs);
+ tree type = declspecs->type;
+ bool type_ok = (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE);
+ bool ok = false;
- if (flag_ms_extensions && TREE_CODE (type) == TYPE_DECL)
- type = TREE_TYPE (type);
- if (TREE_CODE (type) == RECORD_TYPE || TREE_CODE (type) == UNION_TYPE)
+ if (type_ok
+ && (flag_ms_extensions || !declspecs->typedef_p))
{
if (flag_ms_extensions)
- ; /* ok */
+ ok = true;
else if (flag_iso)
- goto warn_unnamed_field;
+ ok = false;
else if (TYPE_NAME (type) == NULL)
- ; /* ok */
+ ok = true;
else
- goto warn_unnamed_field;
+ ok = false;
}
- else
+ if (!ok)
{
- warn_unnamed_field:
- warning ("declaration does not declare anything");
+ pedwarn ("declaration does not declare anything");
return NULL_TREE;
}
+ if (pedantic)
+ pedwarn ("ISO C doesn%'t support unnamed structs/unions");
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
for (y = fieldlist; y != x; y = TREE_CHAIN (y))
if (DECL_NAME (y) == DECL_NAME (x))
{
- error ("%Jduplicate member '%D'", x, x);
+ error ("%Jduplicate member %qD", x, x);
DECL_NAME (x) = NULL_TREE;
}
}
slot = htab_find_slot (htab, y, INSERT);
if (*slot)
{
- error ("%Jduplicate member '%D'", x, x);
+ error ("%Jduplicate member %qD", x, x);
DECL_NAME (x) = NULL_TREE;
}
*slot = y;
break;
if (x == 0)
- pedwarn ("%s has no %s",
- TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
- fieldlist ? _("named members") : _("members"));
+ {
+ if (TREE_CODE (t) == UNION_TYPE)
+ {
+ if (fieldlist)
+ pedwarn ("union has no named members");
+ else
+ pedwarn ("union has no members");
+ }
+ else
+ {
+ if (fieldlist)
+ pedwarn ("struct has no named members");
+ else
+ pedwarn ("struct has no members");
+ }
+ }
}
/* Install struct as DECL_CONTEXT of each field decl.
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
- /* Detect invalid nested redefinition. */
- if (TREE_TYPE (x) == t)
- error ("nested redefinition of `%s'",
- IDENTIFIER_POINTER (TYPE_NAME (t)));
-
if (DECL_INITIAL (x))
{
unsigned HOST_WIDE_INT width = tree_low_cst (DECL_INITIAL (x), 1);
error ("%Jflexible array member not at end of struct", x);
TREE_TYPE (x) = error_mark_node;
}
- else if (! saw_named_field)
+ else if (!saw_named_field)
{
error ("%Jflexible array member in otherwise empty struct", x);
TREE_TYPE (x) = error_mark_node;
= 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
make it one, warn and turn off the flag. */
if (TREE_CODE (t) == UNION_TYPE
&& TYPE_TRANSPARENT_UNION (t)
- && TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))
+ && (!TYPE_FIELDS (t) || TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t))))
{
TYPE_TRANSPARENT_UNION (t) = 0;
- warning ("union cannot be made transparent");
+ warning (0, "union cannot be made transparent");
}
/* If this structure or union completes the type of any previous
if (c_dialect_objc ())
objc_check_decl (decl);
rest_of_decl_compilation (decl, toplevel, 0);
- if (! toplevel)
+ if (!toplevel)
expand_decl (decl);
}
}
/* Finish debugging output for this type. */
rest_of_type_compilation (t, toplevel);
+ /* If we're inside a function proper, i.e. not file-scope and not still
+ parsing parameters, then arrange for the size of a variable sized type
+ to be bound now. */
+ if (cur_stmt_list && variably_modified_type_p (t, NULL))
+ add_stmt (build_stmt (DECL_EXPR, build_decl (TYPE_DECL, NULL, t)));
+
return t;
}
pushtag (name, enumtype);
}
+ if (C_TYPE_BEING_DEFINED (enumtype))
+ error ("nested redefinition of %<enum %E%>", name);
+
C_TYPE_BEING_DEFINED (enumtype) = 1;
if (TYPE_VALUES (enumtype) != 0)
{
/* This enum is a named one that has been declared already. */
- error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
+ error ("redeclaration of %<enum %E%>", name);
/* Completely replace its old definition.
The old enumerators remain defined, however. */
tem = c_common_type_for_size (precision, unsign);
if (tem == NULL)
{
- warning ("enumeration values exceed range of largest integer");
+ warning (0, "enumeration values exceed range of largest integer");
tem = long_long_integer_type_node;
}
}
/* Validate and default VALUE. */
- /* Remove no-op casts from the value. */
- if (value)
- STRIP_TYPE_NOPS (value);
-
if (value != 0)
{
/* Don't issue more errors for error_mark_node (i.e. an
undeclared identifier) - just ignore the value expression. */
if (value == error_mark_node)
value = 0;
- else if (TREE_CODE (value) != INTEGER_CST)
+ else if (!INTEGRAL_TYPE_P (TREE_TYPE (value))
+ || TREE_CODE (value) != INTEGER_CST)
{
- error ("enumerator value for '%E' is not an integer constant", name);
+ error ("enumerator value for %qE is not an integer constant", name);
value = 0;
}
else
error ("overflow in enumeration values");
}
- if (pedantic && ! int_fits_type_p (value, integer_type_node))
+ if (pedantic && !int_fits_type_p (value, integer_type_node))
{
- pedwarn ("ISO C restricts enumerator values to range of `int'");
+ pedwarn ("ISO C restricts enumerator values to range of %<int%>");
/* XXX This causes -pedantic to change the meaning of the program.
Remove? -zw 2004-03-15 */
value = convert (integer_type_node, value);
yyparse to report a parse error. */
int
-start_function (tree declspecs, tree declarator, tree attributes)
+start_function (struct c_declspecs *declspecs, struct c_declarator *declarator,
+ tree attributes)
{
tree decl1, old_decl;
tree restype, resdecl;
+ struct c_label_context_se *nstack_se;
+ struct c_label_context_vm *nstack_vm;
current_function_returns_value = 0; /* Assume, until we see it does. */
current_function_returns_null = 0;
current_extern_inline = 0;
c_switch_stack = NULL;
+ nstack_se = XOBNEW (&parser_obstack, struct c_label_context_se);
+ nstack_se->labels_def = NULL;
+ nstack_se->labels_used = NULL;
+ nstack_se->next = label_context_stack_se;
+ label_context_stack_se = nstack_se;
+
+ nstack_vm = XOBNEW (&parser_obstack, struct c_label_context_vm);
+ nstack_vm->labels_def = NULL;
+ nstack_vm->labels_used = NULL;
+ nstack_vm->scope = 0;
+ nstack_vm->next = label_context_stack_vm;
+ label_context_stack_vm = nstack_vm;
+
/* 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. */
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
- warning ("%Jinline function '%D' given attribute noinline", decl1, decl1);
+ warning (0, "%Jinline function %qD given attribute noinline", decl1, decl1);
announce_function (decl1);
}
if (warn_about_return_type)
- pedwarn_c99 ("return type defaults to `int'");
+ pedwarn_c99 ("return type defaults to %<int%>");
/* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
/* If this definition isn't a prototype and we had a prototype declaration
- before, copy the arg type info from that prototype.
- But not if what we had before was a builtin function. */
+ before, copy the arg type info from that prototype. */
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)
- && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
- TREE_TYPE (TREE_TYPE (old_decl)))
- && TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
- {
- TREE_TYPE (decl1) = composite_type (TREE_TYPE (old_decl),
- TREE_TYPE (decl1));
- current_function_prototype_locus = DECL_SOURCE_LOCATION (old_decl);
+ current_function_prototype_locus = UNKNOWN_LOCATION;
+ current_function_prototype_built_in = false;
+ current_function_prototype_arg_types = NULL_TREE;
+ if (TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
+ {
+ if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
+ && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (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);
+ current_function_prototype_built_in
+ = C_DECL_BUILTIN_PROTOTYPE (old_decl);
+ current_function_prototype_arg_types
+ = TYPE_ARG_TYPES (TREE_TYPE (decl1));
+ }
+ if (TREE_PUBLIC (decl1))
+ {
+ /* If there is an external prototype declaration of this
+ function, record its location but do not copy information
+ to this decl. This may be an invisible declaration
+ (built-in or in a scope which has finished) or simply
+ have more refined argument types than any declaration
+ found above. */
+ struct c_binding *b;
+ for (b = I_SYMBOL_BINDING (DECL_NAME (decl1)); b; b = b->shadowed)
+ if (B_IN_SCOPE (b, external_scope))
+ break;
+ if (b)
+ {
+ tree ext_decl, ext_type;
+ ext_decl = b->decl;
+ ext_type = b->type ? b->type : TREE_TYPE (ext_decl);
+ if (TREE_CODE (ext_type) == FUNCTION_TYPE
+ && comptypes (TREE_TYPE (TREE_TYPE (decl1)),
+ TREE_TYPE (ext_type)))
+ {
+ current_function_prototype_locus
+ = DECL_SOURCE_LOCATION (ext_decl);
+ current_function_prototype_built_in
+ = C_DECL_BUILTIN_PROTOTYPE (ext_decl);
+ current_function_prototype_arg_types
+ = TYPE_ARG_TYPES (ext_type);
+ }
+ }
+ }
}
/* Optionally warn of old-fashioned def with no previous prototype. */
if (warn_strict_prototypes
+ && old_decl != error_mark_node
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning ("function declaration isn't a prototype");
+ warning (0, "function declaration isn%'t a prototype");
/* Optionally warn of any global def with no previous prototype. */
else if (warn_missing_prototypes
+ && old_decl != error_mark_node
&& TREE_PUBLIC (decl1)
- && ! MAIN_NAME_P (DECL_NAME (decl1))
+ && !MAIN_NAME_P (DECL_NAME (decl1))
&& C_DECL_ISNT_PROTOTYPE (old_decl))
- warning ("%Jno previous prototype for '%D'", decl1, decl1);
+ warning (0, "%Jno previous prototype for %qD", decl1, decl1);
/* Optionally warn of any def with no previous prototype
if the function has already been used. */
else if (warn_missing_prototypes
- && old_decl != 0 && TREE_USED (old_decl)
+ && old_decl != 0
+ && old_decl != error_mark_node
+ && TREE_USED (old_decl)
&& TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
- warning ("%J'%D' was used with no prototype before its definition",
+ warning (0, "%J%qD was used with no prototype before its definition",
decl1, decl1);
/* Optionally warn of any global def with no previous declaration. */
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
- && ! MAIN_NAME_P (DECL_NAME (decl1)))
- warning ("%Jno previous declaration for '%D'", decl1, decl1);
+ && !MAIN_NAME_P (DECL_NAME (decl1)))
+ warning (0, "%Jno previous declaration for %qD", decl1, decl1);
/* Optionally warn of any def with no previous declaration
if the function has already been used. */
else if (warn_missing_declarations
- && old_decl != 0 && TREE_USED (old_decl)
+ && old_decl != 0
+ && old_decl != error_mark_node
+ && TREE_USED (old_decl)
&& C_DECL_IMPLICIT (old_decl))
- warning ("%J`%D' was used with no declaration before its definition",
+ warning (0, "%J%qD was used with no declaration before its definition",
decl1, decl1);
/* This is a definition, not a reference.
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
-#ifdef ENABLE_CHECKING
/* This is the earliest point at which we might know the assembler
name of the function. Thus, if it's set before this, die horribly. */
- if (DECL_ASSEMBLER_NAME_SET_P (decl1))
- abort ();
-#endif
+ gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
/* If #pragma weak was used, mark the decl weak now. */
if (current_scope == file_scope)
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
- pedwarn ("%Jreturn type of '%D' is not `int'", decl1, decl1);
+ pedwarn ("%Jreturn type of %qD is not %<int%>", decl1, decl1);
for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
args = TREE_CHAIN (args))
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn ("%Jfirst argument of '%D' should be `int'",
+ pedwarn ("%Jfirst argument of %qD should be %<int%>",
decl1, decl1);
break;
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn ("%Jsecond argument of '%D' should be 'char **'",
+ pedwarn ("%Jsecond argument of %qD should be %<char **%>",
decl1, decl1);
break;
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
- pedwarn ("%Jthird argument of '%D' should probably be "
- "'char **'", decl1, decl1);
+ pedwarn ("%Jthird argument of %qD should probably be "
+ "%<char **%>", decl1, decl1);
break;
}
}
argument because it's only mentioned in an appendix of the
standard. */
if (argct > 0 && (argct < 2 || argct > 3))
- pedwarn ("%J'%D' takes only zero or two arguments", decl1, decl1);
+ pedwarn ("%J%qD takes only zero or two arguments", decl1, decl1);
- if (! TREE_PUBLIC (decl1))
- pedwarn ("%J'%D' is normally a non-static function", decl1, decl1);
+ if (!TREE_PUBLIC (decl1))
+ pedwarn ("%J%qD is normally a non-static function", decl1, decl1);
}
/* Record the decl so that the function name is defined.
definitions (prototype format). The parms already have decls, so we
need only record them as in effect and complain if any redundant
old-style parm decls were written. */
-void
-store_parm_decls_newstyle (tree fndecl, tree arg_info)
+static void
+store_parm_decls_newstyle (tree fndecl, const struct c_arg_info *arg_info)
{
tree decl;
- tree parms = ARG_INFO_PARMS (arg_info);
- tree tags = ARG_INFO_TAGS (arg_info);
- tree others = ARG_INFO_OTHERS (arg_info);
if (current_scope->bindings)
{
(this happens when a function definition has just an ellipsis in
its parameter list). */
else if (warn_traditional && !in_system_header && !current_function_scope
- && ARG_INFO_TYPES (arg_info) != error_mark_node)
- warning ("%Jtraditional C rejects ISO C style function definitions",
+ && arg_info->types != error_mark_node)
+ warning (0, "%Jtraditional C rejects ISO C style function definitions",
fndecl);
/* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */
- for (decl = parms; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->parms; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
}
/* Record the parameter list in the function declaration. */
- DECL_ARGUMENTS (fndecl) = parms;
+ DECL_ARGUMENTS (fndecl) = arg_info->parms;
/* Now make all the ancillary declarations visible, likewise. */
- for (decl = others; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->others; decl; decl = TREE_CHAIN (decl))
{
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
}
/* And all the tag declarations. */
- for (decl = tags; decl; decl = TREE_CHAIN (decl))
+ for (decl = arg_info->tags; decl; decl = TREE_CHAIN (decl))
if (TREE_PURPOSE (decl))
bind (TREE_PURPOSE (decl), TREE_VALUE (decl), current_scope,
/*invisible=*/false, /*nested=*/false);
definitions (separate parameter list and declarations). */
static void
-store_parm_decls_oldstyle (tree fndecl, tree arg_info)
+store_parm_decls_oldstyle (tree fndecl, const struct c_arg_info *arg_info)
{
struct c_binding *b;
tree parm, decl, last;
- tree parmids = ARG_INFO_PARMS (arg_info);
+ tree parmids = arg_info->parms;
/* We use DECL_WEAK as a flag to show which parameters have been
seen already, since it is not used on PARM_DECL. */
#ifdef ENABLE_CHECKING
for (b = current_scope->bindings; b; b = b->prev)
- if (TREE_CODE (b->decl) == PARM_DECL && DECL_WEAK (b->decl))
- abort ();
+ gcc_assert (TREE_CODE (b->decl) != PARM_DECL || !DECL_WEAK (b->decl));
#endif
- if (warn_old_style_definition && !in_system_header)
- warning ("%Jold-style function definition", fndecl);
+ if (!in_system_header)
+ warning (OPT_Wold_style_definition, "%Jold-style function definition", fndecl);
/* Match each formal parameter name with its declaration. Save each
decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
decl = b->decl;
/* If we got something other than a PARM_DECL it is an error. */
if (TREE_CODE (decl) != PARM_DECL)
- error ("%J'%D' declared as a non-parameter", decl, decl);
+ error ("%J%qD declared as a non-parameter", decl, decl);
/* If the declaration is already marked, we have a duplicate
name. Complain and ignore the duplicate. */
else if (DECL_WEAK (decl))
{
- error ("%Jmultiple parameters named '%D'", decl, decl);
+ error ("%Jmultiple parameters named %qD", decl, decl);
TREE_PURPOSE (parm) = 0;
continue;
}
an int. */
else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- error ("%Jparameter '%D' declared with void type", decl, decl);
+ error ("%Jparameter %qD declared with void type", decl, decl);
TREE_TYPE (decl) = integer_type_node;
DECL_ARG_TYPE (decl) = integer_type_node;
layout_decl (decl, 0);
pushdecl (decl);
if (flag_isoc99)
- pedwarn ("%Jtype of '%D' defaults to 'int'", decl, decl);
+ pedwarn ("%Jtype of %qD defaults to %<int%>", decl, decl);
else if (extra_warnings)
- warning ("%Jtype of '%D' defaults to 'int'", decl, decl);
+ warning (0, "%Jtype of %qD defaults to %<int%>", decl, decl);
}
TREE_PURPOSE (parm) = decl;
if (TREE_CODE (parm) != PARM_DECL)
continue;
- if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
+ if (TREE_TYPE (parm) != error_mark_node
+ && !COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- error ("%Jparameter '%D' has incomplete type", parm, parm);
+ error ("%Jparameter %qD has incomplete type", parm, parm);
TREE_TYPE (parm) = error_mark_node;
}
- if (! DECL_WEAK (parm))
+ if (!DECL_WEAK (parm))
{
- error ("%Jdeclaration for parameter '%D' but no such parameter",
+ error ("%Jdeclaration for parameter %qD but no such parameter",
parm, parm);
/* Pretend the parameter was not missing.
set the DECL_ARG_TYPE of each argument according to
the type previously specified, and report any mismatches. */
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ if (current_function_prototype_arg_types)
{
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
- type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ type = current_function_prototype_arg_types;
parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
!= void_type_node));
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
if (parm == 0 || type == 0
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- error ("number of arguments doesn't match prototype");
- error ("%Hprototype declaration",
- ¤t_function_prototype_locus);
+ if (current_function_prototype_built_in)
+ warning (0, "number of arguments doesn%'t match "
+ "built-in prototype");
+ else
+ {
+ error ("number of arguments doesn%'t match prototype");
+ error ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
+ }
break;
}
/* Type for passing arg must be consistent with that
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))))
+ if (!comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type))))
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
== TYPE_MAIN_VARIANT (TREE_VALUE (type)))
if (pedantic)
{
- pedwarn ("promoted argument '%D' "
- "doesn't match prototype", parm);
- pedwarn ("%Hprototype declaration",
- ¤t_function_prototype_locus);
+ /* ??? Is it possible to get here with a
+ built-in prototype or will it always have
+ been diagnosed as conflicting with an
+ old-style definition and discarded? */
+ if (current_function_prototype_built_in)
+ warning (0, "promoted argument %qD "
+ "doesn%'t match built-in prototype", parm);
+ else
+ {
+ pedwarn ("promoted argument %qD "
+ "doesn%'t match prototype", parm);
+ pedwarn ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
+ }
}
}
else
{
- error ("argument '%D' doesn't match prototype", parm);
- error ("%Hprototype declaration",
- ¤t_function_prototype_locus);
+ if (current_function_prototype_built_in)
+ warning (0, "argument %qD doesn%'t match "
+ "built-in prototype", parm);
+ else
+ {
+ error ("argument %qD doesn%'t match prototype", parm);
+ error ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
+ }
}
}
}
}
}
+/* Store parameter declarations passed in ARG_INFO into the current
+ function declaration. */
+
+void
+store_parm_decls_from (struct c_arg_info *arg_info)
+{
+ current_function_arg_info = arg_info;
+ store_parm_decls ();
+}
+
/* Store the parameter declarations into the current function declaration.
This is called after parsing the parameter declarations, before
digesting the body of the function.
bool proto;
/* The argument information block for FNDECL. */
- tree arg_info = current_function_arg_info;
+ struct c_arg_info *arg_info = current_function_arg_info;
current_function_arg_info = 0;
/* True if this definition is written with a prototype. Note:
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. */
- proto = ARG_INFO_TYPES (arg_info) != 0;
+ proto = arg_info->types != 0;
if (proto)
store_parm_decls_newstyle (fndecl, arg_info);
DECL_SAVED_TREE (fndecl) = push_stmt_list ();
/* ??? 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. */
+ to be evaluated. The only reason left to have this is
+ void foo(int n, int array[n++])
+ because we throw away the array type in favor of a pointer type, and
+ thus won't naturally see the SAVE_EXPR containing the increment. All
+ other pending sizes would be handled by gimplify_parameters. */
{
tree t;
for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
cfun->x_dont_save_pending_sizes_p = 1;
}
\f
-/* Give FNDECL and all its nested functions to cgraph for compilation. */
+/* Handle attribute((warn_unused_result)) on FNDECL and all its nested
+ functions. */
static void
-c_finalize (tree fndecl)
+c_warn_unused_result_recursively (tree fndecl)
{
struct cgraph_node *cgn;
/* Handle attribute((warn_unused_result)). Relies on gimple input. */
c_warn_unused_result (&DECL_SAVED_TREE (fndecl));
- /* ??? Objc emits functions after finalizing the compilation unit.
- This should be cleaned up later and this conditional removed. */
- if (cgraph_global_info_ready)
- {
- c_expand_body (fndecl);
- return;
- }
-
/* Finalize all nested functions now. */
cgn = cgraph_node (fndecl);
for (cgn = cgn->nested; cgn ; cgn = cgn->next_nested)
- c_finalize (cgn->decl);
-
- cgraph_finalize_function (fndecl, false);
+ c_warn_unused_result_recursively (cgn->decl);
}
/* Finish up a function declaration and compile that function
{
tree fndecl = current_function_decl;
+ label_context_stack_se = label_context_stack_se->next;
+ label_context_stack_vm = label_context_stack_vm->next;
+
if (TREE_CODE (fndecl) == FUNCTION_DECL
&& targetm.calls.promote_prototypes (TREE_TYPE (fndecl)))
{
/* If warn_main is 1 (-Wmain) or 2 (-Wall), we have already warned.
If warn_main is -1 (-Wno-main) we don't want to be warned. */
if (!warn_main)
- pedwarn ("%Jreturn type of '%D' is not `int'", fndecl, fndecl);
+ pedwarn ("%Jreturn type of %qD is not %<int%>", fndecl, fndecl);
}
else
{
if (flag_isoc99)
- c_finish_return (integer_zero_node);
+ {
+ tree stmt = c_finish_return (integer_zero_node);
+#ifdef USE_MAPPED_LOCATION
+ /* Hack. We don't want the middle-end to warn that this return
+ is unreachable, so we mark its location as special. Using
+ UNKNOWN_LOCATION has the problem that it gets clobbered in
+ annotate_one_with_locus. A cleaner solution might be to
+ ensure ! should_carry_locus_p (stmt), but that needs a flag.
+ */
+ SET_EXPR_LOCATION (stmt, BUILTINS_LOCATION);
+#else
+ /* Hack. We don't want the middle-end to warn that this
+ return is unreachable, so put the statement on the
+ special line 0. */
+ annotate_with_file_line (stmt, input_filename, 0);
+#endif
+ }
}
}
if (warn_return_type
&& TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
- /* Don't complain if we abort. */
+ /* Don't complain if we are no-return. */
&& !current_function_returns_abnormally
/* Don't warn for main(). */
&& !MAIN_NAME_P (DECL_NAME (fndecl))
/* Normally, with -Wreturn-type, flow will complain. Unless we're an
inline function, as we might never be compiled separately. */
&& DECL_INLINE (fndecl))
- warning ("no return statement in function returning non-void");
+ {
+ warning (0, "no return statement in function returning non-void");
+ TREE_NO_WARNING (fndecl) = 1;
+ }
/* With just -Wextra, complain only if function returns both with
and without a value. */
if (extra_warnings
&& current_function_returns_value
&& current_function_returns_null)
- warning ("this function may return with or without a value");
+ warning (0, "this function may return with or without a value");
/* Store the end of the function, so that we get good line number
info for the epilogue. */
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))
{
c_genericize (fndecl);
- lower_nested_functions (fndecl);
- c_finalize (fndecl);
+ c_warn_unused_result_recursively (fndecl);
+
+ /* ??? Objc emits functions after finalizing the compilation unit.
+ This should be cleaned up later and this conditional removed. */
+ if (cgraph_global_info_ready)
+ {
+ c_expand_body (fndecl);
+ return;
+ }
+
+ cgraph_finalize_function (fndecl, false);
}
else
{
}
}
+ 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. */
|| DECL_INITIAL (fndecl) == error_mark_node)
return;
- tree_rest_of_compilation (fndecl, false);
+ tree_rest_of_compilation (fndecl);
if (DECL_STATIC_CONSTRUCTOR (fndecl)
&& targetm.have_ctors_dtors)
/* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't
allow it. */
- error ("'for' loop initial declaration used outside C99 mode");
+ error ("%<for%> loop initial declaration used outside C99 mode");
return;
}
/* C99 subclause 6.8.5 paragraph 3:
{
case VAR_DECL:
if (TREE_STATIC (decl))
- error ("%Jdeclaration of static variable '%D' in 'for' loop "
+ error ("%Jdeclaration of static variable %qD in %<for%> loop "
"initial declaration", decl, decl);
else if (DECL_EXTERNAL (decl))
- error ("%Jdeclaration of 'extern' variable '%D' in 'for' loop "
+ error ("%Jdeclaration of %<extern%> variable %qD in %<for%> loop "
"initial declaration", decl, decl);
break;
case RECORD_TYPE:
- error ("'struct %E' declared in 'for' loop initial declaration", id);
+ error ("%<struct %E%> declared in %<for%> loop initial declaration",
+ id);
break;
case UNION_TYPE:
- error ("'union %E' declared in 'for' loop initial declaration", id);
+ error ("%<union %E%> declared in %<for%> loop initial declaration",
+ id);
break;
case ENUMERAL_TYPE:
- error ("'enum %E' declared in 'for' loop initial declaration", id);
+ error ("%<enum %E%> declared in %<for%> loop initial declaration",
+ id);
break;
default:
- error ("%Jdeclaration of non-variable '%D' in 'for' loop "
+ error ("%Jdeclaration of non-variable %qD in %<for%> loop "
"initial declaration", decl, decl);
}
}
return 0;
}
-/* Dummy function in place of callback used by C++. */
-
-void
-extract_interface_info (void)
-{
-}
-
/* Return the global value of T as a symbol. */
tree
return t;
}
-/* Return a structure for a parameter with the given SPECS, ATTRS and
- DECLARATOR. */
+/* Return a c_parm structure with the given SPECS, ATTRS and DECLARATOR. */
-tree
-build_c_parm (tree specs, tree attrs, tree declarator)
+struct c_parm *
+build_c_parm (struct c_declspecs *specs, tree attrs,
+ struct c_declarator *declarator)
{
- return build_tree_list (build_tree_list (specs, declarator), attrs);
+ struct c_parm *ret = XOBNEW (&parser_obstack, struct c_parm);
+ ret->specs = specs;
+ ret->attrs = attrs;
+ ret->declarator = declarator;
+ return ret;
}
/* 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)
+struct c_declarator *
+build_attrs_declarator (tree attrs, struct c_declarator *target)
{
- return tree_cons (attrs, target, NULL_TREE);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_attrs;
+ ret->declarator = target;
+ ret->u.attrs = attrs;
+ return ret;
}
/* 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)
+struct c_declarator *
+build_function_declarator (struct c_arg_info *args,
+ struct c_declarator *target)
+{
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_function;
+ ret->declarator = target;
+ ret->u.arg_info = args;
+ return ret;
+}
+
+/* Return a declarator for the identifier IDENT (which may be
+ NULL_TREE for an abstract declarator). */
+
+struct c_declarator *
+build_id_declarator (tree ident)
{
- return build_nt (CALL_EXPR, target, args, NULL_TREE);
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ ret->kind = cdk_id;
+ ret->declarator = 0;
+ ret->u.id = ident;
+ /* Default value - may get reset to a more precise location. */
+ ret->id_loc = input_location;
+ return ret;
}
/* 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
- to apply to the pointer type, represented as identifiers, possible mixed
- with attributes.
+ TYPE_QUALS_ATTRS is a structure for type qualifiers and attributes
+ to apply to the pointer type. */
+
+struct c_declarator *
+make_pointer_declarator (struct c_declspecs *type_quals_attrs,
+ struct c_declarator *target)
+{
+ tree attrs;
+ int quals = 0;
+ struct c_declarator *itarget = target;
+ struct c_declarator *ret = XOBNEW (&parser_obstack, struct c_declarator);
+ if (type_quals_attrs)
+ {
+ attrs = type_quals_attrs->attrs;
+ quals = quals_from_declspecs (type_quals_attrs);
+ if (attrs != NULL_TREE)
+ itarget = build_attrs_declarator (attrs, target);
+ }
+ ret->kind = cdk_pointer;
+ ret->declarator = itarget;
+ ret->u.pointer_quals = quals;
+ return ret;
+}
- We return an INDIRECT_REF whose "contents" are TARGET (inside a TREE_LIST,
- if attributes are present) and whose type is the modifier list. */
+/* Return a pointer to a structure for an empty list of declaration
+ specifiers. */
-tree
-make_pointer_declarator (tree type_quals_attrs, tree target)
+struct c_declspecs *
+build_null_declspecs (void)
+{
+ struct c_declspecs *ret = XOBNEW (&parser_obstack, struct c_declspecs);
+ ret->type = 0;
+ ret->decl_attr = 0;
+ ret->attrs = 0;
+ ret->typespec_word = cts_none;
+ ret->storage_class = csc_none;
+ ret->declspecs_seen_p = false;
+ ret->type_seen_p = false;
+ ret->non_sc_seen_p = false;
+ ret->typedef_p = false;
+ ret->tag_defined_p = false;
+ ret->explicit_signed_p = false;
+ ret->deprecated_p = false;
+ ret->default_int_p = false;
+ ret->long_p = false;
+ ret->long_long_p = false;
+ ret->short_p = false;
+ ret->signed_p = false;
+ ret->unsigned_p = false;
+ ret->complex_p = false;
+ ret->inline_p = false;
+ ret->thread_p = false;
+ ret->const_p = false;
+ ret->volatile_p = false;
+ ret->restrict_p = false;
+ return ret;
+}
+
+/* Add the type qualifier QUAL to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_qual (struct c_declspecs *specs, tree qual)
+{
+ enum rid i;
+ bool dupe = false;
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+ gcc_assert (TREE_CODE (qual) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (qual));
+ i = C_RID_CODE (qual);
+ switch (i)
+ {
+ case RID_CONST:
+ dupe = specs->const_p;
+ specs->const_p = true;
+ break;
+ case RID_VOLATILE:
+ dupe = specs->volatile_p;
+ specs->volatile_p = true;
+ break;
+ case RID_RESTRICT:
+ dupe = specs->restrict_p;
+ specs->restrict_p = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (dupe && pedantic && !flag_isoc99)
+ pedwarn ("duplicate %qE", qual);
+ return specs;
+}
+
+/* Add the type specifier TYPE to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_type (struct c_declspecs *specs, struct c_typespec spec)
{
- tree quals, attrs;
- tree itarget = target;
- split_specs_attrs (type_quals_attrs, &quals, &attrs);
- if (attrs != NULL_TREE)
- itarget = build_attrs_declarator (attrs, target);
- return build1 (INDIRECT_REF, quals, itarget);
+ tree type = spec.spec;
+ specs->non_sc_seen_p = true;
+ specs->declspecs_seen_p = true;
+ specs->type_seen_p = true;
+ if (TREE_DEPRECATED (type))
+ specs->deprecated_p = true;
+
+ /* Handle type specifier keywords. */
+ if (TREE_CODE (type) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (type))
+ {
+ enum rid i = C_RID_CODE (type);
+ if (specs->type)
+ {
+ error ("two or more data types in declaration specifiers");
+ return specs;
+ }
+ if ((int) i <= (int) RID_LAST_MODIFIER)
+ {
+ /* "long", "short", "signed", "unsigned" or "_Complex". */
+ bool dupe = false;
+ switch (i)
+ {
+ case RID_LONG:
+ if (specs->long_long_p)
+ {
+ error ("%<long long long%> is too long for GCC");
+ break;
+ }
+ if (specs->long_p)
+ {
+ if (specs->typespec_word == cts_double)
+ {
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ break;
+ }
+ if (pedantic && !flag_isoc99 && !in_system_header
+ && warn_long_long)
+ pedwarn ("ISO C90 does not support %<long long%>");
+ specs->long_long_p = 1;
+ break;
+ }
+ if (specs->short_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<long%> and %<float%> in "
+ "declaration specifiers");
+ else
+ specs->long_p = true;
+ break;
+ case RID_SHORT:
+ dupe = specs->short_p;
+ if (specs->long_p)
+ error ("both %<long%> and %<short%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_char)
+ error ("both %<short%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->short_p = true;
+ break;
+ case RID_SIGNED:
+ dupe = specs->signed_p;
+ if (specs->unsigned_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->signed_p = true;
+ break;
+ case RID_UNSIGNED:
+ dupe = specs->unsigned_p;
+ if (specs->signed_p)
+ error ("both %<signed%> and %<unsigned%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_void)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_float)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_double)
+ error ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->unsigned_p = true;
+ break;
+ case RID_COMPLEX:
+ dupe = specs->complex_p;
+ if (pedantic && !flag_isoc99 && !in_system_header)
+ pedwarn ("ISO C90 does not support complex types");
+ if (specs->typespec_word == cts_void)
+ error ("both %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->typespec_word == cts_bool)
+ error ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers");
+ else
+ specs->complex_p = true;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ if (dupe)
+ error ("duplicate %qE", type);
+
+ return specs;
+ }
+ else
+ {
+ /* "void", "_Bool", "char", "int", "float" or "double". */
+ if (specs->typespec_word != cts_none)
+ {
+ error ("two or more data types in declaration specifiers");
+ return specs;
+ }
+ switch (i)
+ {
+ case RID_VOID:
+ if (specs->long_p)
+ error ("both %<long%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<void%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<void%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_void;
+ return specs;
+ case RID_BOOL:
+ if (specs->long_p)
+ error ("both %<long%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<_Bool%> in "
+ "declaration specifiers");
+ else if (specs->complex_p)
+ error ("both %<complex%> and %<_Bool%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_bool;
+ return specs;
+ case RID_CHAR:
+ if (specs->long_p)
+ error ("both %<long%> and %<char%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<char%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_char;
+ return specs;
+ case RID_INT:
+ specs->typespec_word = cts_int;
+ return specs;
+ case RID_FLOAT:
+ if (specs->long_p)
+ error ("both %<long%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<float%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<float%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_float;
+ return specs;
+ case RID_DOUBLE:
+ if (specs->long_long_p)
+ error ("both %<long long%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->short_p)
+ error ("both %<short%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->signed_p)
+ error ("both %<signed%> and %<double%> in "
+ "declaration specifiers");
+ else if (specs->unsigned_p)
+ error ("both %<unsigned%> and %<double%> in "
+ "declaration specifiers");
+ else
+ specs->typespec_word = cts_double;
+ return specs;
+ default:
+ /* ObjC reserved word "id", handled below. */
+ break;
+ }
+ }
+ }
+
+ /* Now we have a typedef (a TYPE_DECL node), an identifier (some
+ form of ObjC type, cases such as "int" and "long" being handled
+ above), a TYPE (struct, union, enum and typeof specifiers) or an
+ ERROR_MARK. In none of these cases may there have previously
+ been any type specifiers. */
+ if (specs->type || specs->typespec_word != cts_none
+ || specs->long_p || specs->short_p || specs->signed_p
+ || specs->unsigned_p || specs->complex_p)
+ error ("two or more data types in declaration specifiers");
+ else if (TREE_CODE (type) == TYPE_DECL)
+ {
+ if (TREE_TYPE (type) == error_mark_node)
+ ; /* Allow the type to default to int to avoid cascading errors. */
+ else
+ {
+ specs->type = TREE_TYPE (type);
+ specs->decl_attr = DECL_ATTRIBUTES (type);
+ specs->typedef_p = true;
+ specs->explicit_signed_p = C_TYPEDEF_EXPLICITLY_SIGNED (type);
+ }
+ }
+ else if (TREE_CODE (type) == IDENTIFIER_NODE)
+ {
+ tree t = lookup_name (type);
+ if (!t || TREE_CODE (t) != TYPE_DECL)
+ error ("%qE fails to be a typedef or built in type", type);
+ else if (TREE_TYPE (t) == error_mark_node)
+ ;
+ else
+ specs->type = TREE_TYPE (t);
+ }
+ else if (TREE_CODE (type) != ERROR_MARK)
+ {
+ if (spec.kind == ctsk_tagdef || spec.kind == ctsk_tagfirstref)
+ specs->tag_defined_p = true;
+ if (spec.kind == ctsk_typeof)
+ specs->typedef_p = true;
+ specs->type = type;
+ }
+
+ return specs;
+}
+
+/* Add the storage class specifier or function specifier SCSPEC to the
+ declaration specifiers SPECS, returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_scspec (struct c_declspecs *specs, tree scspec)
+{
+ enum rid i;
+ enum c_storage_class n = csc_none;
+ bool dupe = false;
+ specs->declspecs_seen_p = true;
+ gcc_assert (TREE_CODE (scspec) == IDENTIFIER_NODE
+ && C_IS_RESERVED_WORD (scspec));
+ i = C_RID_CODE (scspec);
+ if (extra_warnings && specs->non_sc_seen_p)
+ warning (0, "%qE is not at beginning of declaration", scspec);
+ switch (i)
+ {
+ case RID_INLINE:
+ /* C99 permits duplicate inline. Although of doubtful utility,
+ it seems simplest to permit it in gnu89 mode as well, as
+ there is also little utility in maintaining this as a
+ difference between gnu89 and C99 inline. */
+ dupe = false;
+ specs->inline_p = true;
+ break;
+ case RID_THREAD:
+ dupe = specs->thread_p;
+ if (specs->storage_class == csc_auto)
+ error ("%<__thread%> used with %<auto%>");
+ else if (specs->storage_class == csc_register)
+ error ("%<__thread%> used with %<register%>");
+ else if (specs->storage_class == csc_typedef)
+ error ("%<__thread%> used with %<typedef%>");
+ else
+ specs->thread_p = true;
+ break;
+ case RID_AUTO:
+ n = csc_auto;
+ break;
+ case RID_EXTERN:
+ n = csc_extern;
+ /* Diagnose "__thread extern". */
+ if (specs->thread_p)
+ error ("%<__thread%> before %<extern%>");
+ break;
+ case RID_REGISTER:
+ n = csc_register;
+ break;
+ case RID_STATIC:
+ n = csc_static;
+ /* Diagnose "__thread static". */
+ if (specs->thread_p)
+ error ("%<__thread%> before %<static%>");
+ break;
+ case RID_TYPEDEF:
+ n = csc_typedef;
+ break;
+ default:
+ gcc_unreachable ();
+ }
+ if (n != csc_none && n == specs->storage_class)
+ dupe = true;
+ if (dupe)
+ error ("duplicate %qE", scspec);
+ if (n != csc_none)
+ {
+ if (specs->storage_class != csc_none && n != specs->storage_class)
+ {
+ error ("multiple storage classes in declaration specifiers");
+ }
+ else
+ {
+ specs->storage_class = n;
+ if (n != csc_extern && n != csc_static && specs->thread_p)
+ {
+ error ("%<__thread%> used with %qE", scspec);
+ specs->thread_p = false;
+ }
+ }
+ }
+ return specs;
+}
+
+/* Add the attributes ATTRS to the declaration specifiers SPECS,
+ returning SPECS. */
+
+struct c_declspecs *
+declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
+{
+ specs->attrs = chainon (attrs, specs->attrs);
+ specs->declspecs_seen_p = true;
+ return specs;
+}
+
+/* Combine "long", "short", "signed", "unsigned" and "_Complex" type
+ specifiers with any other type specifier to determine the resulting
+ type. This is where ISO C checks on complex types are made, since
+ "_Complex long" is a prefix of the valid ISO C type "_Complex long
+ double". */
+
+struct c_declspecs *
+finish_declspecs (struct c_declspecs *specs)
+{
+ /* If a type was specified as a whole, we have no modifiers and are
+ done. */
+ if (specs->type != NULL_TREE)
+ {
+ gcc_assert (!specs->long_p && !specs->long_long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ return specs;
+ }
+
+ /* If none of "void", "_Bool", "char", "int", "float" or "double"
+ has been specified, treat it as "int" unless "_Complex" is
+ present and there are no other specifiers. If we just have
+ "_Complex", it is equivalent to "_Complex double", but e.g.
+ "_Complex short" is equivalent to "_Complex short int". */
+ if (specs->typespec_word == cts_none)
+ {
+ if (specs->long_p || specs->short_p
+ || specs->signed_p || specs->unsigned_p)
+ {
+ specs->typespec_word = cts_int;
+ }
+ else if (specs->complex_p)
+ {
+ specs->typespec_word = cts_double;
+ if (pedantic)
+ pedwarn ("ISO C does not support plain %<complex%> meaning "
+ "%<double complex%>");
+ }
+ else
+ {
+ specs->typespec_word = cts_int;
+ specs->default_int_p = true;
+ /* We don't diagnose this here because grokdeclarator will
+ give more specific diagnostics according to whether it is
+ a function definition. */
+ }
+ }
+
+ /* If "signed" was specified, record this to distinguish "int" and
+ "signed int" in the case of a bit-field with
+ -funsigned-bitfields. */
+ specs->explicit_signed_p = specs->signed_p;
+
+ /* Now compute the actual type. */
+ switch (specs->typespec_word)
+ {
+ case cts_void:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ specs->type = void_type_node;
+ break;
+ case cts_bool:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p
+ && !specs->complex_p);
+ specs->type = boolean_type_node;
+ break;
+ case cts_char:
+ gcc_assert (!specs->long_p && !specs->short_p);
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ if (specs->signed_p)
+ specs->type = signed_char_type_node;
+ else if (specs->unsigned_p)
+ specs->type = unsigned_char_type_node;
+ else
+ specs->type = char_type_node;
+ if (specs->complex_p)
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
+ case cts_int:
+ gcc_assert (!(specs->long_p && specs->short_p));
+ gcc_assert (!(specs->signed_p && specs->unsigned_p));
+ if (specs->long_long_p)
+ specs->type = (specs->unsigned_p
+ ? long_long_unsigned_type_node
+ : long_long_integer_type_node);
+ else if (specs->long_p)
+ specs->type = (specs->unsigned_p
+ ? long_unsigned_type_node
+ : long_integer_type_node);
+ else if (specs->short_p)
+ specs->type = (specs->unsigned_p
+ ? short_unsigned_type_node
+ : short_integer_type_node);
+ else
+ specs->type = (specs->unsigned_p
+ ? unsigned_type_node
+ : integer_type_node);
+ if (specs->complex_p)
+ {
+ if (pedantic)
+ pedwarn ("ISO C does not support complex integer types");
+ specs->type = build_complex_type (specs->type);
+ }
+ break;
+ case cts_float:
+ gcc_assert (!specs->long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ specs->type = (specs->complex_p
+ ? complex_float_type_node
+ : float_type_node);
+ break;
+ case cts_double:
+ gcc_assert (!specs->long_long_p && !specs->short_p
+ && !specs->signed_p && !specs->unsigned_p);
+ if (specs->long_p)
+ {
+ specs->type = (specs->complex_p
+ ? complex_long_double_type_node
+ : long_double_type_node);
+ }
+ else
+ {
+ specs->type = (specs->complex_p
+ ? complex_double_type_node
+ : double_type_node);
+ }
+ break;
+ default:
+ gcc_unreachable ();
+ }
+
+ return specs;
}
/* Synthesize a function which calls all the global ctors or global
/* Process the decls in the order they were written. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
- vec[i] = decl;
+ {
+ vec[i] = decl;
+ /* Check for used but undefined static functions using the C
+ standard's definition of "used", and set TREE_NO_WARNING so
+ that check_global_declarations doesn't repeat the check. */
+ if (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INITIAL (decl) == 0
+ && DECL_EXTERNAL (decl)
+ && !TREE_PUBLIC (decl)
+ && C_DECL_USED (decl))
+ {
+ pedwarn ("%J%qF used but never defined", decl, decl);
+ TREE_NO_WARNING (decl) = 1;
+ }
+ }
wrapup_global_declarations (vec, len);
check_global_declarations (vec, len);
/* Close the external scope. */
ext_block = pop_scope ();
external_scope = 0;
- if (current_scope)
- abort ();
+ gcc_assert (!current_scope);
/* Process all file scopes in this compilation, and the external_scope,
through wrapup_global_declarations and check_global_declarations. */
/* 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"