#include "config.h"
#include "system.h"
#include "intl.h"
#include "tree.h"
#include "tree-inline.h"
#include "rtl.h"
#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 "debug.h"
#include "timevar.h"
#include "c-common.h"
#include "c-pragma.h"
#include "hashtab.h"
#include "genindex.h"
#ifdef ENABLE_DMP_TREE
#include "dmp-tree.h"
extern int c_dump_tree_p PARAMS ((FILE *, const char *, tree, int));
extern lang_dump_tree_p_t c_prev_lang_dump_tree_p;
#endif
enum decl_context
{ NORMAL,
FUNCDEF,
PARM,
FIELD,
BITFIELD,
TYPENAME};
tree pending_invalid_xref;
const char *pending_invalid_xref_file;
int pending_invalid_xref_line;
static tree enum_next_value;
static int enum_overflow;
static tree last_function_parms;
static tree last_function_parm_tags;
static tree current_function_parms;
static tree current_function_parm_tags;
static const char *current_function_prototype_file;
static int current_function_prototype_line;
static GTY(()) struct stmt_tree_s c_stmt_tree;
static GTY(()) tree c_scope_stmt_stack;
static GTY(()) tree named_labels;
static GTY(()) tree shadowed_labels;
int current_function_returns_value;
int current_function_returns_null;
int current_function_returns_abnormally;
static int warn_about_return_type;
static int current_extern_inline;
struct binding_level GTY(())
{
tree names;
tree tags_list;
htab_t GTY ((param_is (union tree_node))) tags_ht;
tree shadowed;
tree blocks;
tree this_block;
struct binding_level *level_chain;
char parm_flag;
char tag_transparent;
char subblocks_tag_transparent;
char keep;
char keep_if_subblocks;
tree incomplete_list;
tree parm_order;
};
#define NULL_BINDING_LEVEL (struct binding_level *) NULL
static GTY(()) struct binding_level *current_binding_level;
static GTY((deletable (""))) struct binding_level *free_binding_level;
static GTY(()) struct binding_level *global_binding_level;
static struct binding_level clear_binding_level
= {NULL, NULL, NULL, NULL, NULL, NULL, NULL_BINDING_LEVEL, 0, 0, 0, 0, 0, NULL,
NULL};
static int keep_next_level_flag;
static int keep_next_if_subblocks;
static GTY(()) struct binding_level *label_level_chain;
tree static_ctors, static_dtors;
static struct binding_level * make_binding_level PARAMS ((void));
static void pop_binding_level PARAMS ((struct binding_level **));
static void clear_limbo_values PARAMS ((tree));
static int duplicate_decls PARAMS ((tree, tree, int));
static int redeclaration_error_message PARAMS ((tree, tree));
static void storedecls PARAMS ((tree));
static void storetags PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
struct binding_level *, int));
static tree lookup_tag_reverse PARAMS ((tree));
static tree grokdeclarator PARAMS ((tree, tree, enum decl_context,
int));
static tree grokparms PARAMS ((tree, int));
static void layout_array_type PARAMS ((tree));
static tree c_make_fname_decl PARAMS ((tree, int));
static void c_expand_body PARAMS ((tree, int, int));
static void warn_if_shadowing PARAMS ((tree, tree));
static bool flexible_array_type_p PARAMS ((tree));
static int check_for_loop_tags PARAMS ((PTR *, PTR));
static int set_type_context_value PARAMS ((PTR *, PTR));
static int tags_ht_eq_pointer PARAMS ((const PTR, const PTR));
static hashval_t tags_ht_hash_pointer PARAMS ((const PTR));
static PTR check_tree_value PARAMS ((PTR *, PTR));
PTR htab_traverse_1 PARAMS ((htab_t, htab_trav, PTR));
static htab_t create_tags_ht PARAMS ((void));
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
, DEPRECATED_UNAVAILABLE_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
static htab_t
create_tags_ht ()
{
return htab_create_ggc (11, tags_ht_hash_pointer, tags_ht_eq_pointer, NULL);
}
static int
tags_ht_eq_pointer (p1, p2)
const PTR p1;
const PTR p2;
{
tree t1 = (tree) p1;
tree t2 = (tree) p2;
if (t1 && TREE_PURPOSE (t1))
return TREE_PURPOSE (t1) == t2;
else
return 0;
}
static hashval_t
tags_ht_hash_pointer (p)
const PTR p;
{
hashval_t hash = 0;
unsigned int n = 0;
unsigned int r = 0;
const unsigned char *str;
tree t = (tree) p;
if (t && (TREE_CODE (t) == TREE_LIST) && TREE_PURPOSE (t))
{
t = TREE_PURPOSE (t);
}
if (t && (TREE_CODE (t) == IDENTIFIER_NODE))
{
#define TAGS_HT_HASHSTEP(r, c) ((r) * 67 + ((c) - 113));
n = IDENTIFIER_LENGTH (t);
str = IDENTIFIER_POINTER (t);
while (n--)
r = TAGS_HT_HASHSTEP (r, *str++);
hash = (hashval_t) (r + IDENTIFIER_LENGTH (t));
#undef TAGS_HT_HASHSTEP
}
else
hash = (hashval_t) ((long)p >> 3);
return hash;
}
static void
print_tags_ht_hash_statistics ()
{
fprintf (stderr, "Type hash: size %ld, %ld elements, %f collisions\n",
(long) htab_size (current_binding_level->tags_ht),
(long) htab_elements (current_binding_level->tags_ht),
htab_collisions (current_binding_level->tags_ht));
}
void
c_print_identifier (file, node, indent)
FILE *file;
tree node;
int indent;
{
print_node (file, "global", IDENTIFIER_GLOBAL_VALUE (node), indent + 4);
print_node (file, "local", IDENTIFIER_LOCAL_VALUE (node), indent + 4);
print_node (file, "label", IDENTIFIER_LABEL_VALUE (node), indent + 4);
print_node (file, "implicit", IDENTIFIER_IMPLICIT_DECL (node), indent + 4);
print_node (file, "error locus", IDENTIFIER_ERROR_LOCUS (node), indent + 4);
print_node (file, "limbo value", IDENTIFIER_LIMBO_VALUE (node), indent + 4);
if (C_IS_RESERVED_WORD (node))
{
tree rid = ridpointers[C_RID_CODE (node)];
indent_to (file, indent + 4);
fprintf (file, "rid ");
fprintf (file, HOST_PTR_PRINTF, (void *)rid);
fprintf (file, " \"%s\"", IDENTIFIER_POINTER (rid));
}
}
void
c_finish_incomplete_decl (decl)
tree decl;
{
if (TREE_CODE (decl) == VAR_DECL)
{
tree type = TREE_TYPE (decl);
if (type != error_mark_node
&& TREE_CODE (type) == ARRAY_TYPE
&& ! DECL_EXTERNAL (decl)
&& TYPE_DOMAIN (type) == 0)
{
warning_with_decl (decl, "array `%s' assumed to have one element");
complete_array_type (type, NULL_TREE, 1);
layout_decl (decl, 0);
}
}
}
static struct binding_level *
make_binding_level ()
{
if (free_binding_level)
{
struct binding_level *result = free_binding_level;
free_binding_level = result->level_chain;
return result;
}
else
return (struct binding_level *) ggc_alloc (sizeof (struct binding_level));
}
static void
pop_binding_level (lp)
struct binding_level **lp;
{
struct binding_level *l = *lp;
*lp = l->level_chain;
l->tags_ht = NULL;
memset (l, 0, sizeof (struct binding_level));
l->level_chain = free_binding_level;
free_binding_level = l;
}
struct binding_level *
get_current_binding_level ()
{
return current_binding_level;
}
void
objc_mark_locals_volatile (enclosing_blk)
void *enclosing_blk;
{
struct binding_level *scope;
for (scope = current_binding_level;
scope && scope != enclosing_blk && !scope->parm_flag;
scope = scope->level_chain)
{
tree decl;
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
{
DECL_REGISTER (decl) = 0;
TREE_THIS_VOLATILE (decl) = 1;
}
}
}
int
global_bindings_p ()
{
return current_binding_level == global_binding_level;
}
void
keep_next_level ()
{
keep_next_level_flag = 1;
}
int
kept_level_p ()
{
return ((current_binding_level->keep_if_subblocks
&& current_binding_level->blocks != 0)
|| current_binding_level->keep
|| current_binding_level->names != 0
|| (current_binding_level->tags_ht != 0
&& !current_binding_level->tag_transparent));
}
void
declare_parm_level (definition_flag)
int definition_flag ATTRIBUTE_UNUSED;
{
current_binding_level->parm_flag = 1;
}
int
in_parm_level_p ()
{
return current_binding_level->parm_flag;
}
void
pushlevel (tag_transparent)
int tag_transparent;
{
struct binding_level *newlevel = NULL_BINDING_LEVEL;
if (current_binding_level == global_binding_level)
{
named_labels = 0;
}
newlevel = make_binding_level ();
*newlevel = clear_binding_level;
newlevel->tag_transparent
= (tag_transparent
|| (current_binding_level
? current_binding_level->subblocks_tag_transparent
: 0));
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->keep = keep_next_level_flag;
keep_next_level_flag = 0;
newlevel->keep_if_subblocks = keep_next_if_subblocks;
keep_next_if_subblocks = 0;
}
static void
clear_limbo_values (block)
tree block;
{
tree tem;
for (tem = BLOCK_VARS (block); tem; tem = TREE_CHAIN (tem))
if (DECL_NAME (tem) != 0)
IDENTIFIER_LIMBO_VALUE (DECL_NAME (tem)) = 0;
for (tem = BLOCK_SUBBLOCKS (block); tem; tem = TREE_CHAIN (tem))
clear_limbo_values (tem);
}
static int
set_type_context_value (slot, data)
PTR *slot;
PTR data;
{
tree t = (tree) *slot;
TYPE_CONTEXT (TREE_VALUE (t)) = (tree) data;
return 1;
}
tree
poplevel (keep, reverse, functionbody)
int keep;
int reverse;
int functionbody;
{
tree link;
tree decls;
tree subblocks = current_binding_level->blocks;
tree block = 0;
tree decl;
int block_previously_created;
keep |= current_binding_level->keep;
#if 0
for (link = tags; link; link = TREE_CHAIN (link))
if (!COMPLETE_TYPE_P (TREE_VALUE (link)))
{
tree type = TREE_VALUE (link);
tree type_name = TYPE_NAME (type);
char *id = IDENTIFIER_POINTER (TREE_CODE (type_name) == IDENTIFIER_NODE
? type_name
: DECL_NAME (type_name));
switch (TREE_CODE (type))
{
case RECORD_TYPE:
error ("`struct %s' incomplete in scope ending here", id);
break;
case UNION_TYPE:
error ("`union %s' incomplete in scope ending here", id);
break;
case ENUMERAL_TYPE:
error ("`enum %s' incomplete in scope ending here", id);
break;
}
}
#endif
if (reverse)
current_binding_level->names
= decls = nreverse (current_binding_level->names);
else
decls = current_binding_level->names;
for (decl = decls; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (decl)
&& DECL_INITIAL (decl) != 0
&& TREE_ADDRESSABLE (decl))
{
if (DECL_ABSTRACT_ORIGIN (decl) != 0
&& DECL_ABSTRACT_ORIGIN (decl) != decl)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
}
warn_about_unused_variables (getdecls ());
block = 0;
block_previously_created = (current_binding_level->this_block != 0);
if (block_previously_created)
block = current_binding_level->this_block;
else if (keep || functionbody
|| (current_binding_level->keep_if_subblocks && subblocks != 0))
block = make_node (BLOCK);
if (block != 0)
{
BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks;
}
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
for (link = decls; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != 0)
{
if (DECL_EXTERNAL (link))
{
if (TREE_USED (link))
TREE_USED (DECL_NAME (link)) = 1;
if (TREE_ADDRESSABLE (link))
TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (link)) = 1;
}
IDENTIFIER_LOCAL_VALUE (DECL_NAME (link)) = 0;
}
}
for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
if (functionbody)
{
clear_limbo_values (block);
BLOCK_VARS (block) = 0;
for (link = named_labels; link; link = TREE_CHAIN (link))
{
tree label = TREE_VALUE (link);
if (DECL_INITIAL (label) == 0)
{
error_with_decl (label, "label `%s' used but not defined");
define_label (input_filename, lineno,
DECL_NAME (label));
}
else if (warn_unused_label && !TREE_USED (label))
warning_with_decl (label, "label `%s' defined but not used");
IDENTIFIER_LABEL_VALUE (DECL_NAME (label)) = 0;
TREE_CHAIN (label) = BLOCK_VARS (block);
BLOCK_VARS (block) = label;
}
}
if (functionbody && current_binding_level->tags_ht)
htab_traverse (current_binding_level->tags_ht,
set_type_context_value,
current_function_decl);
else if (block && current_binding_level->tags_ht)
htab_traverse (current_binding_level->tags_ht,
set_type_context_value,
block);
pop_binding_level (¤t_binding_level);
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block)
{
if (!block_previously_created)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
if (block)
TREE_USED (block) = 1;
return block;
}
void
insert_block (block)
tree block;
{
TREE_USED (block) = 1;
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
void
set_block (block)
tree block;
{
current_binding_level->this_block = block;
current_binding_level->names = chainon (current_binding_level->names,
BLOCK_VARS (block));
current_binding_level->blocks = chainon (current_binding_level->blocks,
BLOCK_SUBBLOCKS (block));
}
void
push_label_level ()
{
struct binding_level *newlevel;
newlevel = make_binding_level ();
newlevel->level_chain = label_level_chain;
label_level_chain = newlevel;
newlevel->names = named_labels;
newlevel->shadowed = shadowed_labels;
named_labels = 0;
shadowed_labels = 0;
}
void
pop_label_level ()
{
struct binding_level *level = label_level_chain;
tree link, prev;
for (link = named_labels, prev = 0; link;)
{
if (C_DECLARED_LABEL_FLAG (TREE_VALUE (link)))
{
if (DECL_SOURCE_LINE (TREE_VALUE (link)) == 0)
{
error_with_decl (TREE_VALUE (link),
"label `%s' used but not defined");
define_label (input_filename, lineno,
DECL_NAME (TREE_VALUE (link)));
}
else if (warn_unused_label && !TREE_USED (TREE_VALUE (link)))
warning_with_decl (TREE_VALUE (link),
"label `%s' defined but not used");
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link))) = 0;
link = TREE_CHAIN (link);
if (prev)
TREE_CHAIN (prev) = link;
else
named_labels = link;
}
else
{
prev = link;
link = TREE_CHAIN (link);
}
}
for (link = shadowed_labels; link; link = TREE_CHAIN (link))
if (DECL_NAME (TREE_VALUE (link)) != 0)
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
named_labels = chainon (named_labels, level->names);
shadowed_labels = level->shadowed;
pop_binding_level (&label_level_chain);
}
void
pushtag (name, type)
tree name, type;
{
struct binding_level *b;
for (b = current_binding_level; b->tag_transparent; b = b->level_chain)
continue;
if (name)
{
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = name;
}
b->tags_list = tree_cons (name, type, b->tags_list);
if (!b->tags_ht)
b->tags_ht = create_tags_ht ();
if (b->tags_ht && name)
{
void **slot;
slot = htab_find_slot (b->tags_ht, name, INSERT);
*slot = tree_cons (name, type, NULL);
}
TYPE_STUB_DECL (type) = pushdecl (build_decl (TYPE_DECL, NULL_TREE, type));
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
static int
duplicate_decls (newdecl, olddecl, different_binding_level)
tree newdecl, olddecl;
int different_binding_level;
{
int types_match = comptypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
int new_is_definition = (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_INITIAL (newdecl) != 0);
tree oldtype = TREE_TYPE (olddecl);
tree newtype = TREE_TYPE (newdecl);
int errmsg = 0;
if (DECL_P (olddecl))
{
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared as inline");
warning_with_decl (olddecl,
"previous declaration of function `%s' with attribute noinline");
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared with attribute noinline");
warning_with_decl (olddecl,
"previous declaration of function `%s' was inline");
}
}
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
}
if (TREE_CODE (newtype) == ERROR_MARK
|| TREE_CODE (oldtype) == ERROR_MARK)
types_match = 0;
if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl)
|| DECL_BUILT_IN_NONANSI (olddecl)))
{
if (!TREE_PUBLIC (newdecl))
{
if (!warn_shadow)
;
else if (DECL_BUILT_IN (olddecl))
warning_with_decl (newdecl, "shadowing built-in function `%s'");
else
warning_with_decl (newdecl, "shadowing library function `%s'");
}
else if (! DECL_BUILT_IN (olddecl))
warning_with_decl (newdecl,
"library function `%s' declared as non-function");
else if (DECL_BUILT_IN_NONANSI (olddecl))
warning_with_decl (newdecl,
"built-in function `%s' declared as non-function");
else
warning_with_decl (newdecl,
"built-in function `%s' declared as non-function");
}
else
{
error_with_decl (newdecl, "`%s' redeclared as different kind of symbol");
error_with_decl (olddecl, "previous declaration of `%s'");
}
return 0;
}
if (types_match && TREE_CODE (newdecl) == PARM_DECL
&& TREE_ASM_WRITTEN (olddecl) && ! TREE_ASM_WRITTEN (newdecl))
return 1;
if (TREE_CODE (olddecl) == FUNCTION_DECL && DECL_BUILT_IN (olddecl))
{
if (!TREE_PUBLIC (newdecl))
{
if (warn_shadow)
warning_with_decl (newdecl, "shadowing built-in function `%s'");
return 0;
}
else if (!types_match)
{
tree oldreturntype = TREE_TYPE (oldtype);
tree newreturntype = TREE_TYPE (newtype);
if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
{
tree trytype
= build_function_type (newreturntype,
TYPE_ARG_TYPES (oldtype));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0
&& TYPE_ARG_TYPES (oldtype) != 0
&& TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0
&& TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0
&& (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype)))
== TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype)))))
{
tree trytype
= build_function_type (TREE_TYPE (oldtype),
tree_cons (NULL_TREE,
TREE_VALUE (TYPE_ARG_TYPES (newtype)),
TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
types_match = comptypes (newtype, trytype);
if (types_match)
oldtype = trytype;
}
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
}
else if (TYPE_ARG_TYPES (oldtype) == NULL
&& TYPE_ARG_TYPES (newtype) != NULL)
{
tree trytype
= build_function_type (TREE_TYPE (oldtype),
TYPE_ARG_TYPES (newtype));
trytype = build_type_attribute_variant (trytype,
TYPE_ATTRIBUTES (oldtype));
oldtype = trytype;
if (! different_binding_level)
TREE_TYPE (olddecl) = oldtype;
}
if (!types_match)
{
warning_with_decl (newdecl, "conflicting types for built-in function `%s'");
return 0;
}
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_SOURCE_LINE (olddecl) == 0)
{
if (!TREE_PUBLIC (newdecl))
{
return 0;
}
else if (!types_match)
{
TREE_THIS_VOLATILE (newdecl) |= TREE_THIS_VOLATILE (olddecl);
}
}
else if (!types_match
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (TREE_TYPE (oldtype)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (newtype)) == POINTER_TYPE
&& (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl))
&& ((TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (newtype))) == void_type_node
&& TYPE_ARG_TYPES (oldtype) == 0
&& self_promoting_args_p (TYPE_ARG_TYPES (newtype))
&& TREE_TYPE (TREE_TYPE (oldtype)) == char_type_node)
||
(TREE_TYPE (TREE_TYPE (newtype)) == char_type_node
&& TYPE_ARG_TYPES (newtype) == 0
&& self_promoting_args_p (TYPE_ARG_TYPES (oldtype))
&& TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node)))
{
if (pedantic)
pedwarn_with_decl (newdecl, "conflicting types for `%s'");
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (oldtype))) == void_type_node)
TREE_TYPE (newdecl) = newtype = oldtype;
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
}
else if (!types_match
&& ! (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! pedantic
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype))
&& TYPE_ARG_TYPES (newtype) == 0))
{
error_with_decl (newdecl, "conflicting types for `%s'");
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& comptypes (TREE_TYPE (oldtype),
TREE_TYPE (newtype))
&& ((TYPE_ARG_TYPES (oldtype) == 0
&& DECL_INITIAL (olddecl) == 0)
||
(TYPE_ARG_TYPES (newtype) == 0
&& DECL_INITIAL (newdecl) == 0)))
{
tree t = TYPE_ARG_TYPES (oldtype);
if (t == 0)
t = TYPE_ARG_TYPES (newtype);
for (; t; t = TREE_CHAIN (t))
{
tree type = TREE_VALUE (t);
if (TREE_CHAIN (t) == 0
&& TYPE_MAIN_VARIANT (type) != void_type_node)
{
error ("a parameter list with an ellipsis can't match an empty parameter name list declaration");
break;
}
if (c_type_promotes_to (type) != type)
{
error ("an argument type that has a default promotion can't match an empty parameter name list declaration");
break;
}
}
}
error_with_decl (olddecl, "previous declaration of `%s'");
DECL_INITIAL (newdecl) = 0;
}
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
&& !DECL_THREAD_LOCAL (olddecl) && DECL_THREAD_LOCAL (newdecl))
{
error_with_decl (newdecl, "thread-local declaration of `%s' follows non thread-local declaration");
error_with_decl (olddecl, "previous declaration of `%s'");
}
else if (TREE_CODE (olddecl) == VAR_DECL && TREE_CODE (newdecl) == VAR_DECL
&& DECL_THREAD_LOCAL (olddecl) && !DECL_THREAD_LOCAL (newdecl))
{
error_with_decl (newdecl, "non thread-local declaration of `%s' follows thread-local declaration");
error_with_decl (olddecl, "previous declaration of `%s'");
}
else
{
errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
switch (errmsg)
{
case 1:
error_with_decl (newdecl, "redefinition of `%s'");
break;
case 2:
error_with_decl (newdecl, "redeclaration of `%s'");
break;
case 3:
error_with_decl (newdecl, "conflicting declarations of `%s'");
break;
default:
abort ();
}
error_with_decl (olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
? "`%s' previously defined here"
: "`%s' previously declared here"));
return 0;
}
else if (TREE_CODE (newdecl) == TYPE_DECL
&& (DECL_IN_SYSTEM_HEADER (olddecl)
|| DECL_IN_SYSTEM_HEADER (newdecl)))
{
warning_with_decl (newdecl, "redefinition of `%s'");
warning_with_decl
(olddecl,
((DECL_INITIAL (olddecl)
&& current_binding_level == global_binding_level)
? "`%s' previously defined here"
: "`%s' previously declared here"));
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != 0
&& TYPE_ARG_TYPES (oldtype) == 0
&& TYPE_ARG_TYPES (newtype) != 0
&& TYPE_ACTUAL_ARG_TYPES (oldtype) != 0)
{
tree type, parm;
int nargs;
for (parm = TYPE_ACTUAL_ARG_TYPES (oldtype),
type = TYPE_ARG_TYPES (newtype),
nargs = 1;
;
parm = TREE_CHAIN (parm), type = TREE_CHAIN (type), nargs++)
{
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
&& TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
warning_with_decl (newdecl, "prototype for `%s' follows");
warning_with_decl (olddecl, "non-prototype definition here");
break;
}
if (TYPE_MAIN_VARIANT (TREE_VALUE (parm)) == void_type_node
|| TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
error_with_decl (newdecl,
"prototype for `%s' follows and number of arguments doesn't match");
error_with_decl (olddecl, "non-prototype definition here");
errmsg = 1;
break;
}
if (! comptypes (TREE_VALUE (parm), TREE_VALUE (type)))
{
error_with_decl (newdecl,
"prototype for `%s' follows and argument %d doesn't match",
nargs);
error_with_decl (olddecl, "non-prototype definition here");
errmsg = 1;
break;
}
}
}
else
{
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& TREE_USED (olddecl))
warning_with_decl (newdecl,
"`%s' declared inline after being called");
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning_with_decl (newdecl,
"`%s' declared inline after its definition");
if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
&& TREE_PUBLIC (olddecl)
&& !TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "static declaration for `%s' follows non-static");
if (warn_traditional && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
warning_with_decl (newdecl, "non-static declaration for `%s' follows static");
if (TREE_CODE (olddecl) != FUNCTION_DECL
&& !TREE_READONLY (olddecl)
&& TREE_READONLY (newdecl))
warning_with_decl (newdecl, "const declaration for `%s' follows non-const");
else if (pedantic && TREE_CODE (olddecl) != FUNCTION_DECL
&& (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
pedwarn_with_decl (newdecl, "type qualifiers for `%s' conflict with previous decl");
}
}
if (errmsg == 0 && warn_redundant_decls && DECL_SOURCE_LINE (olddecl) != 0
&& !(TREE_CODE (newdecl) == FUNCTION_DECL && DECL_INITIAL (newdecl) != 0
&& DECL_INITIAL (olddecl) == 0)
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl)))
{
warning_with_decl (newdecl, "redundant redeclaration of `%s' in same scope");
warning_with_decl (olddecl, "previous declaration of `%s'");
}
if (types_match)
{
tree write_olddecl = different_binding_level ? newdecl : olddecl;
if (TREE_CODE (newdecl) != FUNCTION_DECL || !DECL_BUILT_IN (olddecl))
{
if (different_binding_level)
{
if (TYPE_ARG_TYPES (oldtype) != 0
&& TYPE_ARG_TYPES (newtype) == 0)
TREE_TYPE (newdecl) = common_type (newtype, oldtype);
else
TREE_TYPE (newdecl)
= build_type_attribute_variant
(newtype,
merge_attributes (TYPE_ATTRIBUTES (newtype),
TYPE_ATTRIBUTES (oldtype)));
}
else
TREE_TYPE (newdecl)
= TREE_TYPE (olddecl)
= common_type (newtype, oldtype);
}
if (oldtype != TREE_TYPE (newdecl))
{
if (TREE_TYPE (newdecl) != error_mark_node)
layout_type (TREE_TYPE (newdecl));
if (TREE_CODE (newdecl) != FUNCTION_DECL
&& TREE_CODE (newdecl) != TYPE_DECL
&& TREE_CODE (newdecl) != CONST_DECL)
layout_decl (newdecl, 0);
}
else
{
DECL_SIZE (newdecl) = DECL_SIZE (olddecl);
DECL_SIZE_UNIT (newdecl) = DECL_SIZE_UNIT (olddecl);
DECL_MODE (newdecl) = DECL_MODE (olddecl);
if (TREE_CODE (olddecl) != FUNCTION_DECL)
if (DECL_ALIGN (olddecl) > DECL_ALIGN (newdecl))
{
DECL_ALIGN (newdecl) = DECL_ALIGN (olddecl);
DECL_USER_ALIGN (newdecl) |= DECL_ALIGN (olddecl);
}
}
COPY_DECL_RTL (olddecl, newdecl);
if (TREE_READONLY (newdecl))
TREE_READONLY (write_olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
{
TREE_THIS_VOLATILE (write_olddecl) = 1;
if (TREE_CODE (newdecl) == VAR_DECL
&& errmsg == 0)
make_var_volatile (newdecl);
}
if (DECL_INITIAL (newdecl) == 0 && DECL_INITIAL (olddecl) != 0
&& ! different_binding_level)
{
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
}
if (DECL_IN_SYSTEM_HEADER (olddecl))
DECL_IN_SYSTEM_HEADER (newdecl) = 1;
else if (DECL_IN_SYSTEM_HEADER (newdecl))
DECL_IN_SYSTEM_HEADER (write_olddecl) = 1;
if (DECL_INITIAL (newdecl) == 0 && ! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_STATIC_CONSTRUCTOR(newdecl) |= DECL_STATIC_CONSTRUCTOR(olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_NO_LIMIT_STACK (newdecl) |= DECL_NO_LIMIT_STACK (olddecl);
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
}
if (DECL_WEAK_IMPORT (olddecl) != DECL_WEAK_IMPORT (newdecl))
{
if (! DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
warning_with_decl (newdecl,
"inconsistent weak_import attribute with previous declaration of `%s'");
DECL_WEAK_IMPORT (newdecl) = 1;
}
}
else if (! different_binding_level)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
TREE_READONLY (olddecl) = TREE_READONLY (newdecl);
TREE_THIS_VOLATILE (olddecl) = TREE_THIS_VOLATILE (newdecl);
TREE_SIDE_EFFECTS (olddecl) = TREE_SIDE_EFFECTS (newdecl);
}
merge_weak (newdecl, olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
TREE_PUBLIC (newdecl) &= TREE_PUBLIC (olddecl);
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
if (! TREE_PUBLIC (olddecl))
TREE_PUBLIC (DECL_NAME (olddecl)) = 0;
}
if (DECL_EXTERNAL (newdecl))
{
if (! different_binding_level)
{
TREE_STATIC (newdecl) = TREE_STATIC (olddecl);
DECL_EXTERNAL (newdecl) = DECL_EXTERNAL (olddecl);
}
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
if (! DECL_EXTERNAL (newdecl))
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
}
else
{
TREE_STATIC (olddecl) = TREE_STATIC (newdecl);
TREE_PUBLIC (olddecl) = TREE_PUBLIC (newdecl);
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (new_is_definition && DECL_INITIAL (olddecl))
{
if (TREE_USED (olddecl))
(*debug_hooks->outlining_inline_function) (olddecl);
DECL_INLINE (newdecl) = 0;
DECL_UNINLINABLE (newdecl) = 1;
}
else
{
if (DECL_DECLARED_INLINE_P (newdecl)
|| DECL_DECLARED_INLINE_P (olddecl))
DECL_DECLARED_INLINE_P (newdecl) = 1;
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
if (DECL_BUILT_IN (olddecl))
{
if (! types_match || new_is_definition)
{
if (! different_binding_level)
{
TREE_TYPE (olddecl) = TREE_TYPE (newdecl);
DECL_BUILT_IN_CLASS (olddecl) = NOT_BUILT_IN;
}
}
else
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
}
}
if (! new_is_definition)
{
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if (! different_binding_level)
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl);
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
if (DECL_INLINE (olddecl) && ! DECL_UNINLINABLE (newdecl))
{
DECL_INLINE (newdecl) = 1;
DECL_ABSTRACT_ORIGIN (newdecl)
= (different_binding_level
? DECL_ORIGIN (olddecl)
: DECL_ABSTRACT_ORIGIN (olddecl));
}
}
else
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_UNINLINABLE (newdecl))
DECL_INLINE (newdecl) = 1;
}
}
if (different_binding_level)
return 0;
{
unsigned olddecl_uid = DECL_UID (olddecl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common));
DECL_UID (olddecl) = olddecl_uid;
}
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
static void
warn_if_shadowing (x, oldlocal)
tree x, oldlocal;
{
tree name;
if (DECL_EXTERNAL (x))
return;
name = DECL_NAME (x);
if (oldlocal != 0
&& ! current_binding_level->parm_flag
&& current_binding_level->level_chain->parm_flag
&& chain_member (oldlocal, current_binding_level->level_chain->names))
{
if (TREE_CODE (oldlocal) == PARM_DECL)
pedwarn ("declaration of `%s' shadows a parameter",
IDENTIFIER_POINTER (name));
else
pedwarn ("declaration of `%s' shadows a symbol from the parameter list",
IDENTIFIER_POINTER (name));
}
else if (warn_shadow
&& DECL_SOURCE_LINE (x) != 0
&& ! DECL_FROM_INLINE (x))
{
if (TREE_CODE (x) == PARM_DECL
&& current_binding_level->level_chain->parm_flag)
;
else if (oldlocal)
{
if (TREE_CODE (oldlocal) == PARM_DECL)
shadow_warning ("a parameter", name, oldlocal);
else
shadow_warning ("a previous local", name, oldlocal);
}
else if (IDENTIFIER_GLOBAL_VALUE (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) != error_mark_node)
shadow_warning ("a global declaration", name,
IDENTIFIER_GLOBAL_VALUE (name));
}
}
tree
pushdecl (x)
tree x;
{
tree t;
tree name = DECL_NAME (x);
struct binding_level *b = current_binding_level;
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_LANG_SPECIFIC (x))
DECL_LANG_SPECIFIC (x) = (struct lang_decl *)
ggc_alloc_cleared (sizeof (struct lang_decl));
DECL_CONTEXT (x) = current_function_decl;
if ((TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
&& DECL_INITIAL (x) == 0 && DECL_EXTERNAL (x))
DECL_CONTEXT (x) = 0;
if (name)
{
int different_binding_level = 0;
if (warn_nested_externs
&& DECL_EXTERNAL (x)
&& b != global_binding_level
&& x != IDENTIFIER_IMPLICIT_DECL (name)
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of `%s'",
IDENTIFIER_POINTER (name));
t = lookup_name_current_level (name);
if (! t && DECL_EXTERNAL (x) && TREE_PUBLIC (x))
{
t = IDENTIFIER_GLOBAL_VALUE (name);
if (! t || TREE_CODE (t) == TYPE_DECL)
t = IDENTIFIER_LIMBO_VALUE (name);
different_binding_level = 1;
}
if (t != 0 && t == error_mark_node)
{
t = 0;
error_with_decl (x, "`%s' used prior to declaration");
}
if (TREE_PUBLIC (name)
&& ! TREE_PUBLIC (x)
&& (TREE_CODE (x) == FUNCTION_DECL || b == global_binding_level)
&& IDENTIFIER_IMPLICIT_DECL (name) != 0)
{
pedwarn ("`%s' was declared implicitly `extern' and later `static'",
IDENTIFIER_POINTER (name));
pedwarn_with_file_and_line
(DECL_SOURCE_FILE (IDENTIFIER_IMPLICIT_DECL (name)),
DECL_SOURCE_LINE (IDENTIFIER_IMPLICIT_DECL (name)),
"previous declaration of `%s'",
IDENTIFIER_POINTER (name));
TREE_THIS_VOLATILE (name) = 1;
}
if (t != 0 && duplicate_decls (x, t, different_binding_level))
{
if (TREE_CODE (t) == PARM_DECL)
{
TREE_ASM_WRITTEN (t) = TREE_ASM_WRITTEN (x);
return t;
}
return t;
}
if (TREE_CODE (x) == TYPE_DECL)
{
if (DECL_SOURCE_LINE (x) == 0)
{
if (TYPE_NAME (TREE_TYPE (x)) == 0)
TYPE_NAME (TREE_TYPE (x)) = x;
}
else if (TREE_TYPE (x) != error_mark_node
&& DECL_ORIGINAL_TYPE (x) == NULL_TREE)
{
tree tt = TREE_TYPE (x);
DECL_ORIGINAL_TYPE (x) = tt;
tt = build_type_copy (tt);
TYPE_NAME (tt) = x;
TREE_USED (tt) = TREE_USED (x);
TREE_TYPE (x) = tt;
}
}
if (TREE_PUBLIC (x)
&& ! (TREE_CODE (x) == FUNCTION_DECL && DECL_INLINE (x)))
{
tree decl;
if (IDENTIFIER_LIMBO_VALUE (name) != 0)
decl = IDENTIFIER_LIMBO_VALUE (name);
else
decl = 0;
if (decl && ! comptypes (TREE_TYPE (x), TREE_TYPE (decl))
&& !DECL_BUILT_IN (decl))
{
pedwarn_with_decl (x,
"type mismatch with previous external decl");
pedwarn_with_decl (decl, "previous external decl of `%s'");
}
}
if (IDENTIFIER_IMPLICIT_DECL (name) != 0
&& IDENTIFIER_GLOBAL_VALUE (name) == 0
&& TREE_CODE (x) == FUNCTION_DECL
&& ! comptypes (TREE_TYPE (x),
TREE_TYPE (IDENTIFIER_IMPLICIT_DECL (name))))
{
warning_with_decl (x, "type mismatch with previous implicit declaration");
warning_with_decl (IDENTIFIER_IMPLICIT_DECL (name),
"previous implicit declaration of `%s'");
}
if (b == global_binding_level)
{
if (IDENTIFIER_GLOBAL_VALUE (name) == 0 && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
IDENTIFIER_GLOBAL_VALUE (name) = x;
IDENTIFIER_LIMBO_VALUE (name) = 0;
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_USED (x) = 1, TREE_USED (name) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_ADDRESSABLE (x) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name) != 0
&& ! (TREE_CODE (x) == FUNCTION_DECL
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (x)))
== integer_type_node)))
pedwarn ("`%s' was previously implicitly declared to return `int'",
IDENTIFIER_POINTER (name));
if (TREE_PUBLIC (name)
&& ! TREE_PUBLIC (x) && ! DECL_EXTERNAL (x))
{
if (t != 0 && DECL_BUILT_IN (t))
;
else if (t != 0 && DECL_BUILT_IN_NONANSI (t))
;
else if (TREE_CODE (x) == TYPE_DECL)
;
else if (IDENTIFIER_IMPLICIT_DECL (name))
{
if (! TREE_THIS_VOLATILE (name))
pedwarn ("`%s' was declared implicitly `extern' and later `static'",
IDENTIFIER_POINTER (name));
}
else
pedwarn ("`%s' was declared `extern' and later `static'",
IDENTIFIER_POINTER (name));
}
}
else
{
tree oldlocal = IDENTIFIER_LOCAL_VALUE (name);
tree oldglobal = IDENTIFIER_GLOBAL_VALUE (name);
IDENTIFIER_LOCAL_VALUE (name) = x;
if (oldlocal == 0
&& oldglobal != 0
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL
&& DECL_EXTERNAL (x)
&& ! DECL_DECLARED_INLINE_P (x))
{
if (! comptypes (TREE_TYPE (x),
TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (name))))
pedwarn_with_decl (x, "extern declaration of `%s' doesn't match global one");
else
{
if (DECL_DECLARED_INLINE_P (oldglobal))
{
DECL_DECLARED_INLINE_P (x)
= DECL_DECLARED_INLINE_P (oldglobal);
DECL_INLINE (x) = DECL_INLINE (oldglobal);
DECL_INITIAL (x) = (current_function_decl == oldglobal
? 0 : DECL_INITIAL (oldglobal));
DECL_SAVED_INSNS (x) = DECL_SAVED_INSNS (oldglobal);
DECL_NUM_STMTS (x) = DECL_NUM_STMTS (oldglobal);
DECL_ARGUMENTS (x) = DECL_ARGUMENTS (oldglobal);
DECL_RESULT (x) = DECL_RESULT (oldglobal);
TREE_ASM_WRITTEN (x) = TREE_ASM_WRITTEN (oldglobal);
DECL_ABSTRACT_ORIGIN (x)
= DECL_ABSTRACT_ORIGIN (oldglobal);
}
if (DECL_BUILT_IN (oldglobal))
{
DECL_BUILT_IN_CLASS (x) = DECL_BUILT_IN_CLASS (oldglobal);
DECL_FUNCTION_CODE (x) = DECL_FUNCTION_CODE (oldglobal);
}
if (TYPE_ARG_TYPES (TREE_TYPE (oldglobal)) != 0
&& DECL_INITIAL (oldglobal)
&& TYPE_ARG_TYPES (TREE_TYPE (x)) == 0)
TREE_TYPE (x) = TREE_TYPE (oldglobal);
}
}
#if 0
if (oldlocal == 0 && oldglobal != 0
&& !TREE_PUBLIC (oldglobal)
&& DECL_EXTERNAL (x) && TREE_PUBLIC (x))
warning ("`%s' locally external but globally static",
IDENTIFIER_POINTER (name));
#endif
if (oldlocal == 0
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
{
if (oldglobal == 0)
TREE_PUBLIC (name) = 1;
if (IDENTIFIER_LIMBO_VALUE (name) == 0)
IDENTIFIER_LIMBO_VALUE (name) = x;
}
warn_if_shadowing (x, oldlocal);
if (oldlocal != 0)
b->shadowed = tree_cons (name, oldlocal, b->shadowed);
}
if (TREE_TYPE (x) != error_mark_node
&& !COMPLETE_TYPE_P (TREE_TYPE (x)))
{
tree element = TREE_TYPE (x);
while (TREE_CODE (element) == ARRAY_TYPE)
element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_TYPE
|| TREE_CODE (element) == UNION_TYPE)
b->incomplete_list = tree_cons (NULL_TREE, x, b->incomplete_list);
}
}
TREE_CHAIN (x) = b->names;
b->names = x;
return x;
}
tree
pushdecl_top_level (x)
tree x;
{
tree t;
struct binding_level *b = current_binding_level;
current_binding_level = global_binding_level;
t = pushdecl (x);
current_binding_level = b;
return t;
}
tree
implicitly_declare (functionid)
tree functionid;
{
tree decl;
int traditional_warning = 0;
int implicit_warning;
#if 0
if (IDENTIFIER_IMPLICIT_DECL (functionid) != 0)
decl = IDENTIFIER_IMPLICIT_DECL (functionid);
else
#endif
decl = build_decl (FUNCTION_DECL, functionid, default_function_type);
if (TREE_PUBLIC (functionid) && IDENTIFIER_GLOBAL_VALUE (functionid) == 0)
traditional_warning = 1;
implicit_warning = (IDENTIFIER_IMPLICIT_DECL (functionid) == 0);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
IDENTIFIER_IMPLICIT_DECL (functionid) = decl;
pushdecl (decl);
rest_of_decl_compilation (decl, NULL, 0, 0);
if (implicit_warning)
implicit_decl_warning (functionid);
else if (warn_traditional && traditional_warning)
warning ("function `%s' was previously declared within a block",
IDENTIFIER_POINTER (functionid));
gen_aux_info_record (decl, 0, 1, 0);
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
void
implicit_decl_warning (id)
tree id;
{
const char *name = IDENTIFIER_POINTER (id);
if (flag_altivec && IDENTIFIER_GLOBAL_VALUE (id)
&& DECL_BUILT_IN_CLASS (IDENTIFIER_GLOBAL_VALUE (id)) == BUILT_IN_MD)
return;
if (mesg_implicit_function_declaration == 2)
error ("implicit declaration of function `%s'", name);
else if (mesg_implicit_function_declaration == 1)
warning ("implicit declaration of function `%s'", name);
}
static int
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
if (DECL_IN_SYSTEM_HEADER (olddecl) || DECL_IN_SYSTEM_HEADER (newdecl))
return 0;
return 1;
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0
&& ! (DECL_DECLARED_INLINE_P (olddecl) && DECL_EXTERNAL (olddecl)
&& ! (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_EXTERNAL (newdecl))))
return 1;
return 0;
}
else if (DECL_CONTEXT (newdecl) == NULL_TREE)
{
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
if (DECL_INITIAL (olddecl) != 0 && DECL_INITIAL (newdecl) != 0)
return 1;
if (TREE_PUBLIC (olddecl) != TREE_PUBLIC (newdecl))
return 3;
return 0;
}
else if (current_binding_level->parm_flag
&& TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
return 0;
else
{
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl))
&& DECL_CONTEXT (newdecl) == DECL_CONTEXT (olddecl))
return 2;
return 0;
}
}
tree
lookup_label (id)
tree id;
{
tree decl = IDENTIFIER_LABEL_VALUE (id);
if (current_function_decl == 0)
{
error ("label %s referenced outside of any function",
IDENTIFIER_POINTER (id));
return 0;
}
if (decl != 0)
{
if (DECL_CONTEXT (decl) != current_function_decl
&& ! C_DECLARED_LABEL_FLAG (decl))
return shadow_label (id);
return decl;
}
decl = build_decl (LABEL_DECL, id, void_type_node);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
DECL_SOURCE_LINE (decl) = lineno;
DECL_SOURCE_FILE (decl) = input_filename;
IDENTIFIER_LABEL_VALUE (id) = decl;
named_labels = tree_cons (NULL_TREE, decl, named_labels);
return decl;
}
tree
shadow_label (name)
tree name;
{
tree decl = IDENTIFIER_LABEL_VALUE (name);
if (decl != 0)
{
tree dup;
for (dup = named_labels; dup; dup = TREE_CHAIN (dup))
if (TREE_VALUE (dup) == decl)
{
error ("duplicate label declaration `%s'",
IDENTIFIER_POINTER (name));
error_with_decl (TREE_VALUE (dup),
"this is a previous declaration");
return lookup_label (name);
}
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
IDENTIFIER_LABEL_VALUE (name) = decl = 0;
}
return lookup_label (name);
}
tree
define_label (filename, line, name)
const char *filename;
int line;
tree name;
{
tree decl = lookup_label (name);
if (decl != 0 && DECL_CONTEXT (decl) != current_function_decl)
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
IDENTIFIER_LABEL_VALUE (name) = 0;
decl = lookup_label (name);
}
if (warn_traditional && !in_system_header && lookup_name (name))
warning_with_file_and_line (filename, line,
"traditional C lacks a separate namespace for labels, identifier `%s' conflicts",
IDENTIFIER_POINTER (name));
if (DECL_INITIAL (decl) != 0)
{
error_with_file_and_line (filename, line, "duplicate label `%s'",
IDENTIFIER_POINTER (name));
return 0;
}
else
{
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
return decl;
}
}
tree
getdecls ()
{
return current_binding_level->names;
}
static void
storedecls (decls)
tree decls;
{
current_binding_level->names = decls;
}
static void
storetags (tags)
tree tags;
{
if (!tags)
return;
if (!current_binding_level->tags_ht)
current_binding_level->tags_ht = create_tags_ht ();
if (current_binding_level->tags_ht)
{
tree t;
for (t = tags; TREE_CHAIN (t); t = TREE_CHAIN (t))
{
void **slot;
slot = htab_find_slot (current_binding_level->tags_ht, t, INSERT);
*slot = tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), NULL);
}
}
current_binding_level->tags_list = chainon (tags, current_binding_level->tags_list);
}
static tree
lookup_tag (code, name, binding_level, thislevel_only)
enum tree_code code;
struct binding_level *binding_level;
tree name;
int thislevel_only;
{
struct binding_level *level;
int thislevel = 1;
for (level = binding_level; level; level = level->level_chain)
{
tree tail = NULL_TREE;
if (level->tags_ht)
{
void **slot;
slot = htab_find_slot (level->tags_ht, name, NO_INSERT);
if (!slot)
tail = NULL_TREE;
else
tail = (tree) *slot;
if (tail)
{
if (TREE_CODE (TREE_VALUE (tail)) == code)
return TREE_VALUE (tail);
else
{
pending_invalid_xref = name;
pending_invalid_xref_file = input_filename;
pending_invalid_xref_line = lineno;
if (thislevel)
pending_xref_error ();
}
}
}
if (! level->tag_transparent)
{
if (thislevel_only)
return NULL_TREE;
thislevel = 0;
}
}
return NULL_TREE;
}
void
pending_xref_error ()
{
if (pending_invalid_xref != 0)
error_with_file_and_line (pending_invalid_xref_file,
pending_invalid_xref_line,
"`%s' defined as wrong kind of tag",
IDENTIFIER_POINTER (pending_invalid_xref));
pending_invalid_xref = 0;
}
static PTR
check_tree_value (slot, data)
PTR *slot;
PTR data;
{
tree tail = *slot;
if (tail && TREE_VALUE (tail) == (tree) data)
return TREE_PURPOSE (tail);
return NULL;
}
#define EMPTY_ENTRY ((PTR) 0)
#define DELETED_ENTRY ((PTR) 1)
PTR
htab_traverse_1 (htab, callback, info)
htab_t htab;
htab_trav callback;
PTR info;
{
PTR *slot = htab->entries;
PTR *limit = slot + htab->size;
do
{
PTR x = *slot;
PTR r;
if (x != EMPTY_ENTRY && x != DELETED_ENTRY)
{
r= (*callback) (slot, info);
if (r)
return r;
}
}
while (++slot < limit);
return NULL;
}
static tree
lookup_tag_reverse (type)
tree type;
{
struct binding_level *level;
for (level = current_binding_level; level; level = level->level_chain)
{
tree tail;
for (tail = level->tags_list; tail; tail = TREE_CHAIN (tail))
{
if (TREE_VALUE (tail) == type)
return TREE_PURPOSE (tail);
}
}
return NULL_TREE;
}
tree
lookup_name (name)
tree name;
{
tree val;
if (current_binding_level != global_binding_level
&& IDENTIFIER_LOCAL_VALUE (name))
val = IDENTIFIER_LOCAL_VALUE (name);
else
val = IDENTIFIER_GLOBAL_VALUE (name);
return val;
}
tree
lookup_name_current_level (name)
tree name;
{
tree t;
if (current_binding_level == global_binding_level)
return IDENTIFIER_GLOBAL_VALUE (name);
if (IDENTIFIER_LOCAL_VALUE (name) == 0)
return 0;
for (t = current_binding_level->names; t; t = TREE_CHAIN (t))
if (DECL_NAME (t) == name)
break;
return t;
}
void
c_init_decl_processing ()
{
tree endlink;
tree ptr_ftype_void, ptr_ftype_ptr;
c_parse_init ();
current_function_decl = NULL;
named_labels = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
pushlevel (0);
global_binding_level = current_binding_level;
build_common_tree_nodes (flag_signed_char);
c_common_nodes_and_builtins ();
boolean_type_node = integer_type_node;
boolean_true_node = integer_one_node;
boolean_false_node = integer_zero_node;
c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
TYPE_PRECISION (c_bool_type_node) = 1;
pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
c_bool_type_node));
c_bool_false_node = build_int_2 (0, 0);
TREE_TYPE (c_bool_false_node) = c_bool_type_node;
c_bool_true_node = build_int_2 (1, 0);
TREE_TYPE (c_bool_true_node) = c_bool_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));
pedantic_lvalues = pedantic;
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
#ifdef ENABLE_DMP_TREE
c_prev_lang_dump_tree_p = set_dump_tree_p (c_dump_tree_p);
SET_MAX_DMP_TREE_CODE(LAST_C_TREE_CODE);
#endif
}
static tree
c_make_fname_decl (id, type_dep)
tree id;
int type_dep;
{
const char *name = fname_as_string (type_dep);
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)));
decl = build_decl (VAR_DECL, id, type);
DECL_CONTEXT (decl) = current_function_decl;
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
init = build_string (length + 1, name);
TREE_TYPE (init) = type;
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
finish_decl (decl, init, NULL_TREE);
return decl;
}
tree
builtin_function (name, type, function_code, class, library_name, attrs)
const char *name;
tree type;
int function_code;
enum built_in_class class;
const char *library_name;
tree attrs;
{
tree decl = build_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
if (library_name)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (library_name));
make_decl_rtl (decl, NULL);
pushdecl (decl);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = function_code;
if (name[0] != '_' || name[1] != '_')
C_DECL_ANTICIPATED (decl) = 1;
if (attrs)
decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
else
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
tree lang_build_type_variant PARAMS ((tree, int, int));
tree
lang_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
return c_build_type_variant (type, constp, volatilep);
}
void
c_insert_default_attributes (decl)
tree decl;
{
if (!TREE_PUBLIC (decl))
return;
c_common_insert_default_attributes (decl);
}
void
shadow_tag (declspecs)
tree declspecs;
{
shadow_tag_warned (declspecs, 0);
}
void
shadow_tag_warned (declspecs, warned)
tree declspecs;
int warned;
{
int found_tag = 0;
tree link;
tree specs, attrs;
pending_invalid_xref = 0;
split_specs_attrs (declspecs, &specs, &attrs);
for (link = specs; link; link = TREE_CHAIN (link))
{
tree value = TREE_VALUE (link);
enum tree_code code = TREE_CODE (value);
if (code == RECORD_TYPE || code == UNION_TYPE || code == ENUMERAL_TYPE)
{
tree name = lookup_tag_reverse (value);
tree t;
found_tag++;
if (name == 0)
{
if (warned != 1 && code != ENUMERAL_TYPE)
{
pedwarn ("unnamed struct/union that defines no instances");
warned = 1;
}
}
else
{
t = lookup_tag (code, name, current_binding_level, 1);
if (t == 0)
{
t = make_node (code);
pushtag (name, t);
}
}
}
else
{
if (!warned && ! in_system_header)
{
warning ("useless keyword or type name in empty declaration");
warned = 2;
}
}
}
if (found_tag > 1)
error ("two types specified in one empty declaration");
if (warned != 1)
{
if (found_tag == 0)
pedwarn ("empty declaration");
}
}
tree
build_array_declarator (expr, quals, static_p, vla_unspec_p)
tree expr;
tree quals;
int static_p;
int vla_unspec_p;
{
tree decl;
decl = build_nt (ARRAY_REF, NULL_TREE, expr);
TREE_TYPE (decl) = quals;
TREE_STATIC (decl) = (static_p ? 1 : 0);
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 (vla_unspec_p)
pedwarn ("ISO C90 does not support `[*]' array declarators");
}
if (vla_unspec_p)
warning ("GCC does not yet properly implement `[*]' array declarators");
return decl;
}
tree
set_array_declarator_type (decl, type, abstract_p)
tree decl;
tree type;
int abstract_p;
{
TREE_OPERAND (decl, 0) = type;
if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
error ("static or type qualifiers in abstract declarator");
return decl;
}
tree
groktypename (typename)
tree typename;
{
tree specs, attrs;
if (TREE_CODE (typename) != TREE_LIST)
return typename;
split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
typename = grokdeclarator (TREE_VALUE (typename), specs, TYPENAME, 0);
decl_attributes (&typename, attrs, 0);
return typename;
}
tree
groktypename_in_parm_context (typename)
tree typename;
{
if (TREE_CODE (typename) != TREE_LIST)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
PARM, 0);
}
tree
start_decl (declarator, declspecs, initialized, attributes)
tree declarator, declspecs;
int initialized;
tree attributes;
{
tree decl;
tree tem;
#ifdef A_LESS_INEFFICENT_WAY
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
else if (lookup_attribute ("unavailable", attributes))
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
#else
tree a;
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (TREE_CODE (name) == IDENTIFIER_NODE)
if (is_attribute_p ("deprecated", name))
{
deprecated_state = DEPRECATED_SUPPRESS;
break;
}
if (is_attribute_p ("unavailable", name))
{
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
break;
}
}
#endif
decl = grokdeclarator (declarator, declspecs,
NORMAL, initialized);
deprecated_state = DEPRECATED_NORMAL;
if (flag_gen_index)
{
int t;
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
t = INDEX_FUNCTION_DECL;
break;
case CONST_DECL:
t = INDEX_CONST_DECL;
break;
case VAR_DECL:
t = INDEX_VAR_DECL;
break;
case TYPE_DECL:
t = INDEX_TYPE_DECL;
break;
case PARM_DECL:
default:
t = INDEX_ERROR;
break;
}
if (TREE_CODE (decl) != PARM_DECL)
gen_indexing_info (t, IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
&& MAIN_NAME_P (DECL_NAME (decl)))
warning_with_decl (decl, "`%s' is usually a function");
if (initialized)
switch (TREE_CODE (decl))
{
case TYPE_DECL:
error ("typedef `%s' is initialized (use __typeof__ instead)",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
break;
case FUNCTION_DECL:
error ("function `%s' is initialized like a variable",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
break;
case PARM_DECL:
error ("parameter `%s' is initialized",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
break;
default:
if (TREE_TYPE (decl) == error_mark_node)
initialized = 0;
else if (COMPLETE_TYPE_P (TREE_TYPE (decl)))
{
if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST
|| C_DECL_VARIABLE_SIZE (decl))
{
error ("variable-sized object may not be initialized");
initialized = 0;
}
}
else if (TREE_CODE (TREE_TYPE (decl)) != ARRAY_TYPE)
{
error ("variable `%s' has initializer but incomplete type",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
{
error ("elements of array `%s' have incomplete type",
IDENTIFIER_POINTER (DECL_NAME (decl)));
initialized = 0;
}
}
if (initialized)
{
#if 0
if (current_binding_level != global_binding_level
&& DECL_EXTERNAL (decl)
&& TREE_CODE (decl) != FUNCTION_DECL)
warning ("declaration of `%s' has `extern' and is initialized",
IDENTIFIER_POINTER (DECL_NAME (decl)));
#endif
DECL_EXTERNAL (decl) = 0;
if (current_binding_level == global_binding_level)
TREE_STATIC (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
if (TREE_CODE (decl) == FUNCTION_DECL)
gen_aux_info_record (decl, 0, 0, TYPE_ARG_TYPES (TREE_TYPE (decl)) != 0);
if (TREE_CODE (decl) == VAR_DECL
&& !initialized
&& TREE_PUBLIC (decl)
&& !DECL_THREAD_LOCAL (decl)
&& !flag_no_common)
DECL_COMMON (decl) = 1;
decl_attributes (&decl, attributes, 0);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning_with_decl (decl,
"inline function `%s' given attribute noinline");
tem = pushdecl (decl);
if (current_binding_level != global_binding_level
&& !DECL_RTL_SET_P (tem)
&& !DECL_CONTEXT (tem))
{
if (TREE_TYPE (tem) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (tem)))
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != 0)
expand_decl (tem);
}
return tem;
}
void
finish_decl (decl, init, asmspec_tree)
tree decl, init;
tree asmspec_tree;
{
tree type = TREE_TYPE (decl);
int was_incomplete = (DECL_SIZE (decl) == 0);
const char *asmspec = 0;
if (current_binding_level == global_binding_level)
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init != 0 && DECL_INITIAL (decl) == 0)
init = 0;
if (TREE_CODE (decl) == PARM_DECL)
init = 0;
if (init)
store_init_value (decl, init);
if (flag_objc && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == 0
&& TREE_CODE (decl) != TYPE_DECL)
{
int do_default
= (TREE_STATIC (decl)
? pedantic && !TREE_PUBLIC (decl)
: !DECL_EXTERNAL (decl));
int failure
= complete_array_type (type, DECL_INITIAL (decl), do_default);
type = TREE_TYPE (decl);
if (failure == 1)
error_with_decl (decl, "initializer fails to determine size of `%s'");
else if (failure == 2)
{
if (do_default)
error_with_decl (decl, "array size missing in `%s'");
else if (!pedantic && TREE_STATIC (decl) && ! TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
else if (pedantic && TYPE_DOMAIN (type) != 0
&& tree_int_cst_sgn (TYPE_MAX_VALUE (TYPE_DOMAIN (type))) < 0)
error_with_decl (decl, "zero or negative size array `%s'");
layout_decl (decl, 0);
}
if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_SIZE (decl) == 0 && TREE_TYPE (decl) != error_mark_node
&& COMPLETE_TYPE_P (TREE_TYPE (decl)))
layout_decl (decl, 0);
if (DECL_SIZE (decl) == 0
&& TREE_TYPE (decl) != error_mark_node
&& (TREE_STATIC (decl)
?
(DECL_INITIAL (decl) != 0
|| DECL_CONTEXT (decl) != 0)
:
!DECL_EXTERNAL (decl)))
{
error_with_decl (decl, "storage size of `%s' isn't known");
TREE_TYPE (decl) = error_mark_node;
}
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != 0)
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
error_with_decl (decl, "storage size of `%s' isn't constant");
}
if (TREE_USED (type))
TREE_USED (decl) = 1;
}
if (TREE_CODE (decl) == FUNCTION_DECL && asmspec)
{
DECL_BUILT_IN_CLASS (decl) = NOT_BUILT_IN;
SET_DECL_RTL (decl, NULL_RTX);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
}
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL)
{
if (!DECL_CONTEXT (decl))
{
if (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node)
DECL_DEFER_OUTPUT (decl) = 1;
rest_of_decl_compilation (decl, asmspec,
(DECL_CONTEXT (decl) == 0
|| TREE_ASM_WRITTEN (decl)), 0);
}
else
{
if (asmspec)
{
if (DECL_REGISTER (decl))
DECL_C_HARD_REGISTER (decl) = 1;
if (TREE_CODE (decl) == VAR_DECL
&& !DECL_REGISTER (decl)
&& !TREE_STATIC (decl))
warning_with_decl (decl,
"ignoring asm-specifier for non-static local variable `%s'");
else
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
}
if (TREE_CODE (decl) != FUNCTION_DECL)
add_decl_stmt (decl);
}
if (DECL_CONTEXT (decl) != 0)
{
if (was_incomplete
&& ! TREE_STATIC (decl) && ! DECL_EXTERNAL (decl))
{
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
if (DECL_SIZE (decl) == 0)
DECL_INITIAL (decl) = 0;
}
}
}
if (TREE_CODE (decl) == TYPE_DECL)
{
rest_of_decl_compilation (decl, NULL, DECL_CONTEXT (decl) == 0, 0);
}
if (current_binding_level == global_binding_level)
get_pending_sizes ();
}
void
push_parm_decl (parm)
tree parm;
{
tree decl;
int old_immediate_size_expand = immediate_size_expand;
immediate_size_expand = 0;
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
decl_attributes (&decl, TREE_VALUE (parm), 0);
#if 0
if (DECL_NAME (decl))
{
tree olddecl;
olddecl = lookup_name (DECL_NAME (decl));
if (pedantic && olddecl != 0 && TREE_CODE (olddecl) == TYPE_DECL)
pedwarn_with_decl (decl,
"ISO C forbids parameter `%s' shadowing typedef");
}
#endif
decl = pushdecl (decl);
immediate_size_expand = old_immediate_size_expand;
current_binding_level->parm_order
= tree_cons (NULL_TREE, decl, current_binding_level->parm_order);
finish_decl (decl, NULL_TREE, NULL_TREE);
}
void
clear_parm_order ()
{
current_binding_level->parm_order = NULL_TREE;
}
static GTY(()) int compound_literal_number;
tree
build_compound_literal (type, init)
tree type;
tree init;
{
tree decl = build_decl (VAR_DECL, NULL_TREE, type);
tree complit;
tree stmt;
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = (current_binding_level == global_binding_level);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
TREE_READONLY (decl) = TREE_READONLY (type);
store_init_value (decl, init);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
int failure = complete_array_type (type, DECL_INITIAL (decl), 1);
if (failure)
abort ();
}
type = TREE_TYPE (decl);
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
return error_mark_node;
stmt = build_stmt (DECL_STMT, decl);
complit = build1 (COMPOUND_LITERAL_EXPR, TREE_TYPE (decl), stmt);
TREE_SIDE_EFFECTS (complit) = 1;
layout_decl (decl, 0);
if (TREE_STATIC (decl))
{
char *name;
ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
compound_literal_number);
compound_literal_number++;
DECL_NAME (decl) = get_identifier (name);
DECL_DEFER_OUTPUT (decl) = 1;
DECL_COMDAT (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
rest_of_decl_compilation (decl, NULL, 1, 0);
}
return complit;
}
int
complete_array_type (type, initial_value, do_default)
tree type;
tree initial_value;
int do_default;
{
tree maxindex = NULL_TREE;
int value = 0;
if (initial_value)
{
if (TREE_CODE (initial_value) == STRING_CST)
{
int eltsize
= int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
maxindex = build_int_2 ((TREE_STRING_LENGTH (initial_value)
/ eltsize) - 1, 0);
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
tree elts = CONSTRUCTOR_ELTS (initial_value);
maxindex = build_int_2 (-1, -1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
maxindex = fold (build (PLUS_EXPR, integer_type_node,
maxindex, integer_one_node));
}
maxindex = copy_node (maxindex);
}
else
{
if (initial_value != error_mark_node)
value = 1;
maxindex = build_int_2 (0, 0);
}
}
if (!maxindex)
{
if (do_default)
maxindex = build_int_2 (0, 0);
value = 2;
}
if (maxindex)
{
TYPE_DOMAIN (type) = build_index_type (maxindex);
if (!TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = TYPE_DOMAIN (type);
}
layout_type (type);
return value;
}
static bool
flexible_array_type_p (type)
tree type;
{
tree x;
switch (TREE_CODE (type))
{
case RECORD_TYPE:
x = TYPE_FIELDS (type);
if (x == NULL_TREE)
return false;
while (TREE_CHAIN (x) != NULL_TREE)
x = TREE_CHAIN (x);
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
&& TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
return true;
return false;
case UNION_TYPE:
for (x = TYPE_FIELDS (type); x != NULL_TREE; x = TREE_CHAIN (x))
{
if (flexible_array_type_p (TREE_TYPE (x)))
return true;
}
return false;
default:
return false;
}
}
static tree
grokdeclarator (declarator, declspecs, decl_context, initialized)
tree declspecs;
tree declarator;
enum decl_context decl_context;
int initialized;
{
int specbits = 0;
int cw_asm_specbit = 0;
tree spec;
tree type = NULL_TREE;
int longlong = 0;
int constp;
int restrictp;
int volatilep;
int type_quals = TYPE_UNQUALIFIED;
int inlinep;
int explicit_int = 0;
int explicit_char = 0;
int explicit_bool = 0;
int defaulted_int = 0;
tree typedef_decl = 0;
const char *name;
tree typedef_type = 0;
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
int size_varies = 0;
tree decl_attr = NULL_TREE;
tree array_ptr_quals = NULL_TREE;
int array_parm_static = 0;
tree returned_attrs = NULL_TREE;
if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
{
tree decl = declarator;
name = 0;
while (decl)
switch (TREE_CODE (decl))
{
case ARRAY_REF:
case INDIRECT_REF:
case CALL_EXPR:
innermost_code = TREE_CODE (decl);
decl = TREE_OPERAND (decl, 0);
break;
case TREE_LIST:
decl = TREE_VALUE (decl);
break;
case IDENTIFIER_NODE:
name = IDENTIFIER_POINTER (decl);
decl = 0;
break;
default:
abort ();
}
if (name == 0)
name = "type name";
}
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
if (decl_context == NORMAL && !funcdef_flag
&& current_binding_level->parm_flag)
decl_context = PARM;
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
tree id = TREE_VALUE (spec);
if (id && TREE_DEPRECATED (id))
{
if (TREE_UNAVAILABLE (id))
{
if (deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("unavailable"),
NULL_TREE));
#endif
}
else
{
if (deprecated_state != DEPRECATED_SUPPRESS
&& deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("deprecated"),
NULL_TREE));
#endif
}
}
if (id == ridpointers[(int) RID_INT]) {
explicit_int = 1;
if (flag_altivec && explicit_bool) {
type = NULL_TREE;
specbits |= (1 << (int) RID_ALTIVEC_BOOL);
}
}
if (id == ridpointers[(int) RID_CHAR]) {
explicit_char = 1;
if (flag_altivec && explicit_bool) {
type = NULL_TREE;
specbits |= (1 << (int) RID_ALTIVEC_BOOL);
}
}
if (TREE_CODE (id) == IDENTIFIER_NODE && C_IS_RESERVED_WORD (id))
{
enum rid i = C_RID_CODE (id);
if (i == RID_BOOL || i == RID_ALTIVEC_BOOL)
{
explicit_bool = 1;
if (flag_altivec && type)
i = RID_ALTIVEC_BOOL;
}
if (i == RID_ASM)
{
++cw_asm_specbit;
goto found;
}
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 (!flag_isoc99)
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
}
else
error ("duplicate `%s'", IDENTIFIER_POINTER (id));
}
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);
else if (TREE_CODE (id) == TYPE_DECL)
{
if (TREE_TYPE (id) == error_mark_node)
;
else
{
type = TREE_TYPE (id);
decl_attr = DECL_ATTRIBUTES (id);
typedef_decl = id;
}
}
else if (TREE_CODE (id) == IDENTIFIER_NODE)
{
tree t = lookup_name (id);
if (TREE_TYPE (t) == error_mark_node)
;
else if (!t || TREE_CODE (t) != TYPE_DECL)
error ("`%s' fails to be a typedef or built in type",
IDENTIFIER_POINTER (id));
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);
if (type == 0)
{
if ((! (specbits & ((1 << (int) RID_LONG) | (1 << (int) RID_SHORT)
| (1 << (int) RID_SIGNED)
| (1 << (int) RID_UNSIGNED)
| (1 << (int) RID_ALTIVEC_VECTOR)
| (1 << (int) RID_ALTIVEC_PIXEL)
| (1 << (int) RID_COMPLEX))))
&& ! (specbits & (1 << (int) RID_TYPEDEF) && initialized)
&& ! in_system_header)
{
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;
}
if ((specbits & 1 << (int) RID_LONG) && ! longlong
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
specbits &= ~(1 << (int) RID_LONG);
type = long_double_type_node;
warn_about_long_double ();
}
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
&& (!flag_altivec || TREE_CODE (type) != BOOLEAN_TYPE))
error ("long, short, signed or unsigned invalid for `%s'", name);
else
{
ok = 1;
if (!explicit_int && !explicit_bool && !defaulted_int && !explicit_char)
{
error ("long, short, signed or unsigned used invalidly for `%s'",
name);
ok = 0;
}
}
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);
}
if (specbits & 1 << (int) RID_UNSIGNED
|| (bitfield && ! flag_signed_bitfields
&& (explicit_int || defaulted_int || explicit_char
|| ! (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 (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);
}
}
if ((specbits & (1 << (int) RID_ALTIVEC_PIXEL))
&& !(specbits & (1 << (int) RID_ALTIVEC_VECTOR)))
{
error ("__pixel invalid for `%s'", name);
specbits &= ~ (1 << (int) RID_ALTIVEC_PIXEL);
}
if (specbits & 1 << (int) RID_ALTIVEC_VECTOR)
{
if ((type == integer_type_node || type == long_integer_type_node)
&& !explicit_bool && !explicit_int
&& (specbits & (1 << (int) RID_ALTIVEC_PIXEL)))
type = vector_pixel_type_node;
else if (type == long_unsigned_type_node)
{
type = vector_unsigned_long_type_node;
if (warn_altivec_long_deprecated)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
}
else if (type == unsigned_type_node
&& explicit_int && !explicit_bool)
type = vector_unsigned_long_type_node;
else if ((type == long_integer_type_node && explicit_bool)
|| (type == integer_type_node && explicit_int
&& explicit_bool && !(specbits & 1 << (int) RID_SIGNED)))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_boolean_long_type_node;
}
else if ((type == long_integer_type_node && !explicit_bool)
|| (type == integer_type_node && explicit_int
&& !explicit_bool && (specbits & 1 << (int) RID_SIGNED)))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_signed_long_type_node;
}
else if (type == short_unsigned_type_node)
type = vector_unsigned_short_type_node;
else if (type == short_integer_type_node)
type = (explicit_bool
? vector_boolean_short_type_node
: vector_signed_short_type_node);
else if (type == unsigned_char_type_node
|| (explicit_char && type == unsigned_type_node))
type = vector_unsigned_char_type_node;
else if (type == signed_char_type_node
|| (explicit_char && type == integer_type_node))
type = vector_signed_char_type_node;
else if (type == char_type_node && explicit_bool)
type = vector_boolean_char_type_node;
else if (type == float_type_node)
type = vector_float_type_node;
else
{
error ("vector invalid for `%s'", name);
specbits &= ~ ((1 << (int) RID_ALTIVEC_VECTOR) | (1 << (int) RID_ALTIVEC_PIXEL));
}
if ((specbits & (1 << (int) RID_ALTIVEC_PIXEL))
&& type != vector_pixel_type_node)
{
error ("type modifiers do not apply to `vector pixel'");
type = vector_pixel_type_node;
}
}
constp = !! (specbits & 1 << (int) RID_CONST) + TYPE_READONLY (type);
restrictp = !! (specbits & 1 << (int) RID_RESTRICT) + TYPE_RESTRICT (type);
volatilep = !! (specbits & 1 << (int) RID_VOLATILE) + TYPE_VOLATILE (type);
inlinep = !! (specbits & (1 << (int) RID_INLINE));
if (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
if (restrictp > 1 && ! flag_isoc99)
pedwarn ("duplicate `restrict'");
if (volatilep > 1 && ! flag_isoc99)
pedwarn ("duplicate `volatile'");
if (! flag_gen_aux_info && (TYPE_QUALS (type)))
type = TYPE_MAIN_VARIANT (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
{
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++;
if ((specbits & (1 << (int) RID_THREAD
| 1 << (int) RID_STATIC
| 1 << (int) RID_EXTERN)) == (1 << (int) RID_THREAD))
nclasses++;
if (specbits & 1 << (int) RID_PRIVATE_EXTERN) nclasses++;
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_binding_level == global_binding_level))
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)
{
if (current_binding_level == global_binding_level)
warning ("`%s' initialized and declared `extern'", name);
else
error ("`%s' has both `extern' and initializer", name);
}
else if (current_binding_level == global_binding_level)
{
if (specbits & 1 << (int) RID_AUTO)
error ("top-level 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);
}
}
}
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE)
{
if (type == error_mark_node)
{
declarator = TREE_OPERAND (declarator, 0);
continue;
}
if (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;
}
if (TREE_CODE (declarator) == 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);
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);
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);
type = error_mark_node;
}
if (pedantic && 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)
{
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
{
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))
{
itype = build_range_type (sizetype, size, NULL_TREE);
}
else
{
itype = fold (build (MINUS_EXPR, index_type,
convert (index_type, size),
convert (index_type, size_one_node)));
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");
itype = build_range_type (sizetype, size_zero_node, NULL_TREE);
}
if (pedantic && !COMPLETE_TYPE_P (type))
pedwarn ("array type has incomplete element type");
#if 0
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& (constp || volatilep))
pedwarn ("ISO C forbids const or volatile function types");
#endif
type = build_array_type (type, itype);
if (type_quals)
type = c_build_qualified_type (type, type_quals);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
if (size && integer_zerop (size))
{
layout_type (type);
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)
{
tree arg_types;
if (type == error_mark_node)
continue;
size_varies = 0;
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)
{
error ("`%s' declared as function returning an array", name);
type = integer_type_node;
}
arg_types = grokparms (TREE_OPERAND (declarator, 1),
funcdef_flag
&& TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE);
if (type_quals)
{
if (VOID_TYPE_P (type) && pedantic && !in_system_header)
pedwarn ("ISO C forbids qualified void function return type");
else if (extra_warnings
&& !(VOID_TYPE_P (type)
&& type_quals == TYPE_QUAL_VOLATILE))
warning ("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 = TREE_OPERAND (declarator, 0);
if (last_function_parms)
{
tree link;
for (link = last_function_parm_tags;
link;
link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = type;
}
}
else if (TREE_CODE (declarator) == INDIRECT_REF)
{
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);
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 (constp > 1 && ! flag_isoc99)
pedwarn ("duplicate `const'");
if (volatilep > 1 && ! flag_isoc99)
pedwarn ("duplicate `volatile'");
if (restrictp > 1 && ! flag_isoc99)
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 ();
}
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array `%s' is too large", name);
type = error_mark_node;
}
if (specbits & (1 << (int) RID_TYPEDEF))
{
tree decl;
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)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
decl_attributes (&decl, returned_attrs, 0);
return decl;
}
if (type != 0 && typedef_type != 0
&& TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type) == 0
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
{
type = build_array_type (TREE_TYPE (type), 0);
if (size_varies)
C_TYPE_VARIABLE_SIZE (type) = 1;
}
if (decl_context == TYPENAME)
{
if (pedantic && TREE_CODE (type) == FUNCTION_TYPE
&& type_quals)
pedwarn ("ISO C forbids const or volatile function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl_attributes (&type, returned_attrs, 0);
return type;
}
if (VOID_TYPE_P (type) && decl_context != PARM
&& ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
&& ((specbits & (1 << (int) RID_EXTERN))
|| (current_binding_level == global_binding_level
&& !(specbits
& ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
{
error ("variable or field `%s' declared void", name);
type = integer_type_node;
}
{
tree decl;
if (decl_context == PARM)
{
tree type_as_written;
tree promoted_type;
if (TREE_CODE (type) == ARRAY_TYPE)
{
type = TREE_TYPE (type);
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);
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);
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");
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)
{
if (pedantic && type_quals)
pedwarn ("ISO C forbids qualified function types");
if (type_quals)
type = c_build_qualified_type (type, type_quals);
type = build_pointer_type (type);
type_quals = TYPE_UNQUALIFIED;
}
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
type_as_written = type;
decl = build_decl (PARM_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (type == error_mark_node)
promoted_type = type;
else
promoted_type = c_type_promotes_to (type);
DECL_ARG_TYPE (decl) = promoted_type;
DECL_ARG_TYPE_AS_WRITTEN (decl) = type_as_written;
}
else if (decl_context == FIELD)
{
if (TREE_CODE (type) == FUNCTION_TYPE)
{
error ("field `%s' 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);
type = error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
{
type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
type_quals),
TYPE_DOMAIN (type));
#if 0
type_quals = TYPE_UNQUALIFIED;
#endif
}
decl = build_decl (FIELD_DECL, declarator, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
|| current_binding_level == global_binding_level);
if (specbits & (1 << (int) RID_AUTO)
&& (pedantic || current_binding_level == global_binding_level))
pedwarn ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_REGISTER))
error ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_THREAD))
error ("invalid storage class for function `%s'", name);
if (current_binding_level != global_binding_level
&& (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
decl = build_decl (FUNCTION_DECL, declarator, type);
decl = build_decl_attribute_variant (decl, decl_attr);
DECL_LANG_SPECIFIC (decl) = (struct lang_decl *)
ggc_alloc_cleared (sizeof (struct lang_decl));
if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
pedwarn ("ISO C forbids qualified function types");
if ((type_quals & TYPE_QUAL_VOLATILE)
&& !VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl))))
warning ("`noreturn' function returns non-void value");
if (extern_ref)
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl)
= !(specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_AUTO)));
if (defaulted_int)
C_FUNCTION_IMPLICIT_INT (decl) = 1;
DECL_PRIVATE_EXTERN (decl)
= ((specbits & (1 << (int) RID_PRIVATE_EXTERN)) != 0);
if (MAIN_NAME_P (declarator))
{
if (inlinep)
warning ("cannot inline function `main'");
}
else if (inlinep)
{
DECL_DECLARED_INLINE_P (decl) = 1;
if (initialized)
{
DECL_INLINE (decl) = 1;
if (specbits & (1 << (int) RID_EXTERN))
current_extern_inline = 1;
}
}
else if (flag_inline_trees == 2 && initialized)
{
if (!DECL_INLINE (decl))
DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
DECL_DECLARED_INLINE_P (decl) = 0;
}
}
else
{
int extern_ref = !initialized && (specbits & ((1 << (int) RID_EXTERN)
| (1 << (int) RID_PRIVATE_EXTERN)));
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;
#if 0
type_quals = TYPE_UNQUALIFIED;
#endif
}
else if (type_quals)
type = c_build_qualified_type (type, type_quals);
decl = build_decl (VAR_DECL, declarator, type);
if (size_varies)
C_DECL_VARIABLE_SIZE (decl) = 1;
if (inlinep)
pedwarn_with_decl (decl, "variable `%s' declared `inline'");
DECL_EXTERNAL (decl) = extern_ref;
DECL_PRIVATE_EXTERN (decl)
= ((specbits & (1 << (int) RID_PRIVATE_EXTERN)) != 0);
if (current_binding_level == global_binding_level)
{
TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
| (1 << (int) RID_REGISTER)));
TREE_STATIC (decl) = !extern_ref;
}
else
{
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
TREE_PUBLIC (decl) = extern_ref;
}
if (specbits & 1 << (int) RID_THREAD)
{
if (targetm.have_tls)
DECL_THREAD_LOCAL (decl) = 1;
else
error ("thread-local storage not supported for this target");
}
}
if (specbits & (1 << (int) RID_REGISTER))
DECL_REGISTER (decl) = 1;
if (cw_asm_specbit)
{
if (flag_cw_asm_blocks)
{
DECL_CW_ASM_FUNCTION (decl) = 1;
DECL_CW_ASM_NORETURN (decl) = 0;
DECL_CW_ASM_FRAME_SIZE (decl) = -2;
}
else
error ("asm functions not enabled, use `-fasm-blocks'");
}
c_apply_type_quals_to_decl (type_quals, decl);
if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
c_mark_addressable (decl);
decl_attributes (&decl, returned_attrs, 0);
return decl;
}
}
static tree
grokparms (parms_info, funcdef_flag)
tree parms_info;
int funcdef_flag;
{
tree first_parm = TREE_CHAIN (parms_info);
last_function_parms = TREE_PURPOSE (parms_info);
last_function_parm_tags = TREE_VALUE (parms_info);
if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag
&& !in_system_header)
warning ("function declaration isn't a prototype");
if (first_parm != 0
&& TREE_CODE (TREE_VALUE (first_parm)) == IDENTIFIER_NODE)
{
if (! funcdef_flag)
pedwarn ("parameter names (without types) in function declaration");
last_function_parms = first_parm;
return 0;
}
else
{
tree parm;
tree typelt;
#if 0
if (funcdef_flag)
#endif
for (parm = last_function_parms, typelt = first_parm;
parm;
parm = TREE_CHAIN (parm))
if (TREE_CODE (parm) == PARM_DECL)
{
tree type = TREE_VALUE (typelt);
if (type == error_mark_node)
continue;
if (!COMPLETE_TYPE_P (type))
{
if (funcdef_flag && DECL_NAME (parm) != 0)
error ("parameter `%s' has incomplete type",
IDENTIFIER_POINTER (DECL_NAME (parm)));
else
warning ("parameter has incomplete type");
if (funcdef_flag)
{
TREE_VALUE (typelt) = error_mark_node;
TREE_TYPE (parm) = error_mark_node;
}
}
#if 0
else
{
while (TREE_CODE (type) == POINTER_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
type = TYPE_MAIN_VARIANT (type);
if (!COMPLETE_TYPE_P (type))
{
if (DECL_NAME (parm) != 0)
warning ("parameter `%s' points to incomplete type",
IDENTIFIER_POINTER (DECL_NAME (parm)));
else
warning ("parameter points to incomplete type");
}
}
#endif
typelt = TREE_CHAIN (typelt);
}
return first_parm;
}
}
tree
get_parm_info (void_at_end)
int void_at_end;
{
tree decl, t;
tree types = 0;
int erred = 0;
tree tags = 0;
tree parms = getdecls ();
tree new_parms = 0;
tree order = current_binding_level->parm_order;
if (void_at_end && parms != 0
&& TREE_CHAIN (parms) == 0
&& VOID_TYPE_P (TREE_TYPE (parms))
&& ! TREE_THIS_VOLATILE (parms)
&& ! TREE_READONLY (parms)
&& ! DECL_REGISTER (parms)
&& DECL_NAME (parms) == 0)
{
parms = NULL_TREE;
storedecls (NULL_TREE);
return tree_cons (NULL_TREE, NULL_TREE,
tree_cons (NULL_TREE, void_type_node, NULL_TREE));
}
for (decl = parms; decl;)
{
tree next = TREE_CHAIN (decl);
if (TREE_CODE (decl) != PARM_DECL)
{
TREE_CHAIN (decl) = new_parms;
new_parms = decl;
}
else if (TREE_ASM_WRITTEN (decl))
{
error_with_decl (decl,
"parameter `%s' has just a forward declaration");
TREE_CHAIN (decl) = new_parms;
new_parms = decl;
}
decl = next;
}
for (t = order; t; t = TREE_CHAIN (t))
{
if (TREE_CHAIN (t))
TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (TREE_CHAIN (t));
else
TREE_CHAIN (TREE_VALUE (t)) = 0;
}
new_parms = chainon (order ? nreverse (TREE_VALUE (order)) : 0,
new_parms);
storedecls (new_parms);
for (decl = new_parms; decl; decl = TREE_CHAIN (decl))
if (TREE_CODE (decl) == PARM_DECL)
{
tree type = TREE_TYPE (decl);
DECL_ARG_TYPE (decl) = type;
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
if (VOID_TYPE_P (TREE_VALUE (types)) && ! erred
&& DECL_NAME (decl) == 0)
{
error ("`void' in parameter list must be the entire list");
erred = 1;
}
}
if (void_at_end)
return tree_cons (new_parms, tags,
nreverse (tree_cons (NULL_TREE, void_type_node, types)));
return tree_cons (new_parms, tags, nreverse (types));
}
void
parmlist_tags_warning ()
{
tree elt;
static int already;
if (!current_function_parms)
return;
for (elt = current_function_parm_tags; elt; elt = TREE_CHAIN (elt))
{
enum tree_code code = TREE_CODE (TREE_VALUE (elt));
if (TREE_CODE (elt) != TREE_LIST)
continue;
if ((code == UNION_TYPE) && (TREE_PURPOSE (elt) == 0) && !pedantic)
continue;
if (TREE_PURPOSE (elt) != 0)
{
if (code == RECORD_TYPE)
warning ("`struct %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else if (code == UNION_TYPE)
warning ("`union %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
else
warning ("`enum %s' declared inside parameter list",
IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
}
else
{
if (code == RECORD_TYPE)
warning ("anonymous struct declared inside parameter list");
else if (code == UNION_TYPE)
warning ("anonymous union declared inside parameter list");
else
warning ("anonymous enum declared inside parameter list");
}
if (! already)
{
warning ("its scope is only this definition or declaration, which is probably not what you want");
already = 1;
}
}
}
tree
xref_tag (code, name)
enum tree_code code;
tree name;
{
tree ref = lookup_tag (code, name, current_binding_level, 0);
if (ref && TREE_CODE (ref) == code)
return ref;
ref = make_node (code);
if (code == ENUMERAL_TYPE)
{
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
TYPE_USER_ALIGN (ref) = 0;
TREE_UNSIGNED (ref) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
}
pushtag (name, ref);
return ref;
}
tree
start_struct (code, name)
enum tree_code code;
tree name;
{
tree ref = 0;
if (name != 0)
ref = lookup_tag (code, name, current_binding_level, 1);
if (ref && TREE_CODE (ref) == code)
{
if (TYPE_FIELDS (ref))
{
if (code == UNION_TYPE)
error ("redefinition of `union %s'", IDENTIFIER_POINTER (name));
else
error ("redefinition of `struct %s'", IDENTIFIER_POINTER (name));
}
}
else
{
ref = make_node (code);
pushtag (name, ref);
}
C_TYPE_BEING_DEFINED (ref) = 1;
TYPE_PACKED (ref) = flag_pack_struct;
return ref;
}
tree
grokfield (filename, line, declarator, declspecs, width)
const char *filename ATTRIBUTE_UNUSED;
int line ATTRIBUTE_UNUSED;
tree declarator, declspecs, width;
{
tree value;
if (declarator == NULL_TREE && width == NULL_TREE)
{
tree type = TREE_VALUE (declspecs);
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 (flag_ms_extensions)
;
else if (flag_iso)
goto warn_unnamed_field;
else if (TYPE_NAME (type) == NULL)
;
else
goto warn_unnamed_field;
}
else
{
warn_unnamed_field:
warning ("declaration does not declare anything");
return NULL_TREE;
}
}
value = grokdeclarator (declarator, declspecs, width ? BITFIELD : FIELD, 0);
finish_decl (value, NULL_TREE, NULL_TREE);
DECL_INITIAL (value) = width;
return value;
}
tree
finish_struct (t, fieldlist, attributes)
tree t;
tree fieldlist;
tree attributes;
{
tree x;
int toplevel = global_binding_level == current_binding_level;
int saw_named_field;
TYPE_SIZE (t) = 0;
decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
if (in_parm_level_p ())
{
if (pedantic)
pedwarn ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
else
warning ("%s defined inside parms",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("structure"));
}
if (pedantic)
{
for (x = fieldlist; x; x = TREE_CHAIN (x))
if (DECL_NAME (x) != 0)
break;
if (x == 0)
pedwarn ("%s has no %s",
TREE_CODE (t) == UNION_TYPE ? _("union") : _("struct"),
fieldlist ? _("named members") : _("members"));
}
saw_named_field = 0;
for (x = fieldlist; x; x = TREE_CHAIN (x))
{
DECL_CONTEXT (x) = t;
DECL_PACKED (x) |= TYPE_PACKED (t);
if (TREE_READONLY (x))
C_TYPE_FIELDS_READONLY (t) = 1;
else
{
tree t1 = TREE_TYPE (x);
while (TREE_CODE (t1) == ARRAY_TYPE)
t1 = TREE_TYPE (t1);
if ((TREE_CODE (t1) == RECORD_TYPE || TREE_CODE (t1) == UNION_TYPE)
&& C_TYPE_FIELDS_READONLY (t1))
C_TYPE_FIELDS_READONLY (t) = 1;
}
if (TREE_THIS_VOLATILE (x))
C_TYPE_FIELDS_VOLATILE (t) = 1;
if (C_DECL_VARIABLE_SIZE (x))
C_TYPE_VARIABLE_SIZE (t) = 1;
if (TREE_TYPE (x) == t)
error ("nested redefinition of `%s'",
IDENTIFIER_POINTER (TYPE_NAME (t)));
if (DECL_INITIAL (x))
STRIP_NOPS (DECL_INITIAL (x));
if (DECL_INITIAL (x))
{
if (TREE_CODE (DECL_INITIAL (x)) == INTEGER_CST)
constant_expression_warning (DECL_INITIAL (x));
else
{
error_with_decl (x,
"bit-field `%s' width not an integer constant");
DECL_INITIAL (x) = NULL;
}
}
if (DECL_INITIAL (x)
&& TREE_CODE (TREE_TYPE (x)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (x)) != BOOLEAN_TYPE
&& TREE_CODE (TREE_TYPE (x)) != ENUMERAL_TYPE)
{
error_with_decl (x, "bit-field `%s' has invalid type");
DECL_INITIAL (x) = NULL;
}
if (DECL_INITIAL (x) && pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != c_bool_type_node
&& !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (x))
== TYPE_PRECISION (integer_type_node))))
pedwarn_with_decl (x, "bit-field `%s' type invalid in ISO C");
if (DECL_INITIAL (x))
{
int max_width
= (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
error_with_decl (x, "negative width in bit-field `%s'");
else if (0 < compare_tree_int (DECL_INITIAL (x), max_width))
pedwarn_with_decl (x, "width of `%s' exceeds its type");
else if (integer_zerop (DECL_INITIAL (x)) && DECL_NAME (x) != 0)
error_with_decl (x, "zero width for bit-field `%s'");
else
{
unsigned HOST_WIDE_INT width
= tree_low_cst (DECL_INITIAL (x), 1);
if (TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (width < min_precision (TYPE_MIN_VALUE (TREE_TYPE (x)),
TREE_UNSIGNED (TREE_TYPE (x)))
|| (width
< min_precision (TYPE_MAX_VALUE (TREE_TYPE (x)),
TREE_UNSIGNED (TREE_TYPE (x))))))
warning_with_decl (x,
"`%s' is narrower than values of its type");
DECL_SIZE (x) = bitsize_int (width);
DECL_BIT_FIELD (x) = 1;
SET_DECL_C_BIT_FIELD (x);
if (width == 0
&& ! (* targetm.ms_bitfield_layout_p) (t))
{
#ifdef EMPTY_FIELD_BOUNDARY
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), EMPTY_FIELD_BOUNDARY);
#endif
#ifdef PCC_BITFIELD_TYPE_MATTERS
if (PCC_BITFIELD_TYPE_MATTERS)
{
DECL_ALIGN (x) = MAX (DECL_ALIGN (x),
TYPE_ALIGN (TREE_TYPE (x)));
DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
}
#endif
}
}
}
else if (TREE_TYPE (x) != error_mark_node)
{
unsigned int min_align = (DECL_PACKED (x) ? BITS_PER_UNIT
: TYPE_ALIGN (TREE_TYPE (x)));
DECL_ALIGN (x) = MAX (DECL_ALIGN (x), min_align);
if (! DECL_PACKED (x))
DECL_USER_ALIGN (x) |= TYPE_USER_ALIGN (TREE_TYPE (x));
}
DECL_INITIAL (x) = 0;
if (TREE_CODE (TREE_TYPE (x)) == ARRAY_TYPE
&& TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& TYPE_DOMAIN (TREE_TYPE (x)) != NULL_TREE
&& TYPE_MAX_VALUE (TYPE_DOMAIN (TREE_TYPE (x))) == NULL_TREE)
{
if (TREE_CODE (t) == UNION_TYPE)
error_with_decl (x, "flexible array member in union");
else if (TREE_CHAIN (x) != NULL_TREE)
error_with_decl (x, "flexible array member not at end of struct");
else if (! saw_named_field)
error_with_decl (x, "flexible array member in otherwise empty struct");
}
if (pedantic && TREE_CODE (t) == RECORD_TYPE
&& flexible_array_type_p (TREE_TYPE (x)))
pedwarn_with_decl (x, "invalid use of structure with flexible array member");
if (DECL_NAME (x))
saw_named_field = 1;
}
for (x = fieldlist; x && TREE_CHAIN (x);)
if (DECL_NAME (TREE_CHAIN (x)) == 0)
x = TREE_CHAIN (x);
else
{
tree y = fieldlist;
while (1)
{
if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
break;
if (y == x)
break;
y = TREE_CHAIN (y);
}
if (DECL_NAME (y) == DECL_NAME (TREE_CHAIN (x)))
{
error_with_decl (TREE_CHAIN (x), "duplicate member `%s'");
TREE_CHAIN (x) = TREE_CHAIN (TREE_CHAIN (x));
}
else
x = TREE_CHAIN (x);
}
TYPE_FIELDS (t) = fieldlist;
layout_type (t);
{
tree *fieldlistp = &fieldlist;
while (*fieldlistp)
if (TREE_CODE (*fieldlistp) == FIELD_DECL && DECL_INITIAL (*fieldlistp))
*fieldlistp = TREE_CHAIN (*fieldlistp);
else
fieldlistp = &TREE_CHAIN (*fieldlistp);
}
TYPE_FIELDS (t) = fieldlist;
for (x = TYPE_MAIN_VARIANT (t); x; x = TYPE_NEXT_VARIANT (x))
{
TYPE_FIELDS (x) = TYPE_FIELDS (t);
TYPE_LANG_SPECIFIC (x) = TYPE_LANG_SPECIFIC (t);
TYPE_ALIGN (x) = TYPE_ALIGN (t);
TYPE_USER_ALIGN (x) = TYPE_USER_ALIGN (t);
}
if (TREE_CODE (t) == UNION_TYPE
&& TYPE_TRANSPARENT_UNION (t)
&& TYPE_MODE (t) != DECL_MODE (TYPE_FIELDS (t)))
{
TYPE_TRANSPARENT_UNION (t) = 0;
warning ("union cannot be made transparent");
}
if (current_binding_level->incomplete_list != NULL_TREE)
{
tree prev = NULL_TREE;
for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
{
tree decl = TREE_VALUE (x);
if (TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == TYPE_MAIN_VARIANT (t)
&& TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
current_binding_level->incomplete_list = TREE_CHAIN (x);
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
{
tree element = TREE_TYPE (decl);
while (TREE_CODE (element) == ARRAY_TYPE)
element = TREE_TYPE (element);
if (element == t)
{
layout_array_type (TREE_TYPE (decl));
if (TREE_CODE (decl) != TYPE_DECL)
{
layout_decl (decl, 0);
rest_of_decl_compilation (decl, NULL, toplevel, 0);
if (! toplevel)
expand_decl (decl);
}
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
current_binding_level->incomplete_list = TREE_CHAIN (x);
}
}
}
}
rest_of_type_compilation (t, toplevel);
return t;
}
static void
layout_array_type (t)
tree t;
{
if (TREE_CODE (TREE_TYPE (t)) == ARRAY_TYPE)
layout_array_type (TREE_TYPE (t));
layout_type (t);
}
tree
start_enum (name)
tree name;
{
tree enumtype = 0;
if (name != 0)
enumtype = lookup_tag (ENUMERAL_TYPE, name, current_binding_level, 1);
if (enumtype == 0 || TREE_CODE (enumtype) != ENUMERAL_TYPE)
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype);
}
C_TYPE_BEING_DEFINED (enumtype) = 1;
if (TYPE_VALUES (enumtype) != 0)
{
error ("redeclaration of `enum %s'", IDENTIFIER_POINTER (name));
TYPE_VALUES (enumtype) = 0;
}
enum_next_value = integer_zero_node;
enum_overflow = 0;
if (flag_short_enums)
TYPE_PACKED (enumtype) = 1;
return enumtype;
}
tree
finish_enum (enumtype, values, attributes)
tree enumtype;
tree values;
tree attributes;
{
tree pair, tem;
tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
int toplevel = (global_binding_level == current_binding_level);
if (in_parm_level_p ())
warning ("enum defined inside parms");
decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
if (values == error_mark_node)
minnode = maxnode = integer_zero_node;
else
{
minnode = maxnode = TREE_VALUE (values);
for (pair = TREE_CHAIN (values); pair; pair = TREE_CHAIN (pair))
{
tree value = TREE_VALUE (pair);
if (tree_int_cst_lt (maxnode, value))
maxnode = value;
if (tree_int_cst_lt (value, minnode))
minnode = value;
}
}
unsign = (tree_int_cst_sgn (minnode) >= 0);
precision = MAX (min_precision (minnode, unsign),
min_precision (maxnode, unsign));
if (TYPE_PACKED (enumtype) || precision > TYPE_PRECISION (integer_type_node))
{
tree narrowest = c_common_type_for_size (precision, unsign);
if (narrowest == 0)
{
warning ("enumeration values exceed range of largest integer");
narrowest = long_long_integer_type_node;
}
precision = TYPE_PRECISION (narrowest);
}
else
precision = TYPE_PRECISION (integer_type_node);
if (precision == TYPE_PRECISION (integer_type_node))
enum_value_type = c_common_type_for_size (precision, 0);
else
enum_value_type = enumtype;
TYPE_MIN_VALUE (enumtype) = minnode;
TYPE_MAX_VALUE (enumtype) = maxnode;
TYPE_PRECISION (enumtype) = precision;
TREE_UNSIGNED (enumtype) = unsign;
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
if (values != error_mark_node)
{
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
tree enu = TREE_PURPOSE (pair);
TREE_TYPE (enu) = enumtype;
DECL_SIZE (enu) = TYPE_SIZE (enumtype);
DECL_SIZE_UNIT (enu) = TYPE_SIZE_UNIT (enumtype);
DECL_ALIGN (enu) = TYPE_ALIGN (enumtype);
DECL_USER_ALIGN (enu) = TYPE_USER_ALIGN (enumtype);
DECL_MODE (enu) = TYPE_MODE (enumtype);
if (int_fits_type_p (DECL_INITIAL (enu), enum_value_type))
DECL_INITIAL (enu) = convert (enum_value_type, DECL_INITIAL (enu));
else
DECL_INITIAL (enu) = convert (enumtype, DECL_INITIAL (enu));
TREE_PURPOSE (pair) = DECL_NAME (enu);
TREE_VALUE (pair) = DECL_INITIAL (enu);
}
TYPE_VALUES (enumtype) = values;
}
for (tem = TYPE_MAIN_VARIANT (enumtype); tem; tem = TYPE_NEXT_VARIANT (tem))
{
if (tem == enumtype)
continue;
TYPE_VALUES (tem) = TYPE_VALUES (enumtype);
TYPE_MIN_VALUE (tem) = TYPE_MIN_VALUE (enumtype);
TYPE_MAX_VALUE (tem) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (tem) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (tem) = TYPE_SIZE_UNIT (enumtype);
TYPE_MODE (tem) = TYPE_MODE (enumtype);
TYPE_PRECISION (tem) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (tem) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (tem) = TYPE_USER_ALIGN (enumtype);
TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
}
rest_of_type_compilation (enumtype, toplevel);
return enumtype;
}
tree
build_enumerator (name, value)
tree name, value;
{
tree decl, type;
if (value)
STRIP_TYPE_NOPS (value);
if (value != 0)
{
if (TREE_CODE (value) == INTEGER_CST)
{
value = default_conversion (value);
constant_expression_warning (value);
}
else
{
error ("enumerator value for `%s' not integer constant",
IDENTIFIER_POINTER (name));
value = 0;
}
}
if (value == 0)
{
value = enum_next_value;
if (enum_overflow)
error ("overflow in enumeration values");
}
if (pedantic && ! int_fits_type_p (value, integer_type_node))
{
pedwarn ("ISO C restricts enumerator values to range of `int'");
value = convert (integer_type_node, value);
}
enum_next_value = build_binary_op (PLUS_EXPR, value, integer_one_node, 0);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
type = TREE_TYPE (value);
type = c_common_type_for_size (MAX (TYPE_PRECISION (type),
TYPE_PRECISION (integer_type_node)),
(TYPE_PRECISION (type)
>= TYPE_PRECISION (integer_type_node)
&& TREE_UNSIGNED (type)));
decl = build_decl (CONST_DECL, name, type);
DECL_INITIAL (decl) = convert (type, value);
pushdecl (decl);
if (flag_gen_index)
gen_indexing_info (INDEX_ENUM, IDENTIFIER_POINTER (name), lineno);
return tree_cons (decl, value, NULL_TREE);
}
int
start_function (declspecs, declarator, attributes)
tree declarator, declspecs, attributes;
{
tree decl1, old_decl;
tree restype;
int old_immediate_size_expand = immediate_size_expand;
current_function_returns_value = 0;
current_function_returns_null = 0;
current_function_returns_abnormally = 0;
warn_about_return_type = 0;
current_extern_inline = 0;
named_labels = 0;
shadowed_labels = 0;
immediate_size_expand = 0;
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1);
if (decl1 == 0)
{
immediate_size_expand = old_immediate_size_expand;
return 0;
}
decl_attributes (&decl1, attributes, (int)ATTR_FLAG_FUNCTION_DEF);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl1);
if (DECL_DECLARED_INLINE_P (decl1)
&& DECL_UNINLINABLE (decl1)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl1)))
warning_with_decl (decl1,
"inline function `%s' given attribute noinline");
announce_function (decl1);
if (flag_gen_index)
{
const char *name;
name = IDENTIFIER_POINTER (DECL_NAME (decl1));
if (name[1] != '[')
gen_indexing_info (INDEX_FUNCTION_BEGIN, name, lineno);
}
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (decl1))))
{
error ("return type is an incomplete type");
TREE_TYPE (decl1)
= build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl1)));
}
if (warn_about_return_type)
pedwarn_c99 ("return type defaults to `int'");
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
DECL_INITIAL (decl1) = error_mark_node;
old_decl = lookup_name_current_level (DECL_NAME (decl1));
if (old_decl != 0 && TREE_CODE (TREE_TYPE (old_decl)) == FUNCTION_TYPE
&& !DECL_BUILT_IN (old_decl)
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
== TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (old_decl))))
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0)
{
TREE_TYPE (decl1) = TREE_TYPE (old_decl);
current_function_prototype_file = DECL_SOURCE_FILE (old_decl);
current_function_prototype_line = DECL_SOURCE_LINE (old_decl);
}
if (old_decl == 0)
old_decl = IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1));
if (warn_strict_prototypes
&& TYPE_ARG_TYPES (TREE_TYPE (decl1)) == 0
&& !(old_decl != 0
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl)))))
warning ("function declaration isn't a prototype");
else if (warn_missing_prototypes
&& TREE_PUBLIC (decl1)
&& !(old_decl != 0
&& (TYPE_ARG_TYPES (TREE_TYPE (old_decl)) != 0
|| (DECL_BUILT_IN (old_decl)
&& ! C_DECL_ANTICIPATED (old_decl))))
&& ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous prototype for `%s'");
else if (warn_missing_prototypes
&& old_decl != 0 && TREE_USED (old_decl)
&& TYPE_ARG_TYPES (TREE_TYPE (old_decl)) == 0)
warning_with_decl (decl1,
"`%s' was used with no prototype before its definition");
else if (warn_missing_declarations
&& TREE_PUBLIC (decl1)
&& old_decl == 0
&& ! MAIN_NAME_P (DECL_NAME (decl1)))
warning_with_decl (decl1, "no previous declaration for `%s'");
else if (warn_missing_declarations
&& old_decl != 0 && TREE_USED (old_decl)
&& old_decl == IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)))
warning_with_decl (decl1,
"`%s' was used with no declaration before its definition");
DECL_EXTERNAL (decl1) = current_extern_inline;
TREE_STATIC (decl1) = 1;
if (current_function_decl != 0)
TREE_PUBLIC (decl1) = 0;
if (warn_main > 0 && MAIN_NAME_P (DECL_NAME (decl1)))
{
tree args;
int argct = 0;
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (decl1)))
!= integer_type_node)
pedwarn_with_decl (decl1, "return type of `%s' is not `int'");
for (args = TYPE_ARG_TYPES (TREE_TYPE (decl1)); args;
args = TREE_CHAIN (args))
{
tree type = args ? TREE_VALUE (args) : 0;
if (type == void_type_node)
break;
++argct;
switch (argct)
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
pedwarn_with_decl (decl1,
"first argument of `%s' should be `int'");
break;
case 2:
if (TREE_CODE (type) != POINTER_TYPE
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
"second argument of `%s' should be `char **'");
break;
case 3:
if (TREE_CODE (type) != POINTER_TYPE
|| TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
|| (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
!= char_type_node))
pedwarn_with_decl (decl1,
"third argument of `%s' should probably be `char **'");
break;
}
}
if (argct > 0 && (argct < 2 || argct > 3))
pedwarn_with_decl (decl1, "`%s' takes only zero or two arguments");
if (! TREE_PUBLIC (decl1))
pedwarn_with_decl (decl1, "`%s' is normally a non-static function");
}
current_function_decl = pushdecl (decl1);
pushlevel (0);
declare_parm_level (1);
current_binding_level->subblocks_tag_transparent = 1;
make_decl_rtl (current_function_decl, NULL);
restype = TREE_TYPE (TREE_TYPE (current_function_decl));
if (c_promoting_integer_type_p (restype))
{
if (TREE_UNSIGNED (restype)
&& (TYPE_PRECISION (restype)
== TYPE_PRECISION (integer_type_node)))
restype = unsigned_type_node;
else
restype = integer_type_node;
}
DECL_RESULT (current_function_decl)
= build_decl (RESULT_DECL, NULL_TREE, restype);
if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (current_function_decl)))
TREE_ADDRESSABLE (current_function_decl) = 1;
if (DECL_CW_ASM_FUNCTION (current_function_decl))
{
cw_asm_state = cw_asm_decls;
cw_asm_in_decl = 0;
}
immediate_size_expand = old_immediate_size_expand;
start_fname_decls ();
return 1;
}
void
store_parm_decls ()
{
tree fndecl = current_function_decl;
tree parm;
tree specparms = current_function_parms;
tree parmtags = current_function_parm_tags;
tree parmdecls = getdecls ();
tree nonparms = 0;
tree context = decl_function_context (fndecl);
int prototype = 0;
int saved_warn_shadow = warn_shadow;
warn_shadow = 0;
if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
{
tree next;
tree others = 0;
prototype = 1;
if (parmdecls != 0)
{
tree decl, link;
error_with_decl (fndecl,
"parm types given both in parmlist and separately");
for (decl = current_binding_level->names;
decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl))
IDENTIFIER_LOCAL_VALUE (DECL_NAME (decl)) = 0;
for (link = current_binding_level->shadowed;
link; link = TREE_CHAIN (link))
IDENTIFIER_LOCAL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
current_binding_level->names = 0;
current_binding_level->shadowed = 0;
}
specparms = nreverse (specparms);
for (parm = specparms; parm; parm = next)
{
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME (parm) == 0)
error_with_decl (parm, "parameter name omitted");
else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
&& VOID_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' declared void");
TREE_TYPE (parm) = error_mark_node;
}
pushdecl (parm);
}
else
{
TREE_CHAIN (parm) = 0;
others = chainon (others, parm);
}
}
DECL_ARGUMENTS (fndecl) = getdecls ();
#if 0
if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl))))
!= void_type_node)
{
tree dummy = build_decl (PARM_DECL, NULL_TREE, void_type_node);
TREE_TYPE (dummy) = integer_type_node;
DECL_ARG_TYPE (dummy) = integer_type_node;
DECL_ARGUMENTS (fndecl) = chainon (DECL_ARGUMENTS (fndecl), dummy);
}
#endif
for (parm = others; parm; parm = next)
{
next = TREE_CHAIN (parm);
if (DECL_NAME (parm) == 0)
;
else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
;
else if (TREE_CODE (parm) != PARM_DECL)
pushdecl (parm);
}
storetags (parmtags);
}
else
{
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm))
{
tree tail, found = NULL;
if (TREE_VALUE (parm) == 0)
{
error_with_decl (fndecl,
"parameter name missing from parameter list");
TREE_PURPOSE (parm) = 0;
continue;
}
for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
if (DECL_NAME (tail) == TREE_VALUE (parm)
&& TREE_CODE (tail) == PARM_DECL)
{
found = tail;
break;
}
if (found && DECL_WEAK (found))
{
error_with_decl (found, "multiple parameters named `%s'");
found = 0;
}
if (found && VOID_TYPE_P (TREE_TYPE (found)))
{
error_with_decl (found, "parameter `%s' declared void");
TREE_TYPE (found) = integer_type_node;
DECL_ARG_TYPE (found) = integer_type_node;
layout_decl (found, 0);
}
if (!found)
{
found = build_decl (PARM_DECL, TREE_VALUE (parm),
integer_type_node);
DECL_ARG_TYPE (found) = TREE_TYPE (found);
DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
if (flag_isoc99)
pedwarn_with_decl (found, "type of `%s' defaults to `int'");
else if (extra_warnings)
warning_with_decl (found, "type of `%s' defaults to `int'");
pushdecl (found);
}
TREE_PURPOSE (parm) = found;
DECL_WEAK (found) = 1;
}
nonparms = 0;
for (parm = parmdecls; parm;)
{
tree next = TREE_CHAIN (parm);
TREE_CHAIN (parm) = 0;
if (TREE_CODE (parm) != PARM_DECL)
nonparms = chainon (nonparms, parm);
else
{
if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
error_with_decl (parm, "parameter `%s' has incomplete type");
TREE_TYPE (parm) = error_mark_node;
}
if (! DECL_WEAK (parm))
{
error_with_decl (parm,
"declaration for parameter `%s' but no such parameter");
specparms
= chainon (specparms,
tree_cons (parm, NULL_TREE, NULL_TREE));
}
}
parm = next;
}
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0;
{
tree last;
for (last = 0; parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
if (last == 0)
DECL_ARGUMENTS (fndecl) = TREE_PURPOSE (parm);
else
TREE_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
TREE_CHAIN (last) = 0;
}
}
if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
{
tree type;
for (parm = DECL_ARGUMENTS (fndecl),
type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
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_with_file_and_line (current_function_prototype_file,
current_function_prototype_line,
"prototype declaration");
break;
}
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)))
{
DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (TREE_TYPE (parm))
&& TYPE_PRECISION (TREE_TYPE (parm))
< TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (parm) = integer_type_node;
if (pedantic)
{
pedwarn ("promoted argument `%s' doesn't match prototype",
IDENTIFIER_POINTER (DECL_NAME (parm)));
warning_with_file_and_line
(current_function_prototype_file,
current_function_prototype_line,
"prototype declaration");
}
}
else
{
error ("argument `%s' doesn't match prototype",
IDENTIFIER_POINTER (DECL_NAME (parm)));
error_with_file_and_line (current_function_prototype_file,
current_function_prototype_line,
"prototype declaration");
}
}
}
TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
}
else
{
tree actual = 0, last = 0, type;
for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
{
type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
last = type;
}
type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
}
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
}
keep_next_if_subblocks = 1;
#if 0
keep_next_level_flag = 1;
#endif
gen_aux_info_record (fndecl, 1, 0, prototype);
init_function_start (fndecl, input_filename, lineno);
begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
if (context)
{
tree t;
DECL_LANG_SPECIFIC (fndecl)->pending_sizes
= nreverse (get_pending_sizes ());
for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
t;
t = TREE_CHAIN (t))
SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
}
cfun->x_whole_function_mode_p = 1;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
warn_shadow = saved_warn_shadow;
}
void
finish_function (nested, can_defer_p)
int nested;
int can_defer_p;
{
tree fndecl = current_function_decl;
#if 0
TREE_READONLY (fndecl) = 1;
#endif
poplevel (1, 0, 1);
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
if (MAIN_NAME_P (DECL_NAME (fndecl)) && flag_hosted)
{
if (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (fndecl)))
!= integer_type_node)
{
if (! warn_main)
pedwarn_with_decl (fndecl, "return type of `%s' is not `int'");
}
else
{
#ifdef DEFAULT_MAIN_RETURN
DEFAULT_MAIN_RETURN;
#else
if (flag_isoc99)
c_expand_return (integer_zero_node);
#endif
}
}
if (flag_gen_index)
{
const char *name;
name = IDENTIFIER_POINTER (DECL_NAME (fndecl));
gen_indexing_info (INDEX_FUNCTION_END, NULL, lineno);
}
finish_fname_decls ();
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
if (warn_return_type
&& TREE_CODE (TREE_TYPE (TREE_TYPE (fndecl))) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
&& !current_function_returns_abnormally
&& !MAIN_NAME_P (DECL_NAME (fndecl))
&& !C_FUNCTION_IMPLICIT_INT (fndecl)
&& DECL_INLINE (fndecl))
warning ("no return statement in function returning non-void");
free_after_parsing (cfun);
free_after_compilation (cfun);
cfun = NULL;
if (!flag_syntax_only && flag_loop_transpose)
loop_transpose(fndecl);
if (! nested)
{
c_expand_body (fndecl, nested, can_defer_p);
current_function_decl = NULL;
}
}
void
c_expand_deferred_function (fndecl)
tree fndecl;
{
if (DECL_INLINE (fndecl) && DECL_RESULT (fndecl))
{
c_expand_body (fndecl, 0, 0);
current_function_decl = NULL;
}
}
static void
c_expand_body (fndecl, nested_p, can_defer_p)
tree fndecl;
int nested_p, can_defer_p;
{
int uninlinable = 1;
if (flag_syntax_only)
return;
if (flag_inline_trees)
{
timevar_push (TV_INTEGRATION);
uninlinable = ! tree_inlinable_function_p (fndecl);
if (! uninlinable && can_defer_p
&& defer_fn (fndecl))
{
(*debug_hooks->deferred_inline_function) (fndecl);
timevar_pop (TV_INTEGRATION);
return;
}
optimize_inline_calls (fndecl);
timevar_pop (TV_INTEGRATION);
}
timevar_push (TV_EXPAND);
if (nested_p)
{
expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
push_function_context ();
}
current_function_decl = fndecl;
input_filename = DECL_SOURCE_FILE (fndecl);
init_function_start (fndecl, input_filename, DECL_SOURCE_LINE (fndecl));
cfun->x_whole_function_mode_p = 1;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
expand_function_start (fndecl, 0);
if (DECL_NAME (fndecl)
&& MAIN_NAME_P (DECL_NAME (fndecl))
&& DECL_CONTEXT (fndecl) == NULL_TREE)
expand_main_function ();
expand_stmt (DECL_SAVED_TREE (fndecl));
if (uninlinable)
{
DECL_SAVED_TREE (fndecl) = NULL_TREE;
}
immediate_size_expand = 1;
if (lang_expand_function_end)
(*lang_expand_function_end) ();
expand_function_end (input_filename, lineno, 0);
if (nested_p)
ggc_push_context ();
rest_of_compilation (fndecl);
if (nested_p)
ggc_pop_context ();
if (extra_warnings
&& current_function_returns_value
&& current_function_returns_null)
warning ("this function may return with or without a value");
if (warn_larger_than && !DECL_EXTERNAL (fndecl) && TREE_TYPE (fndecl))
{
tree ret_type = TREE_TYPE (TREE_TYPE (fndecl));
if (ret_type && TYPE_SIZE_UNIT (ret_type)
&& TREE_CODE (TYPE_SIZE_UNIT (ret_type)) == INTEGER_CST
&& 0 < compare_tree_int (TYPE_SIZE_UNIT (ret_type),
larger_than_size))
{
unsigned int size_as_int
= TREE_INT_CST_LOW (TYPE_SIZE_UNIT (ret_type));
if (compare_tree_int (TYPE_SIZE_UNIT (ret_type), size_as_int) == 0)
warning_with_decl (fndecl,
"size of return value of `%s' is %u bytes",
size_as_int);
else
warning_with_decl (fndecl,
"size of return value of `%s' is larger than %d bytes",
larger_than_size);
}
}
if (DECL_SAVED_INSNS (fndecl) == 0 && ! nested_p
&& ! flag_inline_trees)
{
if (DECL_INITIAL (fndecl) != 0)
DECL_INITIAL (fndecl) = error_mark_node;
DECL_ARGUMENTS (fndecl) = 0;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
{
if (targetm.have_ctors_dtors)
(* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
DEFAULT_INIT_PRIORITY);
else
static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
}
if (DECL_STATIC_DESTRUCTOR (fndecl))
{
if (targetm.have_ctors_dtors)
(* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
DEFAULT_INIT_PRIORITY);
else
static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
}
if (nested_p)
pop_function_context ();
timevar_pop (TV_EXPAND);
}
static int
check_for_loop_tags (slot, data)
PTR *slot;
PTR data ATTRIBUTE_UNUSED;
{
tree t = (tree) *slot;
if (TREE_PURPOSE (t) != 0)
{
enum tree_code code = TREE_CODE (TREE_VALUE (t));
if (code == RECORD_TYPE)
error ("`struct %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else if (code == UNION_TYPE)
error ("`union %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else
error ("`enum %s' declared in `for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t)));
}
return 1;
}
void
check_for_loop_decls ()
{
tree t;
if (!flag_isoc99)
{
error ("`for' loop initial declaration used outside C99 mode");
return;
}
if (current_binding_level->tags_ht)
htab_traverse (current_binding_level->tags_ht, check_for_loop_tags, NULL);
for (t = getdecls (); t; t = TREE_CHAIN (t))
{
if (TREE_CODE (t) != VAR_DECL && DECL_NAME (t))
error_with_decl (t, "declaration of non-variable `%s' in `for' loop initial declaration");
else if (TREE_STATIC (t))
error_with_decl (t, "declaration of static variable `%s' in `for' loop initial declaration");
else if (DECL_EXTERNAL (t))
error_with_decl (t, "declaration of `extern' variable `%s' in `for' loop initial declaration");
}
}
struct language_function GTY(())
{
struct c_language_function base;
tree named_labels;
tree shadowed_labels;
int returns_value;
int returns_null;
int returns_abnormally;
int warn_about_return_type;
int extern_inline;
struct binding_level *binding_level;
};
void
c_push_function_context (f)
struct function *f;
{
struct language_function *p;
p = ((struct language_function *)
ggc_alloc (sizeof (struct language_function)));
f->language = p;
p->base.x_stmt_tree = c_stmt_tree;
p->base.x_scope_stmt_stack = c_scope_stmt_stack;
p->named_labels = named_labels;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
p->binding_level = current_binding_level;
}
void
c_pop_function_context (f)
struct function *f;
{
struct language_function *p = f->language;
tree link;
for (link = shadowed_labels; link; link = TREE_CHAIN (link))
if (DECL_NAME (TREE_VALUE (link)) != 0)
IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)))
= TREE_VALUE (link);
if (DECL_SAVED_INSNS (current_function_decl) == 0
&& DECL_SAVED_TREE (current_function_decl) == NULL_TREE)
{
DECL_INITIAL (current_function_decl) = error_mark_node;
DECL_ARGUMENTS (current_function_decl) = 0;
}
c_stmt_tree = p->base.x_stmt_tree;
c_scope_stmt_stack = p->base.x_scope_stmt_stack;
named_labels = p->named_labels;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
current_binding_level = p->binding_level;
f->language = NULL;
}
void
c_dup_lang_specific_decl (decl)
tree decl;
{
struct lang_decl *ld;
if (!DECL_LANG_SPECIFIC (decl))
return;
ld = (struct lang_decl *) ggc_alloc (sizeof (struct lang_decl));
memcpy ((char *) ld, (char *) DECL_LANG_SPECIFIC (decl),
sizeof (struct lang_decl));
DECL_LANG_SPECIFIC (decl) = ld;
}
int
stmts_are_full_exprs_p ()
{
return 0;
}
stmt_tree
current_stmt_tree ()
{
return &c_stmt_tree;
}
tree *
current_scope_stmt_stack ()
{
return &c_scope_stmt_stack;
}
int
anon_aggr_type_p (node)
tree node ATTRIBUTE_UNUSED;
{
return 0;
}
void
extract_interface_info ()
{
}
tree
c_begin_compound_stmt ()
{
tree stmt;
stmt = add_stmt (build_stmt (COMPOUND_STMT, NULL_TREE));
return stmt;
}
void
c_expand_decl_stmt (t)
tree t;
{
tree decl = DECL_STMT_DECL (t);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_CONTEXT (decl) == current_function_decl
&& DECL_SAVED_TREE (decl))
c_expand_body (decl, 1, 0);
}
tree
identifier_global_value (t)
tree t;
{
return IDENTIFIER_GLOBAL_VALUE (t);
}
void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
const char *name;
tree type;
{
tree id;
if (name == 0)
id = ridpointers[(int) rid_index];
else
id = get_identifier (name);
pushdecl (build_decl (TYPE_DECL, id, type));
}
tree
build_void_list_node ()
{
tree t = build_tree_list (NULL_TREE, void_type_node);
return t;
}
tree
make_pointer_declarator (type_quals_attrs, target)
tree type_quals_attrs, target;
{
tree quals, attrs;
tree itarget = target;
split_specs_attrs (type_quals_attrs, &quals, &attrs);
if (attrs != NULL_TREE)
itarget = tree_cons (attrs, target, NULL_TREE);
return build1 (INDIRECT_REF, quals, itarget);
}
static tree perform_loop_transpose PARAMS ((tree *, int *, void *));
static tree tree_contains_1 PARAMS ((tree *, int *, void *));
static bool tree_contains PARAMS ((tree, tree));
static tree should_transpose_for_loops_1 PARAMS ((tree *, int *, void *));
static bool should_transpose_for_loops PARAMS ((tree, tree, tree, tree*));
static tree find_tree_with_code_1 PARAMS ((tree *, int *, void *));
static tree find_tree_with_code PARAMS ((tree, enum tree_code));
static tree find_pointer PARAMS ((tree));
static tree
find_tree_with_code_1 (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data;
{
if (*tp == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (*tp) == *((enum tree_code *)data))
return *tp;
return NULL_TREE;
}
static tree find_tree_with_code (body, code)
tree body;
enum tree_code code;
{
enum tree_code temp = code;
return walk_tree_without_duplicates (&body, find_tree_with_code_1, (void *)&temp);
}
static tree
find_pointer (t)
tree t;
{
tree temp2 = find_tree_with_code (t, ARRAY_REF);
if (temp2)
return TREE_OPERAND (temp2, 0);
temp2 = find_tree_with_code (t, INDIRECT_REF);
if (temp2)
{
temp2 = TREE_OPERAND (temp2, 0);
if (TREE_CODE (temp2) == PLUS_EXPR)
{
temp2 = TREE_OPERAND (temp2, 0);
if (TREE_CODE (temp2) == PARM_DECL || TREE_CODE (temp2) == VAR_DECL)
return temp2;
return find_pointer (temp2);
}
}
return NULL_TREE;
}
typedef struct should_transpose_for_loops_t
{
tree inner_var;
tree outer_var;
bool doit;
tree already_modified;
} should_transpose_for_loops_t;
static tree
should_transpose_for_loops_1 (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
void *data;
{
tree assignment_to = *tp;
should_transpose_for_loops_t *temp = (should_transpose_for_loops_t*)data;
tree inner_var = temp->inner_var;
tree outer_var = temp->outer_var;
if (*tp == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (*tp) == LABEL_DECL || TREE_CODE (*tp) == GOTO_STMT
|| TREE_CODE (*tp) == FOR_STMT || TREE_CODE (*tp) == DO_STMT
|| TREE_CODE (*tp) == WHILE_STMT || TREE_CODE (*tp) == IF_STMT
|| TREE_CODE (*tp) == BREAK_STMT || TREE_CODE (*tp) == CONTINUE_STMT
|| TREE_CODE (*tp) == RETURN_EXPR)
{
temp->doit = false;
return *tp;
}
if (TREE_CODE (assignment_to) == MODIFY_EXPR)
{
tree temp1;
tree temp2 = find_pointer (TREE_OPERAND (assignment_to, 0));
if (temp2 != NULL_TREE
&& tree_contains (TREE_OPERAND (assignment_to, 1), temp2))
{
temp->doit = false;
return *tp;
}
for (temp1 = temp->already_modified;
temp1 != NULL_TREE;
temp1 = TREE_CHAIN (temp1))
{
tree temp3 = TREE_VALUE(temp1);
tree temp4 = TREE_OPERAND (assignment_to, 1);
if (tree_contains (temp4, temp3)
|| (temp2 != NULL_TREE && temp3 == temp2))
{
temp->doit = false;
return *tp;
}
}
if(temp2 != NULL_TREE)
temp->already_modified =
tree_cons(NULL_TREE, temp2, temp->already_modified);
}
if ((TREE_CODE (assignment_to) == INDIRECT_REF
&& TREE_CODE (TREE_OPERAND (assignment_to, 0)) == PLUS_EXPR)
|| (TREE_CODE (assignment_to) == ARRAY_REF
&& TREE_CODE (TREE_OPERAND (assignment_to, 1)) == PLUS_EXPR))
{
tree plus1_expr_assignment = TREE_OPERAND (assignment_to,
TREE_CODE (assignment_to) == ARRAY_REF ? 1 : 0);
tree side0 = TREE_OPERAND (plus1_expr_assignment, 0);
tree side1 = TREE_OPERAND (plus1_expr_assignment, 1);
STRIP_NOPS (side0);
STRIP_NOPS (side1);
if ((TREE_CODE (side0) == INDIRECT_REF
&& tree_contains (side0, inner_var)
&& !tree_contains (side0, outer_var)
&& tree_contains (side1, outer_var)
&& !tree_contains (side1, inner_var))
|| (TREE_CODE (side1) == INDIRECT_REF
&& tree_contains (side1, inner_var)
&& !tree_contains (side1, outer_var)
&& tree_contains (side0, outer_var)
&& !tree_contains (side0, inner_var)))
{
*walk_subtrees = 0;
temp->doit = true;
return NULL_TREE;
}
else
{
tree side = NULL_TREE;
if (tree_contains (side0, inner_var)
&& tree_contains (side0, outer_var))
side = side0;
else if (tree_contains (side1, inner_var)
&& tree_contains (side1, outer_var))
side = side1;
if (side && (TREE_CODE (side) == MULT_EXPR))
{
tree temp0 = TREE_OPERAND (side, 0);
tree temp1 = TREE_OPERAND (side, 1);
STRIP_NOPS (temp0);
STRIP_NOPS (temp1);
if (tree_contains (temp0, inner_var)
&& tree_contains (temp0, outer_var))
side = temp0;
else if (tree_contains (temp1, inner_var)
&& tree_contains (temp1, outer_var))
side = temp1;
else
side = NULL_TREE;
}
if (side && (TREE_CODE (side) == PLUS_EXPR))
{
tree side10 = TREE_OPERAND (side, 0);
tree side11 = TREE_OPERAND (side, 1);
STRIP_NOPS (side10);
STRIP_NOPS (side11);
if ((TREE_CODE (side10) == MULT_EXPR
&& tree_contains (side10, inner_var)
&& !tree_contains (side10, outer_var)
&& tree_contains (side11, outer_var)
&& !tree_contains (side11, inner_var))
|| (TREE_CODE (side11) == MULT_EXPR
&& tree_contains (side11, inner_var)
&& !tree_contains (side11, outer_var)
&& tree_contains (side10, outer_var)
&& !tree_contains (side10, inner_var)))
{
*walk_subtrees = 0;
temp->doit = true;
return NULL;
}
else
{
temp->doit = false;
return *tp;
}
}
}
}
if (TREE_CODE (assignment_to) == MODIFY_EXPR)
{
tree side1 = TREE_OPERAND (assignment_to, 1);
STRIP_NOPS (side1);
if (side1 == outer_var || side1 == inner_var)
{
temp->doit = false;
return *tp;
}
}
return NULL_TREE;
}
static bool
should_transpose_for_loops (body, inner_var, outer_var, already_modified)
tree body, inner_var, outer_var, *already_modified;
{
should_transpose_for_loops_t temp;
temp.inner_var = inner_var;
temp.outer_var = outer_var;
temp.already_modified = *already_modified;
temp.doit = false;
if (walk_tree (&body, should_transpose_for_loops_1, &temp, NULL))
return false;
*already_modified = temp.already_modified;
return temp.doit;
}
static tree
tree_contains_1 (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data;
{
if (*tp == data)
return data;
return NULL_TREE;
}
static bool
tree_contains (body, x)
tree body, x;
{
return walk_tree_without_duplicates (&body, tree_contains_1, (void *)x)
!= NULL_TREE;
}
static tree
perform_loop_transpose (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees;
void *data ATTRIBUTE_UNUSED;
{
tree already_modified = NULL_TREE;
if (*tp == NULL_TREE)
return NULL_TREE;
if (TREE_CODE (*tp) == FOR_STMT)
{
tree outer_loop = *tp;
tree inner_loop = TREE_OPERAND (outer_loop, 3);
tree before_inner_loop = NULL_TREE;
tree right_before_inner_loop = NULL_TREE;
if (inner_loop == NULL_TREE
|| find_tree_with_code (inner_loop, CALL_EXPR) != NULL_TREE
|| find_tree_with_code (inner_loop, IF_STMT) != NULL_TREE)
return NULL_TREE;
if (TREE_CODE (inner_loop) == COMPOUND_STMT
&& TREE_OPERAND (inner_loop, 0) != NULL_TREE
&& TREE_CODE (TREE_OPERAND (inner_loop, 0)) == SCOPE_STMT)
{
tree previous = NULL_TREE;
before_inner_loop = TREE_OPERAND (inner_loop, 0);
if (TREE_OPERAND (before_inner_loop, 0) != NULL_TREE)
return NULL_TREE;
for (inner_loop = before_inner_loop;
inner_loop != NULL_TREE && TREE_CODE (inner_loop) != FOR_STMT;
inner_loop = TREE_CHAIN (inner_loop))
previous = inner_loop;
if (inner_loop == NULL_TREE)
return NULL_TREE;
if (inner_loop == before_inner_loop)
before_inner_loop = NULL_TREE;
right_before_inner_loop = previous;
}
if (inner_loop != NULL_TREE && TREE_CODE (inner_loop) == FOR_STMT)
{
tree outer_init = TREE_OPERAND (outer_loop, 0);
tree inner_init = TREE_OPERAND (inner_loop, 0);
if (outer_init != NULL_TREE && inner_init != NULL_TREE
&& TREE_CODE (outer_init) == EXPR_STMT
&& TREE_CODE (inner_init) == EXPR_STMT)
{
tree outer_init_expr = TREE_OPERAND (outer_init, 0);
tree inner_init_expr = TREE_OPERAND (inner_init, 0);
if (outer_init_expr != NULL_TREE && inner_init_expr != NULL_TREE
&& TREE_CODE (inner_init_expr) == MODIFY_EXPR
&& TREE_CODE (outer_init_expr) == MODIFY_EXPR)
{
tree outer_var = TREE_OPERAND (outer_init_expr, 0);
tree inner_var = TREE_OPERAND (inner_init_expr, 0);
if (!tree_contains (TREE_OPERAND (inner_init_expr, 1),
outer_var)
&& !tree_contains (TREE_OPERAND (inner_loop, 1),
outer_var)
&& !tree_contains (TREE_OPERAND (inner_loop, 2),
outer_var)
&& !tree_contains (TREE_OPERAND (outer_loop, 1),
inner_var)
&& !tree_contains (TREE_OPERAND (outer_loop, 2),
inner_var))
{
tree inner_loop_body = TREE_OPERAND (inner_loop, 3);
if (should_transpose_for_loops (inner_loop_body,
inner_var, outer_var, &already_modified))
{
tree newouter;
tree newinner;
if (TREE_CODE (TREE_OPERAND (outer_loop, 3))
== COMPOUND_STMT)
{
tree after_loop = TREE_CHAIN (inner_loop);
tree find;
tree allloops_stmt;
tree outloopafter;
tree outloopbefore;
allloops_stmt = build_stmt (COMPOUND_STMT,
NULL_TREE);
outloopbefore = build_stmt (FOR_STMT, outer_init,
TREE_OPERAND (outer_loop, 1),
TREE_OPERAND (outer_loop, 2),
NULL_TREE);
outloopafter = build_stmt (FOR_STMT, outer_init,
TREE_OPERAND (outer_loop, 1),
TREE_OPERAND (outer_loop, 2),
NULL_TREE);
newinner = build_stmt (FOR_STMT, outer_init,
TREE_OPERAND (outer_loop, 1),
TREE_OPERAND (outer_loop, 2),
inner_loop_body);
newouter = build_stmt (FOR_STMT, inner_init,
TREE_OPERAND (inner_loop, 1),
TREE_OPERAND (inner_loop, 2),
newinner);
COMPOUND_STMT_NO_SCOPE (allloops_stmt) = 1;
if (before_inner_loop != NULL_TREE
&& TREE_CODE (before_inner_loop)
== SCOPE_STMT)
{
if (right_before_inner_loop != NULL_TREE)
TREE_CHAIN (right_before_inner_loop)
= NULL_TREE;
before_inner_loop
= TREE_CHAIN (before_inner_loop);
}
if (before_inner_loop != NULL_TREE)
{
tree beforeloopbody
= build_stmt (COMPOUND_STMT, NULL_TREE);
COMPOUND_STMT_NO_SCOPE (beforeloopbody) = 1;
beforeloopbody
= build_stmt (COMPOUND_STMT, NULL_TREE);
COMPOUND_BODY (beforeloopbody)
= before_inner_loop;
FOR_BODY (outloopbefore) = beforeloopbody;
if (tree_contains (outloopbefore, inner_var))
return NULL_TREE;
for (find = already_modified;
find != NULL_TREE;
find = TREE_CHAIN (find))
{
tree temp3 = TREE_VALUE(find);
if (tree_contains(outloopbefore, temp3))
return NULL_TREE;
}
if (!tree_contains (beforeloopbody,
outer_var))
{
COMPOUND_BODY (allloops_stmt)
= beforeloopbody;
TREE_CHAIN (beforeloopbody) = newouter;
}
else
{
COMPOUND_BODY (allloops_stmt)
= outloopbefore;
TREE_CHAIN (outloopbefore) = newouter;
}
}
else
{
COMPOUND_BODY (allloops_stmt) = newouter;
outloopbefore = NULL_TREE;
}
if (after_loop != NULL_TREE
&& TREE_CHAIN (after_loop) == NULL_TREE)
{
if (TREE_CODE (after_loop) != SCOPE_STMT)
FOR_BODY (outloopafter) = after_loop;
else
outloopafter = NULL_TREE;
}
else
{
tree afterloopbody
= build_stmt (COMPOUND_STMT, NULL_TREE);
tree temp5;
COMPOUND_STMT_NO_SCOPE (afterloopbody) = 1;
COMPOUND_BODY (afterloopbody) = after_loop;
FOR_BODY (outloopafter) = afterloopbody;
for (temp5 = after_loop;
temp5 != NULL_TREE;
temp5 = TREE_CHAIN (temp5))
if (TREE_CODE (TREE_CHAIN (temp5))
== SCOPE_STMT)
TREE_CHAIN (temp5) = NULL_TREE;
if (tree_contains (afterloopbody, inner_var))
return NULL_TREE;
for (find = already_modified;
find != NULL_TREE;
find = TREE_CHAIN (find))
{
tree temp3 = TREE_VALUE(find);
if (tree_contains(afterloopbody, temp3))
return NULL_TREE;
}
if (!tree_contains (afterloopbody, outer_var))
outloopafter = afterloopbody;
}
TREE_CHAIN (newouter) = outloopafter;
if (outloopafter == NULL_TREE
&& outloopbefore == NULL_TREE)
allloops_stmt = newouter;
TREE_CHAIN (allloops_stmt)
= TREE_CHAIN (outer_loop);
*walk_subtrees = 0;
*tp = allloops_stmt;
return NULL_TREE;
}
newinner = build_stmt (FOR_STMT, outer_init,
TREE_OPERAND (outer_loop, 1),
TREE_OPERAND (outer_loop, 2),
inner_loop_body);
newouter = build_stmt (FOR_STMT, inner_init,
TREE_OPERAND (inner_loop, 1),
TREE_OPERAND (inner_loop, 2),
newinner);
TREE_CHAIN (newouter) = TREE_CHAIN (outer_loop);
*tp = newouter;
*walk_subtrees = 0;
}
}
}
}
}
}
return NULL_TREE;
}
void
loop_transpose (fn)
tree fn;
{
timevar_push (TV_LOOP_TRANSPOSE);
walk_tree (&DECL_SAVED_TREE (fn), perform_loop_transpose, NULL, NULL);
timevar_pop (TV_LOOP_TRANSPOSE);
}
#include "gt-c-decl.h"