#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
#include "lex.h"
#include <signal.h>
#include "obstack.h"
#include "defaults.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "../hash.h"
#if defined (_WIN32) && defined (NEXT_PDO)
extern char* exportNamesForDLL;
#endif
#define obstack_chunk_alloc xmalloc
#define obstack_chunk_free free
extern tree builtin_return_address_fndecl;
extern struct obstack permanent_obstack;
extern struct obstack* saveable_obstack;
extern int current_class_depth;
extern tree static_ctors, static_dtors;
extern int static_labelno;
extern tree current_namespace;
extern tree global_namespace;
extern void (*print_error_function) PROTO((char *));
extern int (*valid_lang_attribute) PROTO ((tree, tree, tree, tree));
#include "stack.h"
struct obstack decl_obstack;
static struct stack_level *decl_stack;
#ifndef CHAR_TYPE_SIZE
#define CHAR_TYPE_SIZE BITS_PER_UNIT
#endif
#ifndef SHORT_TYPE_SIZE
#define SHORT_TYPE_SIZE (BITS_PER_UNIT * MIN ((UNITS_PER_WORD + 1) / 2, 2))
#endif
#ifndef INT_TYPE_SIZE
#define INT_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef LONG_TYPE_SIZE
#define LONG_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef LONG_LONG_TYPE_SIZE
#define LONG_LONG_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#ifndef WCHAR_UNSIGNED
#define WCHAR_UNSIGNED 0
#endif
#ifndef FLOAT_TYPE_SIZE
#define FLOAT_TYPE_SIZE BITS_PER_WORD
#endif
#ifndef DOUBLE_TYPE_SIZE
#define DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#ifndef LONG_DOUBLE_TYPE_SIZE
#define LONG_DOUBLE_TYPE_SIZE (BITS_PER_WORD * 2)
#endif
#ifndef BOOL_TYPE_SIZE
#ifdef SLOW_BYTE_ACCESS
#define BOOL_TYPE_SIZE ((SLOW_BYTE_ACCESS) ? (POINTER_SIZE) : (CHAR_TYPE_SIZE))
#else
#define BOOL_TYPE_SIZE CHAR_TYPE_SIZE
#endif
#endif
#ifndef SIZE_TYPE
#define SIZE_TYPE "long unsigned int"
#endif
#ifndef PTRDIFF_TYPE
#define PTRDIFF_TYPE "long int"
#endif
#ifndef WCHAR_TYPE
#define WCHAR_TYPE "int"
#endif
#ifndef OBJCPLUS
static
#endif
tree grokparms PROTO((tree, int));
static tree lookup_nested_type PROTO((tree, tree));
static const char *redeclaration_error_message PROTO((tree, tree));
static struct stack_level *push_decl_level PROTO((struct stack_level *,
struct obstack *));
static void push_binding_level PROTO((struct binding_level *, int,
int));
static void pop_binding_level PROTO((void));
static void suspend_binding_level PROTO((void));
static void resume_binding_level PROTO((struct binding_level *));
static struct binding_level *make_binding_level PROTO((void));
static void declare_namespace_level PROTO((void));
static void signal_catch PROTO((int)) ATTRIBUTE_NORETURN;
static void storedecls PROTO((tree));
static void require_complete_types_for_parms PROTO((tree));
static void push_overloaded_decl_1 PROTO((tree));
static int ambi_op_p PROTO((tree));
static int unary_op_p PROTO((tree));
static tree store_bindings PROTO((tree, tree));
static tree lookup_tag_reverse PROTO((tree, tree));
static tree obscure_complex_init PROTO((tree, tree));
static tree maybe_build_cleanup_1 PROTO((tree, tree));
static tree lookup_name_real PROTO((tree, int, int, int));
static void warn_extern_redeclared_static PROTO((tree, tree));
static void grok_reference_init PROTO((tree, tree, tree));
static tree grokfndecl PROTO((tree, tree, tree, tree, int,
enum overload_flags, tree,
tree, int, int, int, int, int, int, tree));
static tree grokvardecl PROTO((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree lookup_tag PROTO((enum tree_code, tree,
struct binding_level *, int));
static void set_identifier_type_value_with_scope
PROTO((tree, tree, struct binding_level *));
static void record_builtin_type PROTO((enum rid, const char *, tree));
static void record_unknown_type PROTO((tree, const char *));
static int member_function_or_else PROTO((tree, tree, const char *));
static void bad_specifiers PROTO((tree, const char *, int, int, int, int,
int));
static void lang_print_error_function PROTO((char *));
static tree maybe_process_template_type_declaration PROTO((tree, int, struct binding_level*));
static void check_for_uninitialized_const_var PROTO((tree));
static unsigned long typename_hash PROTO((hash_table_key));
static boolean typename_compare PROTO((hash_table_key, hash_table_key));
static void push_binding PROTO((tree, tree, struct binding_level*));
static int add_binding PROTO((tree, tree));
static void pop_binding PROTO((tree, tree));
static tree local_variable_p PROTO((tree));
static tree find_binding PROTO((tree, tree));
static tree select_decl PROTO((tree, int));
static tree unqualified_namespace_lookup PROTO((tree, int));
static int lookup_flags PROTO((int, int));
static tree qualify_lookup PROTO((tree, int));
static tree record_builtin_java_type PROTO((const char *, int));
static const char *tag_name PROTO((enum tag_types code));
static void find_class_binding_level PROTO((void));
static struct binding_level *innermost_nonclass_level PROTO((void));
static tree poplevel_class PROTO((void));
static void warn_about_implicit_typename_lookup PROTO((tree, tree));
static int walk_namespaces_r PROTO((tree, walk_namespaces_fn, void *));
static int walk_globals_r PROTO((tree, void *));
#if defined (DEBUG_CP_BINDING_LEVELS)
static void indent PROTO((void));
#endif
tree error_mark_node;
tree error_mark_list;
tree short_integer_type_node;
tree integer_type_node;
tree long_integer_type_node;
tree long_long_integer_type_node;
tree short_unsigned_type_node;
tree unsigned_type_node;
tree long_unsigned_type_node;
tree long_long_unsigned_type_node;
tree ptrdiff_type_node;
tree unsigned_char_type_node;
tree signed_char_type_node;
tree char_type_node;
tree wchar_type_node;
tree signed_wchar_type_node;
tree unsigned_wchar_type_node;
tree wchar_decl_node;
tree float_type_node;
tree double_type_node;
tree long_double_type_node;
tree complex_integer_type_node;
tree complex_float_type_node;
tree complex_double_type_node;
tree complex_long_double_type_node;
tree vector_unsigned_char_type_node;
tree vector_signed_char_type_node;
tree vector_boolean_char_type_node;
tree vector_unsigned_short_type_node;
tree vector_signed_short_type_node;
tree vector_boolean_short_type_node;
tree vector_unsigned_long_type_node;
tree vector_signed_long_type_node;
tree vector_boolean_long_type_node;
tree vector_float_type_node;
tree vector_pixel_type_node;
tree intQI_type_node;
tree intHI_type_node;
tree intSI_type_node;
tree intDI_type_node;
#if HOST_BITS_PER_WIDE_INT >= 64
tree intTI_type_node;
#endif
tree unsigned_intQI_type_node;
tree unsigned_intHI_type_node;
tree unsigned_intSI_type_node;
tree unsigned_intDI_type_node;
#if HOST_BITS_PER_WIDE_INT >= 64
tree unsigned_intTI_type_node;
#endif
tree java_byte_type_node;
tree java_short_type_node;
tree java_int_type_node;
tree java_long_type_node;
tree java_float_type_node;
tree java_double_type_node;
tree java_char_type_node;
tree java_boolean_type_node;
tree void_type_node, void_list_node;
tree void_zero_node;
tree ptr_type_node;
tree const_ptr_type_node;
tree string_type_node, const_string_type_node;
tree char_array_type_node;
#ifdef PASCAL_STRINGS
tree unsigned_char_array_type_node;
#endif
tree int_array_type_node;
tree wchar_array_type_node;
tree boolean_type_node, boolean_true_node, boolean_false_node;
tree default_function_type;
static tree double_ftype_double, double_ftype_double_double;
static tree int_ftype_int, long_ftype_long;
static tree float_ftype_float;
static tree ldouble_ftype_ldouble;
static tree int_ftype_cptr_cptr_sizet;
tree vtable_entry_type;
tree delta_type_node;
#if 0
tree __baselist_desc_type_node;
tree __i_desc_type_node, __m_desc_type_node;
tree __t_desc_array_type, __i_desc_array_type, __m_desc_array_type;
#endif
tree __t_desc_type_node;
#if 0
tree __tp_desc_type_node;
#endif
tree __access_mode_type_node;
tree __bltn_desc_type_node, __user_desc_type_node, __class_desc_type_node;
tree __ptr_desc_type_node, __attr_desc_type_node, __func_desc_type_node;
tree __ptmf_desc_type_node, __ptmd_desc_type_node;
#if 0
tree __bltn_desc_array_type, __user_desc_array_type, __class_desc_array_type;
tree __ptr_desc_array_type, __attr_dec_array_type, __func_desc_array_type;
tree __ptmf_desc_array_type, __ptmd_desc_array_type;
#endif
static tree global_type_node;
tree class_star_type_node;
tree class_type_node, record_type_node, union_type_node, enum_type_node;
tree unknown_type_node;
tree opaque_type_node, signature_type_node;
tree sigtable_entry_type;
tree vtbl_type_node;
tree vtbl_ptr_type_node;
tree std_node;
int in_std = 0;
static int only_namespace_names;
tree dtor_label;
static rtx last_dtor_insn;
static rtx last_parm_cleanup_insn;
tree ctor_label;
tree abort_fndecl;
tree global_delete_fndecl;
extern rtx cleanup_label, return_label;
static rtx original_result_rtx;
tree base_init_expr;
tree this_identifier, in_charge_identifier;
tree ctor_identifier, dtor_identifier;
tree pfn_identifier, index_identifier, delta_identifier, delta2_identifier;
tree pfn_or_delta2_identifier, tag_identifier;
tree vt_off_identifier;
struct named_label_list
{
struct binding_level *binding_level;
tree names_in_scope;
tree label_decl;
char *filename_o_goto;
int lineno_o_goto;
struct named_label_list *next;
};
static struct named_label_list *named_label_uses = NULL;
tree static_aggregates;
tree integer_zero_node;
tree null_pointer_node;
tree null_node;
tree integer_one_node, integer_two_node, integer_three_node;
static tree enum_next_value;
static int enum_overflow;
tree last_function_parms;
static tree last_function_parm_tags;
static tree current_function_parms;
static tree current_function_parm_tags;
static tree named_labels;
static tree shadowed_labels;
tree current_function_decl;
int current_function_returns_value;
int current_function_returns_null;
tree current_function_return_value;
extern int flag_short_double;
extern int flag_no_builtin;
extern int flag_no_nonansi_builtin;
extern int flag_altivec;
extern int flag_ansi;
extern int flag_huge_objects;
extern int flag_conserve_space;
extern tree *current_lang_base, *current_lang_stack;
static int current_function_assigns_this;
int current_function_just_assigned_this;
int current_function_parms_stored;
extern int spew_debug;
extern tree previous_class_values;
tree signed_size_zero_node;
tree anonymous_namespace_name;
static
struct stack_level *
push_decl_level (stack, obstack)
struct stack_level *stack;
struct obstack *obstack;
{
struct stack_level tem;
tem.prev = stack;
return push_stack_level (obstack, (char *)&tem, sizeof (tem));
}
struct binding_level
{
tree names;
tree tags;
tree usings;
tree using_directives;
tree shadowed;
tree class_shadowed;
tree type_shadowed;
tree blocks;
tree this_block;
struct binding_level *level_chain;
tree incomplete;
tree dead_vars_from_for;
unsigned parm_flag : 4;
unsigned keep : 3;
unsigned tag_transparent : 1;
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
unsigned pseudo_global : 1;
unsigned namespace_p : 1;
unsigned is_for_scope : 1;
#if defined(DEBUG_CP_BINDING_LEVELS)
unsigned binding_depth;
#endif
};
#define NULL_BINDING_LEVEL ((struct binding_level *) NULL)
static struct binding_level *current_binding_level;
static struct binding_level *class_binding_level;
static struct binding_level *free_binding_level;
static struct binding_level *global_binding_level;
static struct binding_level clear_binding_level;
static int keep_next_level_flag;
#if defined(DEBUG_CP_BINDING_LEVELS)
static int binding_depth = 0;
static int is_class_level = 0;
static void
indent ()
{
register unsigned i;
for (i = 0; i < binding_depth*2; i++)
putc (' ', stderr);
}
#endif
static tree pushdecl_with_scope PROTO((tree, struct binding_level *));
static void
push_binding_level (newlevel, tag_transparent, keep)
struct binding_level *newlevel;
int tag_transparent, keep;
{
*newlevel = clear_binding_level;
newlevel->level_chain = current_binding_level;
current_binding_level = newlevel;
newlevel->tag_transparent = tag_transparent;
newlevel->more_cleanups_ok = 1;
newlevel->keep = keep;
#if defined(DEBUG_CP_BINDING_LEVELS)
newlevel->binding_depth = binding_depth;
indent ();
fprintf (stderr, "push %s level 0x%08x line %d\n",
(is_class_level) ? "class" : "block", newlevel, lineno);
is_class_level = 0;
binding_depth++;
#endif
}
static void
find_class_binding_level ()
{
struct binding_level *level = current_binding_level;
while (level && level->parm_flag != 2)
level = level->level_chain;
if (level && level->parm_flag == 2)
class_binding_level = level;
else
class_binding_level = 0;
}
static void
pop_binding_level ()
{
if (global_binding_level)
{
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
#if defined(DEBUG_CP_BINDING_LEVELS)
binding_depth--;
indent ();
fprintf (stderr, "pop %s level 0x%08x line %d\n",
(is_class_level) ? "class" : "block",
current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
{
indent ();
fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
}
is_class_level = 0;
#endif
{
register struct binding_level *level = current_binding_level;
current_binding_level = current_binding_level->level_chain;
level->level_chain = free_binding_level;
#if 0
if (level->binding_depth != binding_depth)
abort ();
#endif
free_binding_level = level;
find_class_binding_level ();
}
}
static void
suspend_binding_level ()
{
if (class_binding_level)
current_binding_level = class_binding_level;
if (global_binding_level)
{
if (current_binding_level == global_binding_level)
my_friendly_abort (123);
}
#if defined(DEBUG_CP_BINDING_LEVELS)
binding_depth--;
indent ();
fprintf (stderr, "suspend %s level 0x%08x line %d\n",
(is_class_level) ? "class" : "block",
current_binding_level, lineno);
if (is_class_level != (current_binding_level == class_binding_level))
{
indent ();
fprintf (stderr, "XXX is_class_level != (current_binding_level == class_binding_level)\n");
}
is_class_level = 0;
#endif
current_binding_level = current_binding_level->level_chain;
find_class_binding_level ();
}
static void
resume_binding_level (b)
struct binding_level *b;
{
my_friendly_assert(!class_binding_level, 386);
my_friendly_assert(b->level_chain == current_binding_level, 386);
current_binding_level = b;
#if defined(DEBUG_CP_BINDING_LEVELS)
b->binding_depth = binding_depth;
indent ();
fprintf (stderr, "resume %s level 0x%08x line %d\n",
(is_class_level) ? "class" : "block", b, lineno);
is_class_level = 0;
binding_depth++;
#endif
}
static
struct binding_level *
make_binding_level ()
{
return (struct binding_level *) xmalloc (sizeof (struct binding_level));
}
int
global_bindings_p ()
{
return current_binding_level == global_binding_level;
}
static struct binding_level *
innermost_nonclass_level ()
{
struct binding_level *b;
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
return b;
}
int
toplevel_bindings_p ()
{
struct binding_level *b = innermost_nonclass_level ();
return b->namespace_p || b->pseudo_global;
}
int
namespace_bindings_p ()
{
struct binding_level *b = innermost_nonclass_level ();
return b->namespace_p;
}
void
keep_next_level ()
{
keep_next_level_flag = 1;
}
int
kept_level_p ()
{
return (current_binding_level->blocks != NULL_TREE
|| current_binding_level->keep
|| current_binding_level->names != NULL_TREE
|| (current_binding_level->tags != NULL_TREE
&& !current_binding_level->tag_transparent));
}
void
declare_parm_level ()
{
current_binding_level->parm_flag = 1;
}
void
declare_pseudo_global_level ()
{
current_binding_level->pseudo_global = 1;
}
static void
declare_namespace_level ()
{
current_binding_level->namespace_p = 1;
}
int
pseudo_global_level_p ()
{
struct binding_level *b = innermost_nonclass_level ();
return b->pseudo_global;
}
void
set_class_shadows (shadows)
tree shadows;
{
class_binding_level->class_shadowed = shadows;
}
void
pushlevel (tag_transparent)
int tag_transparent;
{
register struct binding_level *newlevel = NULL_BINDING_LEVEL;
if (current_binding_level == global_binding_level)
my_friendly_assert (named_labels == NULL_TREE, 134);
#if defined(DEBUG_CP_BINDING_LEVELS)
if (0)
#else
if (free_binding_level)
#endif
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
}
else
{
newlevel = make_binding_level ();
}
push_binding_level (newlevel, tag_transparent, keep_next_level_flag);
GNU_xref_start_scope ((HOST_WIDE_INT) newlevel);
keep_next_level_flag = 0;
}
void
note_level_for_for ()
{
current_binding_level->is_for_scope = 1;
}
void
pushlevel_temporary (tag_transparent)
int tag_transparent;
{
pushlevel (tag_transparent);
current_binding_level->keep = 2;
clear_last_expr ();
expand_start_bindings (0);
}
#define BINDING_LEVEL(NODE) \
(((struct tree_binding*)NODE)->scope.level)
static tree free_binding_nodes;
static void
push_binding (id, decl, level)
tree id;
tree decl;
struct binding_level* level;
{
tree binding;
if (!free_binding_nodes)
{
push_obstacks_nochange ();
end_temporary_allocation ();
binding = make_node (CPLUS_BINDING);
pop_obstacks ();
}
else
{
binding = free_binding_nodes;
free_binding_nodes = TREE_CHAIN (free_binding_nodes);
}
BINDING_VALUE (binding) = decl;
BINDING_TYPE (binding) = NULL_TREE;
BINDING_LEVEL (binding) = level;
INHERITED_VALUE_BINDING_P (binding) = 0;
LOCAL_BINDING_P (binding) = (level != class_binding_level);
TREE_CHAIN (binding) = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
static int
add_binding (id, decl)
tree id;
tree decl;
{
tree binding = IDENTIFIER_BINDING (id);
int ok = 1;
if (TREE_CODE (decl) == TYPE_DECL && DECL_ARTIFICIAL (decl))
BINDING_TYPE (binding) = decl;
else if (!BINDING_VALUE (binding))
BINDING_VALUE (binding) = decl;
else if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
&& DECL_ARTIFICIAL (BINDING_VALUE (binding)))
{
BINDING_TYPE (binding) = BINDING_VALUE (binding);
BINDING_VALUE (binding) = decl;
INHERITED_VALUE_BINDING_P (binding) = 0;
}
else
{
cp_error ("declaration of `%#D'", decl);
cp_error_at ("conflicts with previous declaration `%#D'",
BINDING_VALUE (binding));
ok = 0;
}
return ok;
}
void
push_local_binding (id, decl, flags)
tree id;
tree decl;
int flags;
{
struct binding_level *b;
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
if (lookup_name_current_level (id))
{
if (!add_binding (id, decl))
return;
}
else
push_binding (id, decl, b);
if (TREE_CODE (decl) == OVERLOAD || (flags & PUSH_USING))
decl = build_tree_list (NULL_TREE, decl);
TREE_CHAIN (decl) = b->names;
b->names = decl;
}
int
push_class_binding (id, decl)
tree id;
tree decl;
{
int result = 1;
tree binding = IDENTIFIER_BINDING (id);
tree context;
note_name_declared_in_class (id, decl);
if (binding && BINDING_LEVEL (binding) == class_binding_level)
result = add_binding (id, decl);
else
push_binding (id, decl, class_binding_level);
IDENTIFIER_CLASS_VALUE (id) = BINDING_VALUE (IDENTIFIER_BINDING (id));
binding = IDENTIFIER_BINDING (id);
if (BINDING_VALUE (binding) == decl && TREE_CODE (decl) != TREE_LIST)
{
if (TREE_CODE (decl) == TYPE_DECL
&& IMPLICIT_TYPENAME_P (TREE_TYPE (decl)))
INHERITED_VALUE_BINDING_P (binding) = 1;
else
{
if (TREE_CODE (decl) == OVERLOAD)
context = DECL_REAL_CONTEXT (OVL_CURRENT (decl));
else
{
my_friendly_assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd',
0);
context = DECL_REAL_CONTEXT (decl);
}
if (is_properly_derived_from (current_class_type, context))
INHERITED_VALUE_BINDING_P (binding) = 1;
else
INHERITED_VALUE_BINDING_P (binding) = 0;
}
}
else if (BINDING_VALUE (binding) == decl)
INHERITED_VALUE_BINDING_P (binding) = 1;
return result;
}
static void
pop_binding (id, decl)
tree id;
tree decl;
{
tree binding;
if (id == NULL_TREE)
return;
binding = IDENTIFIER_BINDING (id);
my_friendly_assert (binding != NULL_TREE, 0);
if (BINDING_VALUE (binding) == decl)
BINDING_VALUE (binding) = NULL_TREE;
else if (BINDING_TYPE (binding) == decl)
BINDING_TYPE (binding) = NULL_TREE;
else
my_friendly_abort (0);
if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
{
IDENTIFIER_BINDING (id) = TREE_CHAIN (binding);
TREE_CHAIN (binding) = free_binding_nodes;
free_binding_nodes = binding;
}
}
tree
poplevel (keep, reverse, functionbody)
int keep;
int reverse;
int functionbody;
{
register tree link;
tree decls;
int tmp = functionbody;
int real_functionbody = current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody;
tree tags = functionbody >= 0 ? current_binding_level->tags : 0;
tree subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
tree block = NULL_TREE;
tree decl;
int block_previously_created;
int leaving_for_scope;
if (current_binding_level->parm_flag == 2)
return poplevel_class ();
my_friendly_assert (!current_binding_level->class_shadowed,
19990414);
my_friendly_assert (keep == 0 || keep == 1, 0);
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
current_binding_level->keep);
if (current_binding_level->keep == 1)
keep = 1;
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) != NULL_TREE
&& TREE_ADDRESSABLE (decl)
&& decl_function_context (decl) == current_function_decl)
{
if (DECL_ABSTRACT_ORIGIN (decl) != NULL_TREE)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (decl)) = 1;
else
{
push_function_context ();
output_inline_function (decl);
pop_function_context ();
}
}
block = NULL_TREE;
block_previously_created = (current_binding_level->this_block != NULL_TREE);
if (block_previously_created)
block = current_binding_level->this_block;
else if (keep == 1 || functionbody)
block = make_node (BLOCK);
if (block != NULL_TREE)
{
if (block_previously_created)
{
if (decls || tags || subblocks)
{
if (BLOCK_VARS (block) || BLOCK_TYPE_TAGS (block))
warning ("internal compiler error: debugging info corrupted");
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = chainon (BLOCK_SUBBLOCKS (block),
subblocks);
}
}
else
{
BLOCK_VARS (block) = decls;
BLOCK_TYPE_TAGS (block) = tags;
BLOCK_SUBBLOCKS (block) = subblocks;
remember_end_note (block);
}
}
if (keep >= 0)
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
leaving_for_scope
= current_binding_level->is_for_scope && flag_new_for_scope == 1;
for (link = decls; link; link = TREE_CHAIN (link))
{
if (leaving_for_scope && TREE_CODE (link) == VAR_DECL)
{
tree outer_binding
= TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (link)));
tree ns_binding;
if (!outer_binding)
ns_binding = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (link));
else
ns_binding = NULL_TREE;
if (outer_binding
&& (BINDING_LEVEL (outer_binding)
== current_binding_level->level_chain))
pop_binding (DECL_NAME (link), link);
else if ((outer_binding
&& (TREE_CODE (BINDING_VALUE (outer_binding))
== TYPE_DECL))
|| (ns_binding
&& TREE_CODE (ns_binding) == TYPE_DECL))
pop_binding (DECL_NAME (link), link);
else
{
DECL_DEAD_FOR_LOCAL (link) = 1;
if (outer_binding && BINDING_VALUE (outer_binding))
DECL_SHADOWED_FOR_VAR (link)
= BINDING_VALUE (outer_binding);
current_binding_level->level_chain->dead_vars_from_for
= tree_cons (NULL_TREE, link,
current_binding_level->level_chain->
dead_vars_from_for);
BINDING_LEVEL (IDENTIFIER_BINDING (DECL_NAME (link)))
= 0;
}
}
else
{
decl = link;
if (TREE_CODE (decl) == TREE_LIST)
decl = TREE_VALUE (decl);
if (TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
pop_binding (DECL_NAME (decl), decl);
else if (TREE_CODE (decl) == OVERLOAD)
pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
else
my_friendly_abort (0);
}
}
for (link = current_binding_level->dead_vars_from_for;
link; link = TREE_CHAIN (link))
pop_binding (DECL_NAME (TREE_VALUE (link)), TREE_VALUE (link));
for (link = current_binding_level->type_shadowed;
link; link = TREE_CHAIN (link))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (link), TREE_VALUE (link));
if (block)
{
tree* d;
for (d = &BLOCK_VARS (block); *d; )
{
if (TREE_CODE (*d) == TREE_LIST)
*d = TREE_CHAIN (*d);
else
d = &TREE_CHAIN (*d);
}
}
if (functionbody)
{
BLOCK_VARS (block) = 0;
for (link = named_labels; link; link = TREE_CHAIN (link))
{
register tree label = TREE_VALUE (link);
if (DECL_INITIAL (label) == NULL_TREE)
{
cp_error_at ("label `%D' used but not defined", label);
define_label (input_filename, 1, DECL_NAME (label));
}
else if (warn_unused && !TREE_USED (label))
cp_warning_at ("label `%D' defined but not used", label);
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), NULL_TREE);
TREE_CHAIN (label) = BLOCK_VARS (block);
BLOCK_VARS (block) = label;
}
named_labels = NULL_TREE;
}
{
struct binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
struct named_label_list *labels;
for (labels = named_label_uses; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
}
}
tmp = current_binding_level->keep;
pop_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 (tmp == 2)
{
expand_end_bindings (getdecls (), keep, 1);
if (block)
TREE_USED (block) = 1;
block = poplevel (keep, reverse, real_functionbody);
}
if (block)
TREE_USED (block) = 1;
return block;
}
void
delete_block (block)
tree block;
{
tree t;
if (current_binding_level->blocks == block)
current_binding_level->blocks = TREE_CHAIN (block);
for (t = current_binding_level->blocks; t;)
{
if (TREE_CHAIN (t) == block)
TREE_CHAIN (t) = TREE_CHAIN (block);
else
t = TREE_CHAIN (t);
}
TREE_CHAIN (block) = NULL_TREE;
TREE_USED (block) = 0;
}
void
insert_block (block)
tree block;
{
TREE_USED (block) = 1;
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
}
void
set_block (block)
register tree block;
{
current_binding_level->this_block = block;
}
void
pushlevel_class ()
{
register struct binding_level *newlevel;
#if defined(DEBUG_CP_BINDING_LEVELS)
if (0)
#else
if (free_binding_level)
#endif
{
newlevel = free_binding_level;
free_binding_level = free_binding_level->level_chain;
}
else
newlevel = make_binding_level ();
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
#endif
push_binding_level (newlevel, 0, 0);
decl_stack = push_decl_level (decl_stack, &decl_obstack);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
}
static tree
poplevel_class ()
{
register struct binding_level *level = class_binding_level;
tree shadowed;
my_friendly_assert (level != 0, 354);
decl_stack = pop_stack_level (decl_stack);
if (current_class_depth != 1)
{
struct binding_level* b;
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed)) = NULL_TREE;
b = level->level_chain;
while (b && b->parm_flag != 2)
b = b->level_chain;
if (b)
for (shadowed = b->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
{
tree t;
t = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
while (t && BINDING_LEVEL (t) != b)
t = TREE_CHAIN (t);
if (t)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
= BINDING_VALUE (t);
}
}
else
{
previous_class_type = current_class_type;
previous_class_values = class_binding_level->class_shadowed;
}
for (shadowed = level->type_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (shadowed), TREE_VALUE (shadowed));
for (shadowed = level->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
pop_binding (TREE_PURPOSE (shadowed), TREE_TYPE (shadowed));
GNU_xref_end_scope ((HOST_WIDE_INT) class_binding_level,
(HOST_WIDE_INT) class_binding_level->level_chain,
class_binding_level->parm_flag,
class_binding_level->keep);
#if defined(DEBUG_CP_BINDING_LEVELS)
is_class_level = 1;
#endif
pop_binding_level ();
return NULL_TREE;
}
void
clear_identifier_class_values ()
{
tree t;
if (!class_binding_level)
return;
for (t = class_binding_level->class_shadowed;
t;
t = TREE_CHAIN (t))
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (t)) = NULL_TREE;
}
int
vtable_decl_p (t, data)
tree t;
void *data ATTRIBUTE_UNUSED;
{
return (TREE_CODE (t) == VAR_DECL && DECL_VIRTUAL_P (t));
}
int
vtype_decl_p (t, data)
tree t;
void *data ATTRIBUTE_UNUSED;
{
return (TREE_CODE (t) == TYPE_DECL
&& TREE_TYPE (t) != error_mark_node
&& TYPE_LANG_SPECIFIC (TREE_TYPE (t))
&& CLASSTYPE_VSIZE (TREE_TYPE (t)));
}
int
sigtable_decl_p (t, data)
tree t;
void *data ATTRIBUTE_UNUSED;
{
return (TREE_CODE (t) == VAR_DECL
&& TREE_TYPE (t) != error_mark_node
&& IS_SIGNATURE (TREE_TYPE (t)));
}
static int
walk_namespaces_r (namespace, f, data)
tree namespace;
walk_namespaces_fn f;
void *data;
{
tree current;
int result = 0;
result |= (*f) (namespace, data);
for (current = NAMESPACE_LEVEL (namespace)->names;
current;
current = TREE_CHAIN (current))
{
if (TREE_CODE (current) != NAMESPACE_DECL
|| DECL_NAMESPACE_ALIAS (current))
continue;
if (!DECL_LANG_SPECIFIC (current))
{
my_friendly_assert (current == std_node, 393);
continue;
}
result |= walk_namespaces_r (current, f, data);
}
return result;
}
int
walk_namespaces (f, data)
walk_namespaces_fn f;
void *data;
{
return walk_namespaces_r (global_namespace, f, data);
}
struct walk_globals_data {
walk_globals_pred p;
walk_globals_fn f;
void *data;
};
static int
walk_globals_r (namespace, data)
tree namespace;
void *data;
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_pred p = wgd->p;
walk_globals_fn f = wgd->f;
void *d = wgd->data;
tree *t;
int result = 0;
t = &NAMESPACE_LEVEL (namespace)->names;
while (*t)
{
tree glbl = *t;
if ((*p) (glbl, d))
result |= (*f) (t, d);
if (*t == glbl)
t = &TREE_CHAIN (*t);
}
return result;
}
int
walk_globals (p, f, data)
walk_globals_pred p;
walk_globals_fn f;
void *data;
{
struct walk_globals_data wgd;
wgd.p = p;
wgd.f = f;
wgd.data = data;
return walk_namespaces (walk_globals_r, &wgd);
}
int
wrapup_globals_for_namespace (namespace, data)
tree namespace;
void *data;
{
tree globals = NAMESPACE_LEVEL (namespace)->names;
int len = list_length (globals);
tree *vec = (tree *) alloca (sizeof (tree) * len);
int i;
int result;
tree decl;
int last_time = (data != 0);
if (last_time && namespace == global_namespace)
return 0;
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[len - i - 1] = decl;
if (last_time)
{
check_global_declarations (vec, len);
return 0;
}
for (i = 0; i < len; ++i)
if (vtable_decl_p (vec[i], 0) && !DECL_EXTERNAL (vec[i]))
{
DECL_NOT_REALLY_EXTERN (vec[i]) = 1;
DECL_EXTERNAL (vec[i]) = 1;
}
result = wrapup_global_declarations (vec, len);
for (i = 0; i < len; ++i)
if (vtable_decl_p (vec[i], 0)
&& DECL_NOT_REALLY_EXTERN (vec[i]))
{
DECL_NOT_REALLY_EXTERN (vec[i]) = 0;
DECL_EXTERNAL (vec[i]) = 0;
}
return result;
}
static int no_print_functions = 0;
static int no_print_builtins = 0;
void
print_binding_level (lvl)
struct binding_level *lvl;
{
tree t;
int i = 0, len;
fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
fprintf (stderr, " n_incomplete=%d parm_flag=%d keep=%d",
list_length (lvl->incomplete), lvl->parm_flag, lvl->keep);
if (lvl->tag_transparent)
fprintf (stderr, " tag-transparent");
if (lvl->more_cleanups_ok)
fprintf (stderr, " more-cleanups-ok");
if (lvl->have_cleanups)
fprintf (stderr, " have-cleanups");
fprintf (stderr, "\n");
if (lvl->names)
{
fprintf (stderr, " names:\t");
for (t = lvl->names; t; t = TREE_CHAIN (t))
{
if (no_print_functions && (TREE_CODE (t) == FUNCTION_DECL))
continue;
if (no_print_builtins
&& (TREE_CODE (t) == TYPE_DECL)
&& (!strcmp (DECL_SOURCE_FILE (t),"<built-in>")))
continue;
if (TREE_CODE (t) == FUNCTION_DECL)
len = 3;
else
len = 2;
i += len;
if (i > 6)
{
fprintf (stderr, "\n\t");
i = len;
}
print_node_brief (stderr, "", t, 0);
if (t == error_mark_node)
break;
}
if (i)
fprintf (stderr, "\n");
}
if (lvl->tags)
{
fprintf (stderr, " tags:\t");
i = 0;
for (t = lvl->tags; t; t = TREE_CHAIN (t))
{
if (TREE_PURPOSE (t) == NULL_TREE)
len = 3;
else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
len = 2;
else
len = 4;
i += len;
if (i > 5)
{
fprintf (stderr, "\n\t");
i = len;
}
if (TREE_PURPOSE (t) == NULL_TREE)
{
print_node_brief (stderr, "<unnamed-typedef", TREE_VALUE (t), 0);
fprintf (stderr, ">");
}
else if (TREE_PURPOSE (t) == TYPE_IDENTIFIER (TREE_VALUE (t)))
print_node_brief (stderr, "", TREE_VALUE (t), 0);
else
{
print_node_brief (stderr, "<typedef", TREE_PURPOSE (t), 0);
print_node_brief (stderr, "", TREE_VALUE (t), 0);
fprintf (stderr, ">");
}
}
if (i)
fprintf (stderr, "\n");
}
if (lvl->class_shadowed)
{
fprintf (stderr, " class-shadowed:");
for (t = lvl->class_shadowed; t; t = TREE_CHAIN (t))
{
fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
}
fprintf (stderr, "\n");
}
if (lvl->type_shadowed)
{
fprintf (stderr, " type-shadowed:");
for (t = lvl->type_shadowed; t; t = TREE_CHAIN (t))
{
fprintf (stderr, " %s ", IDENTIFIER_POINTER (TREE_PURPOSE (t)));
}
fprintf (stderr, "\n");
}
}
void
print_other_binding_stack (stack)
struct binding_level *stack;
{
struct binding_level *level;
for (level = stack; level != global_binding_level; level = level->level_chain)
{
fprintf (stderr, "binding level ");
fprintf (stderr, HOST_PTR_PRINTF, level);
fprintf (stderr, "\n");
print_binding_level (level);
}
}
void
print_binding_stack ()
{
struct binding_level *b;
fprintf (stderr, "current_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, current_binding_level);
fprintf (stderr, "\nclass_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, class_binding_level);
fprintf (stderr, "\nglobal_binding_level=");
fprintf (stderr, HOST_PTR_PRINTF, global_binding_level);
fprintf (stderr, "\n");
if (class_binding_level)
{
for (b = class_binding_level; b; b = b->level_chain)
if (b == current_binding_level)
break;
if (b)
b = class_binding_level;
else
b = current_binding_level;
}
else
b = current_binding_level;
print_other_binding_stack (b);
fprintf (stderr, "global:\n");
print_binding_level (global_binding_level);
}
static tree
find_binding (name, scope)
tree name;
tree scope;
{
tree iter, prev = NULL_TREE;
scope = ORIGINAL_NAMESPACE (scope);
for (iter = IDENTIFIER_NAMESPACE_BINDINGS (name); iter;
iter = TREE_CHAIN (iter))
{
my_friendly_assert (TREE_CODE (iter) == CPLUS_BINDING, 374);
if (BINDING_SCOPE (iter) == scope)
{
if (prev)
{
TREE_CHAIN (prev) = TREE_CHAIN (iter);
TREE_CHAIN (iter) = IDENTIFIER_NAMESPACE_BINDINGS (name);
IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
}
return iter;
}
prev = iter;
}
return NULL_TREE;
}
tree
binding_for_name (name, scope)
tree name;
tree scope;
{
tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
tree result;
scope = ORIGINAL_NAMESPACE (scope);
if (b && TREE_CODE (b) != CPLUS_BINDING)
{
IDENTIFIER_NAMESPACE_BINDINGS (name) = NULL_TREE;
BINDING_VALUE (binding_for_name (name, global_namespace)) = b;
b = IDENTIFIER_NAMESPACE_BINDINGS (name);
}
if (b && (result = find_binding (name, scope)))
return result;
push_obstacks (&permanent_obstack, &permanent_obstack);
result = make_node (CPLUS_BINDING);
TREE_CHAIN (result) = b;
IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
BINDING_SCOPE (result) = scope;
BINDING_TYPE (result) = NULL_TREE;
BINDING_VALUE (result) = NULL_TREE;
pop_obstacks ();
return result;
}
tree
namespace_binding (name, scope)
tree name;
tree scope;
{
tree b = IDENTIFIER_NAMESPACE_BINDINGS (name);
if (b == NULL_TREE)
return NULL_TREE;
if (scope == NULL_TREE)
scope = global_namespace;
if (TREE_CODE (b) != CPLUS_BINDING)
return (scope == global_namespace) ? b : NULL_TREE;
name = find_binding (name,scope);
if (name == NULL_TREE)
return name;
return BINDING_VALUE (name);
}
void
set_namespace_binding (name, scope, val)
tree name;
tree scope;
tree val;
{
tree b;
if (scope == NULL_TREE)
scope = global_namespace;
if (scope == global_namespace)
{
b = IDENTIFIER_NAMESPACE_BINDINGS (name);
if (b == NULL_TREE || TREE_CODE (b) != CPLUS_BINDING)
{
IDENTIFIER_NAMESPACE_BINDINGS (name) = val;
return;
}
}
b = binding_for_name (name, scope);
BINDING_VALUE (b) = val;
}
void
push_namespace (name)
tree name;
{
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
int global = 0;
if (!global_namespace)
{
my_friendly_assert (name == get_identifier ("::"), 377);
global = 1;
}
else if (!name)
{
if (!anonymous_namespace_name)
anonymous_namespace_name = get_file_function_name ('N');
name = anonymous_namespace_name;
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d)
need_new = 0;
implicit_use = 1;
}
else if (current_namespace == global_namespace
&& name == DECL_NAME (std_node))
{
in_std++;
return;
}
else
{
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
{
need_new = 0;
if (DECL_NAMESPACE_ALIAS (d))
{
cp_error ("namespace alias `%D' not allowed here, assuming `%D'",
d, DECL_NAMESPACE_ALIAS (d));
d = DECL_NAMESPACE_ALIAS (d);
}
}
}
if (need_new)
{
d = build_lang_decl (NAMESPACE_DECL, name, void_type_node);
if (flag_dump_symbols)
printf ("+Nh %s %u\n", IDENTIFIER_POINTER (DECL_NAME (d)),
DECL_SOURCE_LINE (d));
if (flag_gen_index)
dump_symbol_info ("+Nh ", IDENTIFIER_POINTER (DECL_NAME (d)),
DECL_SOURCE_LINE (d));
if (!global)
{
d = pushdecl (d);
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
}
}
else
resume_binding_level (NAMESPACE_LEVEL (d));
if (implicit_use)
do_using_directive (d);
current_namespace = d;
}
void
pop_namespace ()
{
if (current_namespace == global_namespace)
{
my_friendly_assert (in_std>0, 980421);
in_std--;
return;
}
current_namespace = CP_DECL_CONTEXT (current_namespace);
suspend_binding_level ();
}
struct saved_scope {
struct binding_level *old_binding_level;
tree old_bindings;
tree old_namespace;
struct saved_scope *prev;
tree class_name, class_type;
tree access_specifier;
tree function_decl;
struct binding_level *class_bindings;
tree *lang_base, *lang_stack, lang_name;
int lang_stacksize;
int minimal_parse_mode;
tree last_function_parms;
tree template_parms;
HOST_WIDE_INT processing_template_decl;
tree previous_class_type, previous_class_values;
int processing_specialization;
int processing_explicit_instantiation;
char *class_cache_firstobj;
};
static struct saved_scope *current_saved_scope;
static tree free_binding_vecs;
static tree
store_bindings (names, old_bindings)
tree names, old_bindings;
{
tree t;
for (t = names; t; t = TREE_CHAIN (t))
{
tree binding, t1, id;
if (TREE_CODE (t) == TREE_LIST)
id = TREE_PURPOSE (t);
else
id = DECL_NAME (t);
if (!id
|| !(IDENTIFIER_BINDING (id) || IDENTIFIER_CLASS_VALUE (id)))
continue;
for (t1 = old_bindings; t1; t1 = TREE_CHAIN (t1))
if (TREE_VEC_ELT (t1, 0) == id)
goto skip_it;
if (free_binding_vecs)
{
binding = free_binding_vecs;
free_binding_vecs = TREE_CHAIN (free_binding_vecs);
}
else
binding = make_tree_vec (4);
if (id)
{
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
TREE_VEC_ELT (binding, 0) = id;
TREE_VEC_ELT (binding, 1) = REAL_IDENTIFIER_TYPE_VALUE (id);
TREE_VEC_ELT (binding, 2) = IDENTIFIER_BINDING (id);
TREE_VEC_ELT (binding, 3) = IDENTIFIER_CLASS_VALUE (id);
IDENTIFIER_BINDING (id) = NULL_TREE;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
}
TREE_CHAIN (binding) = old_bindings;
old_bindings = binding;
skip_it:
;
}
return old_bindings;
}
void
maybe_push_to_top_level (pseudo)
int pseudo;
{
extern int current_lang_stacksize;
struct saved_scope *s
= (struct saved_scope *) xmalloc (sizeof (struct saved_scope));
struct binding_level *b = current_binding_level;
tree old_bindings = NULL_TREE;
push_cp_function_context (NULL_TREE);
if (previous_class_type)
old_bindings = store_bindings (previous_class_values, old_bindings);
for (; b; b = b->level_chain)
{
tree t;
if (b == global_binding_level || (pseudo && b->pseudo_global))
break;
old_bindings = store_bindings (b->names, old_bindings);
if (b->parm_flag == 2)
old_bindings = store_bindings (b->class_shadowed, old_bindings);
for (t = b->type_shadowed; t; t = TREE_CHAIN (t))
SET_IDENTIFIER_TYPE_VALUE (TREE_PURPOSE (t), TREE_VALUE (t));
}
s->old_binding_level = current_binding_level;
current_binding_level = b;
s->old_namespace = current_namespace;
s->class_name = current_class_name;
s->class_type = current_class_type;
s->access_specifier = current_access_specifier;
s->function_decl = current_function_decl;
s->class_bindings = class_binding_level;
s->lang_stack = current_lang_stack;
s->lang_base = current_lang_base;
s->lang_stacksize = current_lang_stacksize;
s->lang_name = current_lang_name;
s->minimal_parse_mode = minimal_parse_mode;
s->last_function_parms = last_function_parms;
s->template_parms = current_template_parms;
s->processing_template_decl = processing_template_decl;
s->previous_class_type = previous_class_type;
s->previous_class_values = previous_class_values;
s->class_cache_firstobj = class_cache_firstobj;
s->processing_specialization = processing_specialization;
s->processing_explicit_instantiation = processing_explicit_instantiation;
current_class_name = current_class_type = NULL_TREE;
current_function_decl = NULL_TREE;
class_binding_level = (struct binding_level *)0;
current_lang_stacksize = 10;
current_lang_stack = current_lang_base
= (tree *) xmalloc (current_lang_stacksize * sizeof (tree));
current_lang_name = lang_name_cplusplus;
strict_prototype = strict_prototypes_lang_cplusplus;
named_labels = NULL_TREE;
shadowed_labels = NULL_TREE;
minimal_parse_mode = 0;
previous_class_type = previous_class_values = NULL_TREE;
class_cache_firstobj = 0;
processing_specialization = 0;
processing_explicit_instantiation = 0;
current_template_parms = NULL_TREE;
processing_template_decl = 0;
current_namespace = global_namespace;
s->prev = current_saved_scope;
s->old_bindings = old_bindings;
current_saved_scope = s;
push_obstacks (&permanent_obstack, &permanent_obstack);
}
void
push_to_top_level ()
{
maybe_push_to_top_level (0);
}
void
pop_from_top_level ()
{
extern int current_lang_stacksize;
struct saved_scope *s = current_saved_scope;
tree t;
if (previous_class_type)
invalidate_class_lookup_cache ();
pop_obstacks ();
current_binding_level = s->old_binding_level;
current_saved_scope = s->prev;
for (t = s->old_bindings; t; )
{
tree save = t;
tree id = TREE_VEC_ELT (t, 0);
if (id)
{
SET_IDENTIFIER_TYPE_VALUE (id, TREE_VEC_ELT (t, 1));
IDENTIFIER_BINDING (id) = TREE_VEC_ELT (t, 2);
IDENTIFIER_CLASS_VALUE (id) = TREE_VEC_ELT (t, 3);
}
t = TREE_CHAIN (t);
TREE_CHAIN (save) = free_binding_vecs;
free_binding_vecs = save;
}
current_namespace = s->old_namespace;
current_class_name = s->class_name;
current_class_type = s->class_type;
current_access_specifier = s->access_specifier;
current_function_decl = s->function_decl;
class_binding_level = s->class_bindings;
free (current_lang_base);
current_lang_base = s->lang_base;
current_lang_stack = s->lang_stack;
current_lang_name = s->lang_name;
current_lang_stacksize = s->lang_stacksize;
if (current_lang_name == lang_name_cplusplus)
strict_prototype = strict_prototypes_lang_cplusplus;
else if (current_lang_name == lang_name_c || current_lang_name == lang_name_objc)
strict_prototype = strict_prototypes_lang_c;
minimal_parse_mode = s->minimal_parse_mode;
last_function_parms = s->last_function_parms;
current_template_parms = s->template_parms;
processing_template_decl = s->processing_template_decl;
previous_class_type = s->previous_class_type;
previous_class_values = s->previous_class_values;
processing_specialization = s->processing_specialization;
processing_explicit_instantiation = s->processing_explicit_instantiation;
class_cache_firstobj = s->class_cache_firstobj;
free (s);
pop_cp_function_context (NULL_TREE);
}
static void
set_identifier_type_value_with_scope (id, type, b)
tree id;
tree type;
struct binding_level *b;
{
if (!b->namespace_p)
{
tree old_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
b->type_shadowed
= tree_cons (id, old_type_value, b->type_shadowed);
}
else
{
tree binding = binding_for_name (id, current_namespace);
BINDING_TYPE (binding) = type;
type = global_type_node;
}
SET_IDENTIFIER_TYPE_VALUE (id, type);
}
void
set_identifier_type_value (id, type)
tree id;
tree type;
{
set_identifier_type_value_with_scope (id, type, current_binding_level);
}
tree
identifier_type_value (id)
tree id;
{
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
return NULL_TREE;
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
return REAL_IDENTIFIER_TYPE_VALUE (id);
id = lookup_name_real (id, 2, 1, 0);
if (id)
return TREE_TYPE (id);
return NULL_TREE;
}
void
pop_everything ()
{
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX entering pop_everything ()\n");
#endif
while (!toplevel_bindings_p ())
{
if (current_binding_level->parm_flag == 2)
pop_nested_class ();
else
poplevel (0, 0, 0);
}
#ifdef DEBUG_CP_BINDING_LEVELS
fprintf (stderr, "XXX leaving pop_everything ()\n");
#endif
}
static tree
maybe_process_template_type_declaration (type, globalize, b)
tree type;
int globalize;
struct binding_level* b;
{
tree decl = TYPE_NAME (type);
if (processing_template_parmlist)
;
else
{
maybe_check_template_type (type);
my_friendly_assert (IS_AGGR_TYPE (type)
|| TREE_CODE (type) == ENUMERAL_TYPE, 0);
if (
(processing_template_decl && !globalize)
|| PROCESSING_REAL_TEMPLATE_DECL_P ())
{
tree name = DECL_NAME (decl);
decl = push_template_decl_real (decl, globalize);
if (TREE_CODE (type) != ENUMERAL_TYPE
&& !globalize && b->pseudo_global
&& b->level_chain->parm_flag == 2)
{
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
b->level_chain->tags =
saveable_tree_cons (name, type, b->level_chain->tags);
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
}
}
return decl;
}
void
pushtag (name, type, globalize)
tree name, type;
int globalize;
{
register struct binding_level *b;
b = current_binding_level;
while (b->tag_transparent
|| (globalize && b->parm_flag == 2))
b = b->level_chain;
if (toplevel_bindings_p ())
b->tags = perm_tree_cons (name, type, b->tags);
else
b->tags = saveable_tree_cons (name, type, b->tags);
if (name)
{
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d = NULL_TREE;
int newdecl = 0, in_class = 0;
tree context;
tree c_decl = NULL_TREE;
context = type ? TYPE_CONTEXT (type) : NULL_TREE;
if (! context)
{
tree cs = current_scope ();
if (! globalize)
context = cs;
else if (cs != NULL_TREE
&& TREE_CODE_CLASS (TREE_CODE (cs)) == 't')
context = hack_decl_function_context (get_type_decl (cs));
}
if (context)
c_decl = TREE_CODE (context) == FUNCTION_DECL
? context : TYPE_MAIN_DECL (context);
if (!context)
context = current_namespace;
if ((b->pseudo_global && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
in_class = 1;
else
d = lookup_nested_type (type, c_decl);
if (d == NULL_TREE)
{
newdecl = 1;
d = build_decl (TYPE_DECL, name, type);
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
SET_DECL_ARTIFICIAL (d);
if (! in_class)
set_identifier_type_value_with_scope (name, type, b);
}
else
d = TYPE_MAIN_DECL (d);
TYPE_NAME (type) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
d = maybe_process_template_type_declaration (type,
globalize, b);
if (b->parm_flag == 2)
{
if (newdecl && !PROCESSING_REAL_TEMPLATE_DECL_P ())
finish_member_declaration (d);
else
pushdecl_class_level (d);
}
else
d = pushdecl_with_scope (d, b);
if (newdecl)
{
if (ANON_AGGRNAME_P (name))
DECL_IGNORED_P (d) = 1;
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
DECL_ASSEMBLER_NAME (d) = DECL_NAME (d);
if (!uses_template_parms (type))
DECL_ASSEMBLER_NAME (d)
= get_identifier (build_overload_name (type, 1, 1));
}
}
if (b->parm_flag == 2)
{
if (TYPE_SIZE (current_class_type) == NULL_TREE)
CLASSTYPE_TAGS (current_class_type) = b->tags;
}
}
if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL)
TYPE_STUB_DECL (type) = TYPE_NAME (type);
else
{
tree d = build_decl (TYPE_DECL, NULL_TREE, type);
TYPE_STUB_DECL (type) = pushdecl_with_scope (d, b);
}
}
static int anon_cnt = 0;
tree
make_anon_name ()
{
char buf[32];
sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++);
return get_identifier (buf);
}
void
clear_anon_tags ()
{
register struct binding_level *b;
register tree tags;
static int last_cnt = 0;
if (last_cnt == anon_cnt)
return;
b = current_binding_level;
while (b->tag_transparent)
b = b->level_chain;
tags = b->tags;
while (tags)
{
if (TREE_PURPOSE (tags) == NULL_TREE)
break;
if (ANON_AGGRNAME_P (TREE_PURPOSE (tags)))
TREE_PURPOSE (tags) = NULL_TREE;
tags = TREE_CHAIN (tags);
}
last_cnt = anon_cnt;
}
int
decls_match (newdecl, olddecl)
tree newdecl, olddecl;
{
int types_match;
if (newdecl == olddecl)
return 1;
if (TREE_CODE (newdecl) != TREE_CODE (olddecl))
return 0;
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
tree f1 = TREE_TYPE (newdecl);
tree f2 = TREE_TYPE (olddecl);
tree p1 = TYPE_ARG_TYPES (f1);
tree p2 = TYPE_ARG_TYPES (f2);
if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl)
&& ! (DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c))
return 0;
if (TREE_CODE (f1) == METHOD_TYPE && DECL_STATIC_FUNCTION_P (olddecl))
revert_static_member_fn (&newdecl, &f1, &p1);
else if (TREE_CODE (f2) == METHOD_TYPE
&& DECL_STATIC_FUNCTION_P (newdecl))
revert_static_member_fn (&olddecl, &f2, &p2);
if (TREE_CODE (f1) != TREE_CODE (f2))
{
if (TREE_CODE (f1) == OFFSET_TYPE)
cp_compiler_error ("`%D' redeclared as member function", newdecl);
else
cp_compiler_error ("`%D' redeclared as non-member function", newdecl);
return 0;
}
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (! strict_prototypes_lang_c && DECL_LANGUAGE (olddecl) == lang_c
&& p2 == NULL_TREE)
{
types_match = self_promoting_args_p (p1);
if (p1 == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else if (!strict_prototypes_lang_c && DECL_LANGUAGE (olddecl)==lang_c
&& DECL_LANGUAGE (newdecl) == lang_c && p1 == NULL_TREE)
{
types_match = self_promoting_args_p (p2);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
else
types_match = compparms (p1, p2);
}
else
types_match = 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (!comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
return 0;
if (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
types_match = 1;
else
types_match = decls_match (DECL_TEMPLATE_RESULT (olddecl),
DECL_TEMPLATE_RESULT (newdecl));
}
else
{
if (TREE_TYPE (newdecl) == error_mark_node)
types_match = TREE_TYPE (olddecl) == error_mark_node;
else if (TREE_TYPE (olddecl) == NULL_TREE)
types_match = TREE_TYPE (newdecl) == NULL_TREE;
else if (TREE_TYPE (newdecl) == NULL_TREE)
types_match = 0;
else
types_match = comptypes (TREE_TYPE (newdecl),
TREE_TYPE (olddecl),
COMPARE_REDECLARATION);
}
return types_match;
}
static void
warn_extern_redeclared_static (newdecl, olddecl)
tree newdecl, olddecl;
{
tree name;
static const char *explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
static const char *implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
if (TREE_CODE (newdecl) == TYPE_DECL
#ifdef OBJCPLUS
|| DECL_ARTIFICIAL (olddecl)
#endif
)
return;
name = DECL_ASSEMBLER_NAME (newdecl);
if (TREE_PUBLIC (name) && DECL_THIS_STATIC (newdecl))
{
if (! (TREE_CODE (newdecl) == FUNCTION_DECL
&& olddecl != NULL_TREE
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_BUILT_IN (olddecl)
|| DECL_BUILT_IN_NONANSI (olddecl))))
{
cp_pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
if (olddecl != NULL_TREE)
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
}
}
int
duplicate_decls (newdecl, olddecl)
tree newdecl, olddecl;
{
extern struct obstack permanent_obstack;
unsigned olddecl_uid = DECL_UID (olddecl);
int olddecl_friend = 0, types_match = 0;
int new_defines_function = 0;
if (newdecl == olddecl)
return 1;
types_match = decls_match (newdecl, olddecl);
if (TREE_TYPE (newdecl) == error_mark_node
|| TREE_TYPE (olddecl) == error_mark_node)
types_match = 1;
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl)
&& (DECL_BUILT_IN (olddecl) || DECL_BUILT_IN_NONANSI (olddecl)))
{
if (! TREE_PUBLIC (newdecl)
|| (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl)))
{
if (warn_shadow)
cp_warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
return 0;
}
else if (! types_match)
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
if (! DECL_BUILT_IN (olddecl))
cp_warning ("library function `%#D' redeclared as non-function `%#D'",
olddecl, newdecl);
else
{
cp_error ("declaration of `%#D'", newdecl);
cp_error ("conflicts with built-in declaration `%#D'",
olddecl);
}
return 0;
}
cp_warning ("declaration of `%#D'", newdecl);
cp_warning ("conflicts with built-in declaration `%#D'",
olddecl);
}
}
else if (TREE_CODE (olddecl) != TREE_CODE (newdecl))
{
if ((TREE_CODE (olddecl) == TYPE_DECL && DECL_ARTIFICIAL (olddecl)
&& TREE_CODE (newdecl) != TYPE_DECL
&& ! (TREE_CODE (newdecl) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL))
|| (TREE_CODE (newdecl) == TYPE_DECL && DECL_ARTIFICIAL (newdecl)
&& TREE_CODE (olddecl) != TYPE_DECL
&& ! (TREE_CODE (olddecl) == TEMPLATE_DECL
&& (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl))
== TYPE_DECL))))
{
return 0;
}
if ((TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (olddecl))
|| (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_FUNCTION_TEMPLATE_P (newdecl)))
return 0;
cp_error ("`%#D' redeclared as different kind of symbol", newdecl);
if (TREE_CODE (olddecl) == TREE_LIST)
olddecl = TREE_VALUE (olddecl);
cp_error_at ("previous declaration of `%#D'", olddecl);
return 0;
}
else if (!types_match)
{
if (DECL_REAL_CONTEXT (newdecl) != DECL_REAL_CONTEXT (olddecl))
return 0;
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == TYPE_DECL
|| TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL)
{
cp_error ("declaration of template `%#D'", newdecl);
cp_error_at ("conflicts with previous declaration `%#D'",
olddecl);
}
else if (TREE_CODE (DECL_TEMPLATE_RESULT (olddecl)) == FUNCTION_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl))),
TYPE_ARG_TYPES (TREE_TYPE (DECL_TEMPLATE_RESULT (newdecl))))
&& comp_template_parms (DECL_TEMPLATE_PARMS (newdecl),
DECL_TEMPLATE_PARMS (olddecl)))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANGUAGE (newdecl) == lang_c
&& DECL_LANGUAGE (olddecl) == lang_c)
{
cp_error ("declaration of C function `%#D' conflicts with",
newdecl);
cp_error_at ("previous declaration `%#D' here", olddecl);
}
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
cp_error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
else
return 0;
}
else if (current_class_type == NULL_TREE
|| IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (newdecl)) != current_class_type)
{
cp_error ("conflicting types for `%#D'", newdecl);
cp_error_at ("previous declaration as `%#D'", olddecl);
}
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_SPECIALIZATION (olddecl)
&& (!DECL_TEMPLATE_INFO (newdecl)
|| (DECL_TI_TEMPLATE (newdecl)
!= DECL_TI_TEMPLATE (olddecl))))
|| (DECL_TEMPLATE_SPECIALIZATION (newdecl)
&& (!DECL_TEMPLATE_INFO (olddecl)
|| (DECL_TI_TEMPLATE (olddecl)
!= DECL_TI_TEMPLATE (newdecl))))))
return 0;
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& ((DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_USE_TEMPLATE (newdecl))
|| (DECL_TEMPLATE_INSTANTIATION (newdecl)
&& !DECL_USE_TEMPLATE (olddecl))))
return 0;
else if (TREE_CODE (newdecl) == NAMESPACE_DECL
&& DECL_NAMESPACE_ALIAS (newdecl)
&& DECL_NAMESPACE_ALIAS (newdecl) == DECL_NAMESPACE_ALIAS (olddecl))
return 1;
else
{
const char *errmsg = redeclaration_error_message (newdecl, olddecl);
if (errmsg)
{
cp_error (errmsg, newdecl);
if (DECL_NAME (olddecl) != NULL_TREE)
cp_error_at ((DECL_INITIAL (olddecl)
&& namespace_bindings_p ())
? "`%#D' previously defined here"
: "`%#D' previously declared here", olddecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_INITIAL (olddecl) != NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (olddecl)) == NULL_TREE
&& TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != NULL_TREE)
{
cp_warning_at ("prototype for `%#D'", newdecl);
cp_warning_at ("follows non-prototype definition here", olddecl);
}
else if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_LANGUAGE (newdecl) != DECL_LANGUAGE (olddecl))
{
if (current_lang_stack == current_lang_base)
DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
cp_error ("conflicts with new declaration with %L linkage",
DECL_LANGUAGE (newdecl));
}
}
if (DECL_LANG_SPECIFIC (olddecl) && DECL_USE_TEMPLATE (olddecl))
;
else if (TREE_CODE (olddecl) == FUNCTION_DECL)
{
tree t1 = TYPE_ARG_TYPES (TREE_TYPE (olddecl));
tree t2 = TYPE_ARG_TYPES (TREE_TYPE (newdecl));
int i = 1;
if (TREE_CODE (TREE_TYPE (newdecl)) == METHOD_TYPE)
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2);
for (; t1 && t1 != void_list_node;
t1 = TREE_CHAIN (t1), t2 = TREE_CHAIN (t2), i++)
if (TREE_PURPOSE (t1) && TREE_PURPOSE (t2))
{
if (1 == simple_cst_equal (TREE_PURPOSE (t1),
TREE_PURPOSE (t2)))
{
if (pedantic)
{
cp_pedwarn ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_pedwarn_at ("after previous specification in `%#D'",
olddecl);
}
}
else
{
cp_error ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_error_at ("after previous specification in `%#D'",
olddecl);
}
}
if (DECL_THIS_INLINE (newdecl) && ! DECL_THIS_INLINE (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
cp_warning ("`%#D' was used before it was declared inline",
newdecl);
cp_warning_at ("previous non-inline declaration here",
olddecl);
}
}
}
warn_extern_redeclared_static (newdecl, olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_VINDEX (olddecl))
DECL_VINDEX (newdecl) = DECL_VINDEX (olddecl);
if (DECL_CONTEXT (olddecl))
DECL_CONTEXT (newdecl) = DECL_CONTEXT (olddecl);
if (DECL_CLASS_CONTEXT (olddecl))
DECL_CLASS_CONTEXT (newdecl) = DECL_CLASS_CONTEXT (olddecl);
if (DECL_PENDING_INLINE_INFO (newdecl) == (struct pending_inline *)0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_ABSTRACT_VIRTUAL_P (newdecl) |= DECL_ABSTRACT_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
new_defines_function = DECL_INITIAL (newdecl) != NULL_TREE;
if (warn_redundant_decls && ! DECL_ARTIFICIAL (olddecl)
&& !(new_defines_function && DECL_INITIAL (olddecl) == NULL_TREE)
&& !(DECL_EXTERNAL (olddecl) && ! DECL_EXTERNAL (newdecl))
&& ! DECL_FRIEND_P (newdecl))
{
cp_warning ("redundant redeclaration of `%D' in same scope", newdecl);
cp_warning_at ("previous declaration of `%D'", olddecl);
}
}
if (TREE_CODE (olddecl) == TYPE_DECL)
{
register tree newtype = TREE_TYPE (newdecl);
register tree oldtype = TREE_TYPE (olddecl);
if (newtype != error_mark_node && oldtype != error_mark_node
&& TYPE_LANG_SPECIFIC (newtype) && TYPE_LANG_SPECIFIC (oldtype))
{
CLASSTYPE_VSIZE (newtype) = CLASSTYPE_VSIZE (oldtype);
CLASSTYPE_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
}
}
DECL_MACHINE_ATTRIBUTES (newdecl)
= merge_machine_decl_attributes (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if (! duplicate_decls (DECL_TEMPLATE_RESULT (newdecl),
DECL_TEMPLATE_RESULT (olddecl)))
cp_error ("invalid redeclaration of %D", newdecl);
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
return 1;
}
if (types_match)
{
tree oldtype = TREE_TYPE (olddecl);
tree newtype;
if (oldtype)
push_obstacks (TYPE_OBSTACK (oldtype), TYPE_OBSTACK (oldtype));
else
{
push_obstacks_nochange ();
end_temporary_allocation ();
}
newtype = common_type (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
if (TREE_CODE (newdecl) == VAR_DECL)
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
else if (TREE_CODE (newdecl) == FUNCTION_DECL
&& (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl))
!= TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl))))
{
TREE_TYPE (newdecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)));
TREE_TYPE (olddecl) = build_exception_variant (newtype,
TYPE_RAISES_EXCEPTIONS (oldtype));
if ((pedantic || (! DECL_IN_SYSTEM_HEADER (olddecl)
&& ! DECL_IN_SYSTEM_HEADER (newdecl)))
&& DECL_SOURCE_LINE (olddecl) != 0
&& flag_exceptions
&& ! compexcepttypes (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
{
cp_pedwarn ("declaration of `%D' throws different exceptions",
newdecl);
cp_pedwarn_at ("previous declaration here", olddecl);
}
}
TREE_TYPE (newdecl) = TREE_TYPE (olddecl) = newtype;
if (! same_type_p (newtype, oldtype)
&& TREE_TYPE (newdecl) != error_mark_node
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_type (TREE_TYPE (newdecl));
if ((TREE_CODE (newdecl) == VAR_DECL
|| TREE_CODE (newdecl) == PARM_DECL
|| TREE_CODE (newdecl) == RESULT_DECL
|| TREE_CODE (newdecl) == FIELD_DECL
|| TREE_CODE (newdecl) == TYPE_DECL)
&& !(processing_template_decl && uses_template_parms (newdecl)))
layout_decl (newdecl, 0);
if (TREE_READONLY (newdecl))
TREE_READONLY (olddecl) = 1;
if (TREE_THIS_VOLATILE (newdecl))
TREE_THIS_VOLATILE (olddecl) = 1;
if (DECL_INITIAL (newdecl) == NULL_TREE
&& DECL_INITIAL (olddecl) != NULL_TREE)
{
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
DECL_SOURCE_FILE (newdecl) = DECL_SOURCE_FILE (olddecl);
DECL_SOURCE_LINE (newdecl) = DECL_SOURCE_LINE (olddecl);
if (DECL_LANG_SPECIFIC (newdecl)
&& DECL_LANG_SPECIFIC (olddecl))
DECL_SAVED_TREE (newdecl) = DECL_SAVED_TREE (olddecl);
}
if (DECL_SECTION_NAME (newdecl) == NULL_TREE)
DECL_SECTION_NAME (newdecl) = DECL_SECTION_NAME (olddecl);
if ((DECL_LANG_SPECIFIC (olddecl)
&& !DECL_ABSTRACT_VIRTUAL_P (olddecl))
|| DECL_RTL (olddecl) != DECL_RTL (abort_fndecl))
DECL_RTL (newdecl) = DECL_RTL (olddecl);
pop_obstacks ();
}
else
{
tree oldstatic = value_member (olddecl, static_aggregates);
if (oldstatic)
TREE_VALUE (oldstatic) = error_mark_node;
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);
}
DECL_WEAK (newdecl) |= DECL_WEAK (olddecl);
DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
#ifdef HAVE_COALESCED_SYMBOLS
DECL_COALESCED (newdecl) |= DECL_COALESCED (olddecl);
#endif
#ifdef NEXT_SEMANTICS
DECL_PRIVATE_EXTERN (newdecl) = DECL_PRIVATE_EXTERN (olddecl);
DECL_RELATIVE (newdecl) = DECL_RELATIVE (olddecl);
#endif
if (DECL_LANG_SPECIFIC (newdecl) && DECL_LANG_SPECIFIC (olddecl))
{
DECL_INTERFACE_KNOWN (newdecl) |= DECL_INTERFACE_KNOWN (olddecl);
DECL_NOT_REALLY_EXTERN (newdecl) |= DECL_NOT_REALLY_EXTERN (olddecl);
DECL_COMDAT (newdecl) |= DECL_COMDAT (olddecl);
DECL_TEMPLATE_INSTANTIATED (newdecl)
|= DECL_TEMPLATE_INSTANTIATED (olddecl);
DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
olddecl_friend = DECL_FRIEND_P (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (newdecl))
DECL_BEFRIENDING_CLASSES (newdecl)
= chainon (DECL_BEFRIENDING_CLASSES (newdecl),
DECL_BEFRIENDING_CLASSES (olddecl));
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_TEMPLATE_INSTANTIATION (olddecl)
&& !DECL_TEMPLATE_INSTANTIATION (newdecl))
{
my_friendly_assert (DECL_TEMPLATE_SPECIALIZATION (newdecl),
0);
if (TREE_USED (olddecl))
cp_error ("explicit specialization of %D after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
}
DECL_THIS_INLINE (newdecl) |= DECL_THIS_INLINE (olddecl);
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
if (! types_match)
{
DECL_LANGUAGE (olddecl) = DECL_LANGUAGE (newdecl);
DECL_ASSEMBLER_NAME (olddecl) = DECL_ASSEMBLER_NAME (newdecl);
DECL_RTL (olddecl) = DECL_RTL (newdecl);
}
if (! types_match || new_defines_function)
{
DECL_ARGUMENTS (olddecl) = DECL_ARGUMENTS (newdecl);
DECL_RESULT (olddecl) = DECL_RESULT (newdecl);
}
if (new_defines_function)
DECL_LANGUAGE (newdecl) = DECL_LANGUAGE (olddecl);
else
{
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN (newdecl) = 1;
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
DECL_RTL (newdecl) = DECL_RTL (olddecl);
}
else
DECL_FRAME_SIZE (newdecl) = DECL_FRAME_SIZE (olddecl);
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if ((DECL_SAVED_INSNS (newdecl) = DECL_SAVED_INSNS (olddecl)))
DECL_INITIAL (newdecl) = DECL_INITIAL (olddecl);
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
if (DECL_LANG_SPECIFIC (olddecl))
DECL_MAIN_VARIANT (newdecl) = DECL_MAIN_VARIANT (olddecl);
}
#if defined (_WIN32) && defined (NEXT_PDO)
DECL_DLLIMPORT(newdecl) = DECL_DLLIMPORT(olddecl);
#endif
if (TREE_CODE (newdecl) == NAMESPACE_DECL)
{
NAMESPACE_LEVEL (newdecl) = NAMESPACE_LEVEL (olddecl);
}
TREE_ADDRESSABLE (newdecl) = TREE_ADDRESSABLE (olddecl);
TREE_ASM_WRITTEN (newdecl) = TREE_ASM_WRITTEN (olddecl);
DECL_COMMON (newdecl) = DECL_COMMON (olddecl);
DECL_ASSEMBLER_NAME (newdecl) = DECL_ASSEMBLER_NAME (olddecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
struct lang_decl *ol = DECL_LANG_SPECIFIC (olddecl);
struct lang_decl *nl = DECL_LANG_SPECIFIC (newdecl);
function_size = sizeof (struct tree_decl);
bcopy ((char *) newdecl + sizeof (struct tree_common),
(char *) olddecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
#define ROUND(x) ((x + obstack_alignment_mask (&permanent_obstack)) \
& ~ obstack_alignment_mask (&permanent_obstack))
if (DECL_TEMPLATE_INSTANTIATION (newdecl))
{
tree tmpl = DECL_TI_TEMPLATE (newdecl);
tree decls = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
for (; decls; decls = TREE_CHAIN (decls))
if (TREE_VALUE (decls) == newdecl)
TREE_VALUE (decls) = olddecl;
}
if (((char *)newdecl + ROUND (function_size) == (char *)nl
&& ((char *)newdecl + ROUND (function_size)
+ ROUND (sizeof (struct lang_decl))
== obstack_next_free (&permanent_obstack)))
|| ((char *)newdecl + ROUND (function_size)
== obstack_next_free (&permanent_obstack)))
{
DECL_MAIN_VARIANT (newdecl) = olddecl;
DECL_LANG_SPECIFIC (olddecl) = ol;
bcopy ((char *)nl, (char *)ol, sizeof (struct lang_decl));
obstack_free (&permanent_obstack, newdecl);
}
else if (LANG_DECL_PERMANENT (ol) && ol != nl)
{
if (DECL_MAIN_VARIANT (olddecl) == olddecl)
{
extern tree free_lang_decl_chain;
tree free_lang_decl = (tree) ol;
if (DECL_LANG_SPECIFIC (olddecl) == ol)
abort ();
TREE_CHAIN (free_lang_decl) = free_lang_decl_chain;
free_lang_decl_chain = free_lang_decl;
}
else
{
;
}
}
}
else
{
bcopy ((char *) newdecl + sizeof (struct tree_common),
(char *) olddecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
+ tree_code_length [(int)TREE_CODE (newdecl)] * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
return 1;
}
tree
pushdecl (x)
tree x;
{
register tree t;
register tree name = DECL_ASSEMBLER_NAME (x);
int need_new_binding = 1;
if (DECL_TEMPLATE_PARM_P (x))
;
else
{
if (current_function_decl && x != current_function_decl
&& (TREE_CODE (x) != FUNCTION_DECL || DECL_INITIAL (x))
&& (TREE_CODE (x) != FUNCTION_DECL || !DECL_VIRTUAL_P (x))
&& !DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
if (!DECL_CONTEXT (x))
DECL_CONTEXT (x) = FROB_CONTEXT (current_namespace);
}
if (TREE_CODE (x) == TYPE_DECL || TREE_CODE (x) == VAR_DECL
|| TREE_CODE (x) == NAMESPACE_DECL)
name = DECL_NAME (x);
if (name)
{
#if 0
char *file;
int line;
#endif
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x))
t = namespace_binding (name, DECL_CONTEXT (x));
else
t = lookup_name_current_level (name);
if (t == error_mark_node)
{
t = NULL_TREE;
cp_error_at ("`%#D' used prior to declaration", x);
}
else if (t != NULL_TREE)
{
#if 0
file = DECL_SOURCE_FILE (t);
line = DECL_SOURCE_LINE (t);
#endif
if (TREE_CODE (t) == PARM_DECL)
{
if (DECL_CONTEXT (t) == NULL_TREE)
fatal ("parse errors have confused me too much");
if (duplicate_decls (x, t))
return t;
}
else if (((TREE_CODE (x) == FUNCTION_DECL && DECL_LANGUAGE (x) == lang_c)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
cp_pedwarn ("redeclaration of wchar_t as `%T'", TREE_TYPE (x));
return t;
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
return t;
}
else if (duplicate_decls (x, t))
{
#if 0
if (! TREE_PUBLIC (name) && TREE_PUBLIC (x))
{
if (DECL_LANG_SPECIFIC (t) && DECL_FRIEND_P (t))
return t;
if (extra_warnings)
{
cp_warning ("`static' missing from declaration of `%D'",
t);
warning_with_file_and_line (file, line,
"previous declaration of `%s'",
decl_as_string (t, 0));
}
if (current_function_decl)
TREE_PUBLIC (current_function_decl) = 0;
}
if (current_function_decl == x)
current_function_decl = t;
#endif
if (TREE_CODE (t) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (name, TREE_TYPE (t));
else if (TREE_CODE (t) == FUNCTION_DECL)
check_default_args (t);
return t;
}
else if (DECL_MAIN_P (x))
{
cp_error_at ("invalid redeclaration of `%D'", t);
cp_error ("as `%D'", x);
return x;
}
}
check_template_shadow (x);
if (TREE_CODE (x) == FUNCTION_DECL
&& ! DECL_LANG_SPECIFIC (x))
{
retrofit_lang_decl (x);
DECL_LANGUAGE (x) = lang_c;
}
if (TREE_CODE (x) == FUNCTION_DECL && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x || DECL_LANGUAGE (x) == lang_c)
return t;
if (!namespace_bindings_p ())
need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
return push_overloaded_decl (x, PUSH_GLOBAL);
if (TREE_CODE (x) == TYPE_DECL)
{
tree type = TREE_TYPE (x);
if (DECL_SOURCE_LINE (x) == 0)
{
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = x;
}
else if (type != error_mark_node && TYPE_NAME (type) != x
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))
{
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
DECL_ORIGINAL_TYPE (x) = type;
type = build_type_copy (type);
TYPE_STUB_DECL (type) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
TYPE_NAME (type) = x;
TREE_TYPE (x) = type;
pop_obstacks ();
}
if (type != error_mark_node
&& TYPE_NAME (type)
&& TYPE_IDENTIFIER (type))
set_identifier_type_value_with_scope (DECL_NAME (x), type,
current_binding_level);
}
if (TREE_PUBLIC (x) && TREE_CODE (x) != FUNCTION_DECL)
{
tree decl;
if (IDENTIFIER_NAMESPACE_VALUE (name) != NULL_TREE
&& (DECL_EXTERNAL (IDENTIFIER_NAMESPACE_VALUE (name))
|| TREE_PUBLIC (IDENTIFIER_NAMESPACE_VALUE (name))))
decl = IDENTIFIER_NAMESPACE_VALUE (name);
else
decl = NULL_TREE;
if (decl
&& TREE_CODE (decl) == TREE_CODE (x)
&& !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
cp_pedwarn ("type mismatch with previous external decl", x);
cp_pedwarn_at ("previous external decl of `%#D'", decl);
}
}
if (namespace_bindings_p ())
{
if (IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE && TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
if (!(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)
&& t != NULL_TREE))
{
if (TREE_CODE (x) == FUNCTION_DECL)
my_friendly_assert
((IDENTIFIER_GLOBAL_VALUE (name) == NULL_TREE)
|| (IDENTIFIER_GLOBAL_VALUE (name) == x), 378);
SET_IDENTIFIER_NAMESPACE_VALUE (name, x);
}
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_USED (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_USED (x) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name)
&& TREE_ADDRESSABLE (IDENTIFIER_IMPLICIT_DECL (name)))
TREE_ADDRESSABLE (x) = 1;
if (IDENTIFIER_IMPLICIT_DECL (name) != NULL_TREE
&& ! (TREE_CODE (x) == FUNCTION_DECL
&& TREE_TYPE (TREE_TYPE (x)) == integer_type_node))
cp_warning
("`%D' was previously implicitly declared to return `int'", x);
if (x != NULL_TREE && t != NULL_TREE && decls_match (x, t))
warn_extern_redeclared_static (x, t);
}
else
{
tree oldlocal = IDENTIFIER_VALUE (name);
tree oldglobal = IDENTIFIER_NAMESPACE_VALUE (name);
if (need_new_binding)
{
push_local_binding (name, x, 0);
need_new_binding = 0;
}
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value_with_scope (name, TREE_TYPE (x),
current_binding_level);
if (TREE_CODE (x) == NAMESPACE_DECL)
set_identifier_type_value_with_scope (name, NULL_TREE,
current_binding_level);
if (oldlocal == NULL_TREE
&& DECL_EXTERNAL (x)
&& oldglobal != NULL_TREE
&& TREE_CODE (x) == FUNCTION_DECL
&& TREE_CODE (oldglobal) == FUNCTION_DECL)
{
if (decls_match (x, oldglobal))
;
else
{
cp_warning ("extern declaration of `%#D' doesn't match", x);
cp_warning_at ("global declaration `%#D'", oldglobal);
}
}
if (oldlocal == NULL_TREE
&& oldglobal == NULL_TREE
&& DECL_EXTERNAL (x)
&& TREE_PUBLIC (x))
TREE_PUBLIC (name) = 1;
if (DECL_FROM_INLINE (x))
;
else if (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
&& TREE_CODE (oldlocal) == PARM_DECL
&& DECL_CONTEXT (oldlocal) == current_function_decl
&& TREE_CODE (x) != PARM_DECL)
{
struct binding_level *b = current_binding_level->level_chain;
if (cleanup_label)
b = b->level_chain;
if (b->parm_flag == 1)
cp_error ("declaration of `%#D' shadows a parameter", name);
}
else if (warn_shadow && oldlocal != NULL_TREE
&& current_binding_level->is_for_scope
&& !DECL_DEAD_FOR_LOCAL (oldlocal))
{
warning ("variable `%s' shadows local",
IDENTIFIER_POINTER (name));
cp_warning_at (" this is the shadowed declaration", oldlocal);
}
else if (warn_shadow && !DECL_EXTERNAL (x)
&& ! DECL_ARTIFICIAL (x)
&& ! DECL_FROM_INLINE (x))
{
const char *warnstring = NULL;
if (oldlocal != NULL_TREE && TREE_CODE (oldlocal) == PARM_DECL)
warnstring = "declaration of `%s' shadows a parameter";
else if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
&& current_class_ptr
&& !TREE_STATIC (name))
warnstring = "declaration of `%s' shadows a member of `this'";
else if (oldlocal != NULL_TREE)
warnstring = "declaration of `%s' shadows previous local";
else if (oldglobal != NULL_TREE)
warnstring = "declaration of `%s' shadows global declaration";
if (warnstring)
warning (warnstring, IDENTIFIER_POINTER (name));
}
}
if (TREE_CODE (x) == FUNCTION_DECL)
check_default_args (x);
if (TREE_CODE (x) == VAR_DECL
&& TREE_TYPE (x) != error_mark_node
&& ((TYPE_SIZE (TREE_TYPE (x)) == NULL_TREE
&& PROMOTES_TO_AGGR_TYPE (TREE_TYPE (x), ARRAY_TYPE))
|| (TYPE_LANG_SPECIFIC (TREE_TYPE (x))
&& TYPE_BEING_DEFINED (TREE_TYPE (x)))))
current_binding_level->incomplete
= tree_cons (NULL_TREE, x, current_binding_level->incomplete);
}
if (need_new_binding)
{
TREE_CHAIN (x) = current_binding_level->names;
current_binding_level->names = x;
if (current_binding_level == global_binding_level
&& !TREE_PERMANENT (x))
my_friendly_abort (124);
}
return x;
}
static tree
pushdecl_with_scope (x, level)
tree x;
struct binding_level *level;
{
register struct binding_level *b;
tree function_decl = current_function_decl;
current_function_decl = NULL_TREE;
if (level->parm_flag == 2)
{
b = class_binding_level;
class_binding_level = level;
pushdecl_class_level (x);
class_binding_level = b;
}
else
{
b = current_binding_level;
current_binding_level = level;
x = pushdecl (x);
current_binding_level = b;
}
current_function_decl = function_decl;
return x;
}
tree
pushdecl_namespace_level (x)
tree x;
{
register struct binding_level *b = current_binding_level;
register tree t;
t = pushdecl_with_scope (x, NAMESPACE_LEVEL (current_namespace));
if (TREE_CODE (x) == TYPE_DECL)
{
tree name = DECL_NAME (x);
tree newval;
tree *ptr = (tree *)0;
for (; b != global_binding_level; b = b->level_chain)
{
tree shadowed = b->type_shadowed;
for (; shadowed; shadowed = TREE_CHAIN (shadowed))
if (TREE_PURPOSE (shadowed) == name)
{
ptr = &TREE_VALUE (shadowed);
}
}
newval = TREE_TYPE (x);
if (ptr == (tree *)0)
{
SET_IDENTIFIER_TYPE_VALUE (name, newval);
}
else
{
*ptr = newval;
}
}
return t;
}
tree
pushdecl_top_level (x)
tree x;
{
tree cur_namespace = current_namespace;
current_namespace = global_namespace;
x = pushdecl_namespace_level (x);
current_namespace = cur_namespace;
return x;
}
void
pushdecl_class_level (x)
tree x;
{
register tree name;
if (TREE_CODE (x) == OVERLOAD)
x = OVL_CURRENT (x);
name = DECL_NAME (x);
if (name)
{
push_class_level_binding (name, x);
if (TREE_CODE (x) == TYPE_DECL)
set_identifier_type_value (name, TREE_TYPE (x));
}
else if (ANON_UNION_TYPE_P (TREE_TYPE (x)))
{
tree f;
for (f = TYPE_FIELDS (TREE_TYPE (x));
f;
f = TREE_CHAIN (f))
pushdecl_class_level (f);
}
}
#if 0
void
pushdecl_nonclass_level (x)
tree x;
{
struct binding_level *b = current_binding_level;
my_friendly_assert (b->parm_flag != 2, 180);
#if 0
while (b->pseudo_global)
b = b->level_chain;
#endif
pushdecl_with_scope (x, b);
}
#endif
void
push_class_level_binding (name, x)
tree name;
tree x;
{
tree binding;
if (!class_binding_level)
return;
if (TYPE_BEING_DEFINED (current_class_type))
check_template_shadow (x);
binding = IDENTIFIER_BINDING (name);
if (binding
&& ((TREE_CODE (x) == OVERLOAD
&& BINDING_VALUE (binding)
&& is_overloaded_fn (BINDING_VALUE (binding)))
|| INHERITED_VALUE_BINDING_P (binding)))
{
tree shadow;
tree old_decl;
if (INHERITED_VALUE_BINDING_P (binding)
&& BINDING_VALUE (binding)
&& TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
&& DECL_ARTIFICIAL (BINDING_VALUE (binding))
&& !(TREE_CODE (x) == TYPE_DECL && DECL_ARTIFICIAL (x)))
{
old_decl = BINDING_TYPE (binding);
BINDING_TYPE (binding) = BINDING_VALUE (binding);
BINDING_VALUE (binding) = NULL_TREE;
INHERITED_VALUE_BINDING_P (binding) = 0;
}
else
old_decl = BINDING_VALUE (binding);
for (shadow = class_binding_level->class_shadowed;
shadow;
shadow = TREE_CHAIN (shadow))
if (TREE_PURPOSE (shadow) == name
&& TREE_TYPE (shadow) == old_decl)
{
BINDING_VALUE (binding) = x;
INHERITED_VALUE_BINDING_P (binding) = 0;
TREE_TYPE (shadow) = x;
return;
}
}
if (push_class_binding (name, x))
{
push_cache_obstack ();
class_binding_level->class_shadowed
= tree_cons (name, IDENTIFIER_CLASS_VALUE (name),
class_binding_level->class_shadowed);
pop_obstacks ();
TREE_TYPE (class_binding_level->class_shadowed) = x;
}
}
tree
push_using_decl (scope, name)
tree scope;
tree name;
{
tree decl;
my_friendly_assert (TREE_CODE (scope) == NAMESPACE_DECL, 383);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 384);
for (decl = current_binding_level->usings; decl; decl = TREE_CHAIN (decl))
if (DECL_INITIAL (decl) == scope && DECL_NAME (decl) == name)
break;
if (decl)
return NULL_TREE;
decl = build_lang_decl (USING_DECL, name, void_type_node);
DECL_INITIAL (decl) = scope;
TREE_CHAIN (decl) = current_binding_level->usings;
current_binding_level->usings = decl;
return decl;
}
tree
push_using_directive (used)
tree used;
{
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
if (purpose_member (used, ud) != NULL_TREE)
return NULL_TREE;
for (iter = DECL_NAMESPACE_USING (used); iter; iter = TREE_CHAIN (iter))
push_using_directive (TREE_PURPOSE (iter));
ancestor = namespace_ancestor (current_decl_namespace (), used);
ud = current_binding_level->using_directives;
ud = perm_tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
return ud;
}
tree
push_overloaded_decl (decl, flags)
tree decl;
int flags;
{
tree name = DECL_NAME (decl);
tree old;
tree new_binding;
int doing_global = (namespace_bindings_p () || !(flags & PUSH_LOCAL));
if (doing_global)
{
old = namespace_binding (name, DECL_CONTEXT (decl));
if (old && TREE_CODE (old) == FUNCTION_DECL
&& DECL_ARTIFICIAL (old)
&& (DECL_BUILT_IN (old) || DECL_BUILT_IN_NONANSI (old)))
{
if (duplicate_decls (decl, old))
return old;
old = NULL_TREE;
}
}
else
old = lookup_name_current_level (name);
if (old)
{
if (TREE_CODE (old) == TYPE_DECL && DECL_ARTIFICIAL (old))
{
tree t = TREE_TYPE (old);
if (IS_AGGR_TYPE (t) && warn_shadow
&& (! DECL_IN_SYSTEM_HEADER (decl)
|| ! DECL_IN_SYSTEM_HEADER (old)))
cp_warning ("`%#D' hides constructor for `%#T'", decl, t);
old = NULL_TREE;
}
else if (is_overloaded_fn (old))
{
tree tmp;
for (tmp = old; tmp; tmp = OVL_NEXT (tmp))
{
tree fn = OVL_CURRENT (tmp);
if (TREE_CODE (tmp) == OVERLOAD && OVL_USED (tmp)
&& !(flags & PUSH_USING)
&& compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)),
TYPE_ARG_TYPES (TREE_TYPE (decl))))
cp_error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn);
if (duplicate_decls (decl, fn))
return fn;
}
}
else
{
cp_error_at ("previous non-function declaration `%#D'", old);
cp_error ("conflicts with function declaration `%#D'", decl);
return decl;
}
}
if (old || TREE_CODE (decl) == TEMPLATE_DECL)
{
if (old && TREE_CODE (old) != OVERLOAD)
new_binding = ovl_cons (decl, ovl_cons (old, NULL_TREE));
else
new_binding = ovl_cons (decl, old);
if (flags & PUSH_USING)
OVL_USED (new_binding) = 1;
}
else
new_binding = decl;
if (doing_global)
set_namespace_binding (name, current_namespace, new_binding);
else
{
if (TREE_CODE (new_binding) == OVERLOAD && old)
{
tree *d;
for (d = &BINDING_LEVEL (IDENTIFIER_BINDING (name))->names;
*d;
d = &TREE_CHAIN (*d))
if (*d == old
|| (TREE_CODE (*d) == TREE_LIST
&& TREE_VALUE (*d) == old))
{
if (TREE_CODE (*d) == TREE_LIST)
TREE_VALUE (*d) = new_binding;
else
*d = build_tree_list (NULL_TREE, new_binding);
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
return decl;
}
my_friendly_abort (0);
}
push_local_binding (name, new_binding, flags);
}
return decl;
}
tree
implicitly_declare (functionid)
tree functionid;
{
register tree decl;
int temp = allocation_temporary_p ();
push_obstacks_nochange ();
if (temp && (! warn_implicit || toplevel_bindings_p ()))
end_temporary_allocation ();
decl = build_lang_decl (FUNCTION_DECL, functionid, default_function_type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
pushdecl (decl);
rest_of_decl_compilation (decl, NULL_PTR, 0, 0);
if (warn_implicit
&& IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
{
cp_pedwarn ("implicit declaration of function `%#D'", decl);
}
SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
pop_obstacks ();
return decl;
}
static const char *
redeclaration_error_message (newdecl, olddecl)
tree newdecl, olddecl;
{
if (TREE_CODE (newdecl) == TYPE_DECL)
{
if (same_type_p (TREE_TYPE (newdecl), TREE_TYPE (olddecl)))
return 0;
else
return "redefinition of `%#D'";
}
else if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_LANG_SPECIFIC (olddecl) && DECL_ABSTRACT_VIRTUAL_P (olddecl))
return 0;
if (DECL_NAMESPACE_SCOPE_P (olddecl)
&& DECL_CONTEXT (olddecl) != DECL_CONTEXT (newdecl))
return "`%D' conflicts with used function";
if (DECL_INITIAL (olddecl) != NULL_TREE
&& DECL_INITIAL (newdecl) != NULL_TREE)
{
if (DECL_NAME (olddecl) == NULL_TREE)
return "`%#D' not declared in class";
else
return "redefinition of `%#D'";
}
return 0;
}
else if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
if ((TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == FUNCTION_DECL
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
|| (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
&& TYPE_SIZE (TREE_TYPE (newdecl))
&& TYPE_SIZE (TREE_TYPE (olddecl))))
return "redefinition of `%#D'";
return 0;
}
else if (toplevel_bindings_p ())
{
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
return "redefinition of `%#D'";
}
else
{
if (!(DECL_EXTERNAL (newdecl) && DECL_EXTERNAL (olddecl)))
return "redeclaration of `%#D'";
return 0;
}
}
tree
lookup_label (id)
tree id;
{
register tree decl = IDENTIFIER_LABEL_VALUE (id);
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
return NULL_TREE;
}
if ((decl == NULL_TREE
|| DECL_SOURCE_LINE (decl) == 0)
&& (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl))
{
struct named_label_list *new_ent;
new_ent
= (struct named_label_list*)oballoc (sizeof (struct named_label_list));
new_ent->label_decl = decl;
new_ent->names_in_scope = current_binding_level->names;
new_ent->binding_level = current_binding_level;
new_ent->lineno_o_goto = lineno;
new_ent->filename_o_goto = input_filename;
new_ent->next = named_label_uses;
named_label_uses = new_ent;
}
if (decl != NULL_TREE)
{
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);
label_rtx (decl);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
DECL_SOURCE_LINE (decl) = lineno;
DECL_SOURCE_FILE (decl) = input_filename;
SET_IDENTIFIER_LABEL_VALUE (id, decl);
named_labels = tree_cons (NULL_TREE, decl, named_labels);
named_label_uses->label_decl = decl;
return decl;
}
tree
shadow_label (name)
tree name;
{
register tree decl = IDENTIFIER_LABEL_VALUE (name);
if (decl != NULL_TREE)
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
}
return lookup_label (name);
}
tree
define_label (filename, line, name)
char *filename;
int line;
tree name;
{
tree decl;
if (minimal_parse_mode)
{
push_obstacks (&permanent_obstack, &permanent_obstack);
decl = build_decl (LABEL_DECL, name, void_type_node);
pop_obstacks ();
DECL_SOURCE_LINE (decl) = line;
DECL_SOURCE_FILE (decl) = filename;
add_tree (decl);
return decl;
}
decl = lookup_label (name);
current_binding_level->more_cleanups_ok = 0;
if (decl != NULL_TREE && DECL_CONTEXT (decl) != current_function_decl)
{
shadowed_labels = tree_cons (NULL_TREE, decl, shadowed_labels);
SET_IDENTIFIER_LABEL_VALUE (name, NULL_TREE);
decl = lookup_label (name);
}
if (name == get_identifier ("wchar_t"))
cp_pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
{
cp_error ("duplicate label `%D'", decl);
return 0;
}
else
{
struct named_label_list *uses, *prev;
int identified = 0;
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
prev = NULL;
uses = named_label_uses;
while (uses != NULL)
if (uses->label_decl == decl)
{
struct binding_level *b = current_binding_level;
while (b)
{
tree new_decls = b->names;
tree old_decls = (b == uses->binding_level)
? uses->names_in_scope : NULL_TREE;
while (new_decls != old_decls)
{
if (TREE_CODE (new_decls) == VAR_DECL
&& ! DECL_ARTIFICIAL (new_decls)
&& !(DECL_INITIAL (new_decls) == NULL_TREE
&& pod_type_p (TREE_TYPE (new_decls))))
{
int problem = (DECL_INITIAL (new_decls)
|| (TYPE_NEEDS_CONSTRUCTING
(TREE_TYPE (new_decls))));
if (! identified)
{
if (problem)
{
cp_error ("jump to label `%D'", decl);
error_with_file_and_line
(uses->filename_o_goto,
uses->lineno_o_goto, " from here");
}
else
{
cp_pedwarn ("jump to label `%D'", decl);
pedwarn_with_file_and_line
(uses->filename_o_goto,
uses->lineno_o_goto, " from here");
}
identified = 1;
}
if (problem)
cp_error_at (" crosses initialization of `%#D'",
new_decls);
else
cp_pedwarn_at (" enters scope of non-POD `%#D'",
new_decls);
}
new_decls = TREE_CHAIN (new_decls);
}
if (b == uses->binding_level)
break;
b = b->level_chain;
}
if (prev != NULL)
prev->next = uses->next;
else
named_label_uses = uses->next;
uses = uses->next;
}
else
{
prev = uses;
uses = uses->next;
}
current_function_return_value = NULL_TREE;
return decl;
}
}
struct cp_switch
{
struct binding_level *level;
struct cp_switch *next;
};
static struct cp_switch *switch_stack;
void
push_switch ()
{
struct cp_switch *p
= (struct cp_switch *) oballoc (sizeof (struct cp_switch));
p->level = current_binding_level;
p->next = switch_stack;
switch_stack = p;
}
void
pop_switch ()
{
switch_stack = switch_stack->next;
}
void
define_case_label ()
{
tree cleanup = last_cleanup_this_contour ();
struct binding_level *b = current_binding_level;
int identified = 0;
if (cleanup)
{
static int explained = 0;
cp_warning_at ("destructor needed for `%#D'", TREE_PURPOSE (cleanup));
warning ("where case label appears here");
if (!explained)
{
warning ("(enclose actions of previous case statements requiring");
warning ("destructors in their own binding contours.)");
explained = 1;
}
}
for (; b && b != switch_stack->level; b = b->level_chain)
{
tree new_decls = b->names;
for (; new_decls; new_decls = TREE_CHAIN (new_decls))
{
if (TREE_CODE (new_decls) == VAR_DECL
&& ! DECL_ARTIFICIAL (new_decls)
&& ((DECL_INITIAL (new_decls) != NULL_TREE
&& DECL_INITIAL (new_decls) != error_mark_node)
|| TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (new_decls))))
{
if (! identified)
error ("jump to case label");
identified = 1;
cp_error_at (" crosses initialization of `%#D'",
new_decls);
}
}
}
current_binding_level->more_cleanups_ok = 0;
current_function_return_value = NULL_TREE;
}
tree
getdecls ()
{
return current_binding_level->names;
}
tree
gettags ()
{
return current_binding_level->tags;
}
static void
storedecls (decls)
tree decls;
{
current_binding_level->names = decls;
}
void
storetags (tags)
tree tags;
{
current_binding_level->tags = tags;
}
static tree
lookup_tag (form, name, binding_level, thislevel_only)
enum tree_code form;
tree name;
struct binding_level *binding_level;
int thislevel_only;
{
register struct binding_level *level;
int allow_pseudo_global = 1;
for (level = binding_level; level; level = level->level_chain)
{
register tree tail;
if (ANON_AGGRNAME_P (name))
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TYPE_IDENTIFIER (TREE_VALUE (tail)) == name)
return TREE_VALUE (tail);
}
else if (level->namespace_p)
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
tree old = binding_for_name (name, tail);
if (thislevel_only && !allow_pseudo_global
&& old && BINDING_VALUE (old)
&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (old)))
old = TREE_TYPE (BINDING_VALUE (old));
else
old = BINDING_TYPE (old);
if (old && DECL_ORIGINAL_TYPE (TYPE_NAME (old)))
old = NULL_TREE;
if (old && TREE_CODE (old) != form
&& !(form != ENUMERAL_TYPE && TREE_CODE (old) == TEMPLATE_DECL))
{
cp_error ("`%#D' redeclared as %C", old, form);
return NULL_TREE;
}
if (old)
return old;
if (thislevel_only || tail == global_namespace)
return NULL_TREE;
}
else
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_PURPOSE (tail) == name)
{
enum tree_code code = TREE_CODE (TREE_VALUE (tail));
if (code != form
&& !(form != ENUMERAL_TYPE && code == TEMPLATE_DECL))
{
cp_error ("`%#D' redeclared as %C", TREE_VALUE (tail),
form);
return NULL_TREE;
}
return TREE_VALUE (tail);
}
}
if (thislevel_only && ! level->tag_transparent)
{
if (level->pseudo_global && allow_pseudo_global)
{
allow_pseudo_global = 0;
continue;
}
else
return NULL_TREE;
}
if (current_class_type && level->level_chain->namespace_p)
{
tree context = current_class_type;
while (context)
{
switch (TREE_CODE_CLASS (TREE_CODE (context)))
{
tree these_tags;
case 't':
these_tags = CLASSTYPE_TAGS (context);
if (ANON_AGGRNAME_P (name))
while (these_tags)
{
if (TYPE_IDENTIFIER (TREE_VALUE (these_tags))
== name)
return TREE_VALUE (tail);
these_tags = TREE_CHAIN (these_tags);
}
else
while (these_tags)
{
if (TREE_PURPOSE (these_tags) == name)
{
if (TREE_CODE (TREE_VALUE (these_tags)) != form)
{
cp_error ("`%#D' redeclared as %C in class scope",
TREE_VALUE (tail), form);
return NULL_TREE;
}
return TREE_VALUE (tail);
}
these_tags = TREE_CHAIN (these_tags);
}
if (TYPE_SIZE (context) == NULL_TREE)
goto no_context;
context = DECL_CONTEXT (TYPE_MAIN_DECL (context));
break;
case 'd':
context = DECL_CONTEXT (context);
break;
default:
my_friendly_abort (10);
}
continue;
no_context:
break;
}
}
}
return NULL_TREE;
}
#if 0
void
set_current_level_tags_transparency (tags_transparent)
int tags_transparent;
{
current_binding_level->tag_transparent = tags_transparent;
}
#endif
static tree
lookup_tag_reverse (type, name)
tree type;
tree name;
{
register struct binding_level *level;
for (level = current_binding_level; level; level = level->level_chain)
{
register tree tail;
for (tail = level->tags; tail; tail = TREE_CHAIN (tail))
{
if (TREE_VALUE (tail) == type)
{
if (name)
TREE_PURPOSE (tail) = name;
return TREE_PURPOSE (tail);
}
}
}
return NULL_TREE;
}
static tree
lookup_nested_type (type, context)
tree type;
tree context;
{
if (context == NULL_TREE)
return NULL_TREE;
while (context)
{
switch (TREE_CODE (context))
{
case TYPE_DECL:
{
tree ctype = TREE_TYPE (context);
tree match = value_member (type, CLASSTYPE_TAGS (ctype));
if (match)
return TREE_VALUE (match);
context = DECL_CONTEXT (context);
if (context && TREE_CODE (context) == RECORD_TYPE)
context = TREE_CHAIN (context);
}
break;
case FUNCTION_DECL:
if (TYPE_NAME (type) && TYPE_IDENTIFIER (type))
return lookup_name (TYPE_IDENTIFIER (type), 1);
return NULL_TREE;
default:
my_friendly_abort (12);
}
}
return NULL_TREE;
}
tree
lookup_namespace_name (namespace, name)
tree namespace, name;
{
struct tree_binding _b;
tree val;
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
if (TREE_CODE (name) == NAMESPACE_DECL)
return name;
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
cp_error ("invalid use of `%D'", name);
return error_mark_node;
}
namespace = ORIGINAL_NAMESPACE (namespace);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
val = binding_init (&_b);
if (!qualified_lookup_using_namespace (name, namespace, val, 0))
return error_mark_node;
if (BINDING_VALUE (val))
{
val = BINDING_VALUE (val);
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
return val;
}
cp_error ("`%D' undeclared in namespace `%D'", name, namespace);
return error_mark_node;
}
static unsigned long
typename_hash (k)
hash_table_key k;
{
unsigned long hash;
tree t;
t = (tree) k;
hash = (((unsigned long) TYPE_CONTEXT (t))
^ ((unsigned long) DECL_NAME (TYPE_NAME (t))));
return hash;
}
static boolean
typename_compare (k1, k2)
hash_table_key k1;
hash_table_key k2;
{
tree t1;
tree t2;
tree d1;
tree d2;
t1 = (tree) k1;
t2 = (tree) k2;
d1 = TYPE_NAME (t1);
d2 = TYPE_NAME (t2);
return (DECL_NAME (d1) == DECL_NAME (d2)
&& same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2))
&& ((TREE_TYPE (t1) != NULL_TREE)
== (TREE_TYPE (t2) != NULL_TREE))
&& same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
&& TYPENAME_TYPE_FULLNAME (t1) == TYPENAME_TYPE_FULLNAME (t2));
}
tree
build_typename_type (context, name, fullname, base_type)
tree context;
tree name;
tree fullname;
tree base_type;
{
tree t;
tree d;
struct hash_entry* e;
static struct hash_table ht;
push_obstacks (&permanent_obstack, &permanent_obstack);
if (!ht.table
&& !hash_table_init (&ht, &hash_newfunc, &typename_hash,
&typename_compare))
fatal ("virtual memory exhausted");
if (!TREE_PERMANENT (fullname))
fullname = copy_to_permanent (fullname);
t = make_lang_type (TYPENAME_TYPE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TYPENAME_TYPE_FULLNAME (t) = fullname;
TREE_TYPE (t) = base_type;
d = build_decl (TYPE_DECL, name, t);
TYPE_NAME (TREE_TYPE (d)) = d;
TYPE_STUB_DECL (TREE_TYPE (d)) = d;
DECL_CONTEXT (d) = FROB_CONTEXT (context);
DECL_ARTIFICIAL (d) = 1;
e = hash_lookup (&ht, t, false, 0);
if (e)
{
obstack_free (&permanent_obstack, t);
t = (tree) e->key;
}
else
hash_lookup (&ht, t, true, 0);
pop_obstacks ();
return t;
}
tree
make_typename_type (context, name)
tree context, name;
{
tree t;
tree fullname;
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
{
if (!(TYPE_LANG_SPECIFIC (name)
&& (CLASSTYPE_IS_TEMPLATE (name)
|| CLASSTYPE_USE_TEMPLATE (name))))
name = TYPE_IDENTIFIER (name);
else
name = build_nt (TEMPLATE_ID_EXPR,
CLASSTYPE_TI_TEMPLATE (name),
CLASSTYPE_TI_ARGS (name));
}
else if (TREE_CODE (name) == TYPE_DECL)
name = DECL_NAME (name);
fullname = name;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == TEMPLATE_DECL)
name = TREE_OPERAND (fullname, 0) = DECL_NAME (name);
}
if (TREE_CODE (name) != IDENTIFIER_NODE)
my_friendly_abort (2000);
if (TREE_CODE (context) == NAMESPACE_DECL)
{
cp_error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
if (! uses_template_parms (context)
|| currently_open_class (context))
{
if (TREE_CODE (fullname) == TEMPLATE_ID_EXPR)
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, 0);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
cp_error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
0);
}
else
{
if (IS_AGGR_TYPE (context))
t = lookup_field (context, name, 0, 1);
else
{
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
if (t)
return TREE_TYPE (t);
}
}
if (!uses_template_parms (context) && !t)
{
cp_error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
return build_typename_type (context, name, fullname, NULL_TREE);
}
static tree
select_decl (binding, flags)
tree binding;
int flags;
{
tree val;
val = BINDING_VALUE (binding);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
if (val && TREE_CODE (val) == NAMESPACE_DECL)
return val;
return NULL_TREE;
}
if (BINDING_TYPE (binding)
&& (!val || ((flags & LOOKUP_PREFER_TYPES)
&& TREE_CODE (val) != TYPE_DECL)))
val = TYPE_STUB_DECL (BINDING_TYPE (binding));
else if (val && LOOKUP_TYPES_ONLY (flags) && TREE_CODE (val) != TYPE_DECL
&& (TREE_CODE (val) != TEMPLATE_DECL
|| !DECL_CLASS_TEMPLATE_P (val)))
val = NULL_TREE;
return val;
}
static tree
unqualified_namespace_lookup (name, flags)
tree name;
int flags;
{
struct tree_binding _binding;
tree b = binding_init (&_binding);
tree initial = current_decl_namespace();
tree scope = initial;
tree siter;
struct binding_level *level;
tree val = NULL_TREE;
while (!val)
{
val = binding_for_name (name, scope);
BINDING_VALUE (b) = BINDING_VALUE (val);
BINDING_TYPE (b) = BINDING_TYPE (val);
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
if (!lookup_using_namespace (name, b, level->using_directives,
scope, flags))
return error_mark_node;
siter = initial;
while (1)
{
if (!lookup_using_namespace (name, b, DECL_NAMESPACE_USING (siter),
scope, flags))
return error_mark_node;
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
val = select_decl (b, flags);
if (scope == global_namespace)
break;
scope = CP_DECL_CONTEXT (scope);
}
return val;
}
static int
lookup_flags (prefer_type, namespaces_only)
int prefer_type, namespaces_only;
{
if (namespaces_only)
return LOOKUP_PREFER_NAMESPACES;
if (prefer_type > 1)
return LOOKUP_PREFER_TYPES;
if (prefer_type > 0)
return LOOKUP_PREFER_BOTH;
return 0;
}
static tree
qualify_lookup (val, flags)
tree val;
int flags;
{
if (val == NULL_TREE)
return val;
if ((flags & LOOKUP_PREFER_NAMESPACES) && TREE_CODE (val) == NAMESPACE_DECL)
return val;
if ((flags & LOOKUP_PREFER_TYPES)
&& (TREE_CODE (val) == TYPE_DECL
|| ((flags & LOOKUP_TEMPLATES_EXPECTED)
&& DECL_CLASS_TEMPLATE_P (val))))
return val;
if (flags & (LOOKUP_PREFER_NAMESPACES | LOOKUP_PREFER_TYPES))
return NULL_TREE;
return val;
}
static void
warn_about_implicit_typename_lookup (typename, binding)
tree typename;
tree binding;
{
tree subtype = TREE_TYPE (TREE_TYPE (typename));
tree name = DECL_NAME (typename);
if (! (TREE_CODE (binding) == TEMPLATE_DECL
&& CLASSTYPE_TEMPLATE_INFO (subtype)
&& CLASSTYPE_TI_TEMPLATE (subtype) == binding)
&& ! (TREE_CODE (binding) == TYPE_DECL
&& same_type_p (TREE_TYPE (binding), subtype)))
{
cp_warning ("lookup of `%D' finds `%#D'",
name, binding);
cp_warning (" instead of `%D' from dependent base class",
typename);
cp_warning (" (use `typename %T::%D' if that's what you meant)",
constructor_name (current_class_type), name);
}
}
static tree
lookup_name_real (name, prefer_type, nonclass, namespaces_only)
tree name;
int prefer_type, nonclass, namespaces_only;
{
tree t;
tree val = NULL_TREE;
int yylex = 0;
tree from_obj = NULL_TREE;
int flags;
int val_is_implicit_typename = 0;
if (only_namespace_names)
namespaces_only = 1;
if (prefer_type == -2)
{
extern int looking_for_typename;
tree type = NULL_TREE;
yylex = 1;
prefer_type = looking_for_typename;
flags = lookup_flags (prefer_type, namespaces_only);
if (looking_for_template)
flags |= LOOKUP_TEMPLATES_EXPECTED;
if (got_scope == std_node)
got_scope = void_type_node;
if (got_scope)
type = got_scope;
else if (got_object != error_mark_node)
type = got_object;
if (type)
{
if (type == error_mark_node)
return error_mark_node;
if (TREE_CODE (type) == TYPENAME_TYPE && TREE_TYPE (type))
type = TREE_TYPE (type);
if (TYPE_P (type))
type = complete_type (type);
if (TREE_CODE (type) == VOID_TYPE)
type = global_namespace;
if (TREE_CODE (type) == NAMESPACE_DECL)
{
struct tree_binding b;
val = binding_init (&b);
flags |= LOOKUP_COMPLAIN;
if (!qualified_lookup_using_namespace (name, type, val, flags))
return NULL_TREE;
val = select_decl (val, flags);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (type) == TYPENAME_TYPE)
val = NULL_TREE;
else if (type == current_class_type)
val = IDENTIFIER_CLASS_VALUE (name);
else
val = lookup_member (type, name, 0, prefer_type);
}
else
val = NULL_TREE;
if (got_scope)
goto done;
else if (got_object && val)
from_obj = val;
}
else
{
flags = lookup_flags (prefer_type, namespaces_only);
flags |= LOOKUP_COMPLAIN;
}
for (t = IDENTIFIER_BINDING (name); t; t = TREE_CHAIN (t))
{
tree binding;
if (!LOCAL_BINDING_P (t) && nonclass)
continue;
if (qualify_lookup (BINDING_VALUE (t), flags))
binding = BINDING_VALUE (t);
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (BINDING_TYPE (t), flags))
binding = BINDING_TYPE (t);
else
binding = NULL_TREE;
if (binding
&& (!val || !(TREE_CODE (binding) == TYPE_DECL
&& IMPLICIT_TYPENAME_P (TREE_TYPE (binding)))))
{
if (val_is_implicit_typename && !yylex)
warn_about_implicit_typename_lookup (val, binding);
val = binding;
val_is_implicit_typename
= (TREE_CODE (val) == TYPE_DECL
&& IMPLICIT_TYPENAME_P (TREE_TYPE (val)));
if (!val_is_implicit_typename)
break;
}
}
if (!val || val_is_implicit_typename)
{
t = unqualified_namespace_lookup (name, flags);
if (t)
{
if (val_is_implicit_typename && !yylex)
warn_about_implicit_typename_lookup (val, t);
val = t;
}
}
done:
if (val)
{
if (from_obj && from_obj != val)
{
if (looking_for_typename && TREE_CODE (from_obj) == TYPE_DECL
&& TREE_CODE (val) == TYPE_DECL
&& TREE_TYPE (from_obj) != TREE_TYPE (val))
{
cp_pedwarn ("lookup of `%D' in the scope of `%#T' (`%#T')",
name, got_object, TREE_TYPE (from_obj));
cp_pedwarn (" does not match lookup in the current scope (`%#T')",
TREE_TYPE (val));
}
if (! uses_template_parms (got_object))
val = from_obj;
}
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
}
else if (from_obj)
val = from_obj;
return val;
}
tree
lookup_name_nonclass (name)
tree name;
{
return lookup_name_real (name, 0, 1, 0);
}
tree
lookup_function_nonclass (name, args)
tree name;
tree args;
{
return lookup_arg_dependent (name, lookup_name_nonclass (name), args);
}
tree
lookup_name_namespace_only (name)
tree name;
{
return lookup_name_real (name, 1, 1, 1);
}
tree
lookup_name (name, prefer_type)
tree name;
int prefer_type;
{
return lookup_name_real (name, prefer_type, 0, 0);
}
tree
lookup_name_current_level (name)
tree name;
{
struct binding_level *b;
tree t = NULL_TREE;
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
if (b->namespace_p)
{
t = IDENTIFIER_NAMESPACE_VALUE (name);
if (t != NULL_TREE && TREE_CODE (t) == TREE_LIST)
t = TREE_VALUE (t);
}
else if (IDENTIFIER_BINDING (name)
&& LOCAL_BINDING_P (IDENTIFIER_BINDING (name)))
{
while (1)
{
if (BINDING_LEVEL (IDENTIFIER_BINDING (name)) == b)
return IDENTIFIER_VALUE (name);
if (b->keep == 2)
b = b->level_chain;
else
break;
}
}
return t;
}
tree
lookup_type_current_level (name)
tree name;
{
register tree t = NULL_TREE;
my_friendly_assert (! current_binding_level->namespace_p, 980716);
if (REAL_IDENTIFIER_TYPE_VALUE (name) != NULL_TREE
&& REAL_IDENTIFIER_TYPE_VALUE (name) != global_type_node)
{
struct binding_level *b = current_binding_level;
while (1)
{
if (purpose_member (name, b->type_shadowed))
return REAL_IDENTIFIER_TYPE_VALUE (name);
if (b->keep == 2)
b = b->level_chain;
else
break;
}
}
return t;
}
void
begin_only_namespace_names ()
{
only_namespace_names = 1;
}
void
end_only_namespace_names ()
{
only_namespace_names = 0;
}
static void
signal_catch (sig)
int sig ATTRIBUTE_UNUSED;
{
signal (SIGSEGV, SIG_DFL);
#ifdef SIGIOT
signal (SIGIOT, SIG_DFL);
#endif
#ifdef SIGILL
signal (SIGILL, SIG_DFL);
#endif
#ifdef SIGABRT
signal (SIGABRT, SIG_DFL);
#endif
#ifdef SIGBUS
signal (SIGBUS, SIG_DFL);
#endif
my_friendly_abort (0);
}
#if 0
static tree *builtin_type_tdescs_arr;
static int builtin_type_tdescs_len, builtin_type_tdescs_max;
#endif
static void
record_builtin_type (rid_index, name, type)
enum rid rid_index;
const char *name;
tree type;
{
tree rname = NULL_TREE, tname = NULL_TREE;
tree tdecl = NULL_TREE;
if ((int) rid_index < (int) RID_MAX)
rname = ridpointers[(int) rid_index];
if (name)
tname = get_identifier (name);
TYPE_BUILT_IN (type) = 1;
if (tname)
{
tdecl = pushdecl (build_decl (TYPE_DECL, tname, type));
set_identifier_type_value (tname, NULL_TREE);
if ((int) rid_index < (int) RID_MAX)
SET_IDENTIFIER_GLOBAL_VALUE (tname, tdecl);
}
if (rname != NULL_TREE)
{
if (tname != NULL_TREE)
{
set_identifier_type_value (rname, NULL_TREE);
SET_IDENTIFIER_GLOBAL_VALUE (rname, tdecl);
}
else
{
tdecl = pushdecl (build_decl (TYPE_DECL, rname, type));
set_identifier_type_value (rname, NULL_TREE);
}
}
}
static tree
record_builtin_java_type (name, size)
const char *name;
int size;
{
tree type, decl;
if (size > 0)
type = make_signed_type (size);
else if (size > -32)
{
type = make_unsigned_type (-size);
}
else
{
type = make_node (REAL_TYPE);
TYPE_PRECISION (type) = - size;
layout_type (type);
}
record_builtin_type (RID_MAX, name, type);
decl = TYPE_NAME (type);
DECL_IGNORED_P (decl) = 1;
TYPE_FOR_JAVA (type) = 1;
return type;
}
static void
record_unknown_type (type, name)
tree type;
const char *name;
{
tree decl = pushdecl (build_decl (TYPE_DECL, get_identifier (name), type));
DECL_IGNORED_P (decl) = 1;
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
TYPE_SIZE (type) = TYPE_SIZE (void_type_node);
TYPE_ALIGN (type) = 1;
TYPE_MODE (type) = TYPE_MODE (void_type_node);
}
static void
push_overloaded_decl_1 (x)
tree x;
{
push_overloaded_decl (x, PUSH_GLOBAL);
}
#ifdef __GNUC__
__inline
#endif
tree
auto_function (name, type, code)
tree name, type;
enum built_in_function code;
{
return define_function
(IDENTIFIER_POINTER (name), type, code, push_overloaded_decl_1,
IDENTIFIER_POINTER (build_decl_overload (name, TYPE_ARG_TYPES (type),
0)));
}
void
init_decl_processing ()
{
register tree endlink, int_endlink, double_endlink, unsigned_endlink;
tree fields[20];
tree memcpy_ftype, strlen_ftype;
int wchar_type_size;
tree temp;
tree array_domain_type;
tree vb_off_identifier = NULL_TREE;
tree string_ftype_ptr_ptr, int_ftype_string_string;
tree sizetype_endlink;
tree ptr_ftype, ptr_ftype_unsigned, ptr_ftype_sizetype;
tree void_ftype, void_ftype_int, void_ftype_ptr;
lang_name_cplusplus = get_identifier ("C++");
lang_name_c = get_identifier ("C");
#ifdef OBJCPLUS
lang_name_objc = get_identifier ("Objective-C");
#endif
lang_name_java = get_identifier ("Java");
my_friendly_assert (global_namespace == NULL_TREE, 375);
my_friendly_assert (current_lang_name == NULL_TREE, 375);
current_lang_name = lang_name_cplusplus;
push_namespace (get_identifier ("::"));
global_namespace = current_namespace;
current_lang_name = NULL_TREE;
if (flag_strict_prototype == 2)
flag_strict_prototype = pedantic;
if (! flag_permissive && ! pedantic)
flag_pedantic_errors = 1;
strict_prototypes_lang_c = flag_strict_prototype;
current_lang_name = lang_name_c;
current_function_decl = NULL_TREE;
named_labels = NULL_TREE;
named_label_uses = NULL;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
signal (SIGSEGV, signal_catch);
#ifdef SIGIOT
signal (SIGIOT, signal_catch);
#endif
#ifdef SIGILL
signal (SIGILL, signal_catch);
#endif
#ifdef SIGABRT
signal (SIGABRT, signal_catch);
#endif
#ifdef SIGBUS
signal (SIGBUS, signal_catch);
#endif
gcc_obstack_init (&decl_obstack);
error_mark_node = make_node (ERROR_MARK);
TREE_PERMANENT (error_mark_node) = 1;
TREE_TYPE (error_mark_node) = error_mark_node;
error_mark_list = build_tree_list (error_mark_node, error_mark_node);
TREE_TYPE (error_mark_list) = error_mark_node;
pushlevel (0);
global_binding_level = current_binding_level;
NAMESPACE_LEVEL (global_namespace) = global_binding_level;
declare_namespace_level ();
this_identifier = get_identifier (THIS_NAME);
in_charge_identifier = get_identifier (IN_CHARGE_NAME);
ctor_identifier = get_identifier (CTOR_NAME);
dtor_identifier = get_identifier (DTOR_NAME);
pfn_identifier = get_identifier (VTABLE_PFN_NAME);
index_identifier = get_identifier (VTABLE_INDEX_NAME);
delta_identifier = get_identifier (VTABLE_DELTA_NAME);
delta2_identifier = get_identifier (VTABLE_DELTA2_NAME);
pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2");
if (flag_handle_signatures)
{
tag_identifier = get_identifier (SIGTABLE_TAG_NAME);
vb_off_identifier = get_identifier (SIGTABLE_VB_OFF_NAME);
vt_off_identifier = get_identifier (SIGTABLE_VT_OFF_NAME);
}
integer_type_node = make_signed_type (INT_TYPE_SIZE);
record_builtin_type (RID_INT, NULL_PTR, integer_type_node);
char_type_node
= (flag_signed_char
? make_signed_type (CHAR_TYPE_SIZE)
: make_unsigned_type (CHAR_TYPE_SIZE));
record_builtin_type (RID_CHAR, "char", char_type_node);
record_builtin_type (RID_SIGNED, NULL_PTR, integer_type_node);
long_integer_type_node = make_signed_type (LONG_TYPE_SIZE);
record_builtin_type (RID_LONG, "long int", long_integer_type_node);
unsigned_type_node = make_unsigned_type (INT_TYPE_SIZE);
record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
long_unsigned_type_node = make_unsigned_type (LONG_TYPE_SIZE);
record_builtin_type (RID_MAX, "long unsigned int", long_unsigned_type_node);
record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
long_long_integer_type_node = make_signed_type (LONG_LONG_TYPE_SIZE);
record_builtin_type (RID_MAX, "long long int", long_long_integer_type_node);
long_long_unsigned_type_node = make_unsigned_type (LONG_LONG_TYPE_SIZE);
record_builtin_type (RID_MAX, "long long unsigned int",
long_long_unsigned_type_node);
record_builtin_type (RID_MAX, "long long unsigned",
long_long_unsigned_type_node);
short_integer_type_node = make_signed_type (SHORT_TYPE_SIZE);
record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
short_unsigned_type_node = make_unsigned_type (SHORT_TYPE_SIZE);
record_builtin_type (RID_MAX, "short unsigned int", short_unsigned_type_node);
record_builtin_type (RID_MAX, "unsigned short", short_unsigned_type_node);
set_sizetype
(TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (SIZE_TYPE))));
ptrdiff_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (PTRDIFF_TYPE)));
signed_char_type_node = make_signed_type (CHAR_TYPE_SIZE);
record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
unsigned_char_type_node = make_unsigned_type (CHAR_TYPE_SIZE);
record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
intQI_type_node = make_signed_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intQI_type_node));
intHI_type_node = make_signed_type (GET_MODE_BITSIZE (HImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intHI_type_node));
intSI_type_node = make_signed_type (GET_MODE_BITSIZE (SImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intSI_type_node));
intDI_type_node = make_signed_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
intTI_type_node = make_signed_type (GET_MODE_BITSIZE (TImode));
pushdecl (build_decl (TYPE_DECL, get_identifier ("__int128_t"), intTI_type_node));
#endif
unsigned_intQI_type_node = make_unsigned_type (GET_MODE_BITSIZE (QImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intQI_type_node));
unsigned_intHI_type_node = make_unsigned_type (GET_MODE_BITSIZE (HImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intHI_type_node));
unsigned_intSI_type_node = make_unsigned_type (GET_MODE_BITSIZE (SImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intSI_type_node));
unsigned_intDI_type_node = make_unsigned_type (GET_MODE_BITSIZE (DImode));
pushdecl (build_decl (TYPE_DECL, NULL_TREE, unsigned_intDI_type_node));
#if HOST_BITS_PER_WIDE_INT >= 64
unsigned_intTI_type_node = make_unsigned_type (GET_MODE_BITSIZE (TImode));
pushdecl (build_decl (TYPE_DECL, get_identifier ("__uint128_t"), unsigned_intTI_type_node));
#endif
float_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (float_type_node) = FLOAT_TYPE_SIZE;
record_builtin_type (RID_FLOAT, NULL_PTR, float_type_node);
layout_type (float_type_node);
double_type_node = make_node (REAL_TYPE);
if (flag_short_double)
TYPE_PRECISION (double_type_node) = FLOAT_TYPE_SIZE;
else
TYPE_PRECISION (double_type_node) = DOUBLE_TYPE_SIZE;
record_builtin_type (RID_DOUBLE, NULL_PTR, double_type_node);
layout_type (double_type_node);
long_double_type_node = make_node (REAL_TYPE);
TYPE_PRECISION (long_double_type_node) = LONG_DOUBLE_TYPE_SIZE;
record_builtin_type (RID_MAX, "long double", long_double_type_node);
layout_type (long_double_type_node);
complex_integer_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"),
complex_integer_type_node));
TREE_TYPE (complex_integer_type_node) = integer_type_node;
layout_type (complex_integer_type_node);
complex_float_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex float"),
complex_float_type_node));
TREE_TYPE (complex_float_type_node) = float_type_node;
layout_type (complex_float_type_node);
complex_double_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex double"),
complex_double_type_node));
TREE_TYPE (complex_double_type_node) = double_type_node;
layout_type (complex_double_type_node);
complex_long_double_type_node = make_node (COMPLEX_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("complex long double"),
complex_long_double_type_node));
TREE_TYPE (complex_long_double_type_node) = long_double_type_node;
layout_type (complex_long_double_type_node);
java_byte_type_node = record_builtin_java_type ("__java_byte", 8);
java_short_type_node = record_builtin_java_type ("__java_short", 16);
java_int_type_node = record_builtin_java_type ("__java_int", 32);
java_long_type_node = record_builtin_java_type ("__java_long", 64);
java_float_type_node = record_builtin_java_type ("__java_float", -32);
java_double_type_node = record_builtin_java_type ("__java_double", -64);
java_char_type_node = record_builtin_java_type ("__java_char", -16);
java_boolean_type_node = record_builtin_java_type ("__java_boolean", -1);
vector_unsigned_char_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector unsigned char"),
vector_unsigned_char_type_node));
TREE_TYPE (vector_unsigned_char_type_node) = unsigned_char_type_node;
layout_type (vector_unsigned_char_type_node);
vector_signed_char_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector signed char"),
vector_signed_char_type_node));
TREE_TYPE (vector_signed_char_type_node) = signed_char_type_node;
layout_type (vector_signed_char_type_node);
vector_boolean_char_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector bool char"),
vector_boolean_char_type_node));
TREE_TYPE (vector_boolean_char_type_node) = unsigned_char_type_node;
layout_type (vector_boolean_char_type_node);
vector_unsigned_short_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector unsigned short"),
vector_unsigned_short_type_node));
TREE_TYPE (vector_unsigned_short_type_node) = short_unsigned_type_node;
layout_type (vector_unsigned_short_type_node);
vector_signed_short_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector signed short"),
vector_signed_short_type_node));
TREE_TYPE (vector_signed_short_type_node) = short_integer_type_node;
layout_type (vector_signed_short_type_node);
vector_boolean_short_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector bool short"),
vector_boolean_short_type_node));
TREE_TYPE (vector_boolean_short_type_node) = short_unsigned_type_node;
layout_type (vector_boolean_short_type_node);
vector_unsigned_long_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector unsigned long"),
vector_unsigned_long_type_node));
TREE_TYPE (vector_unsigned_long_type_node) = long_unsigned_type_node;
layout_type (vector_unsigned_long_type_node);
vector_signed_long_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector signed long"),
vector_signed_long_type_node));
TREE_TYPE (vector_signed_long_type_node) = long_integer_type_node;
layout_type (vector_signed_long_type_node);
vector_boolean_long_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector bool long"),
vector_boolean_long_type_node));
TREE_TYPE (vector_boolean_long_type_node) = long_unsigned_type_node;
layout_type (vector_boolean_long_type_node);
vector_float_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector float"),
vector_float_type_node));
TREE_TYPE (vector_float_type_node) = float_type_node;
layout_type (vector_float_type_node);
vector_pixel_type_node = make_node (VECTOR_TYPE);
pushdecl (build_decl (TYPE_DECL, get_identifier ("__vector pixel"),
vector_pixel_type_node));
TREE_TYPE (vector_pixel_type_node) = short_unsigned_type_node;
layout_type (vector_pixel_type_node);
integer_zero_node = build_int_2 (0, 0);
TREE_TYPE (integer_zero_node) = integer_type_node;
integer_one_node = build_int_2 (1, 0);
TREE_TYPE (integer_one_node) = integer_type_node;
integer_two_node = build_int_2 (2, 0);
TREE_TYPE (integer_two_node) = integer_type_node;
integer_three_node = build_int_2 (3, 0);
TREE_TYPE (integer_three_node) = integer_type_node;
boolean_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
TREE_SET_CODE (boolean_type_node, BOOLEAN_TYPE);
TYPE_MAX_VALUE (boolean_type_node) = build_int_2 (1, 0);
TREE_TYPE (TYPE_MAX_VALUE (boolean_type_node)) = boolean_type_node;
TYPE_PRECISION (boolean_type_node) = 1;
record_builtin_type (RID_BOOL, "bool", boolean_type_node);
boolean_false_node = build_int_2 (0, 0);
TREE_TYPE (boolean_false_node) = boolean_type_node;
boolean_true_node = build_int_2 (1, 0);
TREE_TYPE (boolean_true_node) = boolean_type_node;
size_zero_node = size_int (0);
size_one_node = size_int (1);
signed_size_zero_node = build_int_2 (0, 0);
TREE_TYPE (signed_size_zero_node) = make_signed_type (TYPE_PRECISION (sizetype));
void_type_node = make_node (VOID_TYPE);
record_builtin_type (RID_VOID, NULL_PTR, void_type_node);
layout_type (void_type_node);
void_list_node = build_tree_list (NULL_TREE, void_type_node);
TREE_PARMLIST (void_list_node) = 1;
null_pointer_node = build_int_2 (0, 0);
TREE_TYPE (null_pointer_node) = build_pointer_type (void_type_node);
layout_type (TREE_TYPE (null_pointer_node));
void_zero_node = build_int_2 (0, 0);
TREE_TYPE (void_zero_node) = void_type_node;
string_type_node = build_pointer_type (char_type_node);
const_string_type_node
= build_pointer_type (build_qualified_type (char_type_node,
TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, string_type_node);
#endif
array_domain_type = build_index_type (build_int_2 (200, 0));
char_array_type_node
= build_array_type (char_type_node, array_domain_type);
#ifdef PASCAL_STRINGS
unsigned_char_array_type_node
= build_array_type (unsigned_char_type_node, array_domain_type);
#endif
int_array_type_node
= build_array_type (integer_type_node, array_domain_type);
class_star_type_node = build_pointer_type (make_lang_type (RECORD_TYPE));
default_function_type
= build_function_type (integer_type_node, NULL_TREE);
ptr_type_node = build_pointer_type (void_type_node);
const_ptr_type_node
= build_pointer_type (build_qualified_type (void_type_node,
TYPE_QUAL_CONST));
#if 0
record_builtin_type (RID_MAX, NULL_PTR, ptr_type_node);
#endif
endlink = void_list_node;
int_endlink = tree_cons (NULL_TREE, integer_type_node, endlink);
double_endlink = tree_cons (NULL_TREE, double_type_node, endlink);
unsigned_endlink = tree_cons (NULL_TREE, unsigned_type_node, endlink);
ptr_ftype = build_function_type (ptr_type_node, NULL_TREE);
ptr_ftype_unsigned = build_function_type (ptr_type_node, unsigned_endlink);
sizetype_endlink = tree_cons (NULL_TREE, sizetype, endlink);
ptr_ftype_sizetype = build_function_type (ptr_type_node, sizetype_endlink);
void_ftype = build_function_type (void_type_node, endlink);
void_ftype_int = build_function_type (void_type_node, int_endlink);
void_ftype_ptr
= build_function_type (void_type_node,
tree_cons (NULL_TREE, ptr_type_node, endlink));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr,
tree_cons (NULL_TREE, NULL_TREE, NULL_TREE));
float_ftype_float
= build_function_type (float_type_node,
tree_cons (NULL_TREE, float_type_node, endlink));
double_ftype_double
= build_function_type (double_type_node, double_endlink);
ldouble_ftype_ldouble
= build_function_type (long_double_type_node,
tree_cons (NULL_TREE, long_double_type_node,
endlink));
double_ftype_double_double
= build_function_type (double_type_node,
tree_cons (NULL_TREE, double_type_node,
double_endlink));
int_ftype_int
= build_function_type (integer_type_node, int_endlink);
long_ftype_long
= build_function_type (long_integer_type_node,
tree_cons (NULL_TREE, long_integer_type_node,
endlink));
int_ftype_cptr_cptr_sizet
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
tree_cons (NULL_TREE,
sizetype,
endlink))));
string_ftype_ptr_ptr
= build_function_type (string_type_node,
tree_cons (NULL_TREE, string_type_node,
tree_cons (NULL_TREE,
const_string_type_node,
endlink)));
int_ftype_string_string
= build_function_type (integer_type_node,
tree_cons (NULL_TREE, const_string_type_node,
tree_cons (NULL_TREE,
const_string_type_node,
endlink)));
strlen_ftype
= build_function_type (sizetype,
tree_cons (NULL_TREE, const_string_type_node,
endlink));
memcpy_ftype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE, const_ptr_type_node,
sizetype_endlink)));
if (flag_huge_objects)
delta_type_node = long_integer_type_node;
else
delta_type_node = short_integer_type_node;
builtin_function ("__builtin_constant_p", default_function_type,
BUILT_IN_CONSTANT_P, NULL_PTR);
builtin_return_address_fndecl
= builtin_function ("__builtin_return_address", ptr_ftype_unsigned,
BUILT_IN_RETURN_ADDRESS, NULL_PTR);
builtin_function ("__builtin_frame_address", ptr_ftype_unsigned,
BUILT_IN_FRAME_ADDRESS, NULL_PTR);
builtin_function ("__builtin_alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, "alloca");
builtin_function ("__builtin_ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
if (! flag_no_builtin && !flag_no_nonansi_builtin)
{
temp = builtin_function ("alloca", ptr_ftype_sizetype,
BUILT_IN_ALLOCA, NULL_PTR);
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("ffs", int_ftype_int, BUILT_IN_FFS, NULL_PTR);
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("_exit", void_ftype_int,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
DECL_BUILT_IN_NONANSI (temp) = 1;
}
builtin_function ("__builtin_abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
builtin_function ("__builtin_fabsf", float_ftype_float, BUILT_IN_FABS,
NULL_PTR);
builtin_function ("__builtin_fabs", double_ftype_double, BUILT_IN_FABS,
NULL_PTR);
builtin_function ("__builtin_fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
NULL_PTR);
builtin_function ("__builtin_labs", long_ftype_long,
BUILT_IN_LABS, NULL_PTR);
builtin_function ("__builtin_saveregs", ptr_ftype,
BUILT_IN_SAVEREGS, NULL_PTR);
builtin_function ("__builtin_classify_type", default_function_type,
BUILT_IN_CLASSIFY_TYPE, NULL_PTR);
builtin_function ("__builtin_next_arg", ptr_ftype,
BUILT_IN_NEXT_ARG, NULL_PTR);
builtin_function ("__builtin_args_info", int_ftype_int,
BUILT_IN_ARGS_INFO, NULL_PTR);
builtin_function ("__builtin_setjmp",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, ptr_type_node,
endlink)),
BUILT_IN_SETJMP, NULL_PTR);
builtin_function ("__builtin_longjmp",
build_function_type (integer_type_node,
tree_cons (NULL_TREE, ptr_type_node,
tree_cons (NULL_TREE,
integer_type_node,
endlink))),
BUILT_IN_LONGJMP, NULL_PTR);
builtin_function ("__builtin_apply_args", ptr_ftype,
BUILT_IN_APPLY_ARGS, NULL_PTR);
temp = tree_cons (NULL_TREE,
build_pointer_type (build_function_type (void_type_node,
NULL_TREE)),
tree_cons (NULL_TREE, ptr_ftype_sizetype, NULL_TREE));
builtin_function ("__builtin_apply",
build_function_type (ptr_type_node, temp),
BUILT_IN_APPLY, NULL_PTR);
builtin_function ("__builtin_return", void_ftype_ptr,
BUILT_IN_RETURN, NULL_PTR);
builtin_function ("__builtin_memcpy", memcpy_ftype,
BUILT_IN_MEMCPY, "memcpy");
builtin_function ("__builtin_memcmp", int_ftype_cptr_cptr_sizet,
BUILT_IN_MEMCMP, "memcmp");
builtin_function ("__builtin_strcmp", int_ftype_string_string,
BUILT_IN_STRCMP, "strcmp");
builtin_function ("__builtin_strcpy", string_ftype_ptr_ptr,
BUILT_IN_STRCPY, "strcpy");
builtin_function ("__builtin_strlen", strlen_ftype,
BUILT_IN_STRLEN, "strlen");
builtin_function ("__builtin_sqrtf", float_ftype_float,
BUILT_IN_FSQRT, "sqrtf");
builtin_function ("__builtin_fsqrt", double_ftype_double,
BUILT_IN_FSQRT, NULL_PTR);
builtin_function ("__builtin_sqrtl", ldouble_ftype_ldouble,
BUILT_IN_FSQRT, "sqrtl");
builtin_function ("__builtin_sinf", float_ftype_float,
BUILT_IN_SIN, "sinf");
builtin_function ("__builtin_sin", double_ftype_double,
BUILT_IN_SIN, "sin");
builtin_function ("__builtin_sinl", ldouble_ftype_ldouble,
BUILT_IN_SIN, "sinl");
builtin_function ("__builtin_cosf", float_ftype_float,
BUILT_IN_COS, "cosf");
builtin_function ("__builtin_cos", double_ftype_double,
BUILT_IN_COS, "cos");
builtin_function ("__builtin_cosl", ldouble_ftype_ldouble,
BUILT_IN_COS, "cosl");
if (!flag_no_builtin)
{
builtin_function ("abs", int_ftype_int, BUILT_IN_ABS, NULL_PTR);
builtin_function ("fabs", double_ftype_double, BUILT_IN_FABS, NULL_PTR);
builtin_function ("labs", long_ftype_long, BUILT_IN_LABS, NULL_PTR);
builtin_function ("fabsf", float_ftype_float, BUILT_IN_FABS, NULL_PTR);
builtin_function ("fabsl", ldouble_ftype_ldouble, BUILT_IN_FABS,
NULL_PTR);
builtin_function ("memcpy", memcpy_ftype, BUILT_IN_MEMCPY, NULL_PTR);
builtin_function ("memcmp", int_ftype_cptr_cptr_sizet, BUILT_IN_MEMCMP,
NULL_PTR);
builtin_function ("strcmp", int_ftype_string_string, BUILT_IN_STRCMP,
NULL_PTR);
builtin_function ("strcpy", string_ftype_ptr_ptr, BUILT_IN_STRCPY,
NULL_PTR);
builtin_function ("strlen", strlen_ftype, BUILT_IN_STRLEN, NULL_PTR);
builtin_function ("sqrtf", float_ftype_float, BUILT_IN_FSQRT, NULL_PTR);
builtin_function ("sqrt", double_ftype_double, BUILT_IN_FSQRT, NULL_PTR);
builtin_function ("sqrtl", ldouble_ftype_ldouble, BUILT_IN_FSQRT,
NULL_PTR);
builtin_function ("sinf", float_ftype_float, BUILT_IN_SIN, NULL_PTR);
builtin_function ("sin", double_ftype_double, BUILT_IN_SIN, NULL_PTR);
builtin_function ("sinl", ldouble_ftype_ldouble, BUILT_IN_SIN, NULL_PTR);
builtin_function ("cosf", float_ftype_float, BUILT_IN_COS, NULL_PTR);
builtin_function ("cos", double_ftype_double, BUILT_IN_COS, NULL_PTR);
builtin_function ("cosl", ldouble_ftype_ldouble, BUILT_IN_COS, NULL_PTR);
temp = builtin_function ("abort", void_ftype,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
DECL_BUILT_IN_NONANSI (temp) = 1;
temp = builtin_function ("exit", void_ftype_int,
NOT_BUILT_IN, NULL_PTR);
TREE_THIS_VOLATILE (temp) = 1;
TREE_SIDE_EFFECTS (temp) = 1;
DECL_BUILT_IN_NONANSI (temp) = 1;
}
#if 0
builtin_function ("__builtin_div", default_ftype, BUILT_IN_DIV, NULL_PTR);
builtin_function ("__builtin_ldiv", default_ftype, BUILT_IN_LDIV, NULL_PTR);
builtin_function ("__builtin_ffloor", double_ftype_double, BUILT_IN_FFLOOR,
NULL_PTR);
builtin_function ("__builtin_fceil", double_ftype_double, BUILT_IN_FCEIL,
NULL_PTR);
builtin_function ("__builtin_fmod", double_ftype_double_double,
BUILT_IN_FMOD, NULL_PTR);
builtin_function ("__builtin_frem", double_ftype_double_double,
BUILT_IN_FREM, NULL_PTR);
builtin_function ("__builtin_memset", ptr_ftype_ptr_int_int,
BUILT_IN_MEMSET, NULL_PTR);
builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP,
NULL_PTR);
builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN,
NULL_PTR);
#endif
unknown_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
TREE_TYPE (unknown_type_node) = unknown_type_node;
TREE_TYPE (null_node) = type_for_size (POINTER_SIZE, 0);
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
opaque_type_node = copy_node (ptr_type_node);
TYPE_MAIN_VARIANT (opaque_type_node) = opaque_type_node;
record_builtin_type (RID_MAX, 0, opaque_type_node);
wchar_type_node
= TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (get_identifier (WCHAR_TYPE)));
wchar_type_size = TYPE_PRECISION (wchar_type_node);
signed_wchar_type_node = make_signed_type (wchar_type_size);
unsigned_wchar_type_node = make_unsigned_type (wchar_type_size);
wchar_type_node
= TREE_UNSIGNED (wchar_type_node)
? unsigned_wchar_type_node
: signed_wchar_type_node;
record_builtin_type (RID_WCHAR, "__wchar_t", wchar_type_node);
wchar_decl_node = build_decl (TYPE_DECL, get_identifier ("wchar_t"),
wchar_type_node);
pushdecl (wchar_decl_node);
wchar_array_type_node
= build_array_type (wchar_type_node, array_domain_type);
if (flag_vtable_thunks)
{
tree vfunc_type = make_node (FUNCTION_TYPE);
TREE_TYPE (vfunc_type) = integer_type_node;
TYPE_ARG_TYPES (vfunc_type) = NULL_TREE;
layout_type (vfunc_type);
vtable_entry_type = build_pointer_type (vfunc_type);
}
else
{
vtable_entry_type = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
ptr_type_node);
finish_builtin_type (vtable_entry_type, VTBL_PTR_TYPE, fields, 2,
double_type_node);
fields[3] = copy_node (fields[2]);
TREE_TYPE (fields[3]) = delta_type_node;
DECL_NAME (fields[3]) = delta2_identifier;
DECL_MODE (fields[3]) = TYPE_MODE (delta_type_node);
DECL_SIZE (fields[3]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[3]) = 0;
TREE_CHAIN (fields[2]) = fields[3];
vtable_entry_type = build_qualified_type (vtable_entry_type,
TYPE_QUAL_CONST);
}
record_builtin_type (RID_MAX, VTBL_PTR_TYPE, vtable_entry_type);
vtbl_type_node
= build_cplus_array_type (vtable_entry_type, NULL_TREE);
layout_type (vtbl_type_node);
vtbl_type_node = build_qualified_type (vtbl_type_node, TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_type_node);
vtbl_ptr_type_node = build_pointer_type (vtable_entry_type);
layout_type (vtbl_ptr_type_node);
record_builtin_type (RID_MAX, NULL_PTR, vtbl_ptr_type_node);
if (flag_handle_signatures)
{
sigtable_entry_type = make_lang_type (RECORD_TYPE);
fields[0] = build_lang_field_decl (FIELD_DECL, tag_identifier,
delta_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL, vb_off_identifier,
delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
fields[3] = build_lang_field_decl (FIELD_DECL, index_identifier,
delta_type_node);
fields[4] = build_lang_field_decl (FIELD_DECL, pfn_identifier,
ptr_type_node);
finish_builtin_type (sigtable_entry_type, SIGTABLE_PTR_TYPE, fields, 4,
(TYPE_ALIGN (ptr_type_node) > TYPE_ALIGN (delta_type_node))
? ptr_type_node
: delta_type_node);
fields[5] = copy_node (fields[4]);
TREE_TYPE (fields[5]) = delta_type_node;
DECL_NAME (fields[5]) = vt_off_identifier;
DECL_MODE (fields[5]) = TYPE_MODE (delta_type_node);
DECL_SIZE (fields[5]) = TYPE_SIZE (delta_type_node);
TREE_UNSIGNED (fields[5]) = 0;
TREE_CHAIN (fields[4]) = fields[5];
sigtable_entry_type = build_qualified_type (sigtable_entry_type,
TYPE_QUAL_CONST);
record_builtin_type (RID_MAX, SIGTABLE_PTR_TYPE, sigtable_entry_type);
}
std_node = build_decl (NAMESPACE_DECL,
get_identifier (flag_honor_std ? "fake std":"std"),
void_type_node);
pushdecl (std_node);
global_type_node = make_node (LANG_TYPE);
record_unknown_type (global_type_node, "global type");
current_lang_name = lang_name_cplusplus;
{
tree bad_alloc_type_node, newtype, deltype;
if (flag_honor_std)
push_namespace (get_identifier ("std"));
bad_alloc_type_node = xref_tag
(class_type_node, get_identifier ("bad_alloc"), 1);
if (flag_honor_std)
pop_namespace ();
newtype = build_exception_variant
(ptr_ftype_sizetype, build_tree_list (NULL_TREE, bad_alloc_type_node));
deltype = build_exception_variant
(void_ftype_ptr, build_tree_list (NULL_TREE, NULL_TREE));
auto_function (ansi_opname[(int) NEW_EXPR], newtype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_NEW_EXPR], newtype, NOT_BUILT_IN);
global_delete_fndecl
= auto_function (ansi_opname[(int) DELETE_EXPR], deltype, NOT_BUILT_IN);
auto_function (ansi_opname[(int) VEC_DELETE_EXPR], deltype, NOT_BUILT_IN);
}
abort_fndecl
= define_function ("__pure_virtual", void_ftype,
NOT_BUILT_IN, 0, 0);
init_class_processing ();
init_init_processing ();
init_search_processing ();
if (flag_rtti)
init_rtti_processing ();
if (flag_exceptions)
init_exception_processing ();
if (flag_no_inline)
{
flag_inline_functions = 0;
}
if (! supports_one_only ())
flag_weak = 0;
#ifdef INIT_TARGET_INTRINSIC
INIT_TARGET_INTRINSIC (endlink);
#endif
declare_function_name ();
init_function_format_info ();
using_eh_for_cleanups ();
print_error_function = lang_print_error_function;
lang_get_alias_set = &c_get_alias_set;
valid_lang_attribute = cp_valid_lang_attribute;
if (flag_writable_strings)
flag_const_strings = 0;
}
static void
lang_print_error_function (file)
char *file;
{
default_print_error_function (file);
maybe_print_template_context ();
}
tree
define_function (name, type, function_code, pfn, library_name)
const char *name;
tree type;
enum built_in_function function_code;
void (*pfn) PROTO((tree));
const char *library_name;
{
tree decl = build_lang_decl (FUNCTION_DECL, get_identifier (name), type);
DECL_EXTERNAL (decl) = 1;
TREE_PUBLIC (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 392);
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
if (pfn) (*pfn) (decl);
if (library_name)
DECL_ASSEMBLER_NAME (decl) = get_identifier (library_name);
make_function_rtl (decl);
if (function_code != NOT_BUILT_IN)
{
DECL_BUILT_IN (decl) = 1;
DECL_FUNCTION_CODE (decl) = function_code;
}
return decl;
}
tree
lang_builtin_function (name, type, function_code, library_name)
char *name;
tree type;
enum built_in_function function_code;
char *library_name;
{
tree decl = builtin_function (name, type, function_code, library_name);
return decl;
}
int
lang_comptypes (t1, t2)
tree t1, t2;
{
return comptypes (t1, t2, 0);
}
tree
lang_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
return build_type_variant (type, constp, volatilep);
}
void
fixup_anonymous_union (t)
tree t;
{
tree *q;
TYPE_HAS_CONSTRUCTOR (t) = 0;
TYPE_HAS_DEFAULT_CONSTRUCTOR (t) = 0;
TYPE_HAS_INIT_REF (t) = 0;
TYPE_HAS_CONST_INIT_REF (t) = 0;
TYPE_HAS_ASSIGN_REF (t) = 0;
TYPE_HAS_CONST_ASSIGN_REF (t) = 0;
q = &TYPE_METHODS (t);
while (*q)
{
if (DECL_ARTIFICIAL (*q))
*q = TREE_CHAIN (*q);
else
q = &TREE_CHAIN (*q);
}
if (TYPE_METHODS (t))
error ("an anonymous union cannot have function members");
}
tree
check_tag_decl (declspecs)
tree declspecs;
{
int found_type = 0;
tree ob_modifier = NULL_TREE;
register tree link;
register tree t = NULL_TREE;
for (link = declspecs; link; link = TREE_CHAIN (link))
{
register tree value = TREE_VALUE (link);
if (TYPE_P (value))
{
++found_type;
if (IS_AGGR_TYPE (value) || TREE_CODE (value) == ENUMERAL_TYPE)
{
my_friendly_assert (TYPE_MAIN_DECL (value) != NULL_TREE, 261);
t = value;
}
}
else if (value == ridpointers[(int) RID_FRIEND])
{
if (current_class_type == NULL_TREE
|| current_scope () != current_class_type)
ob_modifier = value;
}
else if (value == ridpointers[(int) RID_STATIC]
|| value == ridpointers[(int) RID_EXTERN]
|| value == ridpointers[(int) RID_AUTO]
|| value == ridpointers[(int) RID_REGISTER]
|| value == ridpointers[(int) RID_INLINE]
|| value == ridpointers[(int) RID_VIRTUAL]
|| value == ridpointers[(int) RID_CONST]
|| value == ridpointers[(int) RID_VOLATILE]
|| value == ridpointers[(int) RID_EXPLICIT])
ob_modifier = value;
}
if (found_type > 1)
error ("multiple types in one declaration");
if (t == NULL_TREE && ! current_class_type)
pedwarn ("declaration does not declare anything");
else if (t && TREE_CODE (t) == UNION_TYPE
&& TYPE_NAME (t)
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
{
;
SET_ANON_UNION_TYPE_P (t);
}
else if (ob_modifier)
{
if (ob_modifier == ridpointers[(int) RID_INLINE]
|| ob_modifier == ridpointers[(int) RID_VIRTUAL])
cp_error ("`%D' can only be specified for functions", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_FRIEND])
cp_error ("`%D' can only be specified inside a class", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
cp_error ("`%D' can only be specified for constructors",
ob_modifier);
else
cp_error ("`%D' can only be specified for objects and functions",
ob_modifier);
}
return t;
}
void
shadow_tag (declspecs)
tree declspecs;
{
tree t = check_tag_decl (declspecs);
if (t)
maybe_process_partial_specialization (t);
if (t && ANON_UNION_TYPE_P (t))
{
fixup_anonymous_union (t);
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL_TREE);
finish_anon_union (decl);
}
}
}
tree
groktypename (typename)
tree typename;
{
if (TREE_CODE (typename) != TREE_LIST)
return typename;
return grokdeclarator (TREE_VALUE (typename),
TREE_PURPOSE (typename),
TYPENAME, 0, NULL_TREE);
}
#ifdef OBJCPLUS
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, NULL_TREE);
}
#endif
void
dump_function_def (decl)
tree decl;
{
char ch;
if (DECL_ARTIFICIAL (decl))
return;
if (processing_template_decl)
return;
if (DECL_USE_TEMPLATE (decl))
return;
ch = 'f';
if (DECL_STATIC_FUNCTION_P (decl))
ch = '+';
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
|| DECL_CONSTRUCTOR_P (decl)
|| DECL_DESTRUCTOR_P (decl))
ch = '-';
if (DECL_DESTRUCTOR_P (decl)) printf ("+%cm ~%s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
else {
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) {
printf ("+%cm operator%s %u\n", ch,
operator_name_string (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
else {
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_GLOBAL_", 8)) {
printf ("+%cm %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
}
}
if (TYPE_CHECK (DECL_CLASS_CONTEXT (decl))) {
printf ("+%ci %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CLASS_CONTEXT (decl)))),
DECL_SOURCE_LINE (TYPE_NAME (DECL_CLASS_CONTEXT (decl))));
} else if (DECL_CONTEXT (decl)) {
printf ("+%ci %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (DECL_CONTEXT (decl))),
DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
}
}
void
dump_decl (declarator, declspecs)
tree declarator;
tree declspecs;
{
char ch = 'v';
if (DECL_CLASS_SCOPE_P (declarator))
ch = 'd';
switch (TREE_CODE (declarator))
{
case FUNCTION_DECL:
printf ("+fh %s %u\n", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case CONST_DECL:
printf ("+nh %s %u\n", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case VAR_DECL:
printf ("+%cm %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
if (DECL_CLASS_SCOPE_P (declarator))
{
if (TYPE_CHECK (DECL_CLASS_CONTEXT (declarator)))
{
tree typename = TYPE_NAME (DECL_CLASS_CONTEXT (declarator));
printf ("+%ci %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (typename)),
DECL_SOURCE_LINE (TYPE_NAME (DECL_CLASS_CONTEXT (declarator))));
}
else if (DECL_CONTEXT (declarator))
{
printf ("+%ci %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (DECL_CONTEXT (declarator))),
DECL_SOURCE_LINE (DECL_CONTEXT (declarator)));
}
}
break;
case TYPE_DECL:
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_Trivial", 8))
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_Is_POD", 7))
printf ("+th %s %u\n", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
default:
break;
}
}
void
gen_function_def_index (decl)
tree decl;
{
char fn_type;
char buf[15];
if (DECL_ARTIFICIAL (decl) || processing_template_decl || DECL_USE_TEMPLATE (decl))
return;
fn_type = 'f';
if (DECL_STATIC_FUNCTION_P (decl))
fn_type = '+';
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
|| DECL_CONSTRUCTOR_P (decl)
|| DECL_DESTRUCTOR_P (decl))
fn_type = '-';
if (DECL_DESTRUCTOR_P (decl)) {
sprintf (&buf[0], "+%cm ", fn_type);
dump_symbol_info (buf, NULL, -1);
dump_symbol_info (NULL, "~", -1);
dump_symbol_info (NULL,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
else {
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl))) {
sprintf (&buf[0], "+%cm ", fn_type);
dump_symbol_info (buf, NULL, -1);
dump_symbol_info (NULL, "operator", -1);
dump_symbol_info (NULL,
operator_name_string (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
else {
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (decl)), "_GLOBAL_", 8)) {
sprintf (&buf[0], "+%cm ", fn_type);
dump_symbol_info (buf,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
}
}
if (TYPE_CHECK (DECL_CLASS_CONTEXT (decl))) {
sprintf (&buf[0], "+%ci ", fn_type);
dump_symbol_info (buf,
IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (DECL_CLASS_CONTEXT (decl)))),
DECL_SOURCE_LINE (TYPE_NAME (DECL_CLASS_CONTEXT (decl))));
} else if (DECL_CONTEXT (decl)) {
sprintf (&buf[0], "+%ci ", fn_type);
dump_symbol_info (buf,
IDENTIFIER_POINTER (DECL_NAME (DECL_CONTEXT (decl))),
DECL_SOURCE_LINE (DECL_CONTEXT (decl)));
}
}
void
gen_decl_index (declarator, declspecs)
tree declarator;
tree declspecs;
{
switch (TREE_CODE (declarator))
{
case FUNCTION_DECL:
dump_symbol_info ("+fh ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case CONST_DECL:
dump_symbol_info ("+nh ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case VAR_DECL:
if (DECL_CLASS_SCOPE_P (declarator))
{
dump_symbol_info ("+dm ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
if (TYPE_CHECK (DECL_CLASS_CONTEXT (declarator)))
{
tree typename = TYPE_NAME (DECL_CLASS_CONTEXT (declarator));
dump_symbol_info ("+di ",
IDENTIFIER_POINTER (DECL_NAME (typename)),
DECL_SOURCE_LINE (TYPE_NAME (DECL_CLASS_CONTEXT (declarator))));
}
else if (DECL_CONTEXT (declarator))
{
dump_symbol_info ("+di ",
IDENTIFIER_POINTER (DECL_NAME (DECL_CONTEXT (declarator))),
DECL_SOURCE_LINE (DECL_CONTEXT (declarator)));
}
}
else
dump_symbol_info ("+vm ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case TYPE_DECL:
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_Trivial", 8))
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_Is_POD", 7))
dump_symbol_info ("+th ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
default:
break;
}
}
int debug_temp_inits = 1;
tree
start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
int initialized;
tree attributes, prefix_attributes;
{
register tree decl;
register tree type, tem;
tree context;
extern int have_extern_spec;
extern int used_extern_spec;
tree attrlist;
#if 0
int init_written = initialized;
#endif
if (have_extern_spec && !used_extern_spec)
{
declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"),
declspecs);
used_extern_spec = 1;
}
if (attributes || prefix_attributes)
attrlist = build_scratch_list (attributes, prefix_attributes);
else
attrlist = NULL_TREE;
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
attrlist);
if (decl == NULL_TREE || TREE_CODE (decl) == VOID_TYPE)
return NULL_TREE;
type = TREE_TYPE (decl);
if (type == error_mark_node)
return NULL_TREE;
if (flag_dump_symbols)
dump_decl (decl, declspecs);
if (flag_gen_index)
gen_decl_index (decl, declspecs);
if (! processing_template_decl && TREE_STATIC (decl)
&& TYPE_NEEDS_DESTRUCTOR (complete_type (type))
&& !TREE_PERMANENT (decl))
{
push_obstacks (&permanent_obstack, &permanent_obstack);
decl = copy_node (decl);
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree itype = TYPE_DOMAIN (type);
if (itype && ! TREE_PERMANENT (itype))
{
itype = build_index_type (copy_to_permanent (TYPE_MAX_VALUE (itype)));
type = build_cplus_array_type (TREE_TYPE (type), itype);
TREE_TYPE (decl) = type;
}
}
pop_obstacks ();
}
context
= (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
? DECL_CLASS_CONTEXT (decl)
: DECL_CONTEXT (decl);
if (initialized && context && TREE_CODE (context) == NAMESPACE_DECL
&& context != current_namespace && TREE_CODE (decl) == VAR_DECL)
{
push_decl_namespace (context);
}
if (context && TREE_CODE (context) == NAMESPACE_DECL)
context = NULL_TREE;
if (initialized)
switch (TREE_CODE (decl))
{
case TYPE_DECL:
if (pedantic || list_length (declspecs) > 1)
{
cp_error ("typedef `%D' is initialized", decl);
initialized = 0;
}
break;
case FUNCTION_DECL:
cp_error ("function `%#D' is initialized like a variable", decl);
initialized = 0;
break;
default:
if (! processing_template_decl)
{
if (type != error_mark_node)
{
if (TYPE_SIZE (type) != NULL_TREE
&& ! TREE_CONSTANT (TYPE_SIZE (type)))
{
cp_error
("variable-sized object `%D' may not be initialized",
decl);
initialized = 0;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
{
cp_error
("elements of array `%#D' have incomplete type", decl);
initialized = 0;
}
}
}
}
if (initialized)
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
cp_warning ("declaration of `%#D' has `extern' and is initialized",
decl);
DECL_EXTERNAL (decl) = 0;
if (toplevel_bindings_p ())
TREE_STATIC (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
#endif
cplus_decl_attributes (decl, attributes, prefix_attributes);
if (context && TYPE_SIZE (complete_type (context)) != NULL_TREE)
{
push_nested_class (context, 2);
if (TREE_CODE (decl) == VAR_DECL)
{
tree field = lookup_field (context, DECL_NAME (decl), 0, 0);
if (field == NULL_TREE || TREE_CODE (field) != VAR_DECL)
cp_error ("`%#D' is not a static member of `%#T'", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
cp_pedwarn ("ANSI C++ does not permit `%T::%D' to be defined as `%T::%D'",
DECL_CONTEXT (field), DECL_NAME (decl),
context, DECL_NAME (decl));
DECL_CONTEXT (decl) = DECL_CONTEXT (field);
}
if (DECL_INITIAL (decl) && DECL_INITIAL (field))
cp_error ("duplicate initialization of %D", decl);
if (duplicate_decls (decl, field))
decl = field;
}
}
else
{
tree field = check_classfn (context, decl);
if (field && duplicate_decls (decl, field))
decl = field;
}
DECL_IN_AGGR_P (decl) = 0;
if ((DECL_LANG_SPECIFIC (decl) && DECL_USE_TEMPLATE (decl))
|| CLASSTYPE_USE_TEMPLATE (context))
{
SET_DECL_TEMPLATE_SPECIALIZATION (decl);
if (DECL_INITIAL (decl) == NULL_TREE && processing_specialization)
DECL_EXTERNAL (decl) = 1;
}
if (DECL_EXTERNAL (decl) && ! DECL_TEMPLATE_SPECIALIZATION (decl))
cp_pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
}
if ((TREE_CODE (decl) != PARM_DECL && DECL_CONTEXT (decl) != NULL_TREE
&& TREE_CODE (DECL_CONTEXT (decl)) != NAMESPACE_DECL)
|| (TREE_CODE (decl) == TEMPLATE_DECL && !namespace_bindings_p ())
|| TREE_CODE (type) == LANG_TYPE
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl)))
tem = decl;
else
tem = pushdecl (decl);
if (processing_template_decl)
{
if (! current_function_decl)
tem = push_template_decl (tem);
else if (minimal_parse_mode)
DECL_VINDEX (tem)
= build_min_nt (DECL_STMT, copy_to_permanent (declarator),
copy_to_permanent (declspecs),
NULL_TREE);
}
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
DECL_COMMON (tem) = flag_conserve_space || ! TREE_PUBLIC (tem);
#endif
if (! processing_template_decl)
start_decl_1 (tem);
push_obstacks_nochange ();
#if 0
if (init_written
&& ! (TREE_CODE (tem) == PARM_DECL
|| (TREE_READONLY (tem)
&& (TREE_CODE (tem) == VAR_DECL
|| TREE_CODE (tem) == FIELD_DECL))))
{
if (toplevel_bindings_p () && debug_temp_inits)
{
if (processing_template_decl
|| TYPE_NEEDS_CONSTRUCTING (type)
|| TREE_CODE (type) == REFERENCE_TYPE)
;
else
temporary_allocation ();
}
}
#endif
return tem;
}
void
start_decl_1 (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
int initialized = (DECL_INITIAL (decl) != NULL_TREE);
if (type == error_mark_node)
return;
if (TYPE_NEEDS_DESTRUCTOR (type)
&& current_binding_level->more_cleanups_ok == 0)
pushlevel_temporary (1);
if (initialized)
{
if (TYPE_SIZE (complete_type (type)) != NULL_TREE)
;
else if (TREE_CODE (type) != ARRAY_TYPE)
{
cp_error ("variable `%#D' has initializer but incomplete type",
decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (TYPE_SIZE (complete_type (TREE_TYPE (type))) == NULL_TREE)
{
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
cp_error ("elements of array `%#D' have incomplete type", decl);
initialized = 0;
}
}
if (!initialized
&& TREE_CODE (decl) != TYPE_DECL
&& TREE_CODE (decl) != TEMPLATE_DECL
&& IS_AGGR_TYPE (type) && ! DECL_EXTERNAL (decl))
{
if ((! processing_template_decl || ! uses_template_parms (type))
&& TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
cp_error ("aggregate `%#D' has incomplete type and cannot be initialized",
decl);
type = TREE_TYPE (decl) = error_mark_node;
}
else
{
initialized = TYPE_NEEDS_CONSTRUCTING (type);
}
}
#if 0
if (! toplevel_bindings_p ()
&& DECL_RTL (tem) == NULL_RTX)
{
if (TYPE_SIZE (TREE_TYPE (tem)) != NULL_TREE)
expand_decl (tem);
else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
&& DECL_INITIAL (tem) != NULL_TREE)
expand_decl (tem);
}
#endif
if (! initialized)
DECL_INITIAL (decl) = NULL_TREE;
}
static void
grok_reference_init (decl, type, init)
tree decl, type, init;
{
tree tmp;
if (init == NULL_TREE)
{
if ((DECL_LANG_SPECIFIC (decl) == 0
|| DECL_IN_AGGR_P (decl) == 0)
&& ! DECL_THIS_EXTERN (decl))
{
cp_error ("`%D' declared as reference but not initialized", decl);
if (TREE_CODE (decl) == VAR_DECL)
SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
}
return;
}
if (init == error_mark_node)
return;
if (TREE_CODE (type) == REFERENCE_TYPE
&& TREE_CODE (init) == CONSTRUCTOR)
{
cp_error ("ANSI C++ forbids use of initializer list to initialize reference `%D'", decl);
return;
}
if (TREE_CODE (init) == TREE_LIST)
init = build_compound_expr (init);
if (TREE_CODE (TREE_TYPE (init)) == REFERENCE_TYPE)
init = convert_from_reference (init);
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
{
init = default_conversion (init);
}
tmp = convert_to_reference
(type, init, CONV_IMPLICIT,
LOOKUP_SPECULATIVELY|LOOKUP_NORMAL|DIRECT_BIND, decl);
if (tmp == error_mark_node)
goto fail;
else if (tmp != NULL_TREE)
{
init = tmp;
DECL_INITIAL (decl) = save_expr (init);
}
else
{
cp_error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
goto fail;
}
if (TYPE_SIZE (TREE_TYPE (type)))
{
init = convert_from_reference (decl);
if (TREE_PERMANENT (decl))
init = copy_to_permanent (init);
SET_DECL_REFERENCE_SLOT (decl, init);
}
if (TREE_STATIC (decl) && ! TREE_CONSTANT (DECL_INITIAL (decl)))
{
expand_static_init (decl, DECL_INITIAL (decl));
DECL_INITIAL (decl) = NULL_TREE;
}
return;
fail:
if (TREE_CODE (decl) == VAR_DECL)
SET_DECL_REFERENCE_SLOT (decl, error_mark_node);
return;
}
static tree
obscure_complex_init (decl, init)
tree decl, init;
{
if (! flag_no_inline && TREE_STATIC (decl))
{
if (extract_init (decl, init))
return NULL_TREE;
}
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
if (toplevel_bindings_p () && ! DECL_COMMON (decl))
DECL_INITIAL (decl) = build (CONSTRUCTOR, TREE_TYPE (decl), NULL_TREE,
NULL_TREE);
else
#endif
DECL_INITIAL (decl) = error_mark_node;
return init;
}
static void
check_for_uninitialized_const_var (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (type) != REFERENCE_TYPE
&& CP_TYPE_CONST_P (type)
&& !TYPE_NEEDS_CONSTRUCTING (type)
&& !DECL_INITIAL (decl))
cp_error ("uninitialized const `%D'", decl);
}
void
cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
tree decl, init;
tree asmspec_tree;
int need_pop;
int flags;
{
register tree type;
tree cleanup = NULL_TREE, ttype = NULL_TREE;
int was_incomplete;
int temporary = allocation_temporary_p ();
char *asmspec = NULL;
int was_readonly = 0;
int already_used = 0;
tree core_type;
if (! decl)
{
if (init)
error ("assignment (not initialization) in declaration");
return;
}
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
cp_error ("Cannot initialize `%D' to namespace `%D'",
decl, init);
init = NULL_TREE;
}
if (current_class_type
&& DECL_REAL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_DEFINED_IN_CLASS_P (decl) = 1;
if (TREE_CODE (decl) == VAR_DECL
&& DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == NAMESPACE_DECL
&& DECL_CONTEXT (decl) != current_namespace
&& init)
{
pop_decl_namespace ();
}
type = TREE_TYPE (decl);
if (type == error_mark_node)
{
if (toplevel_bindings_p () && temporary)
end_temporary_allocation ();
return;
}
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
{
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
if (minimal_parse_mode && ! DECL_ARTIFICIAL (decl))
{
tree stmt = DECL_VINDEX (decl);
if (stmt != NULL_TREE && TREE_CODE (stmt) == DECL_STMT)
{
DECL_VINDEX (decl) = NULL_TREE;
TREE_OPERAND (stmt, 2) = copy_to_permanent (init);
add_tree (stmt);
}
}
goto finish_end0;
}
if (TREE_CODE (decl) == TYPE_DECL)
{
if (init && DECL_INITIAL (decl))
{
TREE_TYPE (decl) = type = TREE_TYPE (init);
DECL_INITIAL (decl) = init = NULL_TREE;
}
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
cp_warning ("shadowing previous type declaration of `%#D'", decl);
set_identifier_type_value (DECL_NAME (decl), type);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
GNU_xref_decl (current_function_decl, decl);
if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl
&& TYPE_SIZE (TREE_TYPE (decl)) == NULL_TREE)
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
rest_of_decl_compilation (decl, NULL_PTR,
DECL_CONTEXT (decl) == NULL_TREE, at_eof);
goto finish_end;
}
if (TREE_CODE (decl) != FUNCTION_DECL)
{
ttype = target_type (type);
}
if (! DECL_EXTERNAL (decl) && TREE_READONLY (decl)
&& TYPE_NEEDS_CONSTRUCTING (type))
{
was_readonly = 1;
TREE_READONLY (decl) = 0;
}
if (TREE_CODE (decl) == FIELD_DECL)
{
if (init && init != error_mark_node)
my_friendly_assert (TREE_PERMANENT (init), 147);
if (asmspec)
{
DECL_RTL (TREE_TYPE (decl)) = NULL_RTX;
DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
make_decl_rtl (decl, asmspec, 0);
}
}
else if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
else if (DECL_EXTERNAL (decl))
;
else if (TREE_CODE (type) == REFERENCE_TYPE
|| (TYPE_LANG_SPECIFIC (type) && IS_SIGNATURE_REFERENCE (type)))
{
if (TREE_STATIC (decl))
make_decl_rtl (decl, NULL_PTR,
toplevel_bindings_p ()
|| pseudo_global_level_p ());
grok_reference_init (decl, type, init);
init = NULL_TREE;
}
GNU_xref_decl (current_function_decl, decl);
core_type = type;
while (TREE_CODE (core_type) == ARRAY_TYPE)
core_type = TREE_TYPE (core_type);
if (TREE_CODE (decl) == FIELD_DECL)
#ifdef OBJCPLUS
maybe_objc_check_decl (decl);
#else
;
#endif
else if (TREE_CODE (decl) == CONST_DECL)
{
my_friendly_assert (TREE_CODE (decl) != REFERENCE_TYPE, 148);
DECL_INITIAL (decl) = init;
my_friendly_assert (init != NULL_TREE, 149);
init = NULL_TREE;
}
else if (init)
{
#ifdef OBJCPLUS
maybe_objc_check_decl (decl);
#endif
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
init = digest_init (type, init, (tree *) 0);
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
cp_error ("`%D' must be initialized by constructor, not by `{...}'",
decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
}
else
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
if (init)
init = obscure_complex_init (decl, init);
}
else if (DECL_EXTERNAL (decl))
;
else if (TREE_CODE_CLASS (TREE_CODE (type)) == 't'
&& (IS_AGGR_TYPE (type) || TYPE_NEEDS_CONSTRUCTING (type)))
{
if (! TYPE_NEEDS_CONSTRUCTING (core_type))
{
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
cp_error ("structure `%D' with uninitialized reference members",
decl);
}
check_for_uninitialized_const_var (decl);
if (TYPE_SIZE (type) != NULL_TREE
&& TYPE_NEEDS_CONSTRUCTING (type))
init = obscure_complex_init (decl, NULL_TREE);
}
else
check_for_uninitialized_const_var (decl);
if (toplevel_bindings_p () && temporary)
end_temporary_allocation ();
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE
&& TREE_CODE (decl) != TYPE_DECL)
{
int do_default
= (TREE_STATIC (decl)
? pedantic && ! DECL_EXTERNAL (decl)
: !DECL_EXTERNAL (decl));
tree initializer = init ? init : DECL_INITIAL (decl);
int failure = complete_array_type (type, initializer, do_default);
if (failure == 1)
cp_error ("initializer fails to determine size of `%D'", decl);
if (failure == 2)
{
if (do_default)
cp_error ("array size missing in `%D'", decl);
else if (!pedantic && TREE_STATIC (decl) && !TREE_PUBLIC (decl))
DECL_EXTERNAL (decl) = 1;
}
if (pedantic && TYPE_DOMAIN (type) != NULL_TREE
&& tree_int_cst_lt (TYPE_MAX_VALUE (TYPE_DOMAIN (type)),
integer_zero_node))
cp_error ("zero-size array `%D'", decl);
layout_decl (decl, 0);
}
if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_SIZE (decl) == NULL_TREE
&& TYPE_SIZE (complete_type (TREE_TYPE (decl))) != NULL_TREE)
layout_decl (decl, 0);
if (TREE_STATIC (decl) && DECL_SIZE (decl) == NULL_TREE)
{
if (DECL_INITIAL (decl) != NULL_TREE)
cp_error ("storage size of `%D' isn't known", decl);
init = NULL_TREE;
}
else if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
{
cp_error ("storage size of `%D' isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
else if (!DECL_EXTERNAL (decl) && IS_AGGR_TYPE (ttype))
note_debug_info_needed (ttype);
if (TREE_STATIC (decl) && DECL_CLASS_SCOPE_P (decl))
note_debug_info_needed (DECL_CONTEXT (decl));
if ((DECL_EXTERNAL (decl) || TREE_STATIC (decl))
&& DECL_SIZE (decl) != NULL_TREE
&& ! TREE_CONSTANT (DECL_SIZE (decl)))
{
if (TREE_CODE (DECL_SIZE (decl)) == INTEGER_CST)
constant_expression_warning (DECL_SIZE (decl));
else
cp_error ("storage size of `%D' isn't constant", decl);
}
if (! DECL_EXTERNAL (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& ! TREE_STATIC (decl))
{
int yes = suspend_momentary ();
cleanup = maybe_build_cleanup (decl);
resume_momentary (yes);
}
#ifdef OBJCPLUS
maybe_objc_check_decl (decl);
#endif
}
else if (TREE_CODE (decl) == PARM_DECL && TYPE_NEEDS_DESTRUCTOR (type))
{
if (temporary)
end_temporary_allocation ();
cleanup = maybe_build_cleanup (decl);
if (temporary)
resume_temporary_allocation ();
}
was_incomplete = (DECL_SIZE (decl) == NULL_TREE);
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == RESULT_DECL)
{
int toplev = toplevel_bindings_p () || pseudo_global_level_p ();
int was_temp
= (TREE_STATIC (decl) && TYPE_NEEDS_DESTRUCTOR (type)
&& allocation_temporary_p ());
if (was_temp)
end_temporary_allocation ();
if (TREE_CODE (decl) == VAR_DECL
&& TREE_STATIC (decl)
&& ! TREE_ASM_WRITTEN (decl)
&& current_function_decl
&& DECL_CONTEXT (decl) == current_function_decl
&& (DECL_THIS_INLINE (current_function_decl)
|| DECL_TEMPLATE_INSTANTIATION (current_function_decl))
&& TREE_PUBLIC (current_function_decl))
{
current_function_cannot_inline
= "function with static variable cannot be inline";
if (! flag_weak)
{
if (DECL_INTERFACE_KNOWN (current_function_decl))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
}
else if (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node)
{
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
#ifdef MARK_STATIC_INLINE_DATA_COALESCED
if (flag_pic)
MARK_STATIC_INLINE_DATA_COALESCED (decl);
#endif
if (TREE_PUBLIC (decl))
DECL_ASSEMBLER_NAME (decl)
= build_static_name (current_function_decl, DECL_NAME (decl));
#ifdef HAVE_COALESCED_SYMBOLS
else if (DECL_COALESCED (decl))
;
#endif
else if (! DECL_ARTIFICIAL (decl))
{
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
cp_warning_at (" you can work around this by removing the initializer", decl);
}
}
}
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
&& DECL_COMDAT (decl))
comdat_linkage (decl);
if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
make_decl_rtl (decl, NULL_PTR, toplev);
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
&& ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
{
DECL_INITIAL (decl) = save_expr (DECL_INITIAL (decl));
if (asmspec)
DECL_ASSEMBLER_NAME (decl) = get_identifier (asmspec);
if (! toplev
&& TREE_STATIC (decl)
&& ! TREE_SIDE_EFFECTS (decl)
&& ! TREE_PUBLIC (decl)
&& ! DECL_EXTERNAL (decl)
&& ! TYPE_NEEDS_DESTRUCTOR (type)
&& DECL_MODE (decl) != BLKmode)
{
DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
store_expr (DECL_INITIAL (decl), DECL_RTL (decl), 0);
TREE_ASM_WRITTEN (decl) = 1;
}
else if (toplev && ! TREE_PUBLIC (decl))
{
if (!interface_unknown)
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
}
make_decl_rtl (decl, asmspec, toplev);
}
else
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
else if (TREE_CODE (decl) == VAR_DECL
&& DECL_LANG_SPECIFIC (decl)
&& DECL_IN_AGGR_P (decl))
{
if (TREE_STATIC (decl))
{
if (init == NULL_TREE
#ifdef DEFAULT_STATIC_DEFS
&& TYPE_NEEDS_CONSTRUCTING (type)
#endif
)
{
DECL_EXTERNAL (decl) = 1;
make_decl_rtl (decl, asmspec, 1);
}
else
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
else
goto finish_end0;
}
else
{
#ifdef NEXT_SEMANTICS
if (DECL_INITIAL (decl))
{
tree exp = DECL_INITIAL (decl);
if (TREE_CODE (exp) == CONSTRUCTOR)
DECL_TREE_MAY_BE_WRITTEN (decl) = 1;
}
#endif
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
if (was_temp)
resume_temporary_allocation ();
if (type != error_mark_node
&& TYPE_LANG_SPECIFIC (core_type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
abstract_virtuals_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
abstract_virtuals_error (decl, TREE_TYPE (type));
if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
signature_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& IS_SIGNATURE (TREE_TYPE (type)))
signature_error (decl, TREE_TYPE (type));
if (TREE_CODE (decl) == FUNCTION_DECL)
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
&& DECL_NOT_REALLY_EXTERN (decl)))
{
if (init)
DECL_INITIAL (decl) = init;
}
else if (TREE_STATIC (decl) && type != error_mark_node)
{
if (TYPE_NEEDS_CONSTRUCTING (type) || init != NULL_TREE
|| TYPE_NEEDS_DESTRUCTOR (type))
expand_static_init (decl, init);
}
else if (! toplev)
{
if (was_incomplete && ! TREE_STATIC (decl))
{
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
if (DECL_SIZE (decl) == NULL_TREE)
DECL_INITIAL (decl) = NULL_TREE;
expand_decl (decl);
}
else if (! TREE_ASM_WRITTEN (decl)
&& (TYPE_SIZE (type) != NULL_TREE
|| TREE_CODE (type) == ARRAY_TYPE))
{
if (DECL_RTL (decl) == NULL_RTX)
expand_decl (decl);
else if (cleanup)
{
if (! expand_decl_cleanup (NULL_TREE, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
cleanup = NULL_TREE;
}
}
if (current_binding_level->is_for_scope)
{
struct binding_level *outer
= current_binding_level->level_chain;
tree outer_binding
= TREE_CHAIN (IDENTIFIER_BINDING (DECL_NAME (decl)));
if (outer_binding && BINDING_LEVEL (outer_binding) == outer
&& (TREE_CODE (BINDING_VALUE (outer_binding))
== VAR_DECL)
&& DECL_DEAD_FOR_LOCAL (BINDING_VALUE (outer_binding)))
{
BINDING_VALUE (outer_binding)
= DECL_SHADOWED_FOR_VAR (BINDING_VALUE (outer_binding));
current_binding_level->is_for_scope = 0;
}
else if (DECL_IN_MEMORY_P (decl))
preserve_temp_slots (DECL_RTL (decl));
}
expand_start_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node)
{
expand_decl_init (decl);
already_used = TREE_USED (decl) || TREE_USED (type);
if (init || TYPE_NEEDS_CONSTRUCTING (type))
{
emit_line_note (DECL_SOURCE_FILE (decl),
DECL_SOURCE_LINE (decl));
expand_aggr_init (decl, init, flags);
}
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
&& cleanup == NULL_TREE
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
if (already_used)
TREE_USED (decl) = 1;
}
expand_end_target_temps ();
if (DECL_SIZE (decl) && type != error_mark_node)
{
if (cleanup)
{
if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
}
}
finish_end0:
{
tree context = DECL_REAL_CONTEXT (decl);
if (context
&& TREE_CODE_CLASS (TREE_CODE (context)) == 't'
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL)
&& TYPE_SIZE (context) != NULL_TREE
&& context == current_class_type)
pop_nested_class ();
}
}
finish_end:
if (warn_larger_than
&& ! processing_template_decl
&& (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == PARM_DECL)
&& !DECL_EXTERNAL (decl))
{
register tree decl_size = DECL_SIZE (decl);
if (decl_size && TREE_CODE (decl_size) == INTEGER_CST)
{
unsigned units = TREE_INT_CST_LOW (decl_size) / BITS_PER_UNIT;
if (units > larger_than_size)
warning_with_decl (decl, "size of `%s' is %u bytes", units);
}
}
if (need_pop)
{
pop_obstacks ();
}
if (was_readonly)
TREE_READONLY (decl) = 1;
}
void
finish_decl (decl, init, asmspec_tree)
tree decl, init;
tree asmspec_tree;
{
cp_finish_decl (decl, init, asmspec_tree, 1, 0);
}
void
expand_static_init (decl, init)
tree decl;
tree init;
{
tree oldstatic = value_member (decl, static_aggregates);
if (oldstatic)
{
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
cp_error ("multiple initializations given for `%D'", decl);
}
else if (! toplevel_bindings_p ())
{
tree temp;
push_obstacks (&permanent_obstack, &permanent_obstack);
temp = get_temp_name (integer_type_node, 1);
rest_of_decl_compilation (temp, NULL_PTR, 0, 0);
expand_start_cond (build_binary_op (EQ_EXPR, temp,
integer_zero_node), 0);
expand_start_target_temps ();
if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
|| (init && TREE_CODE (init) == TREE_LIST))
{
expand_aggr_init (decl, init, 0);
do_pending_stack_adjust ();
}
else if (init)
expand_assignment (decl, init, 0, 0);
expand_assignment (temp, integer_one_node, 0, 0);
expand_end_target_temps ();
if (TYPE_NEEDS_DESTRUCTOR (TREE_TYPE (decl)))
{
tree cleanup, fcall;
static tree Atexit = 0;
int saved_flag_access_control;
if (Atexit == 0)
{
tree atexit_fndecl, PFV, pfvlist;
push_obstacks (&permanent_obstack, &permanent_obstack);
PFV = build_pointer_type (build_function_type
(void_type_node, void_list_node));
pfvlist = tree_cons (NULL_TREE, PFV, void_list_node);
push_lang_context (lang_name_c);
atexit_fndecl
= builtin_function ("atexit",
build_function_type (void_type_node,
pfvlist),
NOT_BUILT_IN, NULL_PTR);
mark_used (atexit_fndecl);
Atexit = default_conversion (atexit_fndecl);
pop_lang_context ();
pop_obstacks ();
}
build_cleanup (decl);
cleanup = start_anon_func ();
saved_flag_access_control = flag_access_control;
flag_access_control = 0;
fcall = build_cleanup (decl);
flag_access_control = saved_flag_access_control;
expand_expr_stmt (fcall);
end_anon_func ();
mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
fcall = build_function_call (Atexit,
expr_tree_cons (NULL_TREE,
cleanup,
NULL_TREE));
expand_expr_stmt (fcall);
}
expand_end_cond ();
pop_obstacks ();
}
else
{
if (!TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
preserve_initializer ();
static_aggregates = perm_tree_cons (init, decl, static_aggregates);
}
}
int
complete_array_type (type, initial_value, do_default)
tree type, initial_value;
int do_default;
{
register tree maxindex = NULL_TREE;
int value = 0;
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
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 = size_binop (MINUS_EXPR, integer_zero_node, size_one_node);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
maxindex = size_binop (PLUS_EXPR, maxindex, size_one_node);
}
maxindex = copy_node (maxindex);
}
else
{
if (initial_value != error_mark_node)
value = 1;
else
initial_value = NULL_TREE;
maxindex = build_int_2 (0, 0);
}
}
if (!maxindex)
{
if (do_default)
maxindex = build_int_2 (0, 0);
value = 2;
}
if (maxindex)
{
tree itype;
tree domain;
domain = build_index_type (maxindex);
TYPE_DOMAIN (type) = domain;
if (! TREE_TYPE (maxindex))
TREE_TYPE (maxindex) = domain;
if (initial_value)
itype = TREE_TYPE (initial_value);
else
itype = NULL;
if (itype && !TYPE_DOMAIN (itype))
TYPE_DOMAIN (itype) = domain;
if (! TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)))
TYPE_DOMAIN (TYPE_MAIN_VARIANT (type)) = domain;
}
pop_obstacks();
layout_type (type);
return value;
}
static int
member_function_or_else (ctype, cur_type, string)
tree ctype, cur_type;
const char *string;
{
if (ctype && ctype != cur_type)
{
error (string, TYPE_NAME_STRING (ctype));
return 0;
}
return 1;
}
static void
bad_specifiers (object, type, virtualp, quals, inlinep, friendp, raises)
tree object;
const char *type;
int virtualp, quals, friendp, raises, inlinep;
{
if (virtualp)
cp_error ("`%D' declared as a `virtual' %s", object, type);
if (inlinep)
cp_error ("`%D' declared as an `inline' %s", object, type);
if (quals)
cp_error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
object, type);
if (friendp)
cp_error_at ("invalid friend declaration", object);
if (raises)
cp_error_at ("invalid exception specifications", object);
}
static tree
grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
raises, check, friendp, publicp, inlinep, funcdef_flag,
template_count, in_namespace)
tree ctype, type;
tree declarator;
tree orig_declarator;
int virtualp;
enum overload_flags flags;
tree quals, raises;
int check, friendp, publicp, inlinep, funcdef_flag, template_count;
tree in_namespace;
{
tree cname, decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
int has_default_arg = 0;
tree t;
if (ctype)
cname = TREE_CODE (TYPE_NAME (ctype)) == TYPE_DECL
? TYPE_IDENTIFIER (ctype) : TYPE_NAME (ctype);
else
cname = NULL_TREE;
if (raises)
{
type = build_exception_variant (type, raises);
}
decl = build_lang_decl (FUNCTION_DECL, declarator, type);
if (TYPE_VOLATILE (type))
TREE_THIS_VOLATILE (decl) = 1;
if (in_namespace)
set_decl_namespace (decl, in_namespace, friendp);
else if (publicp && ! ctype)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
if ((MAIN_NAME_P (declarator)
|| (IDENTIFIER_LENGTH (declarator) > 10
&& IDENTIFIER_POINTER (declarator)[0] == '_'
&& IDENTIFIER_POINTER (declarator)[1] == '_'
&& strncmp (IDENTIFIER_POINTER (declarator)+2, "builtin_", 8) == 0))
&& current_lang_name == lang_name_cplusplus
&& ctype == NULL_TREE
&& DECL_CONTEXT (decl) == NULL_TREE)
DECL_LANGUAGE (decl) = lang_c;
#ifdef __MAYBE_FORCE_COALESCED
__MAYBE_FORCE_COALESCED (decl);
#endif
if (staticp)
{
DECL_STATIC_FUNCTION_P (decl) = 1;
DECL_CONTEXT (decl) = ctype;
}
if (ctype)
DECL_CLASS_CONTEXT (decl) = ctype;
if (ctype == NULL_TREE && DECL_MAIN_P (decl))
{
if (processing_template_decl)
error ("cannot declare `main' to be a template");
if (inlinep)
error ("cannot declare `main' to be inline");
else if (! publicp)
error ("cannot declare `main' to be static");
inlinep = 0;
publicp = 1;
}
if (ctype && (ANON_AGGRNAME_P (TYPE_IDENTIFIER (ctype))
|| hack_decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
if (publicp)
{
t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
{
if (DECL_LANGUAGE (decl) == lang_c)
;
else
cp_pedwarn ("non-local function `%#D' uses anonymous type",
decl);
}
else
cp_pedwarn ("non-local function `%#D' uses local type `%T'",
decl, t);
}
}
TREE_PUBLIC (decl) = publicp;
if (! publicp)
{
DECL_INTERFACE_KNOWN (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 1;
}
if (inlinep)
DECL_THIS_INLINE (decl) = DECL_INLINE (decl) = 1;
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
{
cp_error ("%smember function `%D' cannot have `%T' method qualifier",
(ctype ? "static " : "non-"), decl, TREE_VALUE (quals));
quals = NULL_TREE;
}
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
grok_op_properties (decl, virtualp, check < 0);
if (ctype && hack_decl_function_context (decl))
DECL_NO_STATIC_CHAIN (decl) = 1;
for (t = TYPE_ARG_TYPES (TREE_TYPE (decl)); t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
has_default_arg = 1;
break;
}
if (friendp
&& TREE_CODE (orig_declarator) == TEMPLATE_ID_EXPR)
{
if (funcdef_flag)
cp_error
("defining explicit specialization `%D' in friend declaration",
orig_declarator);
else
{
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
cp_error ("template-id `%D' in declaration of primary template",
orig_declarator);
return NULL_TREE;
}
SET_DECL_IMPLICIT_INSTANTIATION (decl);
DECL_TEMPLATE_INFO (decl)
= perm_tree_cons (TREE_OPERAND (orig_declarator, 0),
TREE_OPERAND (orig_declarator, 1),
NULL_TREE);
if (has_default_arg)
{
cp_error ("default arguments are not allowed in declaration of friend template specialization `%D'",
decl);
return NULL_TREE;
}
if (inlinep)
{
cp_error ("`inline' is not allowed in declaration of friend template specialization `%D'",
decl);
return NULL_TREE;
}
}
}
if (has_default_arg)
add_defarg_fn (decl);
if (! ctype && ! processing_template_decl
&& DECL_LANGUAGE (decl) != lang_c
&& (! DECL_USE_TEMPLATE (decl) || name_mangling_version < 1))
set_mangled_name_for_decl (decl);
if (funcdef_flag)
DECL_INITIAL (decl) = error_mark_node;
if (check < 0)
return decl;
if (check && funcdef_flag)
DECL_INITIAL (decl) = error_mark_node;
if (flags == NO_SPECIAL && ctype && constructor_name (cname) == declarator)
{
tree tmp;
DECL_CONSTRUCTOR_P (decl) = 1;
grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (decl == error_mark_node)
return NULL_TREE;
if ((! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT(tmp);
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp && duplicate_decls (decl, tmp))
return tmp;
}
if (! grok_ctor_properties (ctype, decl))
return NULL_TREE;
}
else
{
tree tmp;
if (ctype != NULL_TREE)
grokclassfn (ctype, decl, flags, quals);
decl = check_explicit_specialization (orig_declarator, decl,
template_count,
2 * (funcdef_flag != 0) +
4 * (friendp != 0));
if (decl == error_mark_node)
return NULL_TREE;
if (ctype != NULL_TREE
&& (! TYPE_FOR_JAVA (ctype) || check_java_method (decl))
&& check)
{
tmp = check_classfn (ctype, decl);
if (tmp && TREE_CODE (tmp) == TEMPLATE_DECL)
tmp = DECL_TEMPLATE_RESULT (tmp);
if (tmp && DECL_STATIC_FUNCTION_P (tmp)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
revert_static_member_fn (&decl, NULL, NULL);
last_function_parms = TREE_CHAIN (last_function_parms);
}
if (tmp && DECL_ARTIFICIAL (tmp))
cp_error ("definition of implicitly-declared `%D'", tmp);
if (tmp)
{
if (!duplicate_decls (decl, tmp))
cp_error ("no `%#D' member function declared in class `%T'",
decl, ctype);
return tmp;
}
}
if (ctype == NULL_TREE || check)
return decl;
if (virtualp)
{
DECL_VIRTUAL_P (decl) = 1;
if (DECL_VINDEX (decl) == NULL_TREE)
DECL_VINDEX (decl) = error_mark_node;
IDENTIFIER_VIRTUAL_P (DECL_NAME (decl)) = 1;
}
}
return decl;
}
static tree
grokvardecl (type, declarator, specbits_in, initialized, constp, in_namespace)
tree type;
tree declarator;
RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
tree in_namespace;
{
tree decl;
RID_BIT_TYPE specbits;
specbits = *specbits_in;
if (TREE_CODE (type) == OFFSET_TYPE)
{
tree basetype = TYPE_OFFSET_BASETYPE (type);
type = TREE_TYPE (type);
decl = build_lang_field_decl (VAR_DECL, declarator, type);
DECL_CONTEXT (decl) = basetype;
DECL_CLASS_CONTEXT (decl) = basetype;
DECL_ASSEMBLER_NAME (decl) = build_static_name (basetype, declarator);
}
else
{
tree context;
if (in_namespace)
context = in_namespace;
else if (namespace_bindings_p () || RIDBIT_SETP (RID_EXTERN, specbits))
context = current_namespace;
else
context = NULL_TREE;
decl = build_decl (VAR_DECL, declarator, complete_type (type));
if (context)
set_decl_namespace (decl, context, 0);
context = DECL_CONTEXT (decl);
if (declarator && context && current_lang_name != lang_name_c)
DECL_ASSEMBLER_NAME (decl) = build_static_name (context, declarator);
}
if (in_namespace)
set_decl_namespace (decl, in_namespace, 0);
if (RIDBIT_SETP (RID_EXTERN, specbits))
{
DECL_THIS_EXTERN (decl) = 1;
DECL_EXTERNAL (decl) = !initialized;
}
if (DECL_CLASS_SCOPE_P (decl))
{
TREE_PUBLIC (decl) = 1;
TREE_STATIC (decl) = 1;
DECL_EXTERNAL (decl) = 0;
}
else if (toplevel_bindings_p ())
{
TREE_PUBLIC (decl) = (RIDBIT_NOTSETP (RID_STATIC, specbits)
&& (DECL_THIS_EXTERN (decl) || ! constp));
TREE_STATIC (decl) = ! DECL_EXTERNAL (decl);
}
else
{
TREE_STATIC (decl) = !! RIDBIT_SETP (RID_STATIC, specbits);
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl);
}
if (TREE_PUBLIC (decl))
{
tree t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (t)))
;
else
cp_pedwarn ("non-local variable `%#D' uses local type `%T'",
decl, t);
}
#ifdef __MAYBE_FORCE_COALESCED
__MAYBE_FORCE_COALESCED (decl);
#endif
}
return decl;
}
tree
build_ptrmemfunc_type (type)
tree type;
{
tree fields[4];
tree t;
tree u;
if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type)))
return t;
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
u = make_lang_type (UNION_TYPE);
SET_IS_AGGR_TYPE (u, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_lang_field_decl (FIELD_DECL, delta2_identifier,
delta_type_node);
finish_builtin_type (u, "__ptrmemfunc_type", fields, 1, ptr_type_node);
TYPE_NAME (u) = NULL_TREE;
t = make_lang_type (RECORD_TYPE);
TYPE_PTRMEMFUNC_FLAG (t) = 1;
SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_lang_field_decl (FIELD_DECL, delta_identifier,
delta_type_node);
fields[1] = build_lang_field_decl (FIELD_DECL, index_identifier,
delta_type_node);
fields[2] = build_lang_field_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
pop_obstacks ();
TYPE_NAME (t) = NULL_TREE;
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
CLASSTYPE_GOT_SEMICOLON (t) = 1;
return t;
}
int
check_static_variable_definition (decl, type)
tree decl;
tree type;
{
if (CLASS_TYPE_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
{
cp_error ("in-class initialization of static data member of non-integral type `%T'",
type);
return 1;
}
else if (!CP_TYPE_CONST_P (type))
cp_error ("ANSI C++ forbids in-class initialization of non-const static member `%D'",
decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
cp_pedwarn ("ANSI C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
return 0;
}
enum return_types { return_normal, return_ctor, return_dtor, return_conversion };
tree
grokdeclarator (declarator, declspecs, decl_context, initialized, attrlist)
tree declspecs;
tree declarator;
enum decl_context decl_context;
int initialized;
tree attrlist;
{
RID_BIT_TYPE specbits;
int nclasses = 0;
tree spec;
tree type = NULL_TREE;
int longlong = 0;
int constp;
int restrictp;
int volatilep;
int type_quals;
int virtualp, explicitp, friendp, inlinep, staticp;
int explicit_int = 0;
int explicit_char = 0;
int explicit_bool = 0;
int defaulted_int = 0;
int opaque_typedef = 0;
tree typedef_decl = NULL_TREE;
char *name;
tree typedef_type = NULL_TREE;
int funcdef_flag = 0;
enum tree_code innermost_code = ERROR_MARK;
int bitfield = 0;
#if 0
tree decl_machine_attr = NULL_TREE;
#endif
#if defined (_WIN32) && defined (NEXT_PDO)
int stdcallp; #endif
tree init = NULL_TREE;
enum return_types return_type = return_normal;
tree dname = NULL_TREE;
tree ctype = current_class_type;
tree ctor_return_type = NULL_TREE;
enum overload_flags flags = NO_SPECIAL;
tree quals = NULL_TREE;
tree raises = NULL_TREE;
int template_count = 0;
tree in_namespace = NULL_TREE;
tree inner_attrs;
int ignore_attrs;
RIDBIT_RESET_ALL (specbits);
if (decl_context == FUNCDEF)
funcdef_flag = 1, decl_context = NORMAL;
else if (decl_context == MEMFUNCDEF)
funcdef_flag = -1, decl_context = FIELD;
else if (decl_context == BITFIELD)
bitfield = 1, decl_context = FIELD;
{
tree *next = &declarator;
register tree decl;
name = NULL;
while (next && *next)
{
decl = *next;
switch (TREE_CODE (decl))
{
case TREE_LIST:
#ifdef OBJCPLUS
if(objc_old_semantics_expected) {
return 0;
}
#endif
next = &TREE_VALUE (decl);
break;
case COND_EXPR:
ctype = NULL_TREE;
next = &TREE_OPERAND (decl, 0);
break;
case BIT_NOT_EXPR:
{
tree name = TREE_OPERAND (decl, 0);
tree rename = NULL_TREE;
my_friendly_assert (flags == NO_SPECIAL, 152);
flags = DTOR_FLAG;
return_type = return_dtor;
if (TREE_CODE (name) == TYPE_DECL)
TREE_OPERAND (decl, 0) = name = constructor_name (name);
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 153);
if (ctype == NULL_TREE)
{
if (current_class_type == NULL_TREE)
{
error ("destructors must be member functions");
flags = NO_SPECIAL;
}
else
{
tree t = constructor_name (current_class_name);
if (t != name)
rename = t;
}
}
else
{
tree t = constructor_name (ctype);
if (t != name)
rename = t;
}
if (rename)
{
cp_error ("destructor `%T' must match class name `%T'",
name, rename);
TREE_OPERAND (decl, 0) = rename;
}
next = &name;
}
break;
case ADDR_EXPR:
case ARRAY_REF:
case INDIRECT_REF:
ctype = NULL_TREE;
innermost_code = TREE_CODE (decl);
next = &TREE_OPERAND (decl, 0);
break;
case CALL_EXPR:
if (parmlist_is_exprlist (TREE_OPERAND (decl, 1)))
{
tree attributes, prefix_attributes;
*next = TREE_OPERAND (decl, 0);
init = TREE_OPERAND (decl, 1);
if (attrlist)
{
attributes = TREE_PURPOSE (attrlist);
prefix_attributes = TREE_VALUE (attrlist);
}
else
{
attributes = NULL_TREE;
prefix_attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
attributes, prefix_attributes);
if (decl)
{
if (TREE_USED (TREE_TYPE (decl)))
TREE_USED (decl) = 1;
finish_decl (decl, init, NULL_TREE);
}
else
cp_error ("invalid declarator");
return 0;
}
innermost_code = TREE_CODE (decl);
if (decl_context == FIELD && ctype == NULL_TREE)
ctype = current_class_type;
if (ctype
&& TREE_OPERAND (decl, 0)
&& (TREE_CODE (TREE_OPERAND (decl, 0)) == TYPE_DECL
&& ((DECL_NAME (TREE_OPERAND (decl, 0))
== constructor_name_full (ctype))
|| (DECL_NAME (TREE_OPERAND (decl, 0))
== constructor_name (ctype)))))
TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0);
decl = *next;
if (ctype != NULL_TREE
&& decl != NULL_TREE && flags != DTOR_FLAG
&& decl == constructor_name (ctype))
{
return_type = return_ctor;
ctor_return_type = ctype;
}
ctype = NULL_TREE;
break;
case TEMPLATE_ID_EXPR:
{
tree fns = TREE_OPERAND (decl, 0);
if (TREE_CODE (fns) == LOOKUP_EXPR)
fns = TREE_OPERAND (fns, 0);
dname = fns;
if (TREE_CODE (dname) == COMPONENT_REF)
dname = TREE_OPERAND (dname, 1);
if (TREE_CODE (dname) != IDENTIFIER_NODE)
{
my_friendly_assert (is_overloaded_fn (dname),
19990331);
dname = DECL_NAME (get_first_fn (dname));
}
}
case IDENTIFIER_NODE:
if (TREE_CODE (decl) == IDENTIFIER_NODE)
dname = decl;
next = 0;
if (is_rid (dname))
{
cp_error ("declarator-id missing; using reserved word `%D'",
dname);
name = IDENTIFIER_POINTER (dname);
}
if (! IDENTIFIER_OPNAME_P (dname)
|| (IDENTIFIER_TYPENAME_P (dname) && ! TREE_TYPE (dname)))
name = IDENTIFIER_POINTER (dname);
else
{
if (IDENTIFIER_TYPENAME_P (dname))
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
return_type = return_conversion;
}
name = operator_name_string (dname);
}
break;
case SCOPE_REF:
{
tree cname = TREE_OPERAND (decl, 0);
if (cname == NULL_TREE)
ctype = NULL_TREE;
else if (TREE_CODE (cname) == NAMESPACE_DECL)
{
ctype = NULL_TREE;
in_namespace = TREE_OPERAND (decl, 0);
TREE_OPERAND (decl, 0) = NULL_TREE;
}
else if (! is_aggr_type (cname, 1))
TREE_OPERAND (decl, 0) = NULL_TREE;
else if (TREE_OPERAND (decl, 1)
&& TREE_CODE (TREE_OPERAND (decl, 1)) == INDIRECT_REF)
ctype = cname;
else if (TREE_CODE (cname) == TEMPLATE_TYPE_PARM
|| TREE_CODE (cname) == TEMPLATE_TEMPLATE_PARM)
{
cp_error ("`%T::%D' is not a valid declarator", cname,
TREE_OPERAND (decl, 1));
cp_error (" perhaps you want `typename %T::%D' to make it a type",
cname, TREE_OPERAND (decl, 1));
return void_type_node;
}
else if (ctype == NULL_TREE)
ctype = cname;
else if (TREE_COMPLEXITY (decl) == current_class_depth)
TREE_OPERAND (decl, 0) = ctype;
else
{
if (! UNIQUELY_DERIVED_FROM_P (cname, ctype))
{
cp_error ("type `%T' is not derived from type `%T'",
cname, ctype);
TREE_OPERAND (decl, 0) = NULL_TREE;
}
else
ctype = cname;
}
if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
&& ((DECL_NAME (TREE_OPERAND (decl, 1))
== constructor_name_full (ctype))
|| (DECL_NAME (TREE_OPERAND (decl, 1))
== constructor_name (ctype))))
TREE_OPERAND (decl, 1) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 1);
decl = *next;
if (ctype)
{
if (TREE_CODE (decl) == IDENTIFIER_NODE
&& constructor_name (ctype) == decl)
{
return_type = return_ctor;
ctor_return_type = ctype;
}
else if (TREE_CODE (decl) == BIT_NOT_EXPR
&& TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
&& (constructor_name (ctype) == TREE_OPERAND (decl, 0)
|| constructor_name_full (ctype) == TREE_OPERAND (decl, 0)))
{
return_type = return_dtor;
ctor_return_type = ctype;
flags = DTOR_FLAG;
TREE_OPERAND (decl, 0) = constructor_name (ctype);
next = &TREE_OPERAND (decl, 0);
}
}
}
break;
case ERROR_MARK:
next = 0;
break;
case TYPE_DECL:
cp_error ("`%T' specified as declarator-id", DECL_NAME (decl));
if (TREE_TYPE (decl) == current_class_type)
cp_error (" perhaps you want `%T' for a constructor",
current_class_name);
dname = DECL_NAME (decl);
name = IDENTIFIER_POINTER (dname);
IDENTIFIER_CLASS_VALUE (dname) = NULL_TREE;
declspecs = temp_tree_cons (NULL_TREE, integer_type_node,
declspecs);
*next = dname;
next = 0;
break;
default:
cp_compiler_error ("`%D' as declarator", decl);
return 0;
}
}
if (name == NULL)
name = "type name";
}
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
if (((dname && IDENTIFIER_OPNAME_P (dname)) || flags == TYPENAME_FLAG)
&& innermost_code != CALL_EXPR
&& ! (ctype && declspecs == NULL_TREE))
{
cp_error ("declaration of `%D' as non-function", dname);
return void_type_node;
}
if (decl_context == NORMAL && ! namespace_bindings_p ()
&& ! pseudo_global_level_p ())
{
struct binding_level *b = current_binding_level;
current_binding_level = b->level_chain;
if (current_binding_level != 0 && toplevel_bindings_p ())
decl_context = PARM;
current_binding_level = b;
}
for (spec = declspecs; spec; spec = TREE_CHAIN (spec))
{
register int i;
register tree id;
if (TREE_CODE (spec) != TREE_LIST)
return 0;
id = TREE_VALUE (spec);
if (TREE_CODE (id) == IDENTIFIER_NODE)
{
if (id == ridpointers[(int) RID_INT]
|| id == ridpointers[(int) RID_CHAR]
|| id == ridpointers[(int) RID_BOOL]
|| id == ridpointers[(int) RID_WCHAR])
{
if (type && RIDBIT_NOTSETP (RID_VECTOR, specbits))
{
if (id == ridpointers[(int) RID_BOOL])
error ("`bool' is now a keyword");
else
cp_error ("extraneous `%T' ignored", id);
}
else
{
if (id == ridpointers[(int) RID_INT])
explicit_int = 1;
else if (id == ridpointers[(int) RID_CHAR])
explicit_char = 1;
else if (id == ridpointers[(int) RID_BOOL])
explicit_bool = 1;
if (RIDBIT_NOTSETP (RID_VECTOR, specbits)
|| id != ridpointers[(int) RID_BOOL])
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
}
if (IDENTIFIER_HAS_TYPE_VALUE (id))
{
if (type)
cp_error ("multiple declarations `%T' and `%T'", type, id);
else
type = IDENTIFIER_TYPE_VALUE (id);
goto found;
}
for (i = (int) RID_FIRST_MODIFIER; i <= (int) RID_LAST_MODIFIER; i++)
{
if (ridpointers[i] == id)
{
if (i == (int) RID_LONG && RIDBIT_SETP (i, specbits))
{
if (pedantic && ! in_system_header && warn_long_long)
pedwarn ("ANSI C++ does not support `long long'");
if (longlong)
error ("`long long long' is too long for GCC");
else
longlong = 1;
}
else if (RIDBIT_SETP (i, specbits))
pedwarn ("duplicate `%s'", IDENTIFIER_POINTER (id));
RIDBIT_SET (i, specbits);
goto found;
}
}
}
else if (TREE_CODE (id) == TYPE_DECL || TREE_CODE (id) == TEMPLATE_DECL)
{
if (type)
cp_error ("multiple declarations `%T' and `%T'", type,
TREE_TYPE (id));
else
{
type = TREE_TYPE (id);
TREE_VALUE (spec) = type;
}
goto found;
}
if (type)
error ("two or more data types in declaration of `%s'", name);
else if (TREE_CODE (id) == IDENTIFIER_NODE)
{
register tree t = lookup_name (id, 1);
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);
#if 0
decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
#endif
typedef_decl = t;
}
}
else if (id != error_mark_node)
type = id;
found: ;
}
if (type == NULL_TREE
&& RIDBIT_SETP (RID_VECTOR, specbits)
&& (RIDBIT_SETP (RID_PIXEL, specbits) || explicit_bool))
type = integer_type_node;
typedef_type = type;
if (type == NULL_TREE
&& (RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_UNSIGNED, specbits)
|| RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits)))
{
type = integer_type_node;
defaulted_int = 1;
}
if (type == NULL_TREE)
{
explicit_int = -1;
if (return_type == return_dtor)
type = void_type_node;
else if (return_type == return_ctor)
type = build_pointer_type (ctor_return_type);
else if (return_type == return_conversion)
type = ctor_return_type;
else if (current_class_type
&& IS_SIGNATURE (current_class_type)
&& RIDBIT_SETP (RID_TYPEDEF, specbits)
&& (decl_context == FIELD || decl_context == NORMAL))
{
explicit_int = 0;
opaque_typedef = 1;
type = copy_node (opaque_type_node);
}
else
{
int is_main = (funcdef_flag
&& MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
if (in_system_header)
;
else if (pedantic || ! is_main)
cp_pedwarn ("ANSI C++ forbids declaration `%D' with no type",
dname);
else if (warn_return_type)
cp_warning ("ANSI C++ forbids declaration `%D' with no type",
dname);
type = integer_type_node;
}
}
else if (return_type == return_dtor)
{
error ("return type specification for destructor invalid");
type = void_type_node;
}
else if (return_type == return_ctor)
{
error ("return type specification for constructor invalid");
type = build_pointer_type (ctor_return_type);
}
else if (return_type == return_conversion)
{
if (!same_type_p (type, ctor_return_type))
cp_error ("operator `%T' declared to return `%T'",
ctor_return_type, type);
else
cp_pedwarn ("return type specified for `operator %T'",
ctor_return_type);
type = ctor_return_type;
}
ctype = NULL_TREE;
if (RIDBIT_SETP (RID_LONG, specbits)
&& TYPE_MAIN_VARIANT (type) == double_type_node)
{
RIDBIT_RESET (RID_LONG, specbits);
type = build_qualified_type (long_double_type_node,
CP_TYPE_QUALS (type));
if (warn_long_double
&& ! warned_about_long_double
&& ! in_system_header
&& ! strstr (input_filename, "/System/Library/Frameworks/")
&& ! strstr (input_filename, "/usr/include/"))
{
warning ("use of `long double' type; its size may change in a future release");
warning ("(Long double usage is reported only once for each file.");
warning ("To disable this warning, use -Wno-long-double.)");
warned_about_long_double = 1;
}
}
if (RIDBIT_SETP (RID_UNSIGNED, specbits)
|| RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits))
{
int ok = 0;
if (TREE_CODE (type) == REAL_TYPE)
error ("short, signed or unsigned invalid for `%s'", name);
else if (RIDBIT_SETP (RID_LONG, specbits)
&& RIDBIT_SETP (RID_SHORT, specbits))
error ("long and short specified together for `%s'", name);
else if ((RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits))
&& explicit_char)
error ("long or short specified with char for `%s'", name);
else if ((RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits))
&& TREE_CODE (type) == REAL_TYPE)
error ("long or short specified with floating type for `%s'", name);
else if (RIDBIT_SETP (RID_SIGNED, specbits)
&& RIDBIT_SETP (RID_UNSIGNED, specbits))
error ("signed and unsigned given together for `%s'", name);
else if (RIDBIT_SETP (RID_VECTOR, specbits))
ok = 1;
else if (TREE_CODE (type) != INTEGER_TYPE)
error ("long, short, signed or unsigned invalid for `%s'", name);
else
{
ok = 1;
if (!explicit_int && !defaulted_int && !explicit_char && pedantic)
{
pedwarn ("long, short, signed or unsigned used invalidly for `%s'",
name);
if (flag_pedantic_errors)
ok = 0;
}
}
if (! ok)
{
RIDBIT_RESET (RID_UNSIGNED, specbits);
RIDBIT_RESET (RID_SIGNED, specbits);
RIDBIT_RESET (RID_LONG, specbits);
RIDBIT_RESET (RID_SHORT, specbits);
longlong = 0;
}
}
if (RIDBIT_SETP (RID_COMPLEX, specbits)
&& TREE_CODE (type) != INTEGER_TYPE && TREE_CODE (type) != REAL_TYPE)
{
error ("complex invalid for `%s'", name);
RIDBIT_RESET (RID_COMPLEX, specbits);
}
if (RIDBIT_SETP (RID_UNSIGNED, specbits)
|| (bitfield && ! flag_signed_bitfields
&& (explicit_int || defaulted_int || explicit_char
|| ! (typedef_decl != NULL_TREE
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
&& TREE_CODE (type) != ENUMERAL_TYPE
&& RIDBIT_NOTSETP (RID_SIGNED, specbits)))
{
if (longlong)
type = long_long_unsigned_type_node;
else if (RIDBIT_SETP (RID_LONG, specbits))
type = long_unsigned_type_node;
else if (RIDBIT_SETP (RID_SHORT, specbits))
type = short_unsigned_type_node;
else if (type == char_type_node)
type = unsigned_char_type_node;
else if (typedef_decl)
type = unsigned_type (type);
else
type = unsigned_type_node;
}
else if (RIDBIT_SETP (RID_SIGNED, specbits)
&& type == char_type_node)
type = signed_char_type_node;
else if (longlong)
type = long_long_integer_type_node;
else if (RIDBIT_SETP (RID_LONG, specbits))
type = long_integer_type_node;
else if (RIDBIT_SETP (RID_SHORT, specbits))
type = short_integer_type_node;
if (RIDBIT_SETP (RID_COMPLEX, specbits))
{
if (defaulted_int && ! longlong
&& ! (RIDBIT_SETP (RID_LONG, specbits)
|| RIDBIT_SETP (RID_SHORT, specbits)
|| RIDBIT_SETP (RID_SIGNED, specbits)
|| RIDBIT_SETP (RID_UNSIGNED, specbits)))
type = complex_double_type_node;
else if (type == integer_type_node)
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
type = build_complex_type (type);
}
if (return_type == return_conversion
&& (RIDBIT_SETP (RID_CONST, specbits)
|| RIDBIT_SETP (RID_VOLATILE, specbits)
|| RIDBIT_SETP (RID_RESTRICT, specbits)))
cp_error ("qualifiers are not allowed on declaration of `operator %T'",
ctor_return_type);
if (RIDBIT_SETP (RID_PIXEL, specbits)
&& RIDBIT_NOTSETP (RID_VECTOR, specbits))
{
error ("__pixel invalid for `%s'", name);
RIDBIT_RESET (RID_PIXEL, specbits);
}
if (RIDBIT_SETP (RID_VECTOR, specbits))
{
if ((type == integer_type_node || type == long_integer_type_node)
&& RIDBIT_SETP (RID_PIXEL, specbits))
type = vector_pixel_type_node;
else
if (type == long_unsigned_type_node || type == unsigned_type_node)
type = vector_unsigned_long_type_node;
else if (explicit_bool
&& (type == long_integer_type_node || type == integer_type_node))
type = vector_boolean_long_type_node;
else if (RIDBIT_SETP (RID_SIGNED, specbits)
&& (type == long_integer_type_node || type == integer_type_node))
type = vector_signed_long_type_node;
else if (type == short_unsigned_type_node)
type = vector_unsigned_short_type_node;
else if (explicit_bool && type == short_integer_type_node)
type = vector_boolean_short_type_node;
else if (RIDBIT_SETP (RID_SIGNED, specbits) && type == short_integer_type_node)
type = vector_signed_short_type_node;
else if (type == unsigned_char_type_node)
type = vector_unsigned_char_type_node;
else if (type == signed_char_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);
RIDBIT_RESET (RID_VECTOR, specbits);
RIDBIT_RESET (RID_PIXEL, specbits);
}
if (RIDBIT_SETP (RID_PIXEL, specbits) && type != vector_pixel_type_node)
{
error ("type modifiers do not apply to `vector pixel'");
type = vector_pixel_type_node;
}
}
constp = !! RIDBIT_SETP (RID_CONST, specbits) + CP_TYPE_CONST_P (type);
restrictp =
!! RIDBIT_SETP (RID_RESTRICT, specbits) + CP_TYPE_RESTRICT_P (type);
volatilep =
!! RIDBIT_SETP (RID_VOLATILE, specbits) + CP_TYPE_VOLATILE_P (type);
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
type = cp_build_qualified_type (type, type_quals);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
#if defined (_WIN32) && defined (NEXT_PDO)
stdcallp = !! (RIDBIT_SETP (RID_STDCALL, specbits));
#endif
virtualp = RIDBIT_SETP (RID_VIRTUAL, specbits);
RIDBIT_RESET (RID_VIRTUAL, specbits);
explicitp = RIDBIT_SETP (RID_EXPLICIT, specbits) != 0;
RIDBIT_RESET (RID_EXPLICIT, specbits);
if (RIDBIT_SETP (RID_STATIC, specbits))
staticp = 1 + (decl_context == FIELD);
if (virtualp && staticp == 2)
{
cp_error ("member `%D' cannot be declared both virtual and static",
dname);
staticp = 0;
}
friendp = RIDBIT_SETP (RID_FRIEND, specbits);
RIDBIT_RESET (RID_FRIEND, specbits);
if (friendp && explicitp)
error ("only declarations of constructors can be `explicit'");
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (decl_context == PARM)
{
error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (friendp || decl_context == TYPENAME)
{
error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
if (RIDBIT_ANY_SET (specbits))
{
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
if (RIDBIT_SETP (RID_EXTERN, specbits)) nclasses++;
if (decl_context == PARM && nclasses > 0)
error ("storage class specifiers invalid in parameter declarations");
if (RIDBIT_SETP (RID_TYPEDEF, specbits))
{
if (decl_context == PARM)
error ("typedef declaration invalid in parameter declaration");
nclasses++;
}
if (RIDBIT_SETP (RID_AUTO, specbits)) nclasses++;
if (RIDBIT_SETP (RID_REGISTER, specbits)) nclasses++;
}
if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{
error ("virtual outside class declaration");
virtualp = 0;
}
if (current_class_name == NULL_TREE && RIDBIT_SETP (RID_MUTABLE, specbits))
{
error ("only members can be declared mutable");
RIDBIT_RESET (RID_MUTABLE, specbits);
}
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
&& ANON_UNION_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
if (decl_context == FIELD
&& current_class_type != NULL_TREE
&& IS_SIGNATURE (current_class_type)
&& RIDBIT_NOTSETP (RID_TYPEDEF, specbits))
{
if (type_quals != TYPE_UNQUALIFIED)
{
error ("type qualifiers specified for signature member function `%s'", name);
type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
error ("`inline' specified for signature member function `%s'", name);
inlinep = 0;
}
if (friendp)
{
error ("`friend' declaration in signature definition");
friendp = 0;
}
if (virtualp)
{
error ("`virtual' specified for signature member function `%s'",
name);
virtualp = 0;
}
}
if (nclasses > 1)
error ("multiple storage classes in declaration of `%s'", name);
else if (decl_context != NORMAL && nclasses > 0)
{
if ((decl_context == PARM || decl_context == CATCHPARM)
&& (RIDBIT_SETP (RID_REGISTER, specbits)
|| RIDBIT_SETP (RID_AUTO, specbits)))
;
else if (RIDBIT_SETP (RID_TYPEDEF, specbits))
;
else if (decl_context == FIELD
&& ! IS_SIGNATURE (current_class_type)
&& RIDBIT_SETP (RID_STATIC, specbits))
;
else
{
if (decl_context == FIELD)
{
tree tmp = NULL_TREE;
register int op = 0;
if (declarator)
{
if (TREE_CODE (declarator) == IDENTIFIER_NODE)
tmp = declarator;
else
tmp = TREE_OPERAND (declarator, 0);
op = IDENTIFIER_OPNAME_P (tmp);
}
error ("storage class specified for %s `%s'",
IS_SIGNATURE (current_class_type)
? (op
? "signature member operator"
: "signature member function")
: (op ? "member operator" : "field"),
op ? operator_name_string (tmp) : name);
}
else
error (((decl_context == PARM || decl_context == CATCHPARM)
? "storage class specified for parameter `%s'"
: "storage class specified for typename"), name);
RIDBIT_RESET (RID_REGISTER, specbits);
RIDBIT_RESET (RID_AUTO, specbits);
RIDBIT_RESET (RID_EXTERN, specbits);
if (decl_context == FIELD && IS_SIGNATURE (current_class_type))
{
RIDBIT_RESET (RID_STATIC, specbits);
staticp = 0;
}
}
}
else if (RIDBIT_SETP (RID_EXTERN, specbits) && initialized && !funcdef_flag)
{
if (toplevel_bindings_p ())
{
if (!(type_quals & TYPE_QUAL_CONST))
warning ("`%s' initialized and declared `extern'", name);
}
else
error ("`%s' has both `extern' and initializer", name);
}
else if (RIDBIT_SETP (RID_EXTERN, specbits) && funcdef_flag
&& ! toplevel_bindings_p ())
error ("nested function `%s' declared `extern'", name);
else if (toplevel_bindings_p ())
{
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("top-level declaration of `%s' specifies `auto'", name);
}
if (nclasses > 0 && friendp)
error ("storage class specifiers invalid in friend function declarations");
inner_attrs = NULL_TREE;
ignore_attrs = 0;
while (declarator && TREE_CODE (declarator) != IDENTIFIER_NODE
&& TREE_CODE (declarator) != TEMPLATE_ID_EXPR)
{
if (type == error_mark_node)
{
if (TREE_CODE (declarator) == SCOPE_REF)
declarator = TREE_OPERAND (declarator, 1);
else
declarator = TREE_OPERAND (declarator, 0);
continue;
}
if (quals != NULL_TREE
&& (declarator == NULL_TREE
|| TREE_CODE (declarator) != SCOPE_REF))
{
if (ctype == NULL_TREE && TREE_CODE (type) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (type);
if (ctype != NULL_TREE)
{
tree dummy = build_decl (TYPE_DECL, NULL_TREE, type);
ctype = grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
quals = NULL_TREE;
}
}
if (ignore_attrs)
ignore_attrs = 0;
else if (inner_attrs)
{
decl_attributes (type, inner_attrs, NULL_TREE);
inner_attrs = NULL_TREE;
}
switch (TREE_CODE (declarator))
{
case TREE_LIST:
{
inner_attrs = TREE_PURPOSE (declarator);
ignore_attrs = 1;
declarator = TREE_VALUE (declarator);
}
break;
case ARRAY_REF:
{
register tree itype = NULL_TREE;
register tree size = TREE_OPERAND (declarator, 1);
tree index_type = signed_type (sizetype);
declarator = TREE_OPERAND (declarator, 0);
if (TREE_CODE (type) == VOID_TYPE)
{
cp_error ("declaration of `%D' as array of voids", dname);
type = error_mark_node;
}
if (TREE_CODE (type) == FUNCTION_TYPE)
{
cp_error ("declaration of `%D' as array of functions", dname);
type = error_mark_node;
}
if (TREE_CODE (type) == REFERENCE_TYPE)
{
if (decl_context == TYPENAME)
cp_error ("cannot make arrays of references");
else
cp_error ("declaration of `%D' as array of references",
dname);
type = error_mark_node;
}
if (TREE_CODE (type) == OFFSET_TYPE)
{
cp_error ("declaration of `%D' as array of data members",
dname);
type = error_mark_node;
}
if (TREE_CODE (type) == METHOD_TYPE)
{
cp_error ("declaration of `%D' as array of function members",
dname);
type = error_mark_node;
}
if (size == error_mark_node)
type = error_mark_node;
else if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
cp_error ("declaration of `%D' as multidimensional array",
dname);
cp_error ("must have bounds for all dimensions except the first");
type = error_mark_node;
}
if (type == error_mark_node)
continue;
if (size == NULL_TREE && decl_context == FIELD && ! staticp
&& ! RIDBIT_SETP (RID_TYPEDEF, specbits))
size = integer_zero_node;
if (size)
{
int yes = suspend_momentary ();
if (TREE_CODE (size) == NOP_EXPR
&& TREE_TYPE (size) == TREE_TYPE (TREE_OPERAND (size, 0)))
size = TREE_OPERAND (size, 0);
if (processing_template_decl)
{
if (TREE_CODE (size) == SCOPE_REF
&& TREE_OPERAND (size, 0) == current_class_type)
{
tree t = lookup_field (current_class_type,
TREE_OPERAND (size, 1), 0, 0);
if (t)
size = t;
}
itype = build_index_type (build_min
(MINUS_EXPR, sizetype, size, integer_one_node));
goto dont_grok_size;
}
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
cp_error ("size of array `%D' has non-integer type",
dname);
size = integer_one_node;
}
if (TREE_READONLY_DECL_P (size))
size = decl_constant_value (size);
if (pedantic && integer_zerop (size))
cp_pedwarn ("ANSI C++ forbids zero-size array `%D'", dname);
if (TREE_CONSTANT (size))
{
int old_flag_pedantic_errors = flag_pedantic_errors;
int old_pedantic = pedantic;
pedantic = flag_pedantic_errors = 1;
constant_expression_warning (size);
pedantic = old_pedantic;
flag_pedantic_errors = old_flag_pedantic_errors;
if (INT_CST_LT (size, integer_zero_node))
{
cp_error ("size of array `%D' is negative", dname);
size = integer_one_node;
}
}
else
{
if (pedantic)
{
if (dname)
cp_pedwarn ("ANSI C++ forbids variable-size array `%D'",
dname);
else
cp_pedwarn ("ANSI C++ forbids variable-size array");
}
}
itype
= fold (build_binary_op (MINUS_EXPR,
cp_convert (index_type, size),
cp_convert (index_type,
integer_one_node)));
if (! TREE_CONSTANT (itype))
itype = variable_size (itype);
else if (TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
if (decl_context == PARM
&& allocation_temporary_p () && TREE_PERMANENT (type))
{
push_obstacks (&permanent_obstack, &permanent_obstack);
itype = build_index_type (itype);
pop_obstacks ();
}
else
itype = build_index_type (itype);
dont_grok_size:
resume_momentary (yes);
}
type = build_cplus_array_type (type, itype);
ctype = NULL_TREE;
}
break;
case CALL_EXPR:
{
tree arg_types;
int funcdecl_p;
tree inner_parms = TREE_OPERAND (declarator, 1);
tree inner_decl = TREE_OPERAND (declarator, 0);
type_quals = TYPE_UNQUALIFIED;
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;
}
if (inner_decl && TREE_CODE (inner_decl) == SCOPE_REF)
inner_decl = TREE_OPERAND (inner_decl, 1);
if (inner_decl && TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR)
inner_decl = dname;
quals = TREE_OPERAND (declarator, 2);
raises = TREE_TYPE (declarator);
funcdecl_p
= inner_decl
&& (TREE_CODE (inner_decl) == IDENTIFIER_NODE
|| TREE_CODE (inner_decl) == TEMPLATE_ID_EXPR
|| TREE_CODE (inner_decl) == BIT_NOT_EXPR);
if (ctype == NULL_TREE
&& decl_context == FIELD
&& funcdecl_p
&& (friendp == 0 || dname == current_class_name))
ctype = current_class_type;
if (ctype && return_type == return_conversion)
TYPE_HAS_CONVERSION (ctype) = 1;
if (ctype && constructor_name (ctype) == dname)
{
if (flags == DTOR_FLAG)
{
if (staticp == 2)
error ("destructor cannot be static member function");
if (quals)
{
cp_error ("destructors may not be `%s'",
IDENTIFIER_POINTER (TREE_VALUE (quals)));
quals = NULL_TREE;
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype, current_class_type,
"destructor for alien class `%s' cannot be a member"))
return void_type_node;
}
}
else
{
if (explicitp == 1)
explicitp = 2;
if (staticp == 2)
error ("constructor cannot be static member function");
if (virtualp)
{
pedwarn ("constructors cannot be declared virtual");
virtualp = 0;
}
if (quals)
{
cp_error ("constructors may not be `%s'",
IDENTIFIER_POINTER (TREE_VALUE (quals)));
quals = NULL_TREE;
}
{
RID_BIT_TYPE tmp_bits;
bcopy ((void*)&specbits, (void*)&tmp_bits, sizeof (RID_BIT_TYPE));
RIDBIT_RESET (RID_INLINE, tmp_bits);
RIDBIT_RESET (RID_STATIC, tmp_bits);
if (RIDBIT_ANY_SET (tmp_bits))
error ("return value type specifier for constructor ignored");
}
type = build_pointer_type (ctype);
if (decl_context == FIELD
&& IS_SIGNATURE (current_class_type))
{
error ("constructor not allowed in signature");
return void_type_node;
}
else if (decl_context == FIELD)
{
if (! member_function_or_else (ctype, current_class_type,
"constructor for alien class `%s' cannot be member"))
return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (return_type != return_ctor)
return NULL_TREE;
}
}
if (decl_context == FIELD)
staticp = 0;
}
else if (friendp)
{
if (initialized)
error ("can't initialize friend function `%s'", name);
if (virtualp)
{
error ("virtual functions cannot be friends");
RIDBIT_RESET (RID_FRIEND, specbits);
friendp = 0;
}
if (decl_context == NORMAL)
error ("friend declaration not in class definition");
if (current_function_decl && funcdef_flag)
cp_error ("can't define friend function `%s' in a local class definition",
name);
}
declarator = TREE_OPERAND (declarator, 0);
arg_types = grokparms (inner_parms, funcdecl_p ? funcdef_flag : 0);
if (declarator && flags == DTOR_FLAG)
{
if (TREE_CODE (declarator) == BIT_NOT_EXPR)
declarator = TREE_OPERAND (declarator, 0);
if (strict_prototype == 0 && arg_types == NULL_TREE)
arg_types = void_list_node;
else if (arg_types == NULL_TREE
|| arg_types != void_list_node)
{
cp_error ("destructors may not have parameters");
arg_types = void_list_node;
last_function_parms = NULL_TREE;
}
}
type = build_function_type (type, arg_types);
#ifdef _WIN32
if( stdcallp )
{
type = build_type_copy( type );
TYPE_STDCALL( type ) = 1;
}
#endif
{
tree t;
for (t = arg_types; t; t = TREE_CHAIN (t))
if (TREE_PURPOSE (t)
&& TREE_CODE (TREE_PURPOSE (t)) == DEFAULT_ARG)
{
add_defarg_fn (type);
break;
}
}
}
break;
case ADDR_EXPR:
case INDIRECT_REF:
if (TREE_CODE (type) == REFERENCE_TYPE)
{
error ("cannot declare %s to references",
TREE_CODE (declarator) == ADDR_EXPR
? "references" : "pointers");
declarator = TREE_OPERAND (declarator, 0);
continue;
}
if (TREE_CODE (type) == OFFSET_TYPE
&& (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE
|| TREE_CODE (TREE_TYPE (type)) == REFERENCE_TYPE))
{
cp_error ("cannot declare pointer to `%#T' member",
TREE_TYPE (type));
type = TREE_TYPE (type);
}
type_quals = TYPE_UNQUALIFIED;
if (IS_SIGNATURE (type))
{
if (TREE_CODE (declarator) == ADDR_EXPR)
{
if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE
&& TYPE_SIZE (type))
cp_warning ("empty signature `%T' used in signature reference declaration",
type);
#if 0
type = build_signature_reference_type (type);
#else
sorry ("signature reference");
return NULL_TREE;
#endif
}
else
{
if (CLASSTYPE_METHOD_VEC (type) == NULL_TREE
&& TYPE_SIZE (type))
cp_warning ("empty signature `%T' used in signature pointer declaration",
type);
type = build_signature_pointer_type (type);
}
}
else if (TREE_CODE (declarator) == ADDR_EXPR)
{
if (TREE_CODE (type) == VOID_TYPE)
error ("invalid type: `void &'");
else
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
else
type = build_pointer_type (type);
if (TREE_TYPE (declarator))
{
register 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 (qualifier == ridpointers[(int) RID_CONST])
constp++;
else if (qualifier == ridpointers[(int) RID_VOLATILE])
volatilep++;
#ifdef _WIN32
else if (TREE_VALUE (typemodlist) == ridpointers[(int) RID_STDCALL])
{
stdcallp++;
type = build_type_copy( TREE_TYPE( type ) );
type = build_pointer_type( type );
TYPE_STDCALL( TREE_TYPE( type ) ) = 1;
}
#endif
else if (qualifier == ridpointers[(int) RID_RESTRICT])
restrictp++;
else if (!erred)
{
erred = 1;
error ("invalid type modifier within pointer declarator");
}
}
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
#ifdef _WIN32
if (stdcallp > 1)
pedwarn ("duplicate `stdcall'");
#endif
if (restrictp > 1)
pedwarn ("duplicate `restrict'");
type_quals = ((constp ? TYPE_QUAL_CONST : 0)
| (restrictp ? TYPE_QUAL_RESTRICT : 0)
| (volatilep ? TYPE_QUAL_VOLATILE : 0));
if (TREE_CODE (declarator) == ADDR_EXPR
&& (constp || volatilep))
{
if (constp)
pedwarn ("discarding `const' applied to a reference");
if (volatilep)
pedwarn ("discarding `volatile' applied to a reference");
type_quals &= ~(TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE);
}
type = cp_build_qualified_type (type, type_quals);
}
declarator = TREE_OPERAND (declarator, 0);
ctype = NULL_TREE;
break;
case SCOPE_REF:
{
tree sname = TREE_OPERAND (declarator, 1);
tree t;
if (TREE_CODE (sname) == BIT_NOT_EXPR)
sname = TREE_OPERAND (sname, 0);
if (TREE_COMPLEXITY (declarator) == 0)
;
else if (TREE_COMPLEXITY (declarator) == -1)
pop_decl_namespace ();
else if (friendp && (TREE_COMPLEXITY (declarator) < 2))
;
else if (! IS_AGGR_TYPE_CODE
(TREE_CODE (TREE_OPERAND (declarator, 0))))
;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
{
if (current_template_parms
&& uses_template_parms (type)
&& uses_template_parms (current_class_type))
{
tree args = current_template_args ();
type = tsubst (type, args, 1, NULL_TREE);
}
pop_nested_class ();
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
my_friendly_abort (16);
if (TREE_OPERAND (declarator, 0) == NULL_TREE)
{
declarator = sname;
continue;
}
ctype = TREE_OPERAND (declarator, 0);
t = ctype;
while (t != NULL_TREE && CLASS_TYPE_P (t))
{
if (CLASSTYPE_TEMPLATE_INFO (t) &&
!CLASSTYPE_TEMPLATE_SPECIALIZATION (t))
template_count += 1;
t = TYPE_MAIN_DECL (t);
if (DECL_LANG_SPECIFIC (t))
t = DECL_CLASS_CONTEXT (t);
else
t = NULL_TREE;
}
if (sname == NULL_TREE)
goto done_scoping;
if (TREE_CODE (sname) == IDENTIFIER_NODE)
{
if (ctype == current_class_type)
{
if (pedantic)
cp_pedwarn ("extra qualification `%T::' on member `%s' ignored",
ctype, name);
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
if (current_class_type == NULL_TREE
|| friendp)
type = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
{
cp_error ("cannot declare member function `%T::%s' within `%T'",
ctype, name, current_class_type);
return void_type_node;
}
}
else if (RIDBIT_SETP (RID_TYPEDEF, specbits)
|| TYPE_SIZE (complete_type (ctype)) != NULL_TREE)
{
if (current_class_type)
{
cp_error ("cannot declare member `%T::%s' within `%T'",
ctype, name, current_class_type);
return void_type_node;
}
type = build_offset_type (ctype, type);
}
else if (uses_template_parms (ctype))
{
if (TREE_CODE (type) == FUNCTION_TYPE)
type
= build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
else
{
cp_error ("structure `%T' not yet defined", ctype);
return error_mark_node;
}
declarator = sname;
}
else if (TREE_CODE (sname) == SCOPE_REF)
my_friendly_abort (17);
else
{
done_scoping:
declarator = TREE_OPERAND (declarator, 1);
if (declarator && TREE_CODE (declarator) == CALL_EXPR)
;
else
{
if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
else
type = build_offset_type (ctype, type);
}
}
}
break;
case BIT_NOT_EXPR:
declarator = TREE_OPERAND (declarator, 0);
break;
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
declarator = NULL_TREE;
break;
case ERROR_MARK:
declarator = NULL_TREE;
break;
default:
my_friendly_abort (158);
}
}
if (inner_attrs)
{
if (! ignore_attrs)
decl_attributes (type, inner_attrs, NULL_TREE);
else if (attrlist)
TREE_VALUE (attrlist) = chainon (inner_attrs, TREE_VALUE (attrlist));
else
attrlist = build_decl_list (NULL_TREE, inner_attrs);
}
if (explicitp == 1)
{
error ("only constructors can be declared `explicit'");
explicitp = 0;
}
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (staticp)
{
error ("static `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
if (declarator == NULL_TREE
|| TREE_CODE (declarator) == IDENTIFIER_NODE
|| (TREE_CODE (declarator) == TEMPLATE_ID_EXPR
&& (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)))
;
else if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
{
cp_error ("template-id `%D' used as a declarator", declarator);
declarator = dname;
}
else
my_friendly_abort (990210);
if (RIDBIT_SETP (RID_TYPEDEF, specbits) && decl_context != TYPENAME)
{
tree decl;
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
if (decl_context == FIELD)
{
if (declarator == constructor_name (current_class_type))
cp_pedwarn ("ANSI C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
if (IS_SIGNATURE (current_class_type) && opaque_typedef)
SIGNATURE_HAS_OPAQUE_TYPEDECLS (current_class_type) = 1;
}
else
{
if (type != error_mark_node)
push_obstacks (TYPE_OBSTACK (type), TYPE_OBSTACK (type));
decl = build_decl (TYPE_DECL, declarator, type);
if (type != error_mark_node)
pop_obstacks ();
}
if (type != error_mark_node
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& ANON_AGGRNAME_P (TYPE_IDENTIFIER (type)))
{
tree oldname = TYPE_NAME (type);
tree t;
lookup_tag_reverse (type, declarator);
for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
if (TYPE_NAME (t) == oldname)
TYPE_NAME (t) = decl;
if (TYPE_LANG_SPECIFIC (type))
TYPE_WAS_ANONYMOUS (type) = 1;
if (TYPE_LANG_SPECIFIC (type) && CLASSTYPE_TEMPLATE_INFO (type))
DECL_NAME (CLASSTYPE_TI_TEMPLATE (type))
= TYPE_IDENTIFIER (type);
my_friendly_assert (DECL_CONTEXT (decl) == NULL_TREE, 980404);
if (current_class_type)
DECL_CONTEXT (decl) = current_class_type;
else
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
DECL_ASSEMBLER_NAME (decl) = DECL_NAME (decl);
DECL_ASSEMBLER_NAME (decl)
= get_identifier (build_overload_name (type, 1, 1));
DECL_CONTEXT (decl) = NULL_TREE;
}
if (TREE_CODE (type) == OFFSET_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
cp_error_at ("typedef name may not be class-qualified", decl);
return NULL_TREE;
}
else if (quals)
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
cp_error_at ("invalid type qualifier for non-method type", decl);
else
ctype = TYPE_METHOD_BASETYPE (type);
}
if (ctype != NULL_TREE)
grok_method_quals (ctype, decl, quals);
}
if (RIDBIT_SETP (RID_SIGNED, specbits)
|| (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
if (RIDBIT_SETP (RID_MUTABLE, specbits))
error ("non-object member `%s' cannot be declared mutable", name);
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (initialized)
error ("typedef declaration includes an initializer");
#ifdef _WIN32
if( stdcallp )
TYPE_STDCALL( type ) = 1;
#endif
return decl;
}
if (type == typedef_type && TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE)
{
type = build_cplus_array_type (TREE_TYPE (type), TYPE_DOMAIN (type));
}
if (decl_context == TYPENAME)
{
if (type_quals != TYPE_UNQUALIFIED)
{
if (IS_SIGNATURE (type))
error ("type qualifiers specified for signature type");
type_quals = TYPE_UNQUALIFIED;
}
if (friendp)
{
if (type_quals != TYPE_UNQUALIFIED)
{
cp_error ("type qualifiers specified for friend class declaration");
type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
cp_error ("`inline' specified for friend class declaration");
inlinep = 0;
}
if (type != integer_type_node)
{
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
else
error ("trying to make class `%s' a friend of global scope",
TYPE_NAME_STRING (type));
type = void_type_node;
}
}
else if (quals)
{
tree dummy = build_decl (TYPE_DECL, declarator, type);
if (ctype == NULL_TREE)
{
my_friendly_assert (TREE_CODE (type) == METHOD_TYPE, 159);
ctype = TYPE_METHOD_BASETYPE (type);
}
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
}
return type;
}
else if (declarator == NULL_TREE && decl_context != PARM
&& decl_context != CATCHPARM
&& TREE_CODE (type) != UNION_TYPE
&& ! bitfield)
{
cp_error ("abstract declarator `%T' used as declaration", type);
declarator = make_anon_name ();
}
if (TREE_CODE (type) == VOID_TYPE && decl_context != PARM)
{
if (! declarator)
error ("unnamed variable or field declared void");
else if (TREE_CODE (declarator) == IDENTIFIER_NODE)
{
if (IDENTIFIER_OPNAME_P (declarator))
my_friendly_abort (356);
else
error ("variable or field `%s' declared void", name);
}
else
error ("variable or field declared void");
type = integer_type_node;
}
if (decl_context == PARM || decl_context == CATCHPARM)
{
if (ctype || in_namespace)
error ("cannot use `::' in parameter declaration");
if (TREE_CODE (type) == ARRAY_TYPE)
{
type = build_pointer_type (TREE_TYPE (type));
type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == VOID_TYPE && declarator)
{
error ("declaration of `%s' as void", name);
return NULL_TREE;
}
}
{
register tree decl;
if (decl_context == PARM)
{
decl = build_decl (PARM_DECL, declarator, type);
if (TREE_CODE (type) == ARRAY_TYPE)
{
type = build_pointer_type (TREE_TYPE (type));
type_quals = TYPE_UNQUALIFIED;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == OFFSET_TYPE)
type = build_pointer_type (type);
else if (TREE_CODE (type) == VOID_TYPE && declarator)
{
error ("declaration of `%s' as void", name);
return NULL_TREE;
}
decl = build_decl (PARM_DECL, declarator, complete_type (type));
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (current_class_type
&& IS_SIGNATURE (current_class_type))
{
if (inlinep)
error ("parameter of signature member function declared `inline'");
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("parameter of signature member function declared `auto'");
if (RIDBIT_SETP (RID_REGISTER, specbits))
error ("parameter of signature member function declared `register'");
}
DECL_ARG_TYPE (decl) = type_promotes_to (type);
}
else if (decl_context == FIELD)
{
if (type == error_mark_node)
{
decl = NULL_TREE;
}
else if (in_namespace && !friendp)
{
cp_error ("invalid use of `::'");
decl = NULL_TREE;
}
else if (TREE_CODE (type) == FUNCTION_TYPE)
{
int publicp = 0;
tree function_context;
if (friendp && declarator == ridpointers[(int) RID_SIGNED])
{
cp_error ("function `%D' cannot be declared friend",
declarator);
friendp = 0;
}
if (friendp == 0)
{
if (ctype == NULL_TREE)
ctype = current_class_type;
if (ctype == NULL_TREE)
{
cp_error ("can't make `%D' into a method -- not in a class",
declarator);
return void_type_node;
}
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
cp_error ("function `%D' declared virtual inside a union",
declarator);
return void_type_node;
}
if (declarator == ansi_opname[(int) NEW_EXPR]
|| declarator == ansi_opname[(int) VEC_NEW_EXPR]
|| declarator == ansi_opname[(int) DELETE_EXPR]
|| declarator == ansi_opname[(int) VEC_DELETE_EXPR])
{
if (virtualp)
{
cp_error ("`%D' cannot be declared virtual, since it is always static",
declarator);
virtualp = 0;
}
}
else if (staticp < 2)
type = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
}
function_context = (ctype != NULL_TREE) ?
hack_decl_function_context (TYPE_MAIN_DECL (ctype)) : NULL_TREE;
publicp = (! friendp || ! staticp)
&& function_context == NULL_TREE;
decl = grokfndecl (ctype, type,
TREE_CODE (declarator) != TEMPLATE_ID_EXPR
? declarator : dname,
declarator,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, publicp, inlinep,
funcdef_flag, template_count, in_namespace);
if (decl == NULL_TREE)
return decl;
#if 0
decl = build_decl_attribute_variant (decl, decl_machine_attr);
#endif
#ifdef _WIN32
if( stdcallp )
DECL_STDCALL( decl ) = stdcallp;
#endif
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
else if (DECL_CONSTRUCTOR_P (decl))
{
tree arg_types =
TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)));
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (decl)))
arg_types = TREE_CHAIN (arg_types);
if (arg_types == void_list_node
|| (arg_types
&& TREE_CHAIN (arg_types)
&& TREE_CHAIN (arg_types) != void_list_node
&& !TREE_PURPOSE (TREE_CHAIN (arg_types))))
DECL_NONCONVERTING_P (decl) = 1;
}
}
else if (TREE_CODE (type) == METHOD_TYPE)
{
decl = grokfndecl (ctype, type, declarator, declarator,
virtualp, flags, quals, raises,
friendp ? -1 : 0, friendp, 1, 0, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
}
else if (!staticp && ! processing_template_decl
&& TYPE_SIZE (complete_type (type)) == NULL_TREE
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (declarator)
cp_error ("field `%D' has incomplete type", declarator);
else
cp_error ("name `%T' has incomplete type", type);
if (current_class_type
&& TYPE_NAME (current_class_type)
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (current_class_type))
&& declspecs && TREE_VALUE (declspecs)
&& TREE_TYPE (TREE_VALUE (declspecs)) == type)
cp_error (" in instantiation of template `%T'",
current_class_type);
type = error_mark_node;
decl = NULL_TREE;
}
else
{
if (friendp)
{
error ("`%s' is neither function nor method; cannot be declared friend",
IDENTIFIER_POINTER (declarator));
friendp = 0;
}
decl = NULL_TREE;
}
if (friendp)
{
if (ctype == current_class_type)
warning ("member functions are implicitly friends of their class");
else
{
tree t = NULL_TREE;
if (decl && DECL_NAME (decl))
{
if (template_class_depth (current_class_type) == 0)
{
decl
= check_explicit_specialization
(declarator, decl,
template_count, 2 * (funcdef_flag != 0) + 4);
if (decl == error_mark_node)
return error_mark_node;
}
t = do_friend (ctype, declarator, decl,
last_function_parms, attrlist, flags, quals,
funcdef_flag);
}
if (t && funcdef_flag)
return t;
return void_type_node;
}
}
if (decl == NULL_TREE)
{
if (initialized)
{
if (!staticp)
{
cp_pedwarn ("ANSI C++ forbids initialization of member `%D'",
declarator);
cp_pedwarn ("making `%D' static", declarator);
staticp = 1;
}
if (uses_template_parms (type))
;
else if (check_static_variable_definition (declarator,
type))
return void_type_node;
}
#ifdef OBJCPLUS
if(objc_interface_context == NULL_TREE && objc_implementation_context == NULL_TREE)
#endif
if (declarator == constructor_name (current_class_type)
&& (staticp || ! in_system_header))
cp_warning ("ANSI C++ forbids data member `%D' with same name as enclosing class",
declarator);
if (staticp)
{
decl = build_lang_field_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
}
else
{
decl = build_lang_field_decl (FIELD_DECL, declarator, type);
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
DECL_MUTABLE_P (decl) = 1;
RIDBIT_RESET (RID_MUTABLE, specbits);
}
}
bad_specifiers (decl, "field", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE)
{
tree original_name;
int publicp = 0;
if (! declarator)
return NULL_TREE;
if (TREE_CODE (declarator) == TEMPLATE_ID_EXPR)
original_name = dname;
else
original_name = declarator;
if (RIDBIT_SETP (RID_AUTO, specbits))
error ("storage class `auto' invalid for function `%s'", name);
else if (RIDBIT_SETP (RID_REGISTER, specbits))
error ("storage class `register' invalid for function `%s'", name);
if (! toplevel_bindings_p ()
&& (RIDBIT_SETP (RID_STATIC, specbits)
|| RIDBIT_SETP (RID_INLINE, specbits))
&& pedantic)
{
if (RIDBIT_SETP (RID_STATIC, specbits))
pedwarn ("storage class `static' invalid for function `%s' declared out of global scope", name);
else
pedwarn ("storage class `inline' invalid for function `%s' declared out of global scope", name);
}
if (ctype == NULL_TREE)
{
if (virtualp)
{
error ("virtual non-class function `%s'", name);
virtualp = 0;
}
}
else if (TREE_CODE (type) == FUNCTION_TYPE && staticp < 2)
type = build_cplus_method_type (ctype, TREE_TYPE (type),
TYPE_ARG_TYPES (type));
publicp = (ctype != NULL_TREE
|| RIDBIT_SETP (RID_EXTERN, specbits)
|| !RIDBIT_SETP (RID_STATIC, specbits));
decl = grokfndecl (ctype, type, original_name, declarator,
virtualp, flags, quals, raises,
1, friendp,
publicp, inlinep, funcdef_flag,
template_count, in_namespace);
if (decl == NULL_TREE)
return NULL_TREE;
if (staticp == 1)
{
int illegal_static = 0;
if (TREE_CODE (type) == METHOD_TYPE)
{
cp_pedwarn ("cannot declare member function `%D' to have static linkage", decl);
illegal_static = 1;
}
else if (current_function_decl)
{
error ("cannot declare static function inside another function");
illegal_static = 1;
}
if (illegal_static)
{
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
}
}
else
{
decl = grokvardecl (type, declarator, &specbits,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
cp_pedwarn ("static member `%D' re-declared as static", decl);
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
{
cp_error ("static member `%D' declared `register'", decl);
RIDBIT_RESET (RID_REGISTER, specbits);
}
if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
{
cp_pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
RIDBIT_RESET (RID_EXTERN, specbits);
}
}
}
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
error ("`%s' cannot be declared mutable", name);
}
if (RIDBIT_SETP (RID_REGISTER, specbits))
DECL_REGISTER (decl) = 1;
if (RIDBIT_SETP (RID_EXTERN, specbits))
DECL_THIS_EXTERN (decl) = 1;
if (RIDBIT_SETP (RID_STATIC, specbits))
DECL_THIS_STATIC (decl) = 1;
#if defined (_WIN32) && defined (NEXT_PDO)
if (stdcallp)
TYPE_STDCALL (decl) = 1;
if (RIDBIT_SETP(RID_DLLIMPORT, specbits))
{
DECL_EXTERNAL (decl) = 1;
{
char* newName =
(char*)malloc(strlen( IDENTIFIER_POINTER(DECL_NAME(decl)) ) + 7 ); sprintf( newName, "_imp__%s", IDENTIFIER_POINTER(DECL_NAME(decl)) );
DECL_ASSEMBLER_NAME(decl) = get_identifier( newName );
DECL_DLLIMPORT(decl) = 1;
}
}
else if (RIDBIT_SETP (RID_DLLEXPORT, specbits))
{
char prependCharacter = '_';
char *tail = "";
char *gen_stdcall_suffix ();
char *ident_name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
int length = 1;
if (TREE_CODE (decl) != FUNCTION_DECL)
tail = ",data";
if (exportNamesForDLL)
length += strlen (exportNamesForDLL);
length += strlen (" -export:");
if (strncmp (ident_name, "objc_class_name", 15) == 0)
{
prependCharacter = '.';
tail = "";
}
length += strlen (tail);
if (stdcallp)
ident_name = gen_stdcall_suffix (decl);
length += strlen (ident_name);
if (exportNamesForDLL)
exportNamesForDLL =
(char *) realloc ((void*)exportNamesForDLL, length + 1);
else
{
exportNamesForDLL = (char *) malloc (length + 1);
*exportNamesForDLL = '\0';
}
sprintf (exportNamesForDLL, "%s%s%c%s%s", exportNamesForDLL,
" -export:", prependCharacter, ident_name, tail);
}
#endif
c_apply_type_quals_to_decl (type_quals, decl);
return decl;
}
}
int
parmlist_is_exprlist (exprs)
tree exprs;
{
if (exprs == NULL_TREE || TREE_PARMLIST (exprs))
return 0;
if (toplevel_bindings_p ())
{
while (exprs)
{
if (TREE_CODE (TREE_VALUE (exprs)) != IDENTIFIER_NODE)
return 1;
exprs = TREE_CHAIN (exprs);
}
return 0;
}
return 1;
}
static void
require_complete_types_for_parms (parms)
tree parms;
{
while (parms)
{
tree type = TREE_TYPE (parms);
if (TYPE_SIZE (complete_type (type)) == NULL_TREE)
{
if (DECL_NAME (parms))
error ("parameter `%s' has incomplete type",
IDENTIFIER_POINTER (DECL_NAME (parms)));
else
error ("parameter has incomplete type");
TREE_TYPE (parms) = error_mark_node;
}
else
layout_decl (parms, 0);
parms = TREE_CHAIN (parms);
}
}
static tree
local_variable_p (t)
tree t;
{
if ((TREE_CODE (t) == VAR_DECL
&& !TYPE_P (CP_DECL_CONTEXT (t))
&& TREE_CODE (CP_DECL_CONTEXT (t)) != NAMESPACE_DECL)
|| (TREE_CODE (t) == PARM_DECL))
return t;
return NULL_TREE;
}
tree
check_default_argument (decl, arg)
tree decl;
tree arg;
{
tree var;
tree decl_type;
if (TREE_CODE (arg) == DEFAULT_ARG)
return arg;
if (processing_template_decl || uses_template_parms (arg))
return arg;
if (TYPE_P (decl))
{
decl_type = decl;
decl = NULL_TREE;
}
else
decl_type = TREE_TYPE (decl);
if (arg == error_mark_node
|| decl == error_mark_node
|| TREE_TYPE (arg) == error_mark_node
|| decl_type == error_mark_node)
return error_mark_node;
if (!TREE_TYPE (arg)
|| !can_convert_arg (decl_type, TREE_TYPE (arg), arg))
{
if (decl)
cp_error ("default argument for `%#D' has type `%T'",
decl, TREE_TYPE (arg));
else
cp_error ("default argument for paramter of type `%T' has type `%T'",
decl_type, TREE_TYPE (arg));
return error_mark_node;
}
var = search_tree (arg, local_variable_p);
if (var)
{
cp_error ("default argument `%E' uses local variable `%D'",
arg, var);
return error_mark_node;
}
return arg;
}
#ifdef OBJCPLUS
tree
#else
static tree
#endif
grokparms (first_parm, funcdef_flag)
tree first_parm;
int funcdef_flag;
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
if (first_parm != NULL_TREE
&& 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 NULL_TREE;
}
else if (first_parm != NULL_TREE
&& TREE_CODE (TREE_VALUE (first_parm)) != TREE_LIST
&& TREE_CODE (TREE_VALUE (first_parm)) != VOID_TYPE)
#ifdef OBJCPLUS
return first_parm;
#else
my_friendly_abort (145);
#endif
else
{
register tree parm, chain;
int any_init = 0, any_error = 0;
if (first_parm != NULL_TREE)
{
tree last_result = NULL_TREE;
tree last_decl = NULL_TREE;
for (parm = first_parm; parm != NULL_TREE; parm = chain)
{
tree type = NULL_TREE, list_node = parm;
register tree decl = TREE_VALUE (parm);
tree init = TREE_PURPOSE (parm);
chain = TREE_CHAIN (parm);
if (TREE_CODE (decl) != VOID_TYPE
&& TREE_CODE (decl) != TREE_LIST)
{
if (TREE_CODE (decl) == STRING_CST)
cp_error ("invalid string constant `%E'", decl);
else if (TREE_CODE (decl) == INTEGER_CST)
error ("invalid integer constant in parameter list, did you forget to give parameter name?");
continue;
}
if (TREE_CODE (decl) != VOID_TYPE)
{
decl = grokdeclarator (TREE_VALUE (decl),
TREE_PURPOSE (decl),
PARM, init != NULL_TREE,
NULL_TREE);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
type = TYPE_MAIN_VARIANT (TREE_TYPE (decl));
if (TREE_CODE (type) == VOID_TYPE)
decl = void_type_node;
else if (TREE_CODE (type) == METHOD_TYPE)
{
if (DECL_NAME (decl))
cp_error ("parameter `%D' invalidly declared method type",
DECL_NAME (decl));
else
error ("parameter invalidly declared method type");
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (TREE_CODE (type) == OFFSET_TYPE)
{
if (DECL_NAME (decl))
cp_error ("parameter `%D' invalidly declared offset type",
DECL_NAME (decl));
else
error ("parameter invalidly declared offset type");
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (decl, type);
any_error = 1;
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& IS_SIGNATURE (type))
{
signature_error (decl, type);
any_error = 1;
}
else if (POINTER_TYPE_P (type))
{
tree t = type;
while (POINTER_TYPE_P (t)
|| (TREE_CODE (t) == ARRAY_TYPE
&& TYPE_DOMAIN (t) != NULL_TREE))
t = TREE_TYPE (t);
if (TREE_CODE (t) == ARRAY_TYPE)
cp_error ("parameter type `%T' includes %s to array of unknown bound",
type,
TYPE_PTR_P (type) ? "pointer" : "reference");
}
}
if (TREE_CODE (decl) == VOID_TYPE)
{
if (result == NULL_TREE)
{
result = void_list_node;
last_result = result;
}
else
{
TREE_CHAIN (last_result) = void_list_node;
last_result = void_list_node;
}
if (chain
&& (chain != void_list_node || TREE_CHAIN (chain)))
error ("`void' in parameter list must be entire list");
break;
}
DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
#ifdef PROMOTE_PROTOTYPES
if ((TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
DECL_ARG_TYPE (decl) = integer_type_node;
#endif
if (!any_error && init)
{
any_init++;
init = check_default_argument (decl, init);
}
else
init = NULL_TREE;
if (decls == NULL_TREE)
{
decls = decl;
last_decl = decls;
}
else
{
TREE_CHAIN (last_decl) = decl;
last_decl = decl;
}
if (! current_function_decl && TREE_PERMANENT (list_node))
{
TREE_PURPOSE (list_node) = init;
TREE_VALUE (list_node) = type;
TREE_CHAIN (list_node) = NULL_TREE;
}
else
list_node = saveable_tree_cons (init, type, NULL_TREE);
if (result == NULL_TREE)
{
result = list_node;
last_result = result;
}
else
{
TREE_CHAIN (last_result) = list_node;
last_result = list_node;
}
}
if (last_result)
TREE_CHAIN (last_result) = NULL_TREE;
if (last_decl != NULL_TREE)
TREE_CHAIN (last_decl) = NULL_TREE;
}
}
last_function_parms = decls;
return result;
}
void
replace_defarg (arg, init)
tree arg, init;
{
if (! processing_template_decl
&& ! can_convert_arg (TREE_VALUE (arg), TREE_TYPE (init), init))
cp_pedwarn ("invalid type `%T' for default argument to `%T'",
TREE_TYPE (init), TREE_VALUE (arg));
TREE_PURPOSE (arg) = init;
}
int
copy_args_p (d)
tree d;
{
tree t = FUNCTION_ARG_CHAIN (d);
if (DECL_CONSTRUCTOR_P (d)
&& TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (d)))
t = TREE_CHAIN (t);
if (t && TREE_CODE (TREE_VALUE (t)) == REFERENCE_TYPE
&& (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_VALUE (t)))
== DECL_CLASS_CONTEXT (d))
&& (TREE_CHAIN (t) == NULL_TREE
|| TREE_CHAIN (t) == void_list_node
|| TREE_PURPOSE (TREE_CHAIN (t))))
return 1;
return 0;
}
int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
{
tree parmtypes = FUNCTION_ARG_CHAIN (decl);
tree parmtype = parmtypes ? TREE_VALUE (parmtypes) : void_type_node;
if (TYPE_USES_VIRTUAL_BASECLASSES (ctype))
{
my_friendly_assert (parmtypes
&& TREE_VALUE (parmtypes) == integer_type_node,
980529);
parmtypes = TREE_CHAIN (parmtypes);
parmtype = TREE_VALUE (parmtypes);
}
if (TREE_CODE (parmtype) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (parmtype)) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
|| TREE_PURPOSE (TREE_CHAIN (parmtypes)))
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
&& is_member_template (DECL_TI_TEMPLATE (decl))))
{
TYPE_HAS_INIT_REF (ctype) = 1;
if (CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_INIT_REF (ctype) = 1;
}
else if (TYPE_MAIN_VARIANT (parmtype) == ctype
&& (TREE_CHAIN (parmtypes) == NULL_TREE
|| TREE_CHAIN (parmtypes) == void_list_node
|| TREE_PURPOSE (TREE_CHAIN (parmtypes)))
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
&& is_member_template (DECL_TI_TEMPLATE (decl))))
{
cp_error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
else if (TREE_CODE (parmtype) == VOID_TYPE
|| TREE_PURPOSE (parmtypes) != NULL_TREE)
TYPE_HAS_DEFAULT_CONSTRUCTOR (ctype) = 1;
return 1;
}
static int
ambi_op_p (name)
tree name;
{
return (name == ansi_opname [(int) INDIRECT_REF]
|| name == ansi_opname [(int) ADDR_EXPR]
|| name == ansi_opname [(int) NEGATE_EXPR]
|| name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR]
|| name == ansi_opname [(int) CONVERT_EXPR]);
}
static int
unary_op_p (name)
tree name;
{
return (name == ansi_opname [(int) TRUTH_NOT_EXPR]
|| name == ansi_opname [(int) BIT_NOT_EXPR]
|| name == ansi_opname [(int) COMPONENT_REF]
|| IDENTIFIER_TYPENAME_P (name));
}
void
grok_op_properties (decl, virtualp, friendp)
tree decl;
int virtualp, friendp;
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
if (current_class_type == NULL_TREE)
friendp = 1;
if (! friendp)
{
if (name == ansi_opname[(int) MODIFY_EXPR]
&& !(DECL_TEMPLATE_INSTANTIATION (decl)
&& is_member_template (DECL_TI_TEMPLATE (decl))))
;
else if (name == ansi_opname[(int) CALL_EXPR])
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
else if (name == ansi_opname[(int) ARRAY_REF])
TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
else if (name == ansi_opname[(int) COMPONENT_REF]
|| name == ansi_opname[(int) MEMBER_REF])
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
else if (name == ansi_opname[(int) NEW_EXPR])
TYPE_GETS_NEW (current_class_type) |= 1;
else if (name == ansi_opname[(int) DELETE_EXPR])
TYPE_GETS_DELETE (current_class_type) |= 1;
else if (name == ansi_opname[(int) VEC_NEW_EXPR])
TYPE_GETS_NEW (current_class_type) |= 2;
else if (name == ansi_opname[(int) VEC_DELETE_EXPR])
TYPE_GETS_DELETE (current_class_type) |= 2;
}
if (name == ansi_opname[(int) NEW_EXPR]
|| name == ansi_opname[(int) VEC_NEW_EXPR])
{
if (methodp)
revert_static_member_fn (&decl, NULL, NULL);
if (argtypes == NULL_TREE)
TREE_TYPE (decl)
= build_function_type (ptr_type_node,
hash_tree_chain (integer_type_node,
void_list_node));
else
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
else if (name == ansi_opname[(int) DELETE_EXPR]
|| name == ansi_opname[(int) VEC_DELETE_EXPR])
{
if (methodp)
revert_static_member_fn (&decl, NULL, NULL);
if (argtypes == NULL_TREE)
TREE_TYPE (decl)
= build_function_type (void_type_node,
hash_tree_chain (ptr_type_node,
void_list_node));
else
{
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
if (! friendp && name == ansi_opname[(int) VEC_DELETE_EXPR]
&& (TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (decl)))
!= void_list_node))
TYPE_VEC_DELETE_TAKES_SIZE (current_class_type) = 1;
}
}
else
{
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
if (IDENTIFIER_TYPENAME_P (name)
|| name == ansi_opname[(int) CALL_EXPR]
|| name == ansi_opname[(int) MODIFY_EXPR]
|| name == ansi_opname[(int) COMPONENT_REF]
|| name == ansi_opname[(int) ARRAY_REF])
cp_error ("`%D' must be a nonstatic member function", decl);
else
{
tree p = argtypes;
if (DECL_STATIC_FUNCTION_P (decl))
cp_error ("`%D' must be either a non-static member function or a non-member function", decl);
if (p)
for (; TREE_CODE (TREE_VALUE (p)) != VOID_TYPE ; p = TREE_CHAIN (p))
{
tree arg = TREE_VALUE (p);
if (TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
if (IS_AGGR_TYPE (arg)
|| TREE_CODE (arg) == ENUMERAL_TYPE
|| TREE_CODE (arg) == TEMPLATE_TYPE_PARM
|| TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM)
goto foundaggr;
}
cp_error
("`%D' must have an argument of class or enumerated type",
decl);
foundaggr:
;
}
}
if (name == ansi_opname[(int) CALL_EXPR])
return;
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (TREE_CODE (t) == VOID_TYPE)
pedwarn ("void is not a valid type conversion operator");
else if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (t == current_class_type)
what = "the same type";
else if (IS_AGGR_TYPE (t)
&& TYPE_SIZE (t)
&& DERIVED_FROM_P (t, current_class_type))
what = "a base class";
if (what)
warning ("conversion to %s%s will never use a type conversion operator",
ref ? "a reference to " : "", what);
}
}
if (name == ansi_opname[(int) MODIFY_EXPR])
{
tree parmtype;
if (list_length (argtypes) != 3 && methodp)
{
cp_error ("`%D' must take exactly one argument", decl);
return;
}
parmtype = TREE_VALUE (TREE_CHAIN (argtypes));
if (copy_assignment_arg_p (parmtype, virtualp)
&& ! friendp)
{
TYPE_HAS_ASSIGN_REF (current_class_type) = 1;
if (TREE_CODE (parmtype) != REFERENCE_TYPE
|| CP_TYPE_CONST_P (TREE_TYPE (parmtype)))
TYPE_HAS_CONST_ASSIGN_REF (current_class_type) = 1;
}
}
else if (name == ansi_opname[(int) COND_EXPR])
{
pedwarn ("ANSI C++ prohibits overloading operator ?:");
if (list_length (argtypes) != 4)
cp_error ("`%D' must take exactly three arguments", decl);
}
else if (ambi_op_p (name))
{
if (list_length (argtypes) == 2)
;
else if (list_length (argtypes) == 3)
{
if ((name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
&& ! processing_template_decl
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
cp_error ("postfix `%D' must take `int' as its argument",
decl);
else
cp_error
("postfix `%D' must take `int' as its second argument",
decl);
}
}
else
{
if (methodp)
cp_error ("`%D' must take either zero or one argument", decl);
else
cp_error ("`%D' must take either one or two arguments", decl);
}
if (warn_ecpp
&& (name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR]))
{
tree arg = TREE_VALUE (argtypes);
tree ret = TREE_TYPE (TREE_TYPE (decl));
if (methodp || TREE_CODE (arg) == REFERENCE_TYPE)
arg = TREE_TYPE (arg);
arg = TYPE_MAIN_VARIANT (arg);
if (list_length (argtypes) == 2)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
cp_warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
cp_warning ("postfix `%D' should return `%T'", decl, arg);
}
}
}
else if (unary_op_p (name))
{
if (list_length (argtypes) != 2)
{
if (methodp)
cp_error ("`%D' must take `void'", decl);
else
cp_error ("`%D' must take exactly one argument", decl);
}
}
else
{
if (list_length (argtypes) != 3)
{
if (methodp)
cp_error ("`%D' must take exactly one argument", decl);
else
cp_error ("`%D' must take exactly two arguments", decl);
}
if (warn_ecpp
&& (name == ansi_opname [TRUTH_ANDIF_EXPR]
|| name == ansi_opname [TRUTH_ORIF_EXPR]
|| name == ansi_opname [COMPOUND_EXPR]))
cp_warning ("user-defined `%D' always evaluates both arguments",
decl);
}
if (warn_ecpp
&& list_length (argtypes) == 3
&& (name == ansi_opname [PLUS_EXPR]
|| name == ansi_opname [MINUS_EXPR]
|| name == ansi_opname [TRUNC_DIV_EXPR]
|| name == ansi_opname [MULT_EXPR])
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
cp_warning ("`%D' should return by value", decl);
if (argtypes)
for (; argtypes != void_list_node ; argtypes = TREE_CHAIN (argtypes))
if (TREE_PURPOSE (argtypes))
{
TREE_PURPOSE (argtypes) = NULL_TREE;
if (name == ansi_opname[(int) POSTINCREMENT_EXPR]
|| name == ansi_opname[(int) POSTDECREMENT_EXPR])
{
if (pedantic)
cp_pedwarn ("`%D' cannot have default arguments", decl);
}
else
cp_error ("`%D' cannot have default arguments", decl);
}
}
}
static const char *
tag_name (code)
enum tag_types code;
{
switch (code)
{
case record_type:
return "struct";
case class_type:
return "class";
case union_type:
return "union ";
case enum_type:
return "enum";
case signature_type:
return "signature";
default:
my_friendly_abort (981122);
}
}
tree
xref_tag (code_type_node, name, globalize)
tree code_type_node;
tree name;
int globalize;
{
enum tag_types tag_code;
enum tree_code code;
int temp = 0;
register tree ref, t;
struct binding_level *b = current_binding_level;
int got_type = 0;
tree attributes = NULL_TREE;
tree context = NULL_TREE;
if (TREE_CODE (code_type_node) == TREE_LIST)
{
attributes = TREE_PURPOSE (code_type_node);
code_type_node = TREE_VALUE (code_type_node);
}
tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
switch (tag_code)
{
case record_type:
case class_type:
case signature_type:
code = RECORD_TYPE;
break;
case union_type:
code = UNION_TYPE;
break;
case enum_type:
code = ENUMERAL_TYPE;
break;
default:
my_friendly_abort (18);
}
if (TREE_CODE_CLASS (TREE_CODE (name)) == 't')
{
t = name;
name = TYPE_IDENTIFIER (t);
got_type = 1;
}
else
t = IDENTIFIER_TYPE_VALUE (name);
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
if (! globalize)
{
ref = lookup_tag (code, name, b, 1);
}
else
{
if (t)
{
if (t != TYPE_MAIN_VARIANT (t)
|| (CLASS_TYPE_P (t) && TYPE_WAS_ANONYMOUS (t)))
cp_pedwarn ("using typedef-name `%D' after `%s'",
TYPE_NAME (t), tag_name (tag_code));
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
cp_error ("using template type parameter `%T' after `%s'",
t, tag_name (tag_code));
ref = t;
}
else
ref = lookup_tag (code, name, b, 0);
if (! ref)
{
ref = lookup_name (name, 1);
if (ref != NULL_TREE
&& processing_template_decl
&& DECL_CLASS_TEMPLATE_P (ref)
&& template_class_depth (current_class_type) == 0)
ref = DECL_RESULT (ref);
if (ref && TREE_CODE (ref) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (ref)) == code)
ref = TREE_TYPE (ref);
else
ref = NULL_TREE;
}
if (ref && current_class_type
&& template_class_depth (current_class_type)
&& PROCESSING_REAL_TEMPLATE_DECL_P ())
{
context = TYPE_CONTEXT (ref);
ref = NULL_TREE;
}
}
push_obstacks_nochange ();
if (! ref)
{
temp = allocation_temporary_p ();
if (temp)
end_temporary_allocation ();
if (code == ENUMERAL_TYPE)
{
cp_error ("use of enum `%#D' without previous declaration", name);
ref = make_node (ENUMERAL_TYPE);
TYPE_MODE (ref) = TYPE_MODE (unsigned_type_node);
TYPE_ALIGN (ref) = TYPE_ALIGN (unsigned_type_node);
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, globalize);
}
else
{
struct binding_level *old_b = class_binding_level;
ref = make_lang_type (code);
TYPE_CONTEXT (ref) = context;
if (tag_code == signature_type)
{
SET_SIGNATURE (ref);
CLASSTYPE_INTERFACE_ONLY (ref) = 0;
SET_CLASSTYPE_INTERFACE_KNOWN (ref);
CLASSTYPE_VTABLE_NEEDS_WRITING (ref) = 0;
}
#ifdef NONNESTED_CLASSES
class_binding_level = (struct binding_level *)0;
#endif
pushtag (name, ref, globalize);
class_binding_level = old_b;
}
}
else
{
if (b->namespace_p && !class_binding_level
&& TREE_CODE (name) == IDENTIFIER_NODE)
{
if (IDENTIFIER_NAMESPACE_VALUE (name) == NULL_TREE)
SET_IDENTIFIER_NAMESPACE_VALUE (name, TYPE_NAME (ref));
}
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
redeclare_class_template (ref, current_template_parms);
}
if (TYPE_SIZE (ref) == NULL_TREE
&& ref != current_class_type
&& IS_AGGR_TYPE_CODE (TREE_CODE (ref)))
{
if (tag_code == class_type)
CLASSTYPE_DECLARED_CLASS (ref) = 1;
else if (tag_code == record_type || tag_code == signature_type)
CLASSTYPE_DECLARED_CLASS (ref) = 0;
}
pop_obstacks ();
TREE_TYPE (ref) = attributes;
return ref;
}
tree
xref_tag_from_type (old, id, globalize)
tree old, id;
int globalize;
{
tree code_type_node;
if (TREE_CODE (old) == RECORD_TYPE)
code_type_node = (CLASSTYPE_DECLARED_CLASS (old)
? class_type_node : record_type_node);
else
code_type_node = union_type_node;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
return xref_tag (code_type_node, id, globalize);
}
void
xref_basetypes (code_type_node, name, ref, binfo)
tree code_type_node;
tree name, ref;
tree binfo;
{
tree binfos;
tree base;
int i, len;
enum tag_types tag_code = (enum tag_types) TREE_INT_CST_LOW (code_type_node);
if (tag_code == union_type)
{
cp_error ("derived union `%T' invalid", ref);
return;
}
len = list_length (binfo);
push_obstacks (TYPE_OBSTACK (ref), TYPE_OBSTACK (ref));
for (base = binfo; base; base = TREE_CHAIN (base))
complete_type (TREE_VALUE (base));
SET_CLASSTYPE_MARKED (ref);
BINFO_BASETYPES (TYPE_BINFO (ref)) = binfos = make_tree_vec (len);
for (i = 0; binfo; binfo = TREE_CHAIN (binfo))
{
int via_public
= (TREE_PURPOSE (binfo) == access_public_node
|| TREE_PURPOSE (binfo) == access_public_virtual_node
|| (tag_code != class_type
&& (TREE_PURPOSE (binfo) == access_default_node
|| TREE_PURPOSE (binfo) == access_default_virtual_node)));
int via_protected
= (TREE_PURPOSE (binfo) == access_protected_node
|| TREE_PURPOSE (binfo) == access_protected_virtual_node);
int via_virtual
= (TREE_PURPOSE (binfo) == access_private_virtual_node
|| TREE_PURPOSE (binfo) == access_protected_virtual_node
|| TREE_PURPOSE (binfo) == access_public_virtual_node
|| TREE_PURPOSE (binfo) == access_default_virtual_node);
tree basetype = TREE_VALUE (binfo);
tree base_binfo;
if (basetype && TREE_CODE (basetype) == TYPE_DECL)
basetype = TREE_TYPE (basetype);
if (!basetype
|| (TREE_CODE (basetype) != RECORD_TYPE
&& TREE_CODE (basetype) != TYPENAME_TYPE
&& TREE_CODE (basetype) != TEMPLATE_TYPE_PARM
&& TREE_CODE (basetype) != TEMPLATE_TEMPLATE_PARM))
{
cp_error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
continue;
}
GNU_xref_hier (name, basetype, via_public, via_virtual, 0);
if (TYPE_SIZE (basetype) == NULL_TREE
&& ! (current_template_parms && uses_template_parms (basetype)))
{
cp_error ("base class `%T' has incomplete type", basetype);
continue;
}
else
{
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
cp_error ("recursive type `%T' undefined", basetype);
else
cp_error ("duplicate base type `%T' invalid", basetype);
continue;
}
if (TYPE_FOR_JAVA (basetype)
&& current_lang_stack == current_lang_base)
TYPE_FOR_JAVA (ref) = 1;
base_binfo
= make_binfo (integer_zero_node, basetype,
CLASS_TYPE_P (basetype)
? TYPE_BINFO_VTABLE (basetype) : NULL_TREE,
CLASS_TYPE_P (basetype)
? TYPE_BINFO_VIRTUALS (basetype) : NULL_TREE);
TREE_VEC_ELT (binfos, i) = base_binfo;
TREE_VIA_PUBLIC (base_binfo) = via_public;
TREE_VIA_PROTECTED (base_binfo) = via_protected;
TREE_VIA_VIRTUAL (base_binfo) = via_virtual;
BINFO_INHERITANCE_CHAIN (base_binfo) = TYPE_BINFO (ref);
unshare_base_binfos (base_binfo);
SET_CLASSTYPE_MARKED (basetype);
if (via_virtual || TYPE_USES_VIRTUAL_BASECLASSES (basetype))
{
TYPE_USES_VIRTUAL_BASECLASSES (ref) = 1;
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
}
if (CLASS_TYPE_P (basetype))
{
TYPE_GETS_NEW (ref) |= TYPE_GETS_NEW (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
}
i += 1;
}
}
if (i)
TREE_VEC_LENGTH (binfos) = i;
else
BINFO_BASETYPES (TYPE_BINFO (ref)) = NULL_TREE;
if (i > 1)
TYPE_USES_MULTIPLE_INHERITANCE (ref) = 1;
else if (i == 1)
{
tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, 0));
if (CLASS_TYPE_P (basetype))
TYPE_USES_MULTIPLE_INHERITANCE (ref)
= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
}
if (TYPE_USES_MULTIPLE_INHERITANCE (ref))
TYPE_USES_COMPLEX_INHERITANCE (ref) = 1;
while (--i >= 0)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
CLASSTYPE_VBASECLASSES (ref) = get_vbase_types (ref);
pop_obstacks ();
}
tree
start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
struct binding_level *b = current_binding_level;
push_obstacks (&permanent_obstack, &permanent_obstack);
if (name != NULL_TREE && ! ANON_AGGRNAME_P (name))
enumtype = lookup_tag (ENUMERAL_TYPE, name, b, 1);
if (enumtype != NULL_TREE && TREE_CODE (enumtype) == ENUMERAL_TYPE)
cp_error ("multiple definition of `%#T'", enumtype);
else
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype, 0);
}
if (current_class_type)
TREE_ADDRESSABLE (b->tags) = 1;
enum_next_value = integer_zero_node;
enum_overflow = 0;
GNU_xref_decl (current_function_decl, enumtype);
return enumtype;
}
tree
finish_enum (enumtype)
tree enumtype;
{
register tree minnode = NULL_TREE, maxnode = NULL_TREE;
tree values = TYPE_VALUES (enumtype);
if (values)
{
tree pair;
for (pair = values; pair; pair = TREE_CHAIN (pair))
{
tree decl;
tree value;
decl = TREE_VALUE (pair);
value = DECL_INITIAL (decl);
if (value && !processing_template_decl)
{
TREE_TYPE (value) = enumtype;
if (!minnode)
minnode = maxnode = value;
else if (tree_int_cst_lt (maxnode, value))
maxnode = value;
else if (tree_int_cst_lt (value, minnode))
minnode = value;
}
if (processing_template_decl)
;
else
TREE_VALUE (pair) = value;
}
}
else
maxnode = minnode = integer_zero_node;
TYPE_VALUES (enumtype) = nreverse (values);
if (processing_template_decl)
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
add_tree (build_min (TAG_DEFN, enumtype));
}
else
{
int unsignedp = tree_int_cst_sgn (minnode) >= 0;
int lowprec = min_precision (minnode, unsignedp);
int highprec = min_precision (maxnode, unsignedp);
int precision = MAX (lowprec, highprec);
tree tem;
TYPE_SIZE (enumtype) = NULL_TREE;
TYPE_PRECISION (enumtype) = precision;
if (unsignedp)
fixup_unsigned_type (enumtype);
else
fixup_signed_type (enumtype);
if (flag_short_enums || (precision > TYPE_PRECISION (integer_type_node)))
TYPE_PRECISION (enumtype) = TYPE_PRECISION (type_for_size
(precision, 1));
else
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
TYPE_SIZE (enumtype) = 0;
layout_type (enumtype);
for (tem = TYPE_MAIN_VARIANT (enumtype); tem;
tem = TYPE_NEXT_VARIANT (tem))
{
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);
TREE_UNSIGNED (tem) = TREE_UNSIGNED (enumtype);
}
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
pop_obstacks ();
return enumtype;
}
tree
build_enumerator (name, value, type)
tree name;
tree value;
tree type;
{
tree decl, result;
tree context;
if (value)
STRIP_TYPE_NOPS (value);
if (! processing_template_decl)
{
if (value != NULL_TREE)
{
if (TREE_READONLY_DECL_P (value))
value = decl_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
value = default_conversion (value);
constant_expression_warning (value);
}
else
{
cp_error ("enumerator value for `%D' not integer constant", name);
value = NULL_TREE;
}
}
if (value == NULL_TREE && ! processing_template_decl)
{
value = enum_next_value;
if (enum_overflow)
cp_error ("overflow in enumeration values at `%D'", name);
}
if (value)
STRIP_TYPE_NOPS (value);
#if 0
TREE_TYPE (value) = integer_type_node;
#endif
}
if (value != NULL_TREE)
value = copy_node (value);
context = current_scope ();
if (context && context == current_class_type)
decl = build_lang_field_decl (CONST_DECL, name, type);
else
decl = build_decl (CONST_DECL, name, type);
DECL_CONTEXT (decl) = FROB_CONTEXT (context);
DECL_INITIAL (decl) = value;
TREE_READONLY (decl) = 1;
if (context && context == current_class_type)
finish_member_declaration (decl);
else
{
pushdecl (decl);
GNU_xref_decl (current_function_decl, decl);
}
if (! processing_template_decl)
{
enum_next_value = build_binary_op_nodefault (PLUS_EXPR, value,
integer_one_node, PLUS_EXPR);
enum_overflow = tree_int_cst_lt (enum_next_value, value);
}
if (flag_dump_symbols)
printf ("+vm %s %u\n", IDENTIFIER_POINTER (name), lineno);
if (flag_gen_index)
dump_symbol_info ("+vm ", IDENTIFIER_POINTER (name), lineno);
result = saveable_tree_cons (name, decl, NULL_TREE);
return result;
}
static int function_depth;
int
start_function (declspecs, declarator, attrs, pre_parsed_p)
tree declspecs, declarator, attrs;
int pre_parsed_p;
{
tree decl1;
tree ctype = NULL_TREE;
tree fntype;
tree restype;
extern int have_extern_spec;
extern int used_extern_spec;
int doing_friend = 0;
my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
current_function_returns_value = 0;
current_function_returns_null = 0;
named_labels = 0;
shadowed_labels = 0;
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
current_function_parms_stored = 0;
original_result_rtx = NULL_RTX;
base_init_expr = NULL_TREE;
current_base_init_list = NULL_TREE;
current_member_init_list = NULL_TREE;
ctor_label = dtor_label = NULL_TREE;
static_labelno = 0;
clear_temp_name ();
if (have_extern_spec && !used_extern_spec)
{
declspecs = decl_tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
used_extern_spec = 1;
}
if (pre_parsed_p)
{
decl1 = declarator;
#if 0
if (! DECL_ARGUMENTS (decl1)
&& !DECL_STATIC_FUNCTION_P (decl1)
&& !DECL_ARTIFICIAL (decl1)
&& DECL_CLASS_SCOPE_P (decl1)
&& TYPE_IDENTIFIER (DECL_CONTEXT (decl1))
&& IDENTIFIER_TEMPLATE (TYPE_IDENTIFIER (DECL_CONTEXT (decl1))))
{
tree binding = binding_for_name (DECL_NAME (decl1),
current_namespace);
cp_error ("redeclaration of `%#D'", decl1);
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)))
cp_error_at ("previous declaration here", IDENTIFIER_CLASS_VALUE (DECL_NAME (decl1)));
else if (BINDING_VALUE (binding))
cp_error_at ("previous declaration here", BINDING_VALUE (binding));
}
#endif
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
if (!ctype && DECL_FRIEND_P (decl1))
{
ctype = DECL_CLASS_CONTEXT (decl1);
if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
ctype = NULL_TREE;
else
doing_friend = 1;
}
last_function_parms = DECL_ARGUMENTS (decl1);
last_function_parm_tags = NULL_TREE;
}
else
{
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL_TREE);
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL) return 0;
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
cp_error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_expr_list (NULL_TREE, restype));
CLASSTYPE_GOT_SEMICOLON (restype) = 1;
if (TREE_CODE (fntype) == FUNCTION_TYPE)
fntype = build_function_type (integer_type_node,
TYPE_ARG_TYPES (fntype));
else
fntype = build_cplus_method_type (build_type_variant (TYPE_METHOD_BASETYPE (fntype), TREE_READONLY (decl1), TREE_SIDE_EFFECTS (decl1)),
integer_type_node,
TYPE_ARG_TYPES (fntype));
TREE_TYPE (decl1) = fntype;
}
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
else if (DECL_MAIN_P (decl1))
{
if (TREE_TYPE (TREE_TYPE (decl1)) != integer_type_node)
{
if (pedantic || warn_return_type)
pedwarn ("return type for `main' changed to `int'");
TREE_TYPE (decl1) = fntype = default_function_type;
}
}
}
if (! warn_implicit
&& IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)) != NULL_TREE)
cp_warning_at ("`%D' implicitly declared before its definition", IDENTIFIER_IMPLICIT_DECL (DECL_NAME (decl1)));
announce_function (decl1);
if (flag_dump_symbols)
dump_function_def (decl1);
if (flag_gen_index)
gen_function_def_index (decl1);
if (ctype)
push_nested_class (ctype, 1);
else if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2);
if (pre_parsed_p == 2)
maybe_begin_member_template_processing (decl1);
current_function_decl = decl1;
current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags;
if (! processing_template_decl)
{
require_complete_types_for_parms (current_function_parms);
if (TYPE_SIZE (complete_type (TREE_TYPE (fntype))) == NULL_TREE)
{
cp_error ("return-type `%#T' is an incomplete type",
TREE_TYPE (fntype));
if (ctype)
TREE_TYPE (decl1)
= build_cplus_method_type (build_type_variant (ctype,
TREE_READONLY (decl1),
TREE_SIDE_EFFECTS (decl1)),
void_type_node,
FUNCTION_ARG_CHAIN (decl1));
else
TREE_TYPE (decl1)
= build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl1)));
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (TREE_TYPE (fntype)));
TREE_READONLY (DECL_RESULT (decl1))
= CP_TYPE_CONST_P (TREE_TYPE (fntype));
TREE_THIS_VOLATILE (DECL_RESULT (decl1))
= CP_TYPE_VOLATILE_P (TREE_TYPE (fntype));
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
if (warn_ecpp
&& DECL_NAME (decl1) == ansi_opname[(int) MODIFY_EXPR]
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
cp_warning ("`operator=' should return a reference to `*this'");
DECL_INITIAL (decl1) = error_mark_node;
#ifdef SET_DEFAULT_DECL_ATTRIBUTES
SET_DEFAULT_DECL_ATTRIBUTES (decl1, attrs);
#endif
TREE_STATIC (decl1) = 1;
if (processing_template_decl)
decl1 = push_template_decl (decl1);
if (!processing_template_decl && pre_parsed_p == 0)
{
if ((flag_guiding_decls
|| !DECL_TEMPLATE_SPECIALIZATION (decl1))
&& ! DECL_FUNCTION_MEMBER_P (decl1))
decl1 = pushdecl (decl1);
else
{
if (!DECL_CONTEXT (decl1) && DECL_TEMPLATE_INFO (decl1))
DECL_CONTEXT (decl1) = DECL_CONTEXT (DECL_TI_TEMPLATE (decl1));
check_default_args (decl1);
}
DECL_MAIN_VARIANT (decl1) = decl1;
fntype = TREE_TYPE (decl1);
}
current_function_decl = decl1;
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = hack_decl_function_context (decl1);
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
if (ctx != NULL_TREE && DECL_THIS_INLINE (ctx)
&& TREE_PUBLIC (ctx))
comdat_linkage (decl1);
}
else if (interface_unknown == 0
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
if (DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
= (interface_only
|| (DECL_THIS_INLINE (decl1) && ! flag_implement_inlines
&& !DECL_VINDEX (decl1)));
maybe_make_one_only (decl1);
}
else
DECL_EXTERNAL (decl1) = 0;
DECL_NOT_REALLY_EXTERN (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
}
else if (interface_unknown && interface_only
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
comdat_linkage (decl1);
DECL_EXTERNAL (decl1) = 0;
DECL_INTERFACE_KNOWN (decl1) = 1;
DECL_DEFER_OUTPUT (decl1) = 1;
}
else
{
DECL_EXTERNAL (decl1) = 0;
if ((DECL_THIS_INLINE (decl1) || DECL_TEMPLATE_INSTANTIATION (decl1))
&& ! DECL_INTERFACE_KNOWN (decl1)
&& ! hack_decl_function_context (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
DECL_INTERFACE_KNOWN (decl1) = 1;
}
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1))
{
if (TREE_CODE (fntype) == METHOD_TYPE)
TREE_TYPE (decl1) = fntype
= build_function_type (TREE_TYPE (fntype),
TREE_CHAIN (TYPE_ARG_TYPES (fntype)));
current_function_parms = TREE_CHAIN (current_function_parms);
DECL_ARGUMENTS (decl1) = current_function_parms;
ctype = NULL_TREE;
}
restype = TREE_TYPE (fntype);
if (ctype)
{
if (! doing_friend)
{
tree t = current_function_parms;
my_friendly_assert (t != NULL_TREE
&& TREE_CODE (t) == PARM_DECL, 162);
if (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE)
{
int i;
if (! hack_decl_function_context (decl1))
temporary_allocation ();
i = suspend_momentary ();
current_class_ptr = NULL_TREE;
current_class_ref = build_indirect_ref (t, NULL_PTR);
current_class_ptr = t;
resume_momentary (i);
if (! hack_decl_function_context (decl1))
end_temporary_allocation ();
}
else
current_class_ref = current_class_ptr = t;
}
}
else
current_class_ptr = current_class_ref = NULL_TREE;
pushlevel (0);
current_binding_level->parm_flag = 1;
GNU_xref_function (decl1, current_function_parms);
if (attrs)
cplus_decl_attributes (decl1, NULL_TREE, attrs);
make_function_rtl (decl1);
if (C_PROMOTING_INTEGER_TYPE_P (restype))
restype = type_promotes_to (restype);
if (TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (decl1)))
TREE_ADDRESSABLE (decl1) = 1;
if (DECL_RESULT (decl1) == NULL_TREE)
{
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
TREE_READONLY (DECL_RESULT (decl1)) = CP_TYPE_CONST_P (restype);
TREE_THIS_VOLATILE (DECL_RESULT (decl1)) = CP_TYPE_VOLATILE_P (restype);
}
if (! hack_decl_function_context (decl1))
temporary_allocation ();
if (processing_template_decl)
{
++minimal_parse_mode;
last_tree = DECL_SAVED_TREE (decl1)
= build_nt (EXPR_STMT, void_zero_node);
}
++function_depth;
if (DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl1))
&& DECL_LANGUAGE (decl1) == lang_cplusplus)
{
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
ctor_label = NULL_TREE;
}
else
{
dtor_label = NULL_TREE;
if (DECL_CONSTRUCTOR_P (decl1))
ctor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
}
#ifdef MARK_VIRTUAL_INLINE_STRUCTOR_COALESCED
if ((ctor_label || dtor_label)
&& DECL_VIRTUAL_P (decl1) && DECL_INLINE (decl1))
MARK_VIRTUAL_INLINE_STRUCTOR_COALESCED (decl1);
#endif
return 1;
}
void
expand_start_early_try_stmts ()
{
expand_start_try_stmts ();
last_parm_cleanup_insn = get_last_insn ();
}
void
store_parm_decls ()
{
register tree fndecl = current_function_decl;
register tree parm;
int parms_have_cleanups = 0;
tree cleanups = NULL_TREE;
tree specparms = current_function_parms;
tree parmtags = current_function_parm_tags;
tree nonparms = NULL_TREE;
if (toplevel_bindings_p ())
fatal ("parse errors have confused me too much");
init_function_start (fndecl, input_filename, lineno);
expand_start_bindings (0);
if (specparms != NULL_TREE)
{
register tree next;
storedecls (NULL_TREE);
for (parm = nreverse (specparms); parm; parm = next)
{
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
tree cleanup;
if (DECL_NAME (parm) == NULL_TREE)
{
pushdecl (parm);
}
else if (TREE_CODE (TREE_TYPE (parm)) == VOID_TYPE)
cp_error ("parameter `%D' declared void", parm);
else
{
if (TREE_CODE (TREE_TYPE (parm)) == REFERENCE_TYPE
&& TYPE_SIZE (TREE_TYPE (TREE_TYPE (parm))))
SET_DECL_REFERENCE_SLOT (parm, convert_from_reference (parm));
pushdecl (parm);
}
if (! processing_template_decl
&& (cleanup = maybe_build_cleanup (parm), cleanup))
{
expand_decl (parm);
parms_have_cleanups = 1;
cleanups = tree_cons (parm, cleanup, cleanups);
}
}
else
{
TREE_CHAIN (parm) = NULL_TREE;
nonparms = chainon (nonparms, parm);
}
}
DECL_ARGUMENTS (fndecl) = getdecls ();
storetags (chainon (parmtags, gettags ()));
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
declare_function_name ();
DECL_SAVED_INSNS (fndecl) = NULL_RTX;
if (! processing_template_decl)
expand_function_start (fndecl, parms_have_cleanups);
current_function_parms_stored = 1;
if (DECL_MAIN_P (fndecl))
expand_main_function ();
if (cleanups
&& ! processing_template_decl)
{
for (cleanups = nreverse (cleanups); cleanups; cleanups = TREE_CHAIN (cleanups))
{
if (! expand_decl_cleanup (TREE_PURPOSE (cleanups), TREE_VALUE (cleanups)))
cp_error ("parser lost in parsing declaration of `%D'",
TREE_PURPOSE (cleanups));
}
}
if (parms_have_cleanups)
{
pushlevel (0);
expand_start_bindings (0);
}
if (! processing_template_decl && flag_exceptions)
{
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
expand_start_eh_spec ();
}
last_parm_cleanup_insn = get_last_insn ();
last_dtor_insn = get_last_insn ();
}
void
store_return_init (return_id, init)
tree return_id, init;
{
tree decl = DECL_RESULT (current_function_decl);
if (pedantic)
pedwarn ("ANSI C++ does not permit named return values");
if (return_id != NULL_TREE)
{
if (DECL_NAME (decl) == NULL_TREE)
{
DECL_NAME (decl) = return_id;
DECL_ASSEMBLER_NAME (decl) = return_id;
}
else
cp_error ("return identifier `%D' already in place", decl);
}
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
error ("can't redefine default return value for constructors");
return;
}
if (DECL_NAME (decl) != NULL_TREE)
{
if (DECL_REGISTER (decl))
{
original_result_rtx = DECL_RTL (decl);
DECL_RTL (decl) = gen_reg_rtx (DECL_MODE (decl));
}
DECL_INITIAL (decl) = init;
pushdecl (decl);
if (minimal_parse_mode)
add_tree (build_min_nt (RETURN_INIT, return_id,
copy_to_permanent (init)));
else
cp_finish_decl (decl, init, NULL_TREE, 0, 0);
}
}
void
finish_function (lineno, flags, nested)
int lineno;
int flags;
int nested;
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
rtx last_parm_insn, insns;
tree no_return_label = NULL_TREE;
tree decls = NULL_TREE;
int call_poplevel = (flags & 1) != 0;
int inclass_inline = (flags & 2) != 0;
int in_template;
if (fndecl == NULL_TREE)
return;
if (flag_dump_symbols
&& !(DECL_ARTIFICIAL (fndecl))
&& !(processing_template_decl)
&& !(DECL_USE_TEMPLATE (fndecl)))
{
char ch = 'f';
if (DECL_STATIC_FUNCTION_P (fndecl))
ch = '+';
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
|| DECL_CONSTRUCTOR_P (fndecl)
|| DECL_DESTRUCTOR_P (fndecl))
ch = '-';
printf ("-%cm %u\n", ch, lineno);
}
if (flag_gen_index
&& !(DECL_ARTIFICIAL (fndecl))
&& !(processing_template_decl)
&& !(DECL_USE_TEMPLATE (fndecl)))
{
char buf[5];
char ch = 'f';
if (DECL_STATIC_FUNCTION_P (fndecl))
ch = '+';
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
|| DECL_CONSTRUCTOR_P (fndecl)
|| DECL_DESTRUCTOR_P (fndecl))
ch = '-';
sprintf (&buf[0], "-%cm ", ch);
dump_symbol_info (buf, NULL, lineno);
}
if (function_depth > 1)
nested = 1;
fntype = TREE_TYPE (fndecl);
if (! current_function_parms_stored)
{
call_poplevel = 0;
store_parm_decls ();
}
if (processing_template_decl)
{
if (DECL_CONSTRUCTOR_P (fndecl) && call_poplevel)
{
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0);
}
}
else
{
if (write_symbols != NO_DEBUG )
{
tree ttype = target_type (fntype);
tree parmdecl;
if (IS_AGGR_TYPE (ttype))
note_debug_info_needed (ttype);
for (parmdecl = DECL_ARGUMENTS (fndecl); parmdecl; parmdecl = TREE_CHAIN (parmdecl))
{
ttype = target_type (TREE_TYPE (parmdecl));
if (IS_AGGR_TYPE (ttype))
note_debug_info_needed (ttype);
}
}
do_pending_stack_adjust ();
if (dtor_label)
{
tree binfo = TYPE_BINFO (current_class_type);
tree cond = integer_one_node;
tree exprstmt;
tree in_charge_node = lookup_name (in_charge_identifier, 0);
tree virtual_size;
int ok_to_optimize_dtor = 0;
int empty_dtor = get_last_insn () == last_dtor_insn;
if (current_function_assigns_this)
cond = build (NE_EXPR, boolean_type_node,
current_class_ptr, integer_zero_node);
else
{
int n_baseclasses = CLASSTYPE_N_BASECLASSES (current_class_type);
if ((flag_this_is_variable & 1) == 0)
ok_to_optimize_dtor = 1;
else if (empty_dtor)
ok_to_optimize_dtor
= (n_baseclasses == 0
|| (n_baseclasses == 1
&& TYPE_HAS_DESTRUCTOR (TYPE_BINFO_BASETYPE (current_class_type, 0))));
}
pushlevel (0);
expand_start_bindings (0);
if (current_function_assigns_this)
{
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
}
TYPE_HAS_DESTRUCTOR (current_class_type) = 0;
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)
|| TYPE_GETS_REG_DELETE (current_class_type))
exprstmt = build_delete (current_class_type, current_class_ref, integer_zero_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
else
exprstmt = build_delete (current_class_type, current_class_ref, in_charge_node,
LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR|LOOKUP_NORMAL, 0);
if (exprstmt != error_mark_node
&& (TREE_CODE (exprstmt) != NOP_EXPR
|| TREE_OPERAND (exprstmt, 0) != integer_zero_node
|| TYPE_USES_VIRTUAL_BASECLASSES (current_class_type)))
{
expand_label (dtor_label);
if (cond != integer_one_node)
expand_start_cond (cond, 0);
if (exprstmt != void_zero_node)
expand_expr_stmt (exprstmt);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
{
tree vbases = nreverse (copy_list (CLASSTYPE_VBASECLASSES (current_class_type)));
expand_start_cond (build (BIT_AND_EXPR, integer_type_node,
in_charge_node, integer_two_node), 0);
while (vbases)
{
if (TYPE_NEEDS_DESTRUCTOR (BINFO_TYPE (vbases)))
{
tree vb = get_vbase
(BINFO_TYPE (vbases),
TYPE_BINFO (current_class_type));
expand_expr_stmt
(build_scoped_method_call
(current_class_ref, vb, dtor_identifier,
build_expr_list (NULL_TREE, integer_zero_node)));
}
vbases = TREE_CHAIN (vbases);
}
expand_end_cond ();
}
do_pending_stack_adjust ();
if (cond != integer_one_node)
expand_end_cond ();
}
virtual_size = c_sizeof (current_class_type);
if (TYPE_GETS_REG_DELETE (current_class_type)
|| TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
else
exprstmt = NULL_TREE;
if (exprstmt)
{
cond = build (BIT_AND_EXPR, integer_type_node,
in_charge_node, integer_one_node);
expand_start_cond (cond, 0);
expand_expr_stmt (exprstmt);
expand_end_cond ();
}
expand_end_bindings (NULL_TREE, getdecls () != NULL_TREE, 0);
poplevel (getdecls () != NULL_TREE, 0, 0);
start_sequence ();
if (! empty_dtor || TYPE_USES_COMPLEX_INHERITANCE (current_class_type))
{
expand_direct_vtbls_init (binfo, binfo, 1, 0, current_class_ptr);
if (TYPE_USES_VIRTUAL_BASECLASSES (current_class_type))
expand_indirect_vtbls_init (binfo, current_class_ref, current_class_ptr);
}
if (! ok_to_optimize_dtor)
{
cond = build_binary_op (NE_EXPR,
current_class_ptr, integer_zero_node);
expand_start_cond (cond, 0);
}
insns = get_insns ();
end_sequence ();
last_parm_insn = get_first_nonparm_insn ();
if (last_parm_insn == NULL_RTX)
last_parm_insn = get_last_insn ();
else
last_parm_insn = previous_insn (last_parm_insn);
emit_insns_after (insns, last_parm_insn);
if (! ok_to_optimize_dtor)
expand_end_cond ();
}
else if (current_function_assigns_this)
{
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
if (call_poplevel)
{
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 0, 0);
}
c_expand_return (NULL_TREE);
}
else if (TREE_CODE (TREE_TYPE (DECL_RESULT (current_function_decl))) != VOID_TYPE
&& return_label != NULL_RTX)
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
base_init_expr = NULL_TREE;
}
else if (DECL_CONSTRUCTOR_P (fndecl))
{
tree cond = NULL_TREE, thenclause = NULL_TREE;
tree abstract_virtuals = CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type);
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = NULL_TREE;
if (flag_this_is_variable > 0)
{
cond = build_binary_op (EQ_EXPR,
current_class_ptr, integer_zero_node);
thenclause = build_modify_expr (current_class_ptr, NOP_EXPR,
build_new (NULL_TREE, current_class_type, void_type_node, 0));
}
CLASSTYPE_ABSTRACT_VIRTUALS (current_class_type) = abstract_virtuals;
start_sequence ();
if (flag_this_is_variable > 0)
{
expand_start_cond (cond, 0);
expand_expr_stmt (thenclause);
expand_end_cond ();
}
if (base_init_expr)
{
expand_expr_stmt (base_init_expr);
base_init_expr = NULL_TREE;
}
insns = get_insns ();
end_sequence ();
emit_insns_after (insns, last_parm_cleanup_insn);
end_protect_partials ();
expand_label (ctor_label);
ctor_label = NULL_TREE;
if (call_poplevel)
{
decls = getdecls ();
expand_end_bindings (decls, decls != NULL_TREE, 0);
poplevel (decls != NULL_TREE, 1, 0);
}
c_expand_return (NULL_TREE);
current_function_assigns_this = 0;
current_function_just_assigned_this = 0;
}
else if (DECL_MAIN_P (fndecl))
{
#ifdef VMS
c_expand_return (integer_one_node);
#else
c_expand_return (integer_zero_node);
#endif
}
else if (return_label != NULL_RTX
&& current_function_return_value == NULL_TREE
&& ! DECL_NAME (DECL_RESULT (current_function_decl)))
no_return_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
if (flag_exceptions)
expand_exception_blocks ();
if (no_return_label)
{
DECL_CONTEXT (no_return_label) = fndecl;
DECL_INITIAL (no_return_label) = error_mark_node;
DECL_SOURCE_FILE (no_return_label) = input_filename;
DECL_SOURCE_LINE (no_return_label) = lineno;
expand_goto (no_return_label);
}
if (cleanup_label)
{
expand_end_bindings (0, 0, 0);
poplevel (0, 0, 0);
emit_label (cleanup_label);
}
if (original_result_rtx)
fixup_result_decl (DECL_RESULT (fndecl), original_result_rtx);
if (no_return_label || cleanup_label)
emit_jump (return_label);
if (no_return_label)
{
expand_label (no_return_label);
}
expand_function_end (input_filename, lineno, 1);
}
if (processing_template_decl)
{
--minimal_parse_mode;
DECL_SAVED_TREE (fndecl) = TREE_CHAIN (DECL_SAVED_TREE (fndecl));
in_template = 1;
}
else
in_template = 0;
if (current_binding_level->parm_flag != 1)
my_friendly_abort (122);
poplevel (1, 0, 1);
if (inclass_inline)
maybe_end_member_template_processing ();
if (current_class_name)
{
ctype = current_class_type;
pop_nested_class ();
}
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
if (!in_template)
{
int saved_flag_keep_inline_functions =
flag_keep_inline_functions;
can_reach_end = 0;
if (DECL_CONTEXT (fndecl) != NULL_TREE
&& hack_decl_function_context (fndecl))
flag_keep_inline_functions = 1;
if (DECL_ARTIFICIAL (fndecl))
{
int save_fif = flag_inline_functions;
flag_inline_functions = 1;
DECL_INLINE (fndecl) = 0;
rest_of_compilation (fndecl);
flag_inline_functions = save_fif;
}
else
rest_of_compilation (fndecl);
flag_keep_inline_functions = saved_flag_keep_inline_functions;
if (DECL_SAVED_INSNS (fndecl) && ! TREE_ASM_WRITTEN (fndecl))
{
if (! DECL_EXTERNAL (fndecl))
DECL_NOT_REALLY_EXTERN (fndecl) = 1;
DECL_EXTERNAL (fndecl) = 1;
mark_inline_for_output (fndecl);
}
if (ctype && TREE_ASM_WRITTEN (fndecl))
note_debug_info_needed (ctype);
current_function_returns_null |= can_reach_end;
if (DECL_CONSTRUCTOR_P (fndecl)
|| DECL_NAME (DECL_RESULT (fndecl)) != NULL_TREE)
current_function_returns_null = 0;
if (TREE_THIS_VOLATILE (fndecl) && current_function_returns_null)
cp_warning ("`noreturn' function `%D' does return", fndecl);
else if ((warn_return_type || pedantic)
&& current_function_returns_null
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE)
{
cp_warning ("control reaches end of non-void function `%D'", fndecl);
}
else if (extra_warnings
&& current_function_returns_value && current_function_returns_null)
warning ("this function may return with or without a value");
}
--function_depth;
if (! nested)
permanent_allocation (1);
if (DECL_SAVED_INSNS (fndecl) == NULL_RTX)
{
tree t;
DECL_INITIAL (fndecl) = error_mark_node;
for (t = DECL_ARGUMENTS (fndecl); t; t = TREE_CHAIN (t))
DECL_RTL (t) = DECL_INCOMING_RTL (t) = NULL_RTX;
}
if (DECL_STATIC_CONSTRUCTOR (fndecl))
static_ctors = perm_tree_cons (NULL_TREE, fndecl, static_ctors);
if (DECL_STATIC_DESTRUCTOR (fndecl))
static_dtors = perm_tree_cons (NULL_TREE, fndecl, static_dtors);
if (! nested)
{
current_function_decl = NULL_TREE;
}
named_label_uses = NULL;
current_class_ptr = NULL_TREE;
current_class_ref = NULL_TREE;
}
tree
start_method (declspecs, declarator, attrlist)
tree declarator, declspecs, attrlist;
{
tree fndecl = grokdeclarator (declarator, declspecs, MEMFUNCDEF, 0,
attrlist);
if (fndecl == NULL_TREE)
return NULL_TREE;
if (fndecl == void_type_node)
return fndecl;
if (TREE_CODE (fndecl) != FUNCTION_DECL)
return NULL_TREE;
if (IS_SIGNATURE (current_class_type))
IS_DEFAULT_IMPLEMENTATION (fndecl) = 1;
if (DECL_IN_AGGR_P (fndecl))
{
if (IDENTIFIER_ERROR_LOCUS (DECL_ASSEMBLER_NAME (fndecl)) != current_class_type)
{
if (DECL_CONTEXT (fndecl)
&& TREE_CODE( DECL_CONTEXT (fndecl)) != NAMESPACE_DECL)
cp_error ("`%D' is already defined in class %s", fndecl,
TYPE_NAME_STRING (DECL_CONTEXT (fndecl)));
}
return void_type_node;
}
check_template_shadow (fndecl);
DECL_THIS_INLINE (fndecl) = 1;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
fndecl = push_template_decl (fndecl);
preserve_data ();
if (! DECL_FRIEND_P (fndecl))
{
if (TREE_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
if (DECL_CONSTRUCTOR_P (fndecl))
{
if (! grok_ctor_properties (current_class_type, fndecl))
return void_type_node;
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (fndecl)))
grok_op_properties (fndecl, DECL_VIRTUAL_P (fndecl), 0);
}
cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 0, 0);
pushlevel (0);
current_binding_level->parm_flag = 1;
DECL_IN_AGGR_P (fndecl) = 1;
return fndecl;
}
tree
finish_method (decl)
tree decl;
{
register tree fndecl = decl;
tree old_initial;
register tree link;
if (decl == void_type_node)
return decl;
old_initial = DECL_INITIAL (fndecl);
for (link = current_binding_level->names; link; link = TREE_CHAIN (link))
{
if (DECL_NAME (link) != NULL_TREE)
pop_binding (DECL_NAME (link), link);
my_friendly_assert (TREE_CODE (link) != FUNCTION_DECL, 163);
DECL_CONTEXT (link) = NULL_TREE;
}
GNU_xref_end_scope ((HOST_WIDE_INT) current_binding_level,
(HOST_WIDE_INT) current_binding_level->level_chain,
current_binding_level->parm_flag,
current_binding_level->keep);
poplevel (0, 0, 0);
DECL_INITIAL (fndecl) = old_initial;
if (DECL_FRIEND_P (fndecl))
{
CLASSTYPE_INLINE_FRIENDS (current_class_type)
= tree_cons (NULL_TREE, fndecl, CLASSTYPE_INLINE_FRIENDS (current_class_type));
decl = void_type_node;
}
return decl;
}
void
hack_incomplete_structures (type)
tree type;
{
tree *list;
if (current_binding_level->incomplete == NULL_TREE)
return;
if (!type)
return;
for (list = ¤t_binding_level->incomplete; *list; )
{
tree decl = TREE_VALUE (*list);
if ((decl && TREE_TYPE (decl) == type)
|| (TREE_TYPE (decl)
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type))
{
int toplevel = toplevel_bindings_p ();
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE
&& TREE_TYPE (TREE_TYPE (decl)) == type)
layout_type (TREE_TYPE (decl));
layout_decl (decl, 0);
rest_of_decl_compilation (decl, NULL_PTR, toplevel, 0);
if (! toplevel)
{
tree cleanup;
expand_decl (decl);
cleanup = maybe_build_cleanup (decl);
expand_decl_init (decl);
if (! expand_decl_cleanup (decl, cleanup))
cp_error ("parser lost in parsing declaration of `%D'",
decl);
}
*list = TREE_CHAIN (*list);
}
else
list = &TREE_CHAIN (*list);
}
}
static tree
maybe_build_cleanup_1 (decl, auto_delete)
tree decl, auto_delete;
{
tree type = TREE_TYPE (decl);
if (type != error_mark_node && TYPE_NEEDS_DESTRUCTOR (type))
{
int temp = 0, flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
if (TREE_CODE (decl) != PARM_DECL)
temp = suspend_momentary ();
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
else
{
mark_addressable (decl);
rval = build_unary_op (ADDR_EXPR, decl, 0);
}
if (! TYPE_USES_VIRTUAL_BASECLASSES (type)
|| flag_expensive_optimizations)
flags |= LOOKUP_NONVIRTUAL;
rval = build_delete (TREE_TYPE (rval), rval, auto_delete, flags, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)
&& ! TYPE_HAS_DESTRUCTOR (type))
rval = build_compound_expr (expr_tree_cons (NULL_TREE, rval,
build_expr_list (NULL_TREE, build_vbase_delete (type, decl))));
if (TREE_CODE (decl) != PARM_DECL)
resume_momentary (temp);
return rval;
}
return 0;
}
tree
maybe_build_cleanup_and_delete (decl)
tree decl;
{
return maybe_build_cleanup_1 (decl, integer_three_node);
}
tree
maybe_build_cleanup (decl)
tree decl;
{
return maybe_build_cleanup_1 (decl, integer_two_node);
}
void
cplus_expand_expr_stmt (exp)
tree exp;
{
if (processing_template_decl)
{
add_tree (build_min_nt (EXPR_STMT, exp));
return;
}
expand_start_target_temps ();
exp = require_complete_type_in_void (exp);
if (TREE_CODE (exp) == FUNCTION_DECL)
{
cp_warning ("reference, not call, to function `%D'", exp);
warning ("at this point in file");
}
#if 0
exp = build1 (CLEANUP_POINT_EXPR, TREE_TYPE (exp), exp);
#endif
if (TREE_CODE (exp) == INDIRECT_REF
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (exp, 0))) == REFERENCE_TYPE)
exp = TREE_OPERAND (exp, 0);
if (exp != error_mark_node)
expand_expr_stmt (break_out_cleanups (exp));
expand_end_target_temps ();
}
void
finish_stmt ()
{
extern struct nesting *cond_stack, *loop_stack, *case_stack;
if (current_function_assigns_this
|| ! current_function_just_assigned_this)
return;
if (DECL_CONSTRUCTOR_P (current_function_decl))
{
if (cond_stack || loop_stack || case_stack)
return;
expand_expr_stmt (base_init_expr);
check_base_init (current_class_type);
}
current_function_assigns_this = 1;
}
void
revert_static_member_fn (decl, fn, argtypes)
tree *decl, *fn, *argtypes;
{
tree tmp;
tree function = fn ? *fn : TREE_TYPE (*decl);
tree args = argtypes ? *argtypes : TYPE_ARG_TYPES (function);
if (CP_TYPE_QUALS (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
cp_error ("static member function `%#D' declared with type qualifiers",
*decl);
args = TREE_CHAIN (args);
tmp = build_function_type (TREE_TYPE (function), args);
tmp = build_qualified_type (tmp, CP_TYPE_QUALS (function));
tmp = build_exception_variant (tmp,
TYPE_RAISES_EXCEPTIONS (function));
TREE_TYPE (*decl) = tmp;
if (DECL_ARGUMENTS (*decl))
DECL_ARGUMENTS (*decl) = TREE_CHAIN (DECL_ARGUMENTS (*decl));
DECL_STATIC_FUNCTION_P (*decl) = 1;
if (fn)
*fn = tmp;
if (argtypes)
*argtypes = args;
}
struct cp_function
{
int returns_value;
int returns_null;
int assigns_this;
int just_assigned_this;
int parms_stored;
int temp_name_counter;
tree named_labels;
struct named_label_list *named_label_uses;
tree shadowed_labels;
tree ctor_label;
tree dtor_label;
rtx last_dtor_insn;
rtx last_parm_cleanup_insn;
tree base_init_list;
tree member_init_list;
tree base_init_expr;
tree current_class_ptr;
tree current_class_ref;
rtx result_rtx;
struct cp_function *next;
struct binding_level *binding_level;
int static_labelno;
};
static struct cp_function *cp_function_chain;
extern int temp_name_counter;
void
push_cp_function_context (context)
tree context;
{
struct cp_function *p
= (struct cp_function *) xmalloc (sizeof (struct cp_function));
push_function_context_to (context);
p->next = cp_function_chain;
cp_function_chain = p;
p->named_labels = named_labels;
p->named_label_uses = named_label_uses;
p->shadowed_labels = shadowed_labels;
p->returns_value = current_function_returns_value;
p->returns_null = current_function_returns_null;
p->binding_level = current_binding_level;
p->ctor_label = ctor_label;
p->dtor_label = dtor_label;
p->last_dtor_insn = last_dtor_insn;
p->last_parm_cleanup_insn = last_parm_cleanup_insn;
p->assigns_this = current_function_assigns_this;
p->just_assigned_this = current_function_just_assigned_this;
p->parms_stored = current_function_parms_stored;
p->result_rtx = original_result_rtx;
p->base_init_expr = base_init_expr;
p->temp_name_counter = temp_name_counter;
p->base_init_list = current_base_init_list;
p->member_init_list = current_member_init_list;
p->current_class_ptr = current_class_ptr;
p->current_class_ref = current_class_ref;
p->static_labelno = static_labelno;
}
void
pop_cp_function_context (context)
tree context;
{
struct cp_function *p = cp_function_chain;
tree link;
for (link = shadowed_labels; link; link = TREE_CHAIN (link))
if (DECL_NAME (TREE_VALUE (link)) != 0)
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (TREE_VALUE (link)),
TREE_VALUE (link));
pop_function_context_from (context);
cp_function_chain = p->next;
named_labels = p->named_labels;
named_label_uses = p->named_label_uses;
shadowed_labels = p->shadowed_labels;
current_function_returns_value = p->returns_value;
current_function_returns_null = p->returns_null;
current_binding_level = p->binding_level;
ctor_label = p->ctor_label;
dtor_label = p->dtor_label;
last_dtor_insn = p->last_dtor_insn;
last_parm_cleanup_insn = p->last_parm_cleanup_insn;
current_function_assigns_this = p->assigns_this;
current_function_just_assigned_this = p->just_assigned_this;
current_function_parms_stored = p->parms_stored;
original_result_rtx = p->result_rtx;
base_init_expr = p->base_init_expr;
temp_name_counter = p->temp_name_counter;
current_base_init_list = p->base_init_list;
current_member_init_list = p->member_init_list;
current_class_ptr = p->current_class_ptr;
current_class_ref = p->current_class_ref;
static_labelno = p->static_labelno;
free (p);
}
int
in_function_p ()
{
return function_depth != 0;
}
#ifdef NEXT_SEMANTICS
char *
apple_should_inline_func_p (fndecl)
tree fndecl;
{
rtx insn;
if (DECL_DESTRUCTOR_P (fndecl))
for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn))
{
if (insn && GET_CODE (insn) == NOTE
&& NOTE_LINE_NUMBER (insn) == NOTE_INSN_EH_REGION_BEG)
return ("complex destructor cannot be inline (EH/inliner bug, sorry)");
}
return 0;
}
int
call_destructor_dynamically (dfndecl)
tree dfndecl;
{
tree parms;
tree call;
tree atexit_decl;
tree atexit_type;
tree fnct_type = build_pointer_type (default_function_type);
extern tree default_function_type;
extern tree void_type_node;
atexit_type = build_function_type (void_type_node,
tree_cons (0, fnct_type, 0));
atexit_decl =(tree) builtin_function ("atexit",
atexit_type,
NOT_BUILT_IN, 0);
parms = (tree) build_tree_list (NULL_TREE,
build1 (ADDR_EXPR,
fnct_type,
dfndecl));
call = build_function_call (atexit_decl, parms);
expand_call (call, 0, 0);
}
#ifdef MODERN_OBJC_SYNTAX
void objc_begin_function_pragma() {}
void objc_end_function_pragma() {}
void objc_selector_alias_pragma(tree realname, tree alias) {}
#endif
#endif