#include "flags.h"
#include "function.h"
#include "output.h"
-#include "expr.h"
#include "c-tree.h"
#include "toplev.h"
-#include "ggc.h"
#include "tm_p.h"
#include "cpplib.h"
#include "target.h"
#include "c-lang.h"
#include "langhooks.h"
#include "tree-mudflap.h"
-#include "gimple.h"
#include "tree-iterator.h"
#include "diagnostic.h"
#include "tree-dump.h"
#include "cgraph.h"
#include "hashtab.h"
-#include "libfuncs.h"
-#include "except.h"
#include "langhooks-def.h"
#include "pointer-set.h"
-#include "gimple.h"
#include "plugin.h"
/* In grokdeclarator, distinguish syntactic contexts of declarators. */
case VAR_DECL:
/* Warnings for unused variables. */
- if (!TREE_USED (p)
+ if ((!TREE_USED (p) || !DECL_READ_P (p))
&& !TREE_NO_WARNING (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p)
&& scope != file_scope
&& scope != external_scope)
- warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ {
+ if (!TREE_USED (p))
+ warning (OPT_Wunused_variable, "unused variable %q+D", p);
+ else if (DECL_CONTEXT (p) == current_function_decl)
+ warning_at (DECL_SOURCE_LOCATION (p),
+ OPT_Wunused_but_set_variable,
+ "variable %qD set but not used", p);
+ }
if (b->inner_comp)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_STRUCT_FUNCTION (newdecl) = DECL_STRUCT_FUNCTION (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
- gimple_set_body (newdecl, gimple_body (olddecl));
DECL_ARGUMENTS (newdecl) = copy_list (DECL_ARGUMENTS (olddecl));
for (t = DECL_ARGUMENTS (newdecl); t ; t = TREE_CHAIN (t))
DECL_CONTEXT (t) = newdecl;
TREE_USED (newdecl) = 1;
else if (TREE_USED (newdecl))
TREE_USED (olddecl) = 1;
+ if (TREE_CODE (olddecl) == VAR_DECL || TREE_CODE (olddecl) == PARM_DECL)
+ DECL_READ_P (newdecl) |= DECL_READ_P (olddecl);
if (DECL_PRESERVE_P (olddecl))
DECL_PRESERVE_P (newdecl) = 1;
else if (DECL_PRESERVE_P (newdecl))
switch (TREE_CODE (olddecl))
{
case FUNCTION_DECL:
- gimple_set_body (olddecl, gimple_body (newdecl));
- /* fall through */
-
case FIELD_DECL:
case VAR_DECL:
case PARM_DECL:
else
{
error_at (loc, "%qE undeclared (first use in this function)", id);
-
if (!already)
{
- error_at (loc, "(Each undeclared identifier is reported only once");
- error_at (loc, "for each function it appears in.)");
+ inform (loc, "each undeclared identifier is reported only"
+ " once for each function it appears in");
already = true;
}
using preprocessed headers. */
input_location = BUILTINS_LOCATION;
- build_common_tree_nodes (flag_signed_char, false);
+ build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
}
if (TREE_USED (type))
- TREE_USED (decl) = 1;
+ {
+ TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
+ }
}
/* If this is a function and an assembler name is specified, reset DECL_RTL
/* Don't warn about decl unused; the cleanup uses it. */
TREE_USED (decl) = 1;
TREE_USED (cleanup_decl) = 1;
+ DECL_READ_P (decl) = 1;
push_cleanup (decl, cleanup, false);
}
tree complit;
tree stmt;
- if (type == error_mark_node)
+ if (type == error_mark_node
+ || init == error_mark_node)
return error_mark_node;
decl = build_decl (loc, VAR_DECL, NULL_TREE, type);
TREE_STATIC (decl) = (current_scope == file_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
+ DECL_READ_P (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TYPE_READONLY (type);
store_init_value (loc, decl, init, NULL_TREE);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
else if (VOID_TYPE_P (type))
{
error (errmsg);
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
+ arg_types = NULL_TREE;
}
if (DECL_NAME (parm) && TREE_USED (parm))
type itself. FUNCTION_DECLs appear when there is an implicit
function declaration in the parameter list. */
+ /* When we reinsert this decl in the function body, we need
+ to reconstruct whether it was marked as nested. */
+ gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+ ? b->nested
+ : !b->nested);
TREE_CHAIN (decl) = others;
others = decl;
/* fall through */
Otherwise this is a forward declaration of a structure tag.
If this is something of the form "foo;" and foo is a TYPE_DECL, then
+ If foo names a structure or union without a tag, then this
+ is an anonymous struct (this is permitted by C1X).
If MS extensions are enabled and foo names a structure, then
again this is an anonymous struct.
Otherwise this is an error.
|| TREE_CODE (type) == UNION_TYPE);
bool ok = false;
- if (type_ok
- && (flag_ms_extensions || !declspecs->typedef_p))
+ if (type_ok)
{
if (flag_ms_extensions)
ok = true;
- else if (flag_iso)
- ok = false;
- else if (TYPE_NAME (type) == NULL)
+ else if (TYPE_NAME (TYPE_MAIN_VARIANT (type)) == NULL)
ok = true;
else
ok = false;
pedwarn (loc, 0, "declaration does not declare anything");
return NULL_TREE;
}
- pedwarn (loc, OPT_pedantic, "ISO C doesn%'t support unnamed structs/unions");
+ if (!flag_isoc1x)
+ {
+ if (flag_isoc99)
+ pedwarn (loc, OPT_pedantic,
+ "ISO C99 doesn%'t support unnamed structs/unions");
+ else
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 doesn%'t support unnamed structs/unions");
+ }
}
value = grokdeclarator (declarator, declspecs, FIELD, false,
return value;
}
\f
+/* Subroutine of detect_field_duplicates: add the fields of FIELDLIST
+ to HTAB, giving errors for any duplicates. */
+
+static void
+detect_field_duplicates_hash (tree fieldlist, htab_t htab)
+{
+ tree x, y;
+ void **slot;
+
+ for (x = fieldlist; x ; x = TREE_CHAIN (x))
+ if ((y = DECL_NAME (x)) != 0)
+ {
+ slot = htab_find_slot (htab, y, INSERT);
+ if (*slot)
+ {
+ error ("duplicate member %q+D", x);
+ DECL_NAME (x) = NULL_TREE;
+ }
+ *slot = y;
+ }
+ else if (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
+ detect_field_duplicates_hash (TYPE_FIELDS (TREE_TYPE (x)), htab);
+}
+
/* Generate an error for any duplicate field names in FIELDLIST. Munge
the list such that this does not present a problem later. */
return;
do {
timeout--;
+ if (DECL_NAME (x) == NULL_TREE
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ timeout = 0;
x = TREE_CHAIN (x);
} while (timeout > 0 && x);
- /* If there were "few" fields, avoid the overhead of allocating
- a hash table. Instead just do the nested traversal thing. */
+ /* If there were "few" fields and no anonymous structures or unions,
+ avoid the overhead of allocating a hash table. Instead just do
+ the nested traversal thing. */
if (timeout > 0)
{
for (x = TREE_CHAIN (fieldlist); x ; x = TREE_CHAIN (x))
else
{
htab_t htab = htab_create (37, htab_hash_pointer, htab_eq_pointer, NULL);
- void **slot;
-
- for (x = fieldlist; x ; x = TREE_CHAIN (x))
- if ((y = DECL_NAME (x)) != 0)
- {
- slot = htab_find_slot (htab, y, INSERT);
- if (*slot)
- {
- error ("duplicate member %q+D", x);
- DECL_NAME (x) = NULL_TREE;
- }
- *slot = y;
- }
+ detect_field_duplicates_hash (fieldlist, htab);
htab_delete (htab);
}
}
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
- if (DECL_NAME (x) != 0)
- break;
+ {
+ if (DECL_NAME (x) != 0)
+ break;
+ if (flag_isoc1x
+ && (TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE))
+ break;
+ }
if (x == 0)
{
pedwarn (DECL_SOURCE_LOCATION (x), OPT_pedantic,
"invalid use of structure with flexible array member");
- if (DECL_NAME (x))
+ if (DECL_NAME (x)
+ || TREE_CODE (TREE_TYPE (x)) == RECORD_TYPE
+ || TREE_CODE (TREE_TYPE (x)) == UNION_TYPE)
saw_named_field = 1;
}
error_mark_node is replaced below (in pop_scope) with the BLOCK. */
DECL_INITIAL (decl1) = error_mark_node;
+ /* A nested function is not global. */
+ if (current_function_decl != 0)
+ TREE_PUBLIC (decl1) = 0;
+
/* If this definition isn't a prototype and we had a prototype declaration
before, copy the arg type info from that prototype. */
old_decl = lookup_name_in_scope (DECL_NAME (decl1), current_scope);
(This does not mean `static' in the C sense!) */
TREE_STATIC (decl1) = 1;
- /* A nested function is not global. */
- if (current_function_decl != 0)
- TREE_PUBLIC (decl1) = 0;
-
/* 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. */
gcc_assert (!DECL_ASSEMBLER_NAME_SET_P (decl1));
DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl))
bind (DECL_NAME (decl), decl, current_scope,
- /*invisible=*/false, /*nested=*/false, UNKNOWN_LOCATION);
+ /*invisible=*/false,
+ /*nested=*/(TREE_CODE (decl) == FUNCTION_DECL),
+ UNKNOWN_LOCATION);
}
/* And all the tag declarations. */
thus won't naturally see the SAVE_EXPR containing the increment. All
other pending sizes would be handled by gimplify_parameters. */
{
+ VEC(tree,gc) *pending_sizes = get_pending_sizes ();
tree t;
- for (t = nreverse (get_pending_sizes ()); t ; t = TREE_CHAIN (t))
- add_stmt (TREE_VALUE (t));
+ int i;
+
+ for (i = 0; VEC_iterate (tree, pending_sizes, i, t); i++)
+ add_stmt (t);
}
/* Even though we're inside a function body, we still don't want to
TREE_NO_WARNING (fndecl) = 1;
}
+ /* Complain about parameters that are only set, but never otherwise used. */
+ if (warn_unused_but_set_parameter)
+ {
+ tree decl;
+
+ for (decl = DECL_ARGUMENTS (fndecl);
+ decl;
+ decl = TREE_CHAIN (decl))
+ if (TREE_USED (decl)
+ && TREE_CODE (decl) == PARM_DECL
+ && !DECL_READ_P (decl)
+ && DECL_NAME (decl)
+ && !DECL_ARTIFICIAL (decl)
+ && !TREE_NO_WARNING (decl))
+ warning_at (DECL_SOURCE_LOCATION (decl),
+ OPT_Wunused_but_set_parameter,
+ "parameter %qD set but not used", decl);
+ }
+
/* Store the end of the function, so that we get good line number
info for the epilogue. */
cfun->function_end_locus = input_location;