#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "tree-inline.h"
#include "decl.h"
#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "hashtab.h"
#include "tm_p.h"
#include "target.h"
#include "c-common.h"
#include "c-pragma.h"
#include "diagnostic.h"
#include "debug.h"
#include "timevar.h"
#include "genindex.h"
static const char *redeclaration_error_message PARAMS ((tree, tree));
static void push_binding_level PARAMS ((struct cp_binding_level *, int,
int));
static void pop_binding_level PARAMS ((void));
static void suspend_binding_level PARAMS ((void));
static void resume_binding_level PARAMS ((struct cp_binding_level *));
static struct cp_binding_level *make_binding_level PARAMS ((void));
static void declare_namespace_level PARAMS ((void));
static int decl_jump_unsafe PARAMS ((tree));
static void storedecls PARAMS ((tree));
static void require_complete_types_for_parms PARAMS ((tree));
static int ambi_op_p PARAMS ((enum tree_code));
static int unary_op_p PARAMS ((enum tree_code));
static cxx_saved_binding *store_bindings (tree, cxx_saved_binding *);
static tree lookup_tag_reverse PARAMS ((tree, tree));
static tree lookup_name_real PARAMS ((tree, int, int, int));
static void push_local_name PARAMS ((tree));
static void warn_extern_redeclared_static PARAMS ((tree, tree));
static tree grok_reference_init PARAMS ((tree, tree, tree));
static tree grokfndecl PARAMS ((tree, tree, tree, tree, int,
enum overload_flags, tree,
tree, int, int, int, int, int, int, tree));
static tree grokvardecl PARAMS ((tree, tree, RID_BIT_TYPE *, int, int, tree));
static tree follow_tag_typedef PARAMS ((tree));
static tree lookup_tag PARAMS ((enum tree_code, tree,
struct cp_binding_level *, int));
static void set_identifier_type_value_with_scope
PARAMS ((tree, tree, struct cp_binding_level *));
static void record_unknown_type PARAMS ((tree, const char *));
static tree builtin_function_1 PARAMS ((const char *, tree, tree, int,
enum built_in_class, const char *,
tree));
static tree build_library_fn_1 PARAMS ((tree, enum tree_code, tree));
static int member_function_or_else PARAMS ((tree, tree, enum overload_flags));
static void bad_specifiers PARAMS ((tree, const char *, int, int, int, int,
int));
static tree maybe_process_template_type_declaration PARAMS ((tree, int, struct cp_binding_level*));
static void check_for_uninitialized_const_var PARAMS ((tree));
static hashval_t typename_hash PARAMS ((const void *));
static int typename_compare PARAMS ((const void *, const void *));
static void push_binding PARAMS ((tree, tree, struct cp_binding_level*));
static int add_binding PARAMS ((tree, tree));
static void pop_binding PARAMS ((tree, tree));
static tree local_variable_p_walkfn PARAMS ((tree *, int *, void *));
static cxx_binding *find_binding (tree, tree, cxx_binding *);
static tree select_decl (cxx_binding *, int);
static int lookup_flags PARAMS ((int, int));
static tree qualify_lookup PARAMS ((tree, int));
static tree record_builtin_java_type PARAMS ((const char *, int));
static const char *tag_name PARAMS ((enum tag_types code));
static void find_class_binding_level PARAMS ((void));
static struct cp_binding_level *innermost_nonclass_level PARAMS ((void));
static void warn_about_implicit_typename_lookup PARAMS ((tree, tree));
static int walk_namespaces_r PARAMS ((tree, walk_namespaces_fn, void *));
static int walk_globals_r PARAMS ((tree, void *));
static int walk_vtables_r PARAMS ((tree, void*));
static void add_decl_to_level PARAMS ((tree, struct cp_binding_level *));
static tree make_label_decl PARAMS ((tree, int));
static void use_label PARAMS ((tree));
static void check_previous_goto_1 PARAMS ((tree, struct cp_binding_level *, tree,
const char *, int));
static void check_previous_goto PARAMS ((struct named_label_use_list *));
static void check_switch_goto PARAMS ((struct cp_binding_level *));
static void check_previous_gotos PARAMS ((tree));
static void pop_label PARAMS ((tree, tree));
static void pop_labels PARAMS ((tree));
static void maybe_deduce_size_from_array_init PARAMS ((tree, tree));
static void layout_var_decl PARAMS ((tree));
static void maybe_commonize_var PARAMS ((tree));
static tree check_initializer (tree, tree, int);
static void make_rtl_for_nonlocal_decl PARAMS ((tree, tree, const char *));
static void save_function_data PARAMS ((tree));
static void check_function_type PARAMS ((tree, tree));
static void begin_constructor_body PARAMS ((void));
static void finish_constructor_body PARAMS ((void));
static void begin_destructor_body PARAMS ((void));
static void finish_destructor_body PARAMS ((void));
static tree create_array_type_for_decl PARAMS ((tree, tree, tree));
static tree get_atexit_node PARAMS ((void));
static tree get_dso_handle_node PARAMS ((void));
static tree start_cleanup_fn PARAMS ((void));
static void end_cleanup_fn PARAMS ((void));
static tree cp_make_fname_decl PARAMS ((tree, int));
static void initialize_predefined_identifiers PARAMS ((void));
static tree check_special_function_return_type
PARAMS ((special_function_kind, tree, tree));
static tree push_cp_library_fn PARAMS ((enum tree_code, tree));
static tree build_cp_library_fn PARAMS ((tree, enum tree_code, tree));
static int cp_missing_noreturn_ok_p PARAMS ((tree));
static void initialize_local_var (tree, tree);
static void expand_static_init (tree, tree);
static tree next_initializable_field (tree);
static tree reshape_init (tree, tree *);
#if defined (DEBUG_BINDING_LEVELS)
static void indent PARAMS ((void));
#endif
tree error_mark_list;
tree cp_global_trees[CPTI_MAX];
static GTY(()) tree global_type_node;
static int only_namespace_names;
struct named_label_use_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree label_decl;
const char *filename_o_goto;
int lineno_o_goto;
struct named_label_use_list *next;
};
#define named_label_uses cp_function_chain->x_named_label_uses
#define local_names cp_function_chain->x_local_names
tree static_aggregates;
tree integer_two_node, integer_three_node;
tree last_function_parms;
struct named_label_list GTY(())
{
struct cp_binding_level *binding_level;
tree names_in_scope;
tree old_value;
tree label_decl;
tree bad_decls;
struct named_label_list *next;
unsigned int in_try_scope : 1;
unsigned int in_catch_scope : 1;
};
#define named_labels cp_function_chain->x_named_labels
tree anonymous_namespace_name;
int function_depth;
enum deprecated_states {
DEPRECATED_NORMAL,
DEPRECATED_SUPPRESS
, DEPRECATED_UNAVAILABLE_SUPPRESS
};
static enum deprecated_states deprecated_state = DEPRECATED_NORMAL;
int adding_implicit_members = 0;
bool have_extern_spec;
struct cp_binding_level GTY(())
{
tree names;
size_t names_size;
tree namespaces;
varray_type static_decls;
tree vtables;
tree tags;
tree usings;
tree using_directives;
tree class_shadowed;
tree type_shadowed;
tree shadowed_labels;
tree blocks;
tree this_class;
struct cp_binding_level *level_chain;
tree dead_vars_from_for;
unsigned parm_flag : 2;
unsigned keep : 2;
unsigned tag_transparent : 1;
unsigned more_cleanups_ok : 1;
unsigned have_cleanups : 1;
unsigned template_parms_p : 1;
unsigned template_spec_p : 1;
unsigned namespace_p : 1;
unsigned is_for_scope : 1;
unsigned is_try_scope : 1;
unsigned is_catch_scope : 1;
unsigned binding_depth;
};
#define NULL_BINDING_LEVEL ((struct cp_binding_level *) NULL)
#define current_binding_level \
(cfun && cp_function_chain->bindings \
? cp_function_chain->bindings \
: scope_chain->bindings)
#define class_binding_level scope_chain->class_bindings
static GTY((deletable (""))) struct cp_binding_level *free_binding_level;
static GTY(()) struct cp_binding_level *global_binding_level;
static int keep_next_level_flag;
static GTY(()) tree incomplete_vars;
#if defined(DEBUG_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 PARAMS ((tree, struct cp_binding_level *));
static void
push_binding_level (newlevel, tag_transparent, keep)
struct cp_binding_level *newlevel;
int tag_transparent, keep;
{
memset ((char*) newlevel, 0, sizeof (struct cp_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_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 cp_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)
abort ();
}
#if defined(DEBUG_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 cp_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)
abort ();
}
#if defined(DEBUG_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 cp_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_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 cp_binding_level *
make_binding_level ()
{
return (struct cp_binding_level *) ggc_alloc (sizeof (struct cp_binding_level));
}
struct cp_binding_level *
get_current_binding_level ()
{
return current_binding_level;
}
void
objc_mark_locals_volatile (enclosing_blk)
void *enclosing_blk;
{
struct cp_binding_level *scope;
for (scope = current_binding_level;
scope && scope != enclosing_blk && !scope->parm_flag;
scope = scope->level_chain)
{
tree decl;
for (decl = scope->names; decl; decl = TREE_CHAIN (decl))
{
DECL_REGISTER (decl) = 0;
TREE_THIS_VOLATILE (decl) = 1;
}
}
}
int
global_bindings_p ()
{
return current_binding_level == global_binding_level;
}
static struct cp_binding_level *
innermost_nonclass_level ()
{
struct cp_binding_level *b;
b = current_binding_level;
while (b->parm_flag == 2)
b = b->level_chain;
return b;
}
int
toplevel_bindings_p ()
{
struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p || b->template_parms_p;
}
int
namespace_bindings_p ()
{
struct cp_binding_level *b = innermost_nonclass_level ();
return b->namespace_p;
}
void
keep_next_level (keep)
int keep;
{
keep_next_level_flag = keep;
}
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));
}
static void
declare_namespace_level ()
{
current_binding_level->namespace_p = 1;
}
int
template_parm_scope_p ()
{
return current_binding_level->template_parms_p;
}
tmpl_spec_kind
current_tmpl_spec_kind (n_class_scopes)
int n_class_scopes;
{
int n_template_parm_scopes = 0;
int seen_specialization_p = 0;
int innermost_specialization_p = 0;
struct cp_binding_level *b;
for (b = current_binding_level; b->template_parms_p; b = b->level_chain)
{
if (b->template_spec_p)
{
if (n_template_parm_scopes == 0)
innermost_specialization_p = 1;
else
seen_specialization_p = 1;
}
else if (seen_specialization_p == 1)
return tsk_invalid_member_spec;
++n_template_parm_scopes;
}
if (processing_explicit_instantiation)
{
if (n_template_parm_scopes != 0)
return tsk_invalid_expl_inst;
else
return tsk_expl_inst;
}
if (n_template_parm_scopes < n_class_scopes)
return tsk_insufficient_parms;
else if (n_template_parm_scopes == n_class_scopes)
return tsk_none;
else if (n_template_parm_scopes > n_class_scopes + 1)
return tsk_excessive_parms;
else
return innermost_specialization_p ? tsk_expl_spec : tsk_template;
}
void
set_class_shadows (shadows)
tree shadows;
{
class_binding_level->class_shadowed = shadows;
}
void
pushlevel (tag_transparent)
int tag_transparent;
{
struct cp_binding_level *newlevel;
if (cfun && !doing_semantic_analysis_p ())
return;
#if defined(DEBUG_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);
keep_next_level_flag = 0;
}
void
maybe_push_cleanup_level (type)
tree type;
{
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type)
&& current_binding_level->more_cleanups_ok == 0)
{
keep_next_level (2);
pushlevel (1);
clear_last_expr ();
add_scope_stmt (1, 1);
}
}
void
begin_scope (sk)
scope_kind sk;
{
pushlevel (0);
switch (sk)
{
case sk_template_spec:
current_binding_level->template_spec_p = 1;
case sk_template_parms:
current_binding_level->template_parms_p = 1;
break;
default:
abort ();
}
}
void
finish_scope ()
{
poplevel (0, 0, 0);
}
void
note_level_for_for ()
{
current_binding_level->is_for_scope = 1;
}
void
note_level_for_try ()
{
current_binding_level->is_try_scope = 1;
}
void
note_level_for_catch ()
{
current_binding_level->is_catch_scope = 1;
}
#define BINDING_LEVEL(NODE) ((NODE)->scope.level)
static GTY((deletable (""))) cxx_binding *free_bindings;
static void
push_binding (id, decl, level)
tree id;
tree decl;
struct cp_binding_level* level;
{
cxx_binding *binding;
if (free_bindings)
{
binding = free_bindings;
free_bindings = binding->previous;
}
else
binding = cxx_binding_make ();
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);
BINDING_HAS_LEVEL_P (binding) = 1;
binding->previous = IDENTIFIER_BINDING (id);
IDENTIFIER_BINDING (id) = binding;
}
static int
add_binding (id, decl)
tree id;
tree decl;
{
cxx_binding *binding = IDENTIFIER_BINDING (id);
int ok = 1;
timevar_push (TV_NAME_LOOKUP);
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 if (TREE_CODE (BINDING_VALUE (binding)) == TYPE_DECL
&& TREE_CODE (decl) == TYPE_DECL
&& DECL_NAME (decl) == DECL_NAME (BINDING_VALUE (binding))
&& (same_type_p (TREE_TYPE (decl),
TREE_TYPE (BINDING_VALUE (binding)))
|| uses_template_parms (TREE_TYPE (decl))
|| uses_template_parms (TREE_TYPE (BINDING_VALUE (binding)))))
ok = 0;
else if (TREE_CODE (decl) == VAR_DECL
&& TREE_CODE (BINDING_VALUE (binding)) == VAR_DECL
&& DECL_EXTERNAL (decl)
&& DECL_EXTERNAL (BINDING_VALUE (binding)))
{
duplicate_decls (decl, BINDING_VALUE (binding));
ok = 0;
}
else
{
error ("declaration of `%#D'", decl);
cp_error_at ("conflicts with previous declaration `%#D'",
BINDING_VALUE (binding));
ok = 0;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ok);
}
static void
add_decl_to_level (decl, b)
tree decl;
struct cp_binding_level *b;
{
if (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl))
{
TREE_CHAIN (decl) = b->namespaces;
b->namespaces = decl;
}
else if (TREE_CODE (decl) == VAR_DECL && DECL_VIRTUAL_P (decl))
{
TREE_CHAIN (decl) = b->vtables;
b->vtables = decl;
}
else
{
TREE_CHAIN (decl) = b->names;
b->names = decl;
b->names_size++;
if (b->namespace_p)
if ((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
|| (TREE_CODE (decl) == FUNCTION_DECL
&& (!TREE_PUBLIC (decl) || DECL_DECLARED_INLINE_P (decl))))
VARRAY_PUSH_TREE (b->static_decls, decl);
}
}
void
push_local_binding (id, decl, flags)
tree id;
tree decl;
int flags;
{
struct cp_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);
add_decl_to_level (decl, b);
}
int
push_class_binding (id, decl)
tree id;
tree decl;
{
int result = 1;
cxx_binding *binding = IDENTIFIER_BINDING (id);
tree context;
timevar_push (TV_NAME_LOOKUP);
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 (IMPLICIT_TYPENAME_TYPE_DECL_P (decl))
INHERITED_VALUE_BINDING_P (binding) = 1;
else
{
if (TREE_CODE (decl) == OVERLOAD)
context = CP_DECL_CONTEXT (OVL_CURRENT (decl));
else
{
my_friendly_assert (DECL_P (decl), 0);
context = context_for_name_lookup (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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result);
}
static void
pop_binding (id, decl)
tree id;
tree decl;
{
cxx_binding *binding;
if (id == NULL_TREE)
return;
binding = IDENTIFIER_BINDING (id);
my_friendly_assert (binding != NULL, 0);
if (BINDING_VALUE (binding) == decl)
BINDING_VALUE (binding) = NULL_TREE;
else if (BINDING_TYPE (binding) == decl)
BINDING_TYPE (binding) = NULL_TREE;
else
abort ();
if (!BINDING_VALUE (binding) && !BINDING_TYPE (binding))
{
IDENTIFIER_BINDING (id) = binding->previous;
binding->previous = free_bindings;
free_bindings = binding;
BINDING_LEVEL (binding) = NULL;
}
}
static void
pop_label (label, old_value)
tree label;
tree old_value;
{
if (!processing_template_decl && doing_semantic_analysis_p ())
{
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_label && !TREE_USED (label))
cp_warning_at ("label `%D' defined but not used", label);
}
SET_IDENTIFIER_LABEL_VALUE (DECL_NAME (label), old_value);
}
static void
pop_labels (block)
tree block;
{
struct named_label_list *link;
for (link = named_labels; link; link = link->next)
{
pop_label (link->label_decl, link->old_value);
TREE_CHAIN (link->label_decl) = BLOCK_VARS (block);
BLOCK_VARS (block) = link->label_decl;
}
named_labels = NULL;
}
tree
poplevel (keep, reverse, functionbody)
int keep;
int reverse;
int functionbody;
{
register tree link;
tree decls;
int tmp = functionbody;
int real_functionbody;
tree tags;
tree subblocks;
tree block = NULL_TREE;
tree decl;
int leaving_for_scope;
timevar_push (TV_NAME_LOOKUP);
if (cfun && !doing_semantic_analysis_p ())
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
my_friendly_assert (current_binding_level->parm_flag != 2,
19990916);
real_functionbody = (current_binding_level->keep == 2
? ((functionbody = 0), tmp) : functionbody);
tags = functionbody >= 0 ? current_binding_level->tags : 0;
subblocks = functionbody >= 0 ? current_binding_level->blocks : 0;
my_friendly_assert (!current_binding_level->class_shadowed,
19990414);
my_friendly_assert (keep == 0 || keep == 1, 0);
if (current_binding_level->keep == 1)
keep = 1;
if (cfun && !functionbody)
{
struct cp_binding_level *level_chain;
level_chain = current_binding_level->level_chain;
if (level_chain)
{
struct named_label_use_list *uses;
struct named_label_list *labels;
for (labels = named_labels; labels; labels = labels->next)
if (labels->binding_level == current_binding_level)
{
tree decl;
if (current_binding_level->is_try_scope)
labels->in_try_scope = 1;
if (current_binding_level->is_catch_scope)
labels->in_catch_scope = 1;
for (decl = labels->names_in_scope; decl;
decl = TREE_CHAIN (decl))
if (decl_jump_unsafe (decl))
labels->bad_decls = tree_cons (NULL_TREE, decl,
labels->bad_decls);
labels->binding_level = level_chain;
labels->names_in_scope = level_chain->names;
}
for (uses = named_label_uses; uses; uses = uses->next)
if (uses->binding_level == current_binding_level)
{
uses->binding_level = level_chain;
uses->names_in_scope = level_chain->names;
}
}
}
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 ();
}
}
if (!processing_template_decl)
warn_about_unused_variables (getdecls ());
block = NULL_TREE;
if (keep == 1 || functionbody)
block = make_node (BLOCK);
if (block != NULL_TREE)
{
BLOCK_VARS (block) = decls;
BLOCK_SUBBLOCKS (block) = subblocks;
}
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
&& DECL_NAME (link))
{
cxx_binding *outer_binding
= IDENTIFIER_BINDING (DECL_NAME (link))->previous;
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 (DECL_P (decl))
pop_binding (DECL_NAME (decl), decl);
else if (TREE_CODE (decl) == OVERLOAD)
pop_binding (DECL_NAME (OVL_FUNCTION (decl)), decl);
else
abort ();
}
}
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));
for (link = current_binding_level->shadowed_labels;
link;
link = TREE_CHAIN (link))
pop_label (TREE_VALUE (link), TREE_PURPOSE (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;
pop_labels (block);
}
tmp = current_binding_level->keep;
pop_binding_level ();
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block)
current_binding_level->blocks
= chainon (current_binding_level->blocks, block);
else if (subblocks)
current_binding_level->blocks
= chainon (current_binding_level->blocks, subblocks);
if (block)
TREE_USED (block) = 1;
if (tmp == 2)
{
tree scope_stmts;
tree saved_block = NULL_TREE;
scope_stmts
= add_scope_stmt (0, 1);
if (block)
{
SCOPE_STMT_BLOCK (TREE_PURPOSE (scope_stmts)) = block;
SCOPE_STMT_BLOCK (TREE_VALUE (scope_stmts)) = block;
}
if (block)
saved_block = block;
block = poplevel (keep, reverse, functionbody);
BLOCK_VARS (block) = chainon (BLOCK_VARS (block), BLOCK_VARS (saved_block));
BLOCK_VARS (saved_block) = NULL_TREE;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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)
tree block ATTRIBUTE_UNUSED;
{
my_friendly_assert (cfun && !doing_semantic_analysis_p (), 20000911);
}
void
pushlevel_class ()
{
register struct cp_binding_level *newlevel;
#if defined(DEBUG_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_BINDING_LEVELS)
is_class_level = 1;
#endif
push_binding_level (newlevel, 0, 0);
class_binding_level = current_binding_level;
class_binding_level->parm_flag = 2;
class_binding_level->this_class = current_class_type;
}
void
poplevel_class ()
{
register struct cp_binding_level *level = class_binding_level;
tree shadowed;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (level != 0, 354);
if (current_class_depth != 1)
{
struct cp_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))
{
cxx_binding *binding;
binding = IDENTIFIER_BINDING (TREE_PURPOSE (shadowed));
while (binding && BINDING_LEVEL (binding) != b)
binding = binding->previous;
if (binding)
IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (shadowed))
= BINDING_VALUE (binding);
}
}
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));
#if defined(DEBUG_BINDING_LEVELS)
is_class_level = 1;
#endif
pop_binding_level ();
timevar_pop (TV_NAME_LOOKUP);
}
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_CODE (TREE_TYPE (t)) == RECORD_TYPE
&& TYPE_POLYMORPHIC_P (TREE_TYPE (t)));
}
tree
cp_namespace_decls (ns)
tree ns;
{
return NAMESPACE_LEVEL (ns)->names;
}
struct walk_globals_data {
walk_globals_pred p;
walk_globals_fn f;
void *data;
};
static int
walk_vtables_r (namespace, data)
tree namespace;
void *data;
{
struct walk_globals_data* wgd = (struct walk_globals_data *) data;
walk_globals_fn f = wgd->f;
void *d = wgd->data;
tree decl = NAMESPACE_LEVEL (namespace)->vtables;
int result = 0;
for (; decl ; decl = TREE_CHAIN (decl))
result |= (*f) (&decl, d);
return result;
}
int
walk_vtables (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_vtables_r, &wgd);
}
static int
walk_namespaces_r (namespace, f, data)
tree namespace;
walk_namespaces_fn f;
void *data;
{
int result = 0;
tree current = NAMESPACE_LEVEL (namespace)->namespaces;
result |= (*f) (namespace, data);
for (; current; current = TREE_CHAIN (current))
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);
}
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;
{
struct cp_binding_level *level = NAMESPACE_LEVEL (namespace);
varray_type statics = level->static_decls;
tree *vec = &VARRAY_TREE (statics, 0);
int len = VARRAY_ACTIVE_SIZE (statics);
int last_time = (data != 0);
if (last_time)
{
check_global_declarations (vec, len);
return 0;
}
return wrapup_global_declarations (vec, len);
}
static int no_print_functions = 0;
static int no_print_builtins = 0;
void
print_binding_level (lvl)
struct cp_binding_level *lvl;
{
tree t;
int i = 0, len;
fprintf (stderr, " blocks=");
fprintf (stderr, HOST_PTR_PRINTF, lvl->blocks);
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 cp_binding_level *stack;
{
struct cp_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 cp_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 inline cxx_binding *
find_binding (tree name, tree scope, cxx_binding *front)
{
cxx_binding *iter;
cxx_binding *prev = NULL;
timevar_push (TV_NAME_LOOKUP);
for (iter = front; iter; iter = iter->previous)
{
if (BINDING_SCOPE (iter) == scope)
{
if (prev)
{
prev->previous = iter->previous;
iter->previous = front;
IDENTIFIER_NAMESPACE_BINDINGS (name) = iter;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, iter);
}
prev = iter;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL);
}
cxx_binding *
cxx_scope_find_binding_for_name (tree scope, tree name)
{
cxx_binding *b = IDENTIFIER_NAMESPACE_BINDINGS (name);
if (b)
{
scope = ORIGINAL_NAMESPACE (scope);
if (scope == BINDING_SCOPE (b) && b->previous == NULL)
return b;
return find_binding (name, scope, b);
}
return b;
}
cxx_binding *
binding_for_name (tree name, tree scope)
{
cxx_binding *result;
scope = ORIGINAL_NAMESPACE (scope);
result = cxx_scope_find_binding_for_name (scope, name);
if (result)
return result;
result = cxx_binding_make ();
result->previous = IDENTIFIER_NAMESPACE_BINDINGS (name);
BINDING_TYPE (result) = NULL_TREE;
BINDING_VALUE (result) = NULL_TREE;
BINDING_SCOPE (result) = scope;
result->is_local = false;
result->value_is_inherited = false;
result->has_level = false;
IDENTIFIER_NAMESPACE_BINDINGS (name) = result;
return result;
}
tree
namespace_binding (tree name, tree scope)
{
cxx_binding *b =
cxx_scope_find_binding_for_name (scope ? scope : global_namespace, name);
return b ? b->value : NULL_TREE;
}
void
set_namespace_binding (name, scope, val)
tree name;
tree scope;
tree val;
{
cxx_binding *b;
timevar_push (TV_NAME_LOOKUP);
if (scope == NULL_TREE)
scope = global_namespace;
b = binding_for_name (name, scope);
BINDING_VALUE (b) = val;
timevar_pop (TV_NAME_LOOKUP);
}
void
push_namespace (name)
tree name;
{
tree d = NULL_TREE;
int need_new = 1;
int implicit_use = 0;
int global = 0;
timevar_push (TV_NAME_LOOKUP);
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
{
d = IDENTIFIER_NAMESPACE_VALUE (name);
if (d != NULL_TREE && TREE_CODE (d) == NAMESPACE_DECL)
{
need_new = 0;
if (DECL_NAMESPACE_ALIAS (d))
{
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 0
if (flag_gen_index)
gen_indexing_info (INDEX_NAMESPACE_DECL,
IDENTIFIER_POINTER (DECL_NAME (d)),
DECL_SOURCE_LINE (d));
#endif
if (!global)
{
DECL_CONTEXT (d) = FROB_CONTEXT (current_namespace);
d = pushdecl (d);
pushlevel (0);
declare_namespace_level ();
NAMESPACE_LEVEL (d) = current_binding_level;
VARRAY_TREE_INIT (current_binding_level->static_decls,
name != std_identifier ? 10 : 200,
"Static declarations");
}
}
else
resume_binding_level (NAMESPACE_LEVEL (d));
if (implicit_use)
do_using_directive (d);
current_namespace = d;
timevar_pop (TV_NAME_LOOKUP);
}
void
pop_namespace ()
{
my_friendly_assert (current_namespace != global_namespace, 20010801);
current_namespace = CP_DECL_CONTEXT (current_namespace);
suspend_binding_level ();
}
void
push_nested_namespace (ns)
tree ns;
{
if (ns == global_namespace)
push_to_top_level ();
else
{
push_nested_namespace (CP_DECL_CONTEXT (ns));
push_namespace (DECL_NAME (ns));
}
}
void
pop_nested_namespace (ns)
tree ns;
{
timevar_push (TV_NAME_LOOKUP);
while (ns != global_namespace)
{
pop_namespace ();
ns = CP_DECL_CONTEXT (ns);
}
pop_from_top_level ();
timevar_pop (TV_NAME_LOOKUP);
}
#define cxx_saved_binding_make() \
(ggc_alloc (sizeof (cxx_saved_binding)))
struct cxx_saved_binding GTY(())
{
cxx_saved_binding *previous;
tree identifier;
cxx_binding *binding;
tree class_value;
tree real_type_value;
};
struct saved_scope *scope_chain;
static cxx_saved_binding *
store_bindings (tree names, cxx_saved_binding *old_bindings)
{
tree t;
cxx_saved_binding *search_bindings = old_bindings;
timevar_push (TV_NAME_LOOKUP);
for (t = names; t; t = TREE_CHAIN (t))
{
tree id;
cxx_saved_binding *saved;
cxx_saved_binding *t1;
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 = search_bindings; t1; t1 = t1->previous)
if (t1->identifier == id)
goto skip_it;
my_friendly_assert (TREE_CODE (id) == IDENTIFIER_NODE, 135);
saved = cxx_saved_binding_make ();
saved->previous = old_bindings;
saved->identifier = id;
saved->binding = IDENTIFIER_BINDING (id);
saved->class_value = IDENTIFIER_CLASS_VALUE (id);;
saved->real_type_value = REAL_IDENTIFIER_TYPE_VALUE (id);
IDENTIFIER_BINDING (id) = NULL;
IDENTIFIER_CLASS_VALUE (id) = NULL_TREE;
old_bindings = saved;
skip_it:
;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old_bindings);
}
void
maybe_push_to_top_level (pseudo)
int pseudo;
{
struct saved_scope *s;
struct cp_binding_level *b;
cxx_saved_binding *old_bindings;
int need_pop;
timevar_push (TV_NAME_LOOKUP);
s = (struct saved_scope *) ggc_alloc_cleared (sizeof (struct saved_scope));
b = scope_chain ? current_binding_level : 0;
if (cfun)
{
need_pop = 1;
push_function_context_to (NULL_TREE);
}
else
need_pop = 0;
old_bindings = NULL;
if (scope_chain && 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->template_parms_p))
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->prev = scope_chain;
s->old_bindings = old_bindings;
s->bindings = b;
s->need_pop_function_context = need_pop;
s->function_decl = current_function_decl;
s->last_parms = last_function_parms;
scope_chain = s;
current_function_decl = NULL_TREE;
VARRAY_TREE_INIT (current_lang_base, 10, "current_lang_base");
current_lang_name = lang_name_cplusplus;
current_namespace = global_namespace;
timevar_pop (TV_NAME_LOOKUP);
}
void
push_to_top_level ()
{
maybe_push_to_top_level (0);
}
void
pop_from_top_level ()
{
struct saved_scope *s = scope_chain;
cxx_saved_binding *saved;
timevar_push (TV_NAME_LOOKUP);
if (previous_class_type)
invalidate_class_lookup_cache ();
current_lang_base = 0;
scope_chain = s->prev;
for (saved = s->old_bindings; saved; saved = saved->previous)
{
tree id = saved->identifier;
IDENTIFIER_BINDING (id) = saved->binding;
IDENTIFIER_CLASS_VALUE (id) = saved->class_value;
SET_IDENTIFIER_TYPE_VALUE (id, saved->real_type_value);
}
if (s->need_pop_function_context)
pop_function_context_from (NULL_TREE);
current_function_decl = s->function_decl;
last_function_parms = s->last_parms;
timevar_pop (TV_NAME_LOOKUP);
}
static void
set_identifier_type_value_with_scope (id, type, b)
tree id;
tree type;
struct cp_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
{
cxx_binding *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;
{
timevar_push (TV_NAME_LOOKUP);
if (REAL_IDENTIFIER_TYPE_VALUE (id) == NULL_TREE)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (REAL_IDENTIFIER_TYPE_VALUE (id) != global_type_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, REAL_IDENTIFIER_TYPE_VALUE (id));
id = lookup_name_real (id, 2, 1, 0);
if (id)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_TYPE (id));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
void
pop_everything ()
{
#ifdef DEBUG_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_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 cp_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)
{
tree name = DECL_NAME (decl);
decl = push_template_decl_real (decl, globalize);
if (TREE_CODE (type) != ENUMERAL_TYPE
&& !globalize && b->template_parms_p
&& b->level_chain->parm_flag == 2)
{
finish_member_declaration (CLASSTYPE_TI_TEMPLATE (type));
b->level_chain->tags =
tree_cons (name, type, b->level_chain->tags);
if (!COMPLETE_TYPE_P (current_class_type))
{
maybe_add_class_template_decl_list (current_class_type,
type, 0);
CLASSTYPE_TAGS (current_class_type) = b->level_chain->tags;
}
}
}
}
return decl;
}
tree
create_implicit_typedef (name, type)
tree name;
tree type;
{
tree decl;
decl = build_decl (TYPE_DECL, name, type);
DECL_ARTIFICIAL (decl) = 1;
SET_DECL_IMPLICIT_TYPEDEF_P (decl);
TYPE_NAME (type) = decl;
return decl;
}
static void
push_local_name (decl)
tree decl;
{
size_t i, nelts;
tree t, name;
timevar_push (TV_NAME_LOOKUP);
if (!local_names)
VARRAY_TREE_INIT (local_names, 8, "local_names");
name = DECL_NAME (decl);
nelts = VARRAY_ACTIVE_SIZE (local_names);
for (i = 0; i < nelts; i++)
{
t = VARRAY_TREE (local_names, i);
if (DECL_NAME (t) == name)
{
if (!DECL_LANG_SPECIFIC (decl))
retrofit_lang_decl (decl);
DECL_LANG_SPECIFIC (decl)->decl_flags.u2sel = 1;
if (DECL_LANG_SPECIFIC (t))
DECL_DISCRIMINATOR (decl) = DECL_DISCRIMINATOR (t) + 1;
else
DECL_DISCRIMINATOR (decl) = 1;
VARRAY_TREE (local_names, i) = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
}
VARRAY_PUSH_TREE (local_names, decl);
timevar_pop (TV_NAME_LOOKUP);
}
void
pushtag (name, type, globalize)
tree name, type;
int globalize;
{
register struct cp_binding_level *b;
timevar_push (TV_NAME_LOOKUP);
b = current_binding_level;
while (b->tag_transparent
|| (b->parm_flag == 2
&& (globalize
|| COMPLETE_TYPE_P (b->this_class))))
b = b->level_chain;
b->tags = tree_cons (name, type, b->tags);
if (name)
{
if (IDENTIFIER_TYPE_VALUE (name) != type)
{
register tree d = NULL_TREE;
int in_class = 0;
tree context = TYPE_CONTEXT (type);
if (! context)
{
tree cs = current_scope ();
if (! globalize)
context = cs;
else if (cs != NULL_TREE && TYPE_P (cs))
context = decl_function_context (get_type_decl (cs));
}
if (!context)
context = current_namespace;
if ((b->template_parms_p && b->level_chain->parm_flag == 2)
|| b->parm_flag == 2)
in_class = 1;
if (current_lang_name == lang_name_java)
TYPE_FOR_JAVA (type) = 1;
d = create_implicit_typedef (name, type);
DECL_CONTEXT (d) = FROB_CONTEXT (context);
if (! in_class)
set_identifier_type_value_with_scope (name, type, b);
d = maybe_process_template_type_declaration (type,
globalize, b);
if (b->parm_flag == 2)
{
if (!PROCESSING_REAL_TEMPLATE_DECL_P ())
finish_member_declaration (d);
else
pushdecl_class_level (d);
}
else
d = pushdecl_with_scope (d, b);
if (ANON_AGGRNAME_P (name))
DECL_IGNORED_P (d) = 1;
TYPE_CONTEXT (type) = DECL_CONTEXT (d);
if (TYPE_CONTEXT (type)
&& TREE_CODE (TYPE_CONTEXT (type)) == FUNCTION_DECL
&& !processing_template_decl)
VARRAY_PUSH_TREE (local_classes, type);
}
if (b->parm_flag == 2)
{
if (!COMPLETE_TYPE_P (current_class_type))
{
maybe_add_class_template_decl_list (current_class_type,
type, 0);
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);
}
timevar_pop (TV_NAME_LOOKUP);
}
static GTY(()) int anon_cnt;
tree
make_anon_name ()
{
char buf[32];
sprintf (buf, ANON_AGGRNAME_FORMAT, anon_cnt++);
return get_identifier (buf);
}
void
clear_anon_tags ()
{
register struct cp_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 (CP_DECL_CONTEXT (newdecl) != CP_DECL_CONTEXT (olddecl)
&& ! (DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl)))
return 0;
if (TREE_CODE (f1) != TREE_CODE (f2))
return 0;
if (same_type_p (TREE_TYPE (f1), TREE_TYPE (f2)))
{
if (p2 == NULL_TREE && DECL_EXTERN_C_P (olddecl)
&& (DECL_BUILT_IN (olddecl)
#ifndef NO_IMPLICIT_EXTERN_C
|| (DECL_IN_SYSTEM_HEADER (newdecl) && !DECL_CLASS_SCOPE_P (newdecl))
|| (DECL_IN_SYSTEM_HEADER (olddecl) && !DECL_CLASS_SCOPE_P (olddecl))
#endif
))
{
types_match = self_promoting_args_p (p1);
if (p1 == void_list_node)
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#ifndef NO_IMPLICIT_EXTERN_C
else if (p1 == NULL_TREE
&& (DECL_EXTERN_C_P (olddecl)
&& DECL_IN_SYSTEM_HEADER (olddecl)
&& !DECL_CLASS_SCOPE_P (olddecl))
&& (DECL_EXTERN_C_P (newdecl)
&& DECL_IN_SYSTEM_HEADER (newdecl)
&& !DECL_CLASS_SCOPE_P (newdecl)))
{
types_match = self_promoting_args_p (p2);
TREE_TYPE (newdecl) = TREE_TYPE (olddecl);
}
#endif
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))
!= TREE_CODE (DECL_TEMPLATE_RESULT (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;
{
static const char *const explicit_extern_static_warning
= "`%D' was declared `extern' and later `static'";
static const char *const implicit_extern_static_warning
= "`%D' was declared implicitly `extern' and later `static'";
tree name;
if (TREE_CODE (newdecl) == TYPE_DECL
|| (flag_objc && DECL_ARTIFICIAL (olddecl))
|| TREE_CODE (newdecl) == TEMPLATE_DECL
|| TREE_CODE (newdecl) == CONST_DECL)
return;
if (TREE_CODE (newdecl) == FUNCTION_DECL
&& DECL_STATIC_FUNCTION_P (newdecl))
return;
if (DECL_THIS_STATIC (olddecl) || !DECL_THIS_STATIC (newdecl))
return;
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
return;
name = DECL_ASSEMBLER_NAME (newdecl);
pedwarn (IDENTIFIER_IMPLICIT_DECL (name)
? implicit_extern_static_warning
: explicit_extern_static_warning, newdecl);
cp_pedwarn_at ("previous declaration of `%D'", olddecl);
}
int
duplicate_decls (newdecl, olddecl)
tree newdecl, olddecl;
{
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 (DECL_P (olddecl)
&& TREE_CODE (newdecl) == FUNCTION_DECL
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl)))
{
if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
;
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
;
else if (DECL_DECLARED_INLINE_P (newdecl)
&& DECL_UNINLINABLE (olddecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (olddecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared as inline");
warning_with_decl (olddecl,
"previous declaration of function `%s' with attribute noinline");
}
else if (DECL_DECLARED_INLINE_P (olddecl)
&& DECL_UNINLINABLE (newdecl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (newdecl)))
{
warning_with_decl (newdecl,
"function `%s' redeclared with attribute noinline");
warning_with_decl (olddecl,
"previous declaration of function `%s' was inline");
}
}
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_ARTIFICIAL (olddecl))
{
if (TREE_CODE (newdecl) != FUNCTION_DECL)
{
if (DECL_ANTICIPATED (olddecl))
return 0;
if (! TREE_PUBLIC (newdecl))
{
if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
return 0;
}
else if (! DECL_BUILT_IN (olddecl))
warning ("library function `%#D' redeclared as non-function `%#D'",
olddecl, newdecl);
else
{
error ("declaration of `%#D'", newdecl);
error ("conflicts with built-in declaration `%#D'",
olddecl);
}
return 0;
}
else if (!types_match)
{
if (DECL_ANTICIPATED (olddecl))
;
else if ((DECL_EXTERN_C_P (newdecl)
&& DECL_EXTERN_C_P (olddecl))
|| compparms (TYPE_ARG_TYPES (TREE_TYPE (newdecl)),
TYPE_ARG_TYPES (TREE_TYPE (olddecl))))
{
if (TREE_PUBLIC (newdecl))
{
warning ("new declaration `%#D'", newdecl);
warning ("ambiguates built-in declaration `%#D'",
olddecl);
}
else if (warn_shadow)
warning ("shadowing %s function `%#D'",
DECL_BUILT_IN (olddecl) ? "built-in" : "library",
olddecl);
}
else
return 0;
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
if (DECL_THIS_STATIC (newdecl) && !DECL_THIS_STATIC (olddecl))
{
DECL_THIS_STATIC (olddecl) = 1;
TREE_PUBLIC (olddecl) = 0;
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
SET_DECL_RTL (olddecl, DECL_RTL (newdecl));
}
}
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;
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 (CP_DECL_CONTEXT (newdecl) != CP_DECL_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)
{
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))
&& same_type_p (TREE_TYPE (TREE_TYPE (newdecl)),
TREE_TYPE (TREE_TYPE (olddecl))))
{
error ("new declaration `%#D'", newdecl);
cp_error_at ("ambiguates old declaration `%#D'", olddecl);
}
return 0;
}
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
if (DECL_EXTERN_C_P (newdecl) && DECL_EXTERN_C_P (olddecl))
{
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))))
{
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)
{
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)
{
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);
return 0;
}
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_depth () == 0)
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else
{
cp_error_at ("previous declaration of `%#D' with %L linkage",
olddecl, DECL_LANGUAGE (olddecl));
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)))
{
pedwarn ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_pedwarn_at ("after previous specification in `%#D'",
olddecl);
}
else
{
error ("default argument given for parameter %d of `%#D'",
i, newdecl);
cp_error_at ("after previous specification in `%#D'",
olddecl);
}
}
if (DECL_DECLARED_INLINE_P (newdecl)
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& TREE_ADDRESSABLE (olddecl) && warn_inline)
{
warning ("`%#D' was used before it was declared inline",
newdecl);
cp_warning_at ("previous non-inline declaration here",
olddecl);
}
}
}
if (TREE_CODE (olddecl) == TYPE_DECL
&& (DECL_IMPLICIT_TYPEDEF_P (olddecl)
|| DECL_IMPLICIT_TYPEDEF_P (newdecl)))
return 0;
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);
DECL_STATIC_CONSTRUCTOR (newdecl) |= DECL_STATIC_CONSTRUCTOR (olddecl);
DECL_STATIC_DESTRUCTOR (newdecl) |= DECL_STATIC_DESTRUCTOR (olddecl);
DECL_PURE_VIRTUAL_P (newdecl) |= DECL_PURE_VIRTUAL_P (olddecl);
DECL_VIRTUAL_P (newdecl) |= DECL_VIRTUAL_P (olddecl);
DECL_NEEDS_FINAL_OVERRIDER_P (newdecl) |= DECL_NEEDS_FINAL_OVERRIDER_P (olddecl);
DECL_THIS_STATIC (newdecl) |= DECL_THIS_STATIC (olddecl);
if (DECL_OVERLOADED_OPERATOR_P (olddecl) != ERROR_MARK)
SET_OVERLOADED_OPERATOR_CODE
(newdecl, DECL_OVERLOADED_OPERATOR_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) || DECL_FRIEND_P (olddecl)))
{
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_FRIEND_CLASSES (newtype)
= CLASSTYPE_FRIEND_CLASSES (oldtype);
\
DECL_ORIGINAL_TYPE (newdecl) = DECL_ORIGINAL_TYPE (olddecl);
}
if (types_match
&& DECL_WEAK_IMPORT (olddecl) != DECL_WEAK_IMPORT (newdecl)
&& ! DECL_EXTERNAL (olddecl)
&& ! DECL_EXTERNAL (newdecl))
warning_with_decl (newdecl,
"inconsistent weak_import attribute with declaration of `%s'");
DECL_ATTRIBUTES (newdecl)
= (*targetm.merge_decl_attributes) (olddecl, newdecl);
if (TREE_CODE (newdecl) == TEMPLATE_DECL)
{
TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
DECL_TEMPLATE_SPECIALIZATIONS (olddecl)
= chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
if (DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)) == NULL_TREE
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl)) != NULL_TREE)
{
DECL_SOURCE_LOCATION (olddecl)
= DECL_SOURCE_LOCATION (DECL_TEMPLATE_RESULT (olddecl))
= DECL_SOURCE_LOCATION (newdecl);
}
return 1;
}
if (types_match)
{
tree oldtype = TREE_TYPE (olddecl);
tree newtype;
newtype = merge_types (TREE_TYPE (newdecl), TREE_TYPE (olddecl));
if (TREE_CODE (newdecl) == TYPE_DECL
&& newtype == DECL_ORIGINAL_TYPE (newdecl))
newtype = oldtype;
if (TREE_CODE (newdecl) == VAR_DECL)
{
DECL_THIS_EXTERN (newdecl) |= DECL_THIS_EXTERN (olddecl);
DECL_INITIALIZED_P (newdecl) |= DECL_INITIALIZED_P (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_SOURCE_LINE (olddecl) != 0
&& flag_exceptions
&& !comp_except_specs (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (newdecl)),
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (olddecl)), 1))
{
error ("declaration of `%F' throws different exceptions",
newdecl);
cp_error_at ("than previous declaration `%F'", 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_LOCATION (newdecl) = DECL_SOURCE_LOCATION (olddecl);
if (CAN_HAVE_FULL_LANG_DECL_P (newdecl)
&& 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 (TREE_CODE (newdecl) == FUNCTION_DECL)
{
DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (newdecl)
|= DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (olddecl);
DECL_NO_LIMIT_STACK (newdecl)
|= DECL_NO_LIMIT_STACK (olddecl);
COPY_DECL_RTL (olddecl, newdecl);
}
else if (TREE_CODE (newdecl) == VAR_DECL
&& (DECL_SIZE (olddecl) || !DECL_SIZE (newdecl)))
{
COPY_DECL_RTL (olddecl, newdecl);
}
}
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);
}
merge_weak (newdecl, olddecl);
DECL_ONE_ONLY (newdecl) |= DECL_ONE_ONLY (olddecl);
DECL_DEFER_OUTPUT (newdecl) |= DECL_DEFER_OUTPUT (olddecl);
TREE_PUBLIC (newdecl) = TREE_PUBLIC (olddecl);
TREE_STATIC (olddecl) = TREE_STATIC (newdecl) |= TREE_STATIC (olddecl);
if (! DECL_EXTERNAL (olddecl))
DECL_EXTERNAL (newdecl) = 0;
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_LANG_SPECIFIC (newdecl)->decl_flags.u2 =
DECL_LANG_SPECIFIC (olddecl)->decl_flags.u2;
DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
DECL_INITIALIZED_IN_CLASS_P (newdecl)
|= DECL_INITIALIZED_IN_CLASS_P (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));
DECL_THUNKS (newdecl) = DECL_THUNKS (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))
error ("explicit specialization of %D after first use",
olddecl);
SET_DECL_TEMPLATE_SPECIALIZATION (olddecl);
}
else
{
if (DECL_PENDING_INLINE_INFO (newdecl) == 0)
DECL_PENDING_INLINE_INFO (newdecl) = DECL_PENDING_INLINE_INFO (olddecl);
DECL_DECLARED_INLINE_P (newdecl) |= DECL_DECLARED_INLINE_P (olddecl);
if (DECL_INLINE (newdecl) && DECL_INITIAL (olddecl) == NULL_TREE)
DECL_INLINE (olddecl) = 1;
DECL_INLINE (newdecl) = DECL_INLINE (olddecl);
DECL_UNINLINABLE (newdecl) = DECL_UNINLINABLE (olddecl)
= (DECL_UNINLINABLE (newdecl) || DECL_UNINLINABLE (olddecl));
}
DECL_ABSTRACT (newdecl) = DECL_ABSTRACT (olddecl);
if (! types_match)
{
SET_DECL_LANGUAGE (olddecl, DECL_LANGUAGE (newdecl));
COPY_DECL_ASSEMBLER_NAME (newdecl, olddecl);
SET_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)
SET_DECL_LANGUAGE (newdecl, DECL_LANGUAGE (olddecl));
else if (types_match)
{
if (DECL_BUILT_IN (olddecl))
{
DECL_BUILT_IN_CLASS (newdecl) = DECL_BUILT_IN_CLASS (olddecl);
DECL_FUNCTION_CODE (newdecl) = DECL_FUNCTION_CODE (olddecl);
SET_DECL_RTL (newdecl, DECL_RTL (olddecl));
}
else
DECL_NUM_STMTS (newdecl) = DECL_NUM_STMTS (olddecl);
DECL_RESULT (newdecl) = DECL_RESULT (olddecl);
if (DECL_ARGUMENTS (olddecl))
DECL_ARGUMENTS (newdecl) = DECL_ARGUMENTS (olddecl);
}
}
else 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_PRIVATE_EXTERN (newdecl) = DECL_PRIVATE_EXTERN (olddecl);
DECL_COALESCED (newdecl) = DECL_COALESCED (olddecl);
COPY_DECL_ASSEMBLER_NAME (olddecl, newdecl);
if (TREE_CODE (newdecl) == FUNCTION_DECL)
{
int function_size;
function_size = sizeof (struct tree_decl);
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
function_size - sizeof (struct tree_common));
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;
}
}
else
{
memcpy ((char *) olddecl + sizeof (struct tree_common),
(char *) newdecl + sizeof (struct tree_common),
sizeof (struct tree_decl) - sizeof (struct tree_common)
+ TREE_CODE_LENGTH (TREE_CODE (newdecl)) * sizeof (char *));
}
DECL_UID (olddecl) = olddecl_uid;
if (olddecl_friend)
DECL_FRIEND_P (olddecl) = 1;
DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
return 1;
}
tree
pushdecl (x)
tree x;
{
register tree t;
register tree name;
int need_new_binding;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (!cfun || doing_semantic_analysis_p (),
19990913);
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) == VAR_DECL && DECL_EXTERNAL (x))
&& !DECL_CONTEXT (x))
DECL_CONTEXT (x) = current_function_decl;
if (TREE_CODE (x) == FUNCTION_DECL
&& DECL_NAMESPACE_SCOPE_P (x)
&& current_function_decl
&& x != current_function_decl)
DECL_LOCAL_FUNCTION_P (x) = 1;
}
name = DECL_NAME (x);
if (name)
{
int different_binding_level = 0;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
if (TREE_CODE (x) == VAR_DECL && DECL_NAMESPACE_SCOPE_P (x)
&& namespace_bindings_p ())
t = namespace_binding (name, DECL_CONTEXT (x));
else
t = lookup_name_current_level (name);
if (! t && current_function_decl && x != current_function_decl
&& (TREE_CODE (x) == FUNCTION_DECL || TREE_CODE (x) == VAR_DECL)
&& DECL_EXTERNAL (x))
{
t = IDENTIFIER_VALUE (name);
if (! t)
t = namespace_binding (name, DECL_CONTEXT (x));
if (t && DECL_P (t) && ! (TREE_STATIC (t) || DECL_EXTERNAL (t)))
t = NULL_TREE;
if (t)
different_binding_level = 1;
}
if (t && TREE_CODE (t) == OVERLOAD)
{
tree match;
if (TREE_CODE (x) == FUNCTION_DECL)
for (match = t; match; match = OVL_NEXT (match))
{
if (decls_match (OVL_CURRENT (match), x))
break;
}
else
match = t;
if (match)
t = OVL_CURRENT (match);
else
t = NULL_TREE;
}
if (t == error_mark_node)
{
t = NULL_TREE;
cp_error_at ("`%#D' used prior to declaration", x);
}
else if (t != NULL_TREE)
{
if (different_binding_level)
{
if (decls_match (x, t))
TREE_PUBLIC (x) = TREE_PUBLIC (t);
}
else if (TREE_CODE (t) == PARM_DECL)
{
if (DECL_CONTEXT (t) == NULL_TREE)
abort ();
if (duplicate_decls (x, t))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if ((DECL_EXTERN_C_FUNCTION_P (x)
|| DECL_FUNCTION_TEMPLATE_P (x))
&& is_overloaded_fn (t))
;
else if (t == wchar_decl_node)
{
if (pedantic && ! DECL_IN_SYSTEM_HEADER (x))
pedwarn ("redeclaration of `wchar_t' as `%T'",
TREE_TYPE (x));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (TREE_CODE (t) != TREE_CODE (x))
{
if (duplicate_decls (x, t))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (duplicate_decls (x, t))
{
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);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
else if (DECL_MAIN_P (x))
{
cp_error_at ("invalid redeclaration of `%D'", t);
error ("as `%D'", x);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
}
check_template_shadow (x);
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_LANG_SPECIFIC (x))
{
retrofit_lang_decl (x);
SET_DECL_LANGUAGE (x, lang_c);
}
if (DECL_NON_THUNK_FUNCTION_P (x) && ! DECL_FUNCTION_MEMBER_P (x))
{
t = push_overloaded_decl (x, PUSH_LOCAL);
if (t != x)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
if (!namespace_bindings_p ())
need_new_binding = 0;
}
else if (DECL_FUNCTION_TEMPLATE_P (x) && DECL_NAMESPACE_SCOPE_P (x))
{
t = push_overloaded_decl (x, PUSH_GLOBAL);
if (t == x)
add_decl_to_level (x, NAMESPACE_LEVEL (CP_DECL_CONTEXT (t)));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
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)))
{
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;
}
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;
decl = IDENTIFIER_NAMESPACE_VALUE (name);
if (decl && TREE_CODE (decl) == OVERLOAD)
decl = OVL_FUNCTION (decl);
if (decl && decl != error_mark_node
&& (DECL_EXTERNAL (decl) || TREE_PUBLIC (decl))
&& TREE_CODE (decl) == TREE_CODE (x)
&& !same_type_p (TREE_TYPE (x), TREE_TYPE (decl)))
{
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)
&& (TREE_CODE (x) == TYPE_DECL
|| TREE_CODE (x) == VAR_DECL
|| TREE_CODE (x) == NAMESPACE_DECL
|| TREE_CODE (x) == CONST_DECL
|| TREE_CODE (x) == TEMPLATE_DECL))
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))
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)
{
tree d = oldlocal;
while (oldlocal
&& TREE_CODE (oldlocal) == VAR_DECL
&& DECL_DEAD_FOR_LOCAL (oldlocal))
oldlocal = DECL_SHADOWED_FOR_VAR (oldlocal);
if (oldlocal == NULL_TREE)
oldlocal = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (d));
}
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
{
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 (oldlocal != NULL_TREE && !DECL_EXTERNAL (x)
&& !DECL_FROM_INLINE (x)
&& TREE_CODE (oldlocal) == PARM_DECL)
{
bool err = false;
if (DECL_CONTEXT (oldlocal) == current_function_decl
&& TREE_CODE (x) != PARM_DECL)
{
struct cp_binding_level *b = current_binding_level->level_chain;
if (b->parm_flag == 1)
{
error ("declaration of `%#D' shadows a parameter",
name);
err = true;
}
}
if (warn_shadow && !err)
shadow_warning ("a parameter", name, oldlocal);
}
else if (warn_shadow && !DECL_EXTERNAL (x)
&& ! DECL_ARTIFICIAL (x)
&& ! DECL_FROM_INLINE (x))
{
if (IDENTIFIER_CLASS_VALUE (name) != NULL_TREE
&& current_class_ptr
&& !TREE_STATIC (name))
warning ("declaration of `%s' shadows a member of `this'",
IDENTIFIER_POINTER (name));
else if (oldlocal != NULL_TREE
&& TREE_CODE (oldlocal) == VAR_DECL)
shadow_warning ("a previous local", name, oldlocal);
else if (oldglobal != NULL_TREE
&& TREE_CODE (oldglobal) == VAR_DECL)
shadow_warning ("a global declaration", name, oldglobal);
}
}
if (TREE_CODE (x) == FUNCTION_DECL)
check_default_args (x);
if (TREE_CODE (x) == VAR_DECL)
maybe_register_incomplete_var (x);
}
if (need_new_binding)
add_decl_to_level (x,
DECL_NAMESPACE_SCOPE_P (x)
? NAMESPACE_LEVEL (CP_DECL_CONTEXT (x))
: current_binding_level);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
static tree
pushdecl_with_scope (x, level)
tree x;
struct cp_binding_level *level;
{
register struct cp_binding_level *b;
tree function_decl = current_function_decl;
timevar_push (TV_NAME_LOOKUP);
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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
tree
pushdecl_namespace_level (x)
tree x;
{
register struct cp_binding_level *b = current_binding_level;
register tree t;
timevar_push (TV_NAME_LOOKUP);
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;
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
tree
pushdecl_top_level (x)
tree x;
{
timevar_push (TV_NAME_LOOKUP);
push_to_top_level ();
x = pushdecl_namespace_level (x);
pop_from_top_level ();
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, x);
}
void
pushdecl_class_level (x)
tree x;
{
tree name;
timevar_push (TV_NAME_LOOKUP);
if (TREE_CODE (x) == OVERLOAD)
name = DECL_NAME (get_first_fn (x));
else
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_AGGR_TYPE_P (TREE_TYPE (x)))
{
tree f;
for (f = TYPE_FIELDS (TREE_TYPE (x)); f; f = TREE_CHAIN (f))
pushdecl_class_level (f);
}
timevar_pop (TV_NAME_LOOKUP);
}
tree
maybe_push_decl (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
if (decl == error_mark_node
|| (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) == UNKNOWN_TYPE
|| (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_TEMPLATE_SPECIALIZATION (decl)))
return decl;
else
return pushdecl (decl);
}
void
push_class_level_binding (name, x)
tree name;
tree x;
{
cxx_binding *binding;
timevar_push (TV_NAME_LOOKUP);
if (!class_binding_level)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
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;
IDENTIFIER_CLASS_VALUE (name) = x;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
}
if (push_class_binding (name, x))
{
class_binding_level->class_shadowed
= tree_cons (name, NULL,
class_binding_level->class_shadowed);
TREE_TYPE (class_binding_level->class_shadowed) = x;
}
timevar_pop (TV_NAME_LOOKUP);
}
tree
push_using_decl (scope, name)
tree scope;
tree name;
{
tree decl;
timevar_push (TV_NAME_LOOKUP);
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)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_bindings_p () ? decl : 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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
tree
push_using_directive (used)
tree used;
{
tree ud = current_binding_level->using_directives;
tree iter, ancestor;
timevar_push (TV_NAME_LOOKUP);
if (purpose_member (used, ud) != NULL_TREE)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 = tree_cons (used, ancestor, ud);
current_binding_level->using_directives = ud;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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));
timevar_push (TV_NAME_LOOKUP);
if (doing_global)
old = namespace_binding (name, DECL_CONTEXT (decl));
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)))
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))))
error ("`%#D' conflicts with previous using declaration `%#D'",
decl, fn);
if (duplicate_decls (decl, fn))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, fn);
}
}
else if (old == error_mark_node)
old = NULL_TREE;
else
{
cp_error_at ("previous non-function declaration `%#D'", old);
error ("conflicts with function declaration `%#D'", decl);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 = tree_cons (NULL_TREE, new_binding,
TREE_CHAIN (*d));
BINDING_VALUE (IDENTIFIER_BINDING (name))
= new_binding;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
abort ();
}
push_local_binding (name, new_binding, flags);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
tree
implicitly_declare (functionid)
tree functionid;
{
register tree decl;
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, 0, 0);
if (warn_implicit
&& IDENTIFIER_IMPLICIT_DECL (functionid) == NULL_TREE)
{
pedwarn ("implicit declaration of function `%#D'", decl);
}
SET_IDENTIFIER_IMPLICIT_DECL (functionid, decl);
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_PURE_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_TEMPLATE_RESULT (newdecl)
!= DECL_TEMPLATE_RESULT (olddecl))
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (newdecl))
&& DECL_INITIAL (DECL_TEMPLATE_RESULT (olddecl)))
|| (TREE_CODE (DECL_TEMPLATE_RESULT (newdecl)) == TYPE_DECL
&& COMPLETE_TYPE_P (TREE_TYPE (newdecl))
&& COMPLETE_TYPE_P (TREE_TYPE (olddecl))))
return "redefinition of `%#D'";
return 0;
}
else if (toplevel_bindings_p () || DECL_NAMESPACE_SCOPE_P (newdecl))
{
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;
}
}
static tree
make_label_decl (id, local_p)
tree id;
int local_p;
{
tree decl;
decl = build_decl (LABEL_DECL, id, void_type_node);
if (expanding_p)
label_rtx (decl);
DECL_CONTEXT (decl) = current_function_decl;
DECL_MODE (decl) = VOIDmode;
C_DECLARED_LABEL_FLAG (decl) = local_p;
DECL_SOURCE_LINE (decl) = lineno;
DECL_SOURCE_FILE (decl) = input_filename;
SET_IDENTIFIER_LABEL_VALUE (id, decl);
return decl;
}
static void
use_label (decl)
tree decl;
{
if (named_label_uses == NULL
|| named_label_uses->names_in_scope != current_binding_level->names
|| named_label_uses->label_decl != decl)
{
struct named_label_use_list *new_ent;
new_ent = ((struct named_label_use_list *)
ggc_alloc (sizeof (struct named_label_use_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;
}
}
tree
lookup_label (id)
tree id;
{
tree decl;
struct named_label_list *ent;
timevar_push (TV_NAME_LOOKUP);
if (current_function_decl == NULL_TREE)
{
error ("label `%s' referenced outside of any function",
IDENTIFIER_POINTER (id));
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
decl = IDENTIFIER_LABEL_VALUE (id);
if (decl != NULL_TREE && DECL_CONTEXT (decl) == current_function_decl)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
ent = ((struct named_label_list *)
ggc_alloc_cleared (sizeof (struct named_label_list)));
ent->old_value = IDENTIFIER_LABEL_VALUE (id);
ent->next = named_labels;
named_labels = ent;
decl = make_label_decl (id, 0);
ent->label_decl = decl;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
tree
declare_local_label (id)
tree id;
{
tree decl;
current_binding_level->shadowed_labels
= tree_cons (IDENTIFIER_LABEL_VALUE (id), NULL_TREE,
current_binding_level->shadowed_labels);
decl = make_label_decl (id, 1);
TREE_VALUE (current_binding_level->shadowed_labels) = decl;
return decl;
}
static int
decl_jump_unsafe (decl)
tree decl;
{
if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
return 0;
if (DECL_INITIAL (decl) == NULL_TREE
&& pod_type_p (TREE_TYPE (decl)))
return 0;
if (DECL_INITIAL (decl)
|| (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))))
return 2;
return 1;
}
static void
check_previous_goto_1 (decl, level, names, file, line)
tree decl;
struct cp_binding_level *level;
tree names;
const char *file;
int line;
{
int identified = 0;
int saw_eh = 0;
struct cp_binding_level *b = current_binding_level;
for (; b; b = b->level_chain)
{
tree new_decls = b->names;
tree old_decls = (b == level ? names : NULL_TREE);
for (; new_decls != old_decls;
new_decls = TREE_CHAIN (new_decls))
{
int problem = decl_jump_unsafe (new_decls);
if (! problem)
continue;
if (! identified)
{
if (decl)
pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
if (file)
pedwarn_with_file_and_line (file, line, " from here");
identified = 1;
}
if (problem > 1)
cp_error_at (" crosses initialization of `%#D'",
new_decls);
else
cp_pedwarn_at (" enters scope of non-POD `%#D'",
new_decls);
}
if (b == level)
break;
if ((b->is_try_scope || b->is_catch_scope) && ! saw_eh)
{
if (! identified)
{
if (decl)
pedwarn ("jump to label `%D'", decl);
else
pedwarn ("jump to case label");
if (file)
pedwarn_with_file_and_line (file, line, " from here");
identified = 1;
}
if (b->is_try_scope)
error (" enters try block");
else
error (" enters catch block");
saw_eh = 1;
}
}
}
static void
check_previous_goto (use)
struct named_label_use_list *use;
{
check_previous_goto_1 (use->label_decl, use->binding_level,
use->names_in_scope, use->filename_o_goto,
use->lineno_o_goto);
}
static void
check_switch_goto (level)
struct cp_binding_level *level;
{
check_previous_goto_1 (NULL_TREE, level, level->names, NULL, 0);
}
static void
check_previous_gotos (decl)
tree decl;
{
struct named_label_use_list **usep;
if (! TREE_USED (decl))
return;
for (usep = &named_label_uses; *usep; )
{
struct named_label_use_list *use = *usep;
if (use->label_decl == decl)
{
check_previous_goto (use);
*usep = use->next;
}
else
usep = &(use->next);
}
}
void
check_goto (decl)
tree decl;
{
int identified = 0;
tree bad;
struct named_label_list *lab;
if (! DECL_P (decl))
return;
if (! DECL_INITIAL (decl))
{
use_label (decl);
return;
}
for (lab = named_labels; lab; lab = lab->next)
if (decl == lab->label_decl)
break;
if (lab == 0)
return;
if ((lab->in_try_scope || lab->in_catch_scope || lab->bad_decls)
&& !identified)
{
cp_pedwarn_at ("jump to label `%D'", decl);
pedwarn (" from here");
identified = 1;
}
for (bad = lab->bad_decls; bad; bad = TREE_CHAIN (bad))
{
tree b = TREE_VALUE (bad);
int u = decl_jump_unsafe (b);
if (u > 1 && DECL_ARTIFICIAL (b))
cp_error_at (" enters catch block", b);
else if (u > 1)
cp_error_at (" skips initialization of `%#D'", b);
else
cp_pedwarn_at (" enters scope of non-POD `%#D'", b);
}
if (lab->in_try_scope)
error (" enters try block");
else if (lab->in_catch_scope)
error (" enters catch block");
}
tree
define_label (filename, line, name)
const char *filename;
int line;
tree name;
{
tree decl = lookup_label (name);
struct named_label_list *ent;
register struct cp_binding_level *p;
timevar_push (TV_NAME_LOOKUP);
for (ent = named_labels; ent; ent = ent->next)
if (ent->label_decl == decl)
break;
for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
p->more_cleanups_ok = 0;
if (name == get_identifier ("wchar_t"))
pedwarn ("label named wchar_t");
if (DECL_INITIAL (decl) != NULL_TREE)
{
error ("duplicate label `%D'", decl);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
else
{
DECL_INITIAL (decl) = error_mark_node;
DECL_SOURCE_FILE (decl) = filename;
DECL_SOURCE_LINE (decl) = line;
if (ent)
{
ent->names_in_scope = current_binding_level->names;
ent->binding_level = current_binding_level;
}
check_previous_gotos (decl);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
}
timevar_pop (TV_NAME_LOOKUP);
}
struct cp_switch
{
struct cp_binding_level *level;
struct cp_switch *next;
tree switch_stmt;
splay_tree cases;
};
static struct cp_switch *switch_stack;
void
push_switch (switch_stmt)
tree switch_stmt;
{
struct cp_switch *p
= (struct cp_switch *) xmalloc (sizeof (struct cp_switch));
p->level = current_binding_level;
p->next = switch_stack;
p->switch_stmt = switch_stmt;
p->cases = splay_tree_new (case_compare, NULL, NULL);
switch_stack = p;
}
void
pop_switch ()
{
struct cp_switch *cs;
cs = switch_stack;
splay_tree_delete (cs->cases);
switch_stack = switch_stack->next;
free (cs);
}
tree
finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
tree cond, r;
register struct cp_binding_level *p;
if (! switch_stack)
{
if (high_value)
error ("case label not within a switch statement");
else if (low_value)
error ("case label `%E' not within a switch statement",
low_value);
else
error ("`default' label not within a switch statement");
return NULL_TREE;
}
if (processing_template_decl)
{
tree label;
label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
return add_stmt (build_case_label (low_value, high_value, label));
}
cond = SWITCH_COND (switch_stack->switch_stmt);
if (cond && TREE_CODE (cond) == TREE_LIST)
cond = TREE_VALUE (cond);
r = c_add_case_label (switch_stack->cases, cond, low_value, high_value);
if (r == error_mark_node)
r = NULL_TREE;
check_switch_goto (switch_stack->level);
for (p = current_binding_level; !(p->parm_flag); p = p->level_chain)
p->more_cleanups_ok = 0;
return r;
}
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
follow_tag_typedef (type)
tree type;
{
tree original;
original = original_type (type);
if (! TYPE_NAME (original))
return NULL_TREE;
if (TYPE_IDENTIFIER (original) == TYPE_IDENTIFIER (type)
&& (CP_DECL_CONTEXT (TYPE_NAME (original))
== CP_DECL_CONTEXT (TYPE_NAME (type)))
&& !(CLASS_TYPE_P (original) && TYPE_WAS_ANONYMOUS (original)))
return original;
else
return NULL_TREE;
}
static tree
lookup_tag (form, name, binding_level, thislevel_only)
enum tree_code form;
tree name;
struct cp_binding_level *binding_level;
int thislevel_only;
{
register struct cp_binding_level *level;
int allow_template_parms_p = 1;
timevar_push (TV_NAME_LOOKUP);
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)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
}
else if (level->namespace_p)
for (tail = current_namespace; 1; tail = CP_DECL_CONTEXT (tail))
{
cxx_binding *binding =
cxx_scope_find_binding_for_name (tail, name);
tree old;
if (thislevel_only && !allow_template_parms_p
&& binding && BINDING_VALUE (binding)
&& DECL_CLASS_TEMPLATE_P (BINDING_VALUE (binding)))
old = TREE_TYPE (BINDING_VALUE (binding));
else if (binding)
old = BINDING_TYPE (binding);
else
old = NULL;
if (old)
{
old = follow_tag_typedef (old);
if (!old)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
if (TREE_CODE (old) != form
&& (form == ENUMERAL_TYPE
|| TREE_CODE (old) == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", old, form);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, old);
}
if (thislevel_only || tail == global_namespace)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 == ENUMERAL_TYPE))
{
error ("`%#D' redeclared as %C", TREE_VALUE (tail), form);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_VALUE (tail));
}
}
if (thislevel_only && ! level->tag_transparent)
{
if (level->template_parms_p && allow_template_parms_p)
{
allow_template_parms_p = 0;
continue;
}
else
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 cp_binding_level *level;
timevar_push (TV_NAME_LOOKUP);
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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, TREE_PURPOSE (tail));
}
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
}
tree
lookup_namespace_name (namespace, name)
tree namespace, name;
{
tree val;
tree template_id = NULL_TREE;
cxx_binding binding;
timevar_push (TV_NAME_LOOKUP);
my_friendly_assert (TREE_CODE (namespace) == NAMESPACE_DECL, 370);
if (TREE_CODE (name) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, name);
else if (TREE_CODE (name) == TEMPLATE_DECL)
{
error ("invalid use of `%D'", name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
namespace = ORIGINAL_NAMESPACE (namespace);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
template_id = name;
name = TREE_OPERAND (name, 0);
if (TREE_CODE (name) == OVERLOAD)
name = DECL_NAME (OVL_CURRENT (name));
else if (DECL_P (name))
name = DECL_NAME (name);
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 373);
cxx_binding_clear (&binding);
if (!qualified_lookup_using_namespace (name, namespace, &binding, 0))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (binding.value)
{
val = binding.value;
if (template_id)
{
if (DECL_CLASS_TEMPLATE_P (val))
val = lookup_template_class (val,
TREE_OPERAND (template_id, 1),
NULL_TREE,
NULL_TREE,
0,
tf_error | tf_warning);
else if (DECL_FUNCTION_TEMPLATE_P (val)
|| TREE_CODE (val) == OVERLOAD)
val = lookup_template_function (val,
TREE_OPERAND (template_id, 1));
else
{
error ("`%D::%D' is not a template",
namespace, name);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
}
if (TREE_CODE (val) == OVERLOAD && ! really_overloaded_fn (val))
val = OVL_FUNCTION (val);
if (!val || !DECL_P(val)
|| !DECL_LANG_SPECIFIC(val)
|| !DECL_ANTICIPATED (val))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
error ("`%D' undeclared in namespace `%D'", name, namespace);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
}
static hashval_t
typename_hash (k)
const void * k;
{
hashval_t hash;
tree t = (tree) k;
hash = (htab_hash_pointer (TYPE_CONTEXT (t))
^ htab_hash_pointer (DECL_NAME (TYPE_NAME (t))));
return hash;
}
static int
typename_compare (k1, k2)
const void * k1;
const void * 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)
&& 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));
}
static GTY ((param_is (union tree_node))) htab_t typename_htab;
tree
build_typename_type (context, name, fullname, base_type)
tree context;
tree name;
tree fullname;
tree base_type;
{
tree t;
tree d;
PTR *e;
if (typename_htab == NULL)
{
typename_htab = htab_create_ggc (61, &typename_hash,
&typename_compare, NULL);
}
t = make_aggr_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 = htab_find_slot (typename_htab, t, INSERT);
if (*e)
t = (tree) *e;
else
*e = t;
return t;
}
tree
make_typename_type (context, name, complain)
tree context, name;
tsubst_flags_t complain;
{
tree fullname;
if (TYPE_P (name))
{
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) == TEMPLATE_DECL)
{
error ("`%D' used without template parameters", name);
return error_mark_node;
}
if (TREE_CODE (name) != IDENTIFIER_NODE)
abort ();
if (TREE_CODE (context) == NAMESPACE_DECL)
{
if (complain & tf_error)
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))
{
if (complain & tf_error)
error ("no class template named `%#T' in `%#T'",
name, context);
return error_mark_node;
}
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, tmpl);
else
enforce_access (context, tmpl);
}
return lookup_template_class (tmpl,
TREE_OPERAND (fullname, 1),
NULL_TREE, context,
0,
tf_error | tf_warning);
}
else
{
tree t;
if (!IS_AGGR_TYPE (context))
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
t = lookup_field (context, name, 0, 1);
if (t)
{
if (TREE_CODE (t) != TYPE_DECL)
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, t);
else
enforce_access (context, t);
}
if (DECL_ARTIFICIAL (t) || !(complain & tf_keep_type_decl))
t = TREE_TYPE (t);
if (IMPLICIT_TYPENAME_P (t))
{
t = copy_node (t);
TREE_TYPE (t) = NULL_TREE;
}
return t;
}
}
}
if (!uses_template_parms (context))
{
if (complain & tf_error)
error ("no type named `%#T' in `%#T'", name, context);
return error_mark_node;
}
return build_typename_type (context, name, fullname, NULL_TREE);
}
tree
make_unbound_class_template (context, name, complain)
tree context, name;
tsubst_flags_t complain;
{
tree t;
tree d;
if (TYPE_P (name))
name = TYPE_IDENTIFIER (name);
else if (DECL_P (name))
name = DECL_NAME (name);
if (TREE_CODE (name) != IDENTIFIER_NODE)
abort ();
if (!uses_template_parms (context)
|| currently_open_class (context))
{
tree tmpl = NULL_TREE;
if (IS_AGGR_TYPE (context))
tmpl = lookup_field (context, name, 0, 0);
if (!tmpl || !DECL_CLASS_TEMPLATE_P (tmpl))
{
if (complain & tf_error)
error ("no class template named `%#T' in `%#T'", name, context);
return error_mark_node;
}
if (complain & tf_error)
{
if (complain & tf_parsing)
type_access_control (context, tmpl);
else
enforce_access (context, tmpl);
}
return tmpl;
}
t = make_aggr_type (UNBOUND_CLASS_TEMPLATE);
TYPE_CONTEXT (t) = FROB_CONTEXT (context);
TREE_TYPE (t) = NULL_TREE;
d = build_decl (TEMPLATE_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;
return t;
}
static tree
select_decl (cxx_binding *binding, int flags)
{
tree val;
timevar_push (TV_NAME_LOOKUP);
val = BINDING_VALUE (binding);
if (LOOKUP_NAMESPACES_ONLY (flags))
{
if (val && TREE_CODE (val) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, val);
}
tree
unqualified_namespace_lookup (name, flags, spacesp)
tree name;
int flags;
tree *spacesp;
{
tree initial = current_decl_namespace ();
tree scope = initial;
tree siter;
struct cp_binding_level *level;
tree val = NULL_TREE;
cxx_binding binding;
timevar_push (TV_NAME_LOOKUP);
cxx_binding_clear (&binding);
if (spacesp)
*spacesp = NULL_TREE;
for (; !val; scope = CP_DECL_CONTEXT (scope))
{
cxx_binding *b;
if (spacesp)
*spacesp = tree_cons (scope, NULL_TREE, *spacesp);
b = cxx_scope_find_binding_for_name (scope, name);
if (b && BINDING_VALUE (b) && DECL_P (BINDING_VALUE (b))
&& DECL_LANG_SPECIFIC (BINDING_VALUE (b))
&& DECL_ANTICIPATED (BINDING_VALUE (b)))
;
else if (b)
{
binding.value = BINDING_VALUE (b);
binding.type = BINDING_TYPE (b);
}
for (level = current_binding_level;
!level->namespace_p;
level = level->level_chain)
if (!lookup_using_namespace (name, &binding, level->using_directives,
scope, flags, spacesp))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
siter = initial;
while (1)
{
if (!lookup_using_namespace (name, &binding,
DECL_NAMESPACE_USING (siter),
scope, flags, spacesp))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (siter == scope) break;
siter = CP_DECL_CONTEXT (siter);
}
val = select_decl (&binding, flags);
if (scope == global_namespace)
break;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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
&& CLASS_TYPE_P (subtype)
&& CLASSTYPE_TEMPLATE_INFO (subtype)
&& CLASSTYPE_TI_TEMPLATE (subtype) == binding)
&& ! (TREE_CODE (binding) == TYPE_DECL
&& same_type_p (TREE_TYPE (binding), subtype)))
{
warning ("lookup of `%D' finds `%#D'",
name, binding);
warning (" instead of `%D' from dependent base class",
typename);
warning (" (use `typename %T::%D' if that's what you meant)",
constructor_name (current_class_type), name);
}
}
tree
check_for_out_of_scope_variable (tree decl)
{
tree shadowed;
if (!(TREE_CODE (decl) == VAR_DECL && DECL_DEAD_FOR_LOCAL (decl)))
return decl;
shadowed = DECL_SHADOWED_FOR_VAR (decl);
while (shadowed != NULL_TREE && TREE_CODE (shadowed) == VAR_DECL
&& DECL_DEAD_FOR_LOCAL (shadowed))
shadowed = DECL_SHADOWED_FOR_VAR (shadowed);
if (!shadowed)
shadowed = IDENTIFIER_NAMESPACE_VALUE (DECL_NAME (decl));
if (shadowed)
{
if (!DECL_ERROR_REPORTED (decl))
{
warning ("name lookup of `%D' changed",
DECL_NAME (decl));
cp_warning_at (" matches this `%D' under ISO standard rules",
shadowed);
cp_warning_at (" matches this `%D' under old rules", decl);
DECL_ERROR_REPORTED (decl) = 1;
}
return shadowed;
}
if (DECL_ERROR_REPORTED (decl))
return decl;
DECL_ERROR_REPORTED (decl) = 1;
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
{
error ("name lookup of `%D' changed for new ISO `for' scoping",
DECL_NAME (decl));
cp_error_at (" cannot use obsolete binding at `%D' because it has a destructor", decl);
return error_mark_node;
}
else
{
pedwarn ("name lookup of `%D' changed for new ISO `for' scoping",
DECL_NAME (decl));
cp_pedwarn_at (" using obsolete binding at `%D'", decl);
}
return decl;
}
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;
cxx_binding *iter;
timevar_push (TV_NAME_LOOKUP);
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)
type = got_scope;
else if (got_object != error_mark_node)
type = got_object;
if (type)
{
if (type == error_mark_node)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, error_mark_node);
if (IMPLICIT_TYPENAME_P (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)
{
cxx_binding b;
cxx_binding_clear (&b);
flags |= LOOKUP_COMPLAIN;
if (!qualified_lookup_using_namespace (name, type, &b, flags))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, NULL_TREE);
val = select_decl (&b, flags);
}
else if (! IS_AGGR_TYPE (type)
|| TREE_CODE (type) == TEMPLATE_TYPE_PARM
|| TREE_CODE (type) == BOUND_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);
if (!uses_template_parms (type))
type_access_control (type, val);
if (got_scope && got_scope != type
&& val && TREE_CODE (val) == TYPE_DECL
&& TREE_CODE (TREE_TYPE (val)) == TYPENAME_TYPE)
{
val = TREE_TYPE (val);
val = build_typename_type (got_scope, name,
TYPENAME_TYPE_FULLNAME (val),
TREE_TYPE (val));
val = TYPE_STUB_DECL (val);
}
}
}
else
val = NULL_TREE;
if (got_scope)
goto done;
else if (got_object && val)
{
from_obj = val;
val = NULL_TREE;
}
}
else
{
flags = lookup_flags (prefer_type, namespaces_only);
flags |= LOOKUP_COMPLAIN;
}
if (current_class_type == NULL_TREE)
nonclass = 1;
for (iter = IDENTIFIER_BINDING (name); iter; iter = iter->previous)
{
tree binding;
if (!LOCAL_BINDING_P (iter) && nonclass)
continue;
if (qualify_lookup (BINDING_VALUE (iter), flags))
binding = BINDING_VALUE (iter);
else if ((flags & LOOKUP_PREFER_TYPES)
&& qualify_lookup (BINDING_TYPE (iter), flags))
binding = BINDING_TYPE (iter);
else
binding = NULL_TREE;
if (binding && ! yylex
&& BINDING_LEVEL (iter) && BINDING_LEVEL (iter)->parm_flag == 2)
type_access_control (BINDING_LEVEL (iter)->this_class, binding);
if (binding
&& (!val || !IMPLICIT_TYPENAME_TYPE_DECL_P (binding)))
{
if (val_is_implicit_typename && !yylex)
warn_about_implicit_typename_lookup (val, binding);
val = binding;
val_is_implicit_typename
= IMPLICIT_TYPENAME_TYPE_DECL_P (val);
if (!val_is_implicit_typename)
break;
}
}
if (!val && !nonclass && current_class_type)
val = qualify_lookup (lookup_nested_field (name, !yylex), flags);
if (!val || val_is_implicit_typename)
{
t = unqualified_namespace_lookup (name, flags, 0);
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
&& ! same_type_p (TREE_TYPE (from_obj), TREE_TYPE (val)))
pedwarn ("\
lookup of `%D' in the scope of `%#T' (`%#D') \
does not match lookup in the current scope (`%#D')",
name, got_object, from_obj, 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;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, 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 cp_binding_level *b;
tree t = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
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)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, IDENTIFIER_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
break;
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
tree
lookup_type_current_level (name)
tree name;
{
register tree t = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
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 cp_binding_level *b = current_binding_level;
while (1)
{
if (purpose_member (name, b->type_shadowed))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
REAL_IDENTIFIER_TYPE_VALUE (name));
if (b->keep == 2)
b = b->level_chain;
else
break;
}
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, t);
}
void
begin_only_namespace_names ()
{
only_namespace_names = 1;
}
void
end_only_namespace_names ()
{
only_namespace_names = 0;
}
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_USER_ALIGN (type) = 0;
TYPE_MODE (type) = TYPE_MODE (void_type_node);
}
typedef struct predefined_identifier
{
const char *const name;
tree *const node;
const int ctor_or_dtor_p;
} predefined_identifier;
static void
initialize_predefined_identifiers ()
{
const predefined_identifier *pid;
static const predefined_identifier predefined_identifiers[] = {
{ "C++", &lang_name_cplusplus, 0 },
{ "C", &lang_name_c, 0 },
{ "Objective-C", &lang_name_objc, 0 },
{ "Java", &lang_name_java, 0 },
{ CTOR_NAME, &ctor_identifier, 1 },
{ "__base_ctor", &base_ctor_identifier, 1 },
{ "__comp_ctor", &complete_ctor_identifier, 1 },
{ DTOR_NAME, &dtor_identifier, 1 },
{ "__comp_dtor", &complete_dtor_identifier, 1 },
{ "__base_dtor", &base_dtor_identifier, 1 },
{ "__deleting_dtor", &deleting_dtor_identifier, 1 },
{ IN_CHARGE_NAME, &in_charge_identifier, 0 },
{ "nelts", &nelts_identifier, 0 },
{ THIS_NAME, &this_identifier, 0 },
{ VTABLE_DELTA_NAME, &delta_identifier, 0 },
{ VTABLE_PFN_NAME, &pfn_identifier, 0 },
{ "_vptr", &vptr_identifier, 0 },
{ "__vtt_parm", &vtt_parm_identifier, 0 },
{ "std", &std_identifier, 0 },
{ NULL, NULL, 0 }
};
for (pid = predefined_identifiers; pid->name; ++pid)
{
*pid->node = get_identifier (pid->name);
if (pid->ctor_or_dtor_p)
IDENTIFIER_CTOR_OR_DTOR_P (*pid->node) = 1;
}
if (flag_apple_kext)
{
delta2_identifier = get_identifier ("__delta2");
index_identifier = get_identifier ("__index");
pfn_or_delta2_identifier = get_identifier ("__pfn_or_delta2");
}
}
void
cxx_init_decl_processing ()
{
tree void_ftype;
tree void_ftype_ptr;
initialize_predefined_identifiers ();
lang_missing_noreturn_ok_p = &cp_missing_noreturn_ok_p;
push_to_top_level ();
my_friendly_assert (global_namespace == NULL_TREE, 375);
push_namespace (get_identifier ("::"));
global_namespace = current_namespace;
current_lang_name = NULL_TREE;
if (! flag_permissive && ! pedantic)
flag_pedantic_errors = 1;
if (!flag_no_inline)
{
flag_inline_trees = 1;
flag_no_inline = 1;
}
if (flag_inline_functions)
{
flag_inline_trees = 2;
flag_inline_functions = 0;
}
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_pfn
&& force_align_functions_log < 1)
force_align_functions_log = 1;
current_lang_name = lang_name_c;
current_function_decl = NULL_TREE;
current_binding_level = NULL_BINDING_LEVEL;
free_binding_level = NULL_BINDING_LEVEL;
build_common_tree_nodes (flag_signed_char);
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 ();
VARRAY_TREE_INIT (global_binding_level->static_decls,
200,
"Static declarations");
push_namespace (std_identifier);
std_node = current_namespace;
pop_namespace ();
c_common_nodes_and_builtins ();
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);
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;
empty_except_spec = build_tree_list (NULL_TREE, NULL_TREE);
#if 0
record_builtin_type (RID_MAX, NULL, string_type_node);
#endif
if (flag_apple_kext)
delta_type_node = short_integer_type_node;
else
delta_type_node = ptrdiff_type_node;
vtable_index_type = ptrdiff_type_node;
vtt_parm_type = build_pointer_type (const_ptr_type_node);
void_ftype = build_function_type (void_type_node, void_list_node);
void_ftype_ptr = build_function_type (void_type_node,
tree_cons (NULL_TREE,
ptr_type_node,
void_list_node));
void_ftype_ptr
= build_exception_variant (void_ftype_ptr, empty_except_spec);
unknown_type_node = make_node (UNKNOWN_TYPE);
record_unknown_type (unknown_type_node, "unknown type");
TREE_TYPE (unknown_type_node) = unknown_type_node;
TYPE_POINTER_TO (unknown_type_node) = unknown_type_node;
TYPE_REFERENCE_TO (unknown_type_node) = unknown_type_node;
{
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);
}
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, 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, vtbl_ptr_type_node);
push_namespace (get_identifier ("__cxxabiv1"));
abi_node = current_namespace;
pop_namespace ();
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;
tree ptr_ftype_sizetype;
push_namespace (std_identifier);
bad_alloc_type_node
= xref_tag (class_type, get_identifier ("bad_alloc"),
NULL_TREE, 1);
pop_namespace ();
ptr_ftype_sizetype
= build_function_type (ptr_type_node,
tree_cons (NULL_TREE,
size_type_node,
void_list_node));
newtype = build_exception_variant
(ptr_ftype_sizetype, add_exception_specifier
(NULL_TREE, bad_alloc_type_node, -1));
deltype = build_exception_variant (void_ftype_ptr, empty_except_spec);
push_cp_library_fn (NEW_EXPR, newtype);
push_cp_library_fn (VEC_NEW_EXPR, newtype);
global_delete_fndecl = push_cp_library_fn (DELETE_EXPR, deltype);
push_cp_library_fn (VEC_DELETE_EXPR, deltype);
}
abort_fndecl
= build_library_fn_ptr ("__cxa_pure_virtual", void_ftype);
init_class_processing ();
init_search_processing ();
init_rtti_processing ();
if (flag_exceptions)
init_exception_processing ();
if (! supports_one_only ())
flag_weak = 0;
make_fname_decl = cp_make_fname_decl;
start_fname_decls ();
using_eh_for_cleanups ();
if (flag_writable_strings)
flag_const_strings = 0;
}
tree
cp_fname_init (name)
const char *name;
{
tree domain = NULL_TREE;
tree type;
tree init = NULL_TREE;
size_t length = 0;
if (name)
{
length = strlen (name);
domain = build_index_type (size_int (length));
init = build_string (length + 1, name);
}
type = build_qualified_type (char_type_node, TYPE_QUAL_CONST);
type = build_cplus_array_type (type, domain);
if (init)
TREE_TYPE (init) = type;
else
init = build (ERROR_MARK, type);
return init;
}
static tree
cp_make_fname_decl (id, type_dep)
tree id;
int type_dep;
{
const char *const name = (type_dep && processing_template_decl
? NULL : fname_as_string (type_dep));
tree init = cp_fname_init (name);
tree decl = build_decl (VAR_DECL, id, TREE_TYPE (init));
DECL_CONTEXT (decl) = current_function_decl;
DECL_PRETTY_FUNCTION_P (decl) = type_dep;
TREE_STATIC (decl) = 1;
TREE_READONLY (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
DECL_INITIAL (decl) = init;
TREE_USED (decl) = 1;
cp_finish_decl (decl, init, NULL_TREE, LOOKUP_ONLYCONVERTING);
return decl;
}
static tree
builtin_function_1 (name, type, context, code, class, libname, attrs)
const char *name;
tree type;
tree context;
int code;
enum built_in_class class;
const char *libname;
tree attrs;
{
tree decl = build_library_fn_1 (get_identifier (name), ERROR_MARK, type);
DECL_BUILT_IN_CLASS (decl) = class;
DECL_FUNCTION_CODE (decl) = code;
DECL_CONTEXT (decl) = context;
pushdecl (decl);
if (libname)
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (libname));
make_decl_rtl (decl, NULL);
if (class != BUILT_IN_MD && (name[0] != '_' || name[1] != '_'))
DECL_ANTICIPATED (decl) = 1;
if (attrs)
decl_attributes (&decl, attrs, ATTR_FLAG_BUILT_IN);
else
decl_attributes (&decl, NULL_TREE, 0);
return decl;
}
tree
builtin_function (name, type, code, class, libname, attrs)
const char *name;
tree type;
int code;
enum built_in_class class;
const char *libname;
tree attrs;
{
if (name[0] != '_' && class != BUILT_IN_MD && strcmp (name, "alloca"))
{
push_namespace (std_identifier);
builtin_function_1 (name, type, std_node, code, class, libname, attrs);
pop_namespace ();
}
return builtin_function_1 (name, type, NULL_TREE, code,
class, libname, attrs);
}
static tree
build_library_fn_1 (name, operator_code, type)
tree name;
enum tree_code operator_code;
tree type;
{
tree fn = build_lang_decl (FUNCTION_DECL, name, type);
DECL_EXTERNAL (fn) = 1;
TREE_PUBLIC (fn) = 1;
DECL_ARTIFICIAL (fn) = 1;
TREE_NOTHROW (fn) = 1;
SET_OVERLOADED_OPERATOR_CODE (fn, operator_code);
SET_DECL_LANGUAGE (fn, lang_c);
return fn;
}
tree
build_library_fn (name, type)
tree name;
tree type;
{
return build_library_fn_1 (name, ERROR_MARK, type);
}
static tree
build_cp_library_fn (name, operator_code, type)
tree name;
enum tree_code operator_code;
tree type;
{
tree fn = build_library_fn_1 (name, operator_code, type);
TREE_NOTHROW (fn) = TYPE_NOTHROW_P (type);
DECL_CONTEXT (fn) = FROB_CONTEXT (current_namespace);
SET_DECL_LANGUAGE (fn, lang_cplusplus);
set_mangled_name_for_decl (fn);
return fn;
}
tree
build_library_fn_ptr (name, type)
const char *name;
tree type;
{
return build_library_fn (get_identifier (name), type);
}
tree
build_cp_library_fn_ptr (name, type)
const char *name;
tree type;
{
return build_cp_library_fn (get_identifier (name), ERROR_MARK, type);
}
tree
push_library_fn (name, type)
tree name, type;
{
tree fn = build_library_fn (name, type);
pushdecl_top_level (fn);
return fn;
}
static tree
push_cp_library_fn (operator_code, type)
enum tree_code operator_code;
tree type;
{
tree fn = build_cp_library_fn (ansi_opname (operator_code),
operator_code,
type);
pushdecl (fn);
return fn;
}
tree
push_void_library_fn (name, parmtypes)
tree name, parmtypes;
{
tree type = build_function_type (void_type_node, parmtypes);
return push_library_fn (name, type);
}
tree
push_throw_library_fn (name, type)
tree name, type;
{
tree fn = push_library_fn (name, type);
TREE_THIS_VOLATILE (fn) = 1;
TREE_NOTHROW (fn) = 0;
return fn;
}
tree lang_build_type_variant PARAMS ((tree, int, int));
tree
lang_build_type_variant (type, constp, volatilep)
tree type;
int constp, volatilep;
{
return build_type_variant (type, constp, volatilep);
}
void
cxx_insert_default_attributes (decl)
tree decl;
{
if (!DECL_EXTERN_C_FUNCTION_P (decl))
return;
if (!TREE_PUBLIC (decl))
return;
c_common_insert_default_attributes (decl);
}
void
fixup_anonymous_aggr (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))
cp_error_at ("an anonymous union cannot have function members", t);
if (TREE_CODE (t) != UNION_TYPE)
{
tree field, type;
for (field = TYPE_FIELDS (t); field; field = TREE_CHAIN (field))
if (TREE_CODE (field) == FIELD_DECL)
{
type = TREE_TYPE (field);
if (CLASS_TYPE_P (type))
{
if (TYPE_NEEDS_CONSTRUCTING (type))
cp_error_at ("member %#D' with constructor not allowed in anonymous aggregate",
field);
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
cp_error_at ("member %#D' with destructor not allowed in anonymous aggregate",
field);
if (TYPE_HAS_COMPLEX_ASSIGN_REF (type))
cp_error_at ("member %#D' with copy assignment operator not allowed in anonymous aggregate",
field);
}
}
}
}
tree
check_tag_decl (declspecs)
tree declspecs;
{
int found_type = 0;
int saw_friend = 0;
int saw_typedef = 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)
|| TREE_CODE (value) == TYPE_DECL
|| (TREE_CODE (value) == IDENTIFIER_NODE
&& IDENTIFIER_GLOBAL_VALUE (value)
&& TREE_CODE (IDENTIFIER_GLOBAL_VALUE (value)) == TYPE_DECL))
{
++found_type;
if (found_type == 2 && TREE_CODE (value) == IDENTIFIER_NODE)
{
if (! in_system_header)
pedwarn ("redeclaration of C++ built-in type `%T'", value);
return NULL_TREE;
}
if (TYPE_P (value)
&& ((TREE_CODE (value) != TYPENAME_TYPE && 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_TYPEDEF])
saw_typedef = 1;
else if (value == ridpointers[(int) RID_FRIEND])
{
if (current_class_type == NULL_TREE
|| current_scope () != current_class_type)
ob_modifier = value;
else
saw_friend = 1;
}
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]
|| value == ridpointers[(int) RID_THREAD])
ob_modifier = value;
}
if (found_type > 1)
error ("multiple types in one declaration");
if (t == NULL_TREE && ! saw_friend)
pedwarn ("declaration does not declare anything");
else if (t && IS_AGGR_TYPE_CODE (TREE_CODE (t))
&& TYPE_ANONYMOUS_P (t))
{
if (saw_typedef)
{
error ("missing type-name in typedef-declaration");
return NULL_TREE;
}
;
SET_ANON_AGGR_TYPE_P (t);
if (TREE_CODE (t) != UNION_TYPE && pedantic && ! in_system_header)
pedwarn ("ISO C++ prohibits anonymous structs");
}
else if (ob_modifier)
{
if (ob_modifier == ridpointers[(int) RID_INLINE]
|| ob_modifier == ridpointers[(int) RID_VIRTUAL])
error ("`%D' can only be specified for functions", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_FRIEND])
error ("`%D' can only be specified inside a class", ob_modifier);
else if (ob_modifier == ridpointers[(int) RID_EXPLICIT])
error ("`%D' can only be specified for constructors",
ob_modifier);
else
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_AGGR_TYPE_P (t))
{
fixup_anonymous_aggr (t);
if (TYPE_FIELDS (t))
{
tree decl = grokdeclarator (NULL_TREE, declspecs, NORMAL, 0,
NULL);
finish_anon_union (decl);
}
}
}
tree
groktypename (typename)
tree typename;
{
tree specs, attrs;
tree type;
if (TREE_CODE (typename) != TREE_LIST)
return typename;
split_specs_attrs (TREE_PURPOSE (typename), &specs, &attrs);
type = grokdeclarator (TREE_VALUE (typename), specs,
TYPENAME, 0, &attrs);
if (attrs)
cplus_decl_attributes (&type, attrs, 0);
return type;
}
tree
groktypename_in_parm_context (objcp_typename)
tree objcp_typename;
{
tree specs, objcp_attrs;
tree objcp_type;
if (TREE_CODE (objcp_typename) != TREE_LIST)
return objcp_typename;
split_specs_attrs (TREE_PURPOSE (objcp_typename), &specs, &objcp_attrs);
objcp_type = grokdeclarator (TREE_VALUE (objcp_typename), specs,
PARM, 0, &objcp_attrs);
if (objcp_attrs)
cplus_decl_attributes (&objcp_type, objcp_attrs, 0);
return objcp_type;
}
tree
start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
tree declarator, declspecs;
int initialized;
tree attributes, prefix_attributes;
{
tree decl;
register tree type, tem;
tree context;
tree a;
#if 0
int init_written = initialized;
#endif
if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"),
declspecs);
have_extern_spec = false;
}
#ifdef A_LESS_INEFFICENT_WAY
if (lookup_attribute ("deprecated", attributes))
deprecated_state = DEPRECATED_SUPPRESS;
else if (lookup_attribute ("unavailable", attributes))
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
#else
for (a = attributes; a; a = TREE_CHAIN (a))
{
tree name = TREE_PURPOSE (a);
if (TREE_CODE (name) == IDENTIFIER_NODE)
if (is_attribute_p ("deprecated", name))
{
deprecated_state = DEPRECATED_SUPPRESS;
break;
}
if (is_attribute_p ("unavailable", name))
{
deprecated_state = DEPRECATED_UNAVAILABLE_SUPPRESS;
break;
}
}
#endif
attributes = chainon (attributes, prefix_attributes);
decl = grokdeclarator (declarator, declspecs, NORMAL, initialized,
&attributes);
deprecated_state = DEPRECATED_NORMAL;
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_gen_index)
{
int info_tag = INDEX_ERROR;
switch (TREE_CODE (decl))
{
case FUNCTION_DECL:
info_tag = INDEX_FUNCTION_DECL;
break;
case CONST_DECL:
info_tag = INDEX_CONST_DECL;
break;
case VAR_DECL:
if (DECL_CLASS_SCOPE_P (decl))
info_tag = INDEX_DATA_DECL;
else
info_tag = INDEX_VAR_DECL;
break;
case TYPE_DECL:
info_tag = INDEX_TYPE_DECL;
break;
default:
break;
}
gen_indexing_info (info_tag,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
if (DECL_CLASS_SCOPE_P (decl))
{
if (TYPE_CHECK (DECL_CLASS_CONTEXT (decl)))
{
tree typename = TYPE_NAME (DECL_CLASS_CONTEXT (decl));
gen_indexing_info (INDEX_DATA_INHERITANCE,
IDENTIFIER_POINTER (DECL_NAME (typename)),
DECL_SOURCE_LINE (typename));
}
else if (DECL_CONTEXT (decl))
{
tree t = DECL_CONTEXT (decl);
gen_indexing_info (INDEX_DATA_INHERITANCE,
IDENTIFIER_POINTER (DECL_NAME (t)),
DECL_SOURCE_LINE (t));
}
}
}
context = 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:
error ("typedef `%D' is initialized (use __typeof__ instead)", decl);
initialized = 0;
break;
case FUNCTION_DECL:
error ("function `%#D' is initialized like a variable", decl);
initialized = 0;
break;
default:
break;
}
if (initialized)
{
if (! toplevel_bindings_p ()
&& DECL_EXTERNAL (decl))
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;
}
cplus_decl_attributes (&decl, attributes, 0);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (decl)
&& DECL_UNINLINABLE (decl)
&& lookup_attribute ("noinline", DECL_ATTRIBUTES (decl)))
warning_with_decl (decl,
"inline function `%s' given attribute noinline");
if (context && COMPLETE_TYPE_P (complete_type (context)))
{
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)
error ("`%#D' is not a static member of `%#T'", decl, context);
else
{
if (DECL_CONTEXT (field) != context)
{
pedwarn ("ISO 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))
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_TEMPLATE_INSTANTIATION (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))
pedwarn ("declaration of `%#D' outside of class is not definition",
decl);
}
tem = maybe_push_decl (decl);
if (processing_template_decl)
tem = push_template_decl (tem);
#if ! defined (ASM_OUTPUT_BSS) && ! defined (ASM_OUTPUT_ALIGNED_BSS)
DECL_COMMON (tem) = ((TREE_CODE (tem) != VAR_DECL
|| !DECL_THREAD_LOCAL (tem))
&& (flag_conserve_space || ! TREE_PUBLIC (tem)));
#endif
if (! processing_template_decl)
start_decl_1 (tem);
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;
maybe_push_cleanup_level (type);
if (initialized)
{
if (COMPLETE_TYPE_P (complete_type (type)))
;
else if (TREE_CODE (type) != ARRAY_TYPE)
{
error ("variable `%#D' has initializer but incomplete type",
decl);
initialized = 0;
type = TREE_TYPE (decl) = error_mark_node;
}
else if (!COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
error ("elements of array `%#D' have incomplete type", decl);
initialized = 0;
}
}
if (!initialized
&& TREE_CODE (decl) != TYPE_DECL
&& TREE_CODE (decl) != TEMPLATE_DECL
&& type != error_mark_node
&& IS_AGGR_TYPE (type)
&& ! DECL_EXTERNAL (decl))
{
if ((! processing_template_decl || ! uses_template_parms (type))
&& !COMPLETE_TYPE_P (complete_type (type)))
{
error ("aggregate `%#D' has incomplete type and cannot be defined",
decl);
type = TREE_TYPE (decl) = error_mark_node;
}
else
{
initialized = TYPE_NEEDS_CONSTRUCTING (type);
}
}
if (! initialized)
DECL_INITIAL (decl) = NULL_TREE;
}
static tree
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))
error ("`%D' declared as reference but not initialized", decl);
return NULL_TREE;
}
if (init == error_mark_node)
return NULL_TREE;
if (TREE_CODE (init) == CONSTRUCTOR)
{
error ("ISO C++ forbids use of initializer list to initialize reference `%D'", decl);
return NULL_TREE;
}
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 = initialize_reference (type, init, decl);
if (tmp == error_mark_node)
return NULL_TREE;
else if (tmp == NULL_TREE)
{
error ("cannot initialize `%T' from `%T'", type, TREE_TYPE (init));
return NULL_TREE;
}
if (TREE_STATIC (decl) && !TREE_CONSTANT (tmp))
return tmp;
DECL_INITIAL (decl) = tmp;
return NULL_TREE;
}
static void
maybe_deduce_size_from_array_init (decl, init)
tree decl;
tree init;
{
tree type = TREE_TYPE (decl);
if (TREE_CODE (type) == ARRAY_TYPE
&& TYPE_DOMAIN (type) == NULL_TREE
&& TREE_CODE (decl) != TYPE_DECL)
{
int do_default = !DECL_EXTERNAL (decl);
tree initializer = init ? init : DECL_INITIAL (decl);
int failure = complete_array_type (type, initializer, do_default);
if (failure == 1)
error ("initializer fails to determine size of `%D'", decl);
if (failure == 2)
{
if (do_default)
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))
error ("zero-size array `%D'", decl);
layout_decl (decl, 0);
}
}
static void
layout_var_decl (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
#if 0
tree ttype = target_type (type);
#endif
if (!DECL_EXTERNAL (decl))
complete_type (type);
if (!DECL_SIZE (decl)
&& TREE_TYPE (decl) != error_mark_node
&& (COMPLETE_TYPE_P (type)
|| (TREE_CODE (type) == ARRAY_TYPE
&& !TYPE_DOMAIN (type)
&& COMPLETE_TYPE_P (TREE_TYPE (type)))))
layout_decl (decl, 0);
if (!DECL_EXTERNAL (decl) && DECL_SIZE (decl) == NULL_TREE)
{
error ("storage size of `%D' isn't known", decl);
TREE_TYPE (decl) = error_mark_node;
}
#if 0
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));
#endif
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
error ("storage size of `%D' isn't constant", decl);
}
if (TREE_STATIC (decl)
&& !DECL_ARTIFICIAL (decl)
&& current_function_decl
&& DECL_CONTEXT (decl) == current_function_decl)
push_local_name (decl);
}
static void
maybe_commonize_var (decl)
tree decl;
{
if (TREE_STATIC (decl)
&& ! DECL_ARTIFICIAL (decl)
&& DECL_FUNCTION_SCOPE_P (decl)
&& (DECL_COMDAT (DECL_CONTEXT (decl))
|| ((DECL_DECLARED_INLINE_P (DECL_CONTEXT (decl))
|| DECL_TEMPLATE_INSTANTIATION (DECL_CONTEXT (decl)))
&& TREE_PUBLIC (DECL_CONTEXT (decl)))))
{
if (flag_weak)
{
comdat_linkage (decl);
}
else
{
#ifdef MAKE_DECL_COALESCED
if (DECL_INTERFACE_KNOWN (current_function_decl))
DECL_EXTERNAL (decl) = DECL_EXTERNAL (current_function_decl);
TREE_PUBLIC (decl) = 1;
MAKE_DECL_COALESCED (decl);
#else
if (DECL_INITIAL (decl) == NULL_TREE
|| DECL_INITIAL (decl) == error_mark_node)
{
TREE_PUBLIC (decl) = 1;
DECL_COMMON (decl) = 1;
}
else
{
TREE_PUBLIC (decl) = 0;
DECL_COMMON (decl) = 0;
cp_warning_at ("sorry: semantics of inline function static data `%#D' are wrong (you'll wind up with multiple copies)", decl);
warning ("%J you can work around this by removing the initializer",
decl);
}
#endif
}
}
else if (DECL_LANG_SPECIFIC (decl) && DECL_COMDAT (decl))
comdat_linkage (decl);
}
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))
error ("uninitialized const `%D'", decl);
}
static tree
next_initializable_field (tree field)
{
while (field
&& (TREE_CODE (field) != FIELD_DECL
|| (DECL_C_BIT_FIELD (field) && !DECL_NAME (field))
|| DECL_ARTIFICIAL (field)))
field = TREE_CHAIN (field);
return field;
}
static tree
reshape_init (tree type, tree *initp)
{
tree inits;
tree old_init;
tree old_init_value;
tree new_init;
bool brace_enclosed_p;
old_init = *initp;
old_init_value = (TREE_CODE (*initp) == TREE_LIST
? TREE_VALUE (*initp) : old_init);
if (!old_init_value)
{
my_friendly_assert (TREE_CODE (old_init) == TREE_LIST, 20021202);
TREE_VALUE (old_init) = error_mark_node;
return old_init;
}
if (TREE_CODE (old_init_value) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (old_init_value))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
inits = CONSTRUCTOR_ELTS (old_init_value);
initp = &inits;
brace_enclosed_p = true;
}
else
{
inits = NULL_TREE;
brace_enclosed_p = false;
}
if (!CP_AGGREGATE_TYPE_P (type))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
if (brace_enclosed_p)
{
error ("brace-enclosed initializer used to initialize `%T'",
type);
if (TREE_CODE (old_init) == TREE_LIST)
TREE_VALUE (old_init) = error_mark_node;
else
old_init = error_mark_node;
}
return old_init;
}
if (CLASS_TYPE_P (type)
&& !brace_enclosed_p
&& can_convert_arg (type, TREE_TYPE (old_init_value), old_init_value))
{
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
return old_init;
}
if (TREE_CODE (old_init_value) == STRING_CST
&& TREE_CODE (type) == ARRAY_TYPE
&& char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type))))
{
new_init = old_init;
*initp = TREE_CHAIN (old_init);
TREE_CHAIN (old_init) = NULL_TREE;
}
else
{
new_init = build (CONSTRUCTOR, type, NULL_TREE, NULL_TREE);
TREE_HAS_CONSTRUCTOR (new_init) = 1;
if (CLASS_TYPE_P (type))
{
tree field;
field = next_initializable_field (TYPE_FIELDS (type));
if (!field)
{
if (!brace_enclosed_p)
error ("initializer for `%T' must be brace-enclosed",
type);
}
else
{
while (*initp && field)
{
tree field_init;
field_init = reshape_init (TREE_TYPE (field), initp);
TREE_CHAIN (field_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = field_init;
if (TREE_CODE (type) == UNION_TYPE)
break;
field = next_initializable_field (TREE_CHAIN (field));
}
}
}
else if (TREE_CODE (type) == ARRAY_TYPE)
{
tree index;
tree max_index;
max_index = (TYPE_DOMAIN (type)
? array_type_nelts (type) : NULL_TREE);
for (index = size_zero_node;
*initp && (!max_index || !tree_int_cst_lt (max_index, index));
index = size_binop (PLUS_EXPR, index, size_one_node))
{
tree element_init;
element_init = reshape_init (TREE_TYPE (type), initp);
TREE_CHAIN (element_init) = CONSTRUCTOR_ELTS (new_init);
CONSTRUCTOR_ELTS (new_init) = element_init;
if (TREE_PURPOSE (element_init))
index = TREE_PURPOSE (element_init);
}
}
else
abort ();
CONSTRUCTOR_ELTS (new_init) = nreverse (CONSTRUCTOR_ELTS (new_init));
if (TREE_CODE (old_init) == TREE_LIST)
new_init = build_tree_list (TREE_PURPOSE (old_init), new_init);
}
if (brace_enclosed_p && *initp)
error ("too many initializers for `%T'", type);
return new_init;
}
static tree
check_initializer (tree decl, tree init, int flags)
{
tree type = TREE_TYPE (decl);
if (init != NULL_TREE && DECL_INITIAL (decl) == NULL_TREE)
init = NULL_TREE;
DECL_INITIAL (decl) = NULL_TREE;
TREE_TYPE (decl) = type = complete_type (TREE_TYPE (decl));
if (type == error_mark_node)
init = NULL_TREE;
else if (init && COMPLETE_TYPE_P (type)
&& !TREE_CONSTANT (TYPE_SIZE (type)))
{
error ("variable-sized object `%D' may not be initialized", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) == ARRAY_TYPE
&& !COMPLETE_TYPE_P (complete_type (TREE_TYPE (type))))
{
error ("elements of array `%#D' have incomplete type", decl);
init = NULL_TREE;
}
else if (TREE_CODE (type) != ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
error ("`%D' has incomplete type", decl);
TREE_TYPE (decl) = error_mark_node;
init = NULL_TREE;
}
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 (!DECL_EXTERNAL (decl) && TREE_CODE (type) == REFERENCE_TYPE)
init = grok_reference_init (decl, type, init);
else if (init)
{
if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
{
if (CP_AGGREGATE_TYPE_P (type))
init = reshape_init (type, &init);
}
maybe_deduce_size_from_array_init (decl, init);
type = TREE_TYPE (decl);
if (TREE_CODE (init) == CONSTRUCTOR && TREE_HAS_CONSTRUCTOR (init))
TREE_TYPE (init) = type;
if (TYPE_HAS_CONSTRUCTOR (type) || TYPE_NEEDS_CONSTRUCTING (type))
{
if (TREE_CODE (type) == ARRAY_TYPE)
goto initialize_aggr;
else if (TREE_CODE (init) == CONSTRUCTOR
&& TREE_HAS_CONSTRUCTOR (init))
{
if (TYPE_NON_AGGREGATE_CLASS (type))
{
error ("`%D' must be initialized by constructor, not by `{...}'",
decl);
init = error_mark_node;
}
else
goto dont_use_constructor;
}
else
{
int saved_stmts_are_full_exprs_p;
initialize_aggr:
saved_stmts_are_full_exprs_p = 0;
if (building_stmt_tree ())
{
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
}
init = build_aggr_init (decl, init, flags);
if (building_stmt_tree ())
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
return init;
}
}
else
{
dont_use_constructor:
if (TREE_CODE (init) != TREE_VEC)
init = store_init_value (decl, init);
}
}
else if (DECL_EXTERNAL (decl))
;
else if (TYPE_P (type) && TYPE_NEEDS_CONSTRUCTING (type))
goto initialize_aggr;
else if (IS_AGGR_TYPE (type))
{
tree core_type = strip_array_types (type);
if (CLASSTYPE_READONLY_FIELDS_NEED_INIT (core_type))
error ("structure `%D' with uninitialized const members", decl);
if (CLASSTYPE_REF_FIELDS_NEED_INIT (core_type))
error ("structure `%D' with uninitialized reference members",
decl);
check_for_uninitialized_const_var (decl);
}
else
check_for_uninitialized_const_var (decl);
if (init && init != error_mark_node)
init = build (INIT_EXPR, type, decl, init);
return init;
}
static void
make_rtl_for_nonlocal_decl (decl, init, asmspec)
tree decl;
tree init;
const char *asmspec;
{
int toplev = toplevel_bindings_p ();
int defer_p;
if (TREE_CODE (decl) != VAR_DECL)
{
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
return;
}
if (DECL_LANG_SPECIFIC (decl) && DECL_IN_AGGR_P (decl))
{
my_friendly_assert (TREE_STATIC (decl), 19990828);
if (init == NULL_TREE)
my_friendly_assert (DECL_EXTERNAL (decl), 20000723);
}
if (asmspec)
{
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
if (DECL_REGISTER (decl))
DECL_C_HARD_REGISTER (decl) = 1;
}
if (DECL_FUNCTION_SCOPE_P (decl) && !TREE_STATIC (decl))
return;
defer_p = DECL_FUNCTION_SCOPE_P (decl) || DECL_VIRTUAL_P (decl);
if (!DECL_VIRTUAL_P (decl)
&& TREE_READONLY (decl)
&& DECL_INITIAL (decl) != NULL_TREE
&& DECL_INITIAL (decl) != error_mark_node
&& ! EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl))
&& toplev
&& !TREE_PUBLIC (decl))
{
if (!interface_unknown && !TREE_PUBLIC (decl))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = interface_only;
}
defer_p = 1;
}
else if (DECL_COMDAT (decl))
defer_p = 1;
if (defer_p && asmspec)
make_decl_rtl (decl, asmspec);
else if (!defer_p && init != NULL_TREE && TREE_READONLY (decl) && toplev)
{
TREE_READONLY (decl) = 0;
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
TREE_READONLY (decl) = 1;
}
else if (!defer_p)
rest_of_decl_compilation (decl, asmspec, toplev, at_eof);
}
void
maybe_inject_for_scope_var (decl)
tree decl;
{
timevar_push (TV_NAME_LOOKUP);
if (!DECL_NAME (decl))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
if (DECL_PRETTY_FUNCTION_P (decl))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
if (current_binding_level->is_for_scope)
{
struct cp_binding_level *outer
= current_binding_level->level_chain;
cxx_binding *outer_binding
= IDENTIFIER_BINDING (DECL_NAME (decl))->previous;
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));
}
timevar_pop (TV_NAME_LOOKUP);
}
static void
initialize_local_var (decl, init)
tree decl;
tree init;
{
tree type = TREE_TYPE (decl);
my_friendly_assert (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == RESULT_DECL,
20021010);
my_friendly_assert (!TREE_STATIC (decl), 20021010);
if (DECL_SIZE (decl) == NULL_TREE)
{
DECL_INITIAL (decl) = NULL_TREE;
TREE_ADDRESSABLE (decl) = TREE_USED (decl);
}
if (DECL_SIZE (decl) && type != error_mark_node)
{
int already_used;
already_used = TREE_USED (decl) || TREE_USED (type);
if (init)
{
int saved_stmts_are_full_exprs_p;
my_friendly_assert (building_stmt_tree (), 20000906);
saved_stmts_are_full_exprs_p = stmts_are_full_exprs_p ();
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
finish_expr_stmt (init);
current_stmt_tree ()->stmts_are_full_exprs_p =
saved_stmts_are_full_exprs_p;
}
if (TYPE_NEEDS_CONSTRUCTING (type)
&& ! already_used
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (type)
&& DECL_NAME (decl))
TREE_USED (decl) = 0;
else if (already_used)
TREE_USED (decl) = 1;
}
if (TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
tree cleanup;
cleanup = cxx_maybe_build_cleanup (decl);
if (DECL_SIZE (decl) && cleanup)
finish_decl_cleanup (decl, cleanup);
}
}
void
cp_finish_decl (decl, init, asmspec_tree, flags)
tree decl, init;
tree asmspec_tree;
int flags;
{
register tree type;
tree ttype = NULL_TREE;
const char *asmspec = NULL;
int was_readonly = 0;
if (! decl)
{
if (init)
error ("assignment (not initialization) in declaration");
return;
}
if (current_binding_level == global_binding_level)
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init && TREE_CODE (init) == NAMESPACE_DECL)
{
error ("cannot initialize `%D' to namespace `%D'",
decl, init);
init = NULL_TREE;
}
if (current_class_type
&& CP_DECL_CONTEXT (decl) == current_class_type
&& TYPE_BEING_DEFINED (current_class_type)
&& (DECL_INITIAL (decl) || init))
DECL_INITIALIZED_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)
return;
if (TYPE_HAS_MUTABLE_P (type))
TREE_READONLY (decl) = 0;
if (processing_template_decl)
{
if (at_function_scope_p ()
&& TREE_CODE (decl) != RESULT_DECL)
add_decl_stmt (decl);
if (init && DECL_INITIAL (decl))
DECL_INITIAL (decl) = init;
goto finish_end0;
}
my_friendly_assert (TREE_CODE (decl) != PARM_DECL, 19990828);
if (TREE_CODE (decl) == TYPE_DECL)
{
if (type != error_mark_node
&& IS_AGGR_TYPE (type) && DECL_NAME (decl))
{
if (TREE_TYPE (DECL_NAME (decl)) && TREE_TYPE (decl) != type)
warning ("shadowing previous type declaration of `%#D'", decl);
set_identifier_type_value (DECL_NAME (decl), type);
CLASSTYPE_GOT_SEMICOLON (type) = 1;
}
if (TYPE_MAIN_DECL (TREE_TYPE (decl)) == decl
&& !COMPLETE_TYPE_P (TREE_TYPE (decl)))
TYPE_DECL_SUPPRESS_DEBUG (decl) = 1;
rest_of_decl_compilation (decl, NULL,
DECL_CONTEXT (decl) == NULL_TREE, at_eof);
goto finish_end;
}
if (flag_objc && (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == FIELD_DECL))
objc_check_decl (decl);
if (TREE_CODE (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 && asmspec)
{
SET_DECL_RTL (TREE_TYPE (decl), NULL_RTX);
SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
make_decl_rtl (decl, asmspec);
}
else if (TREE_CODE (decl) == RESULT_DECL)
init = check_initializer (decl, init, flags);
else if (TREE_CODE (decl) == VAR_DECL)
{
if (DECL_THREAD_LOCAL (decl) && !pod_type_p (TREE_TYPE (decl)))
error ("`%D' cannot be thread-local because it has non-POD type `%T'",
decl, TREE_TYPE (decl));
if (!DECL_INITIALIZED_P (decl)
&& (!DECL_EXTERNAL (decl) || init))
{
init = check_initializer (decl, init, flags);
if (DECL_THREAD_LOCAL (decl) && init)
{
error ("`%D' is thread-local and so cannot be dynamically "
"initialized", decl);
init = NULL_TREE;
}
if (TREE_STATIC (decl) && !DECL_INITIAL (decl))
DECL_INITIAL (decl) = build_zero_init (TREE_TYPE (decl),
NULL_TREE,
true);
DECL_INITIALIZED_P (decl) = 1;
}
else if (TREE_CODE (type) == ARRAY_TYPE)
layout_type (type);
}
if (building_stmt_tree ()
&& at_function_scope_p ()
&& TREE_CODE (decl) != RESULT_DECL)
add_decl_stmt (decl);
if (TREE_CODE (decl) == VAR_DECL)
layout_var_decl (decl);
if (TREE_CODE (decl) == VAR_DECL || TREE_CODE (decl) == FUNCTION_DECL
|| TREE_CODE (decl) == RESULT_DECL)
{
if (TREE_CODE (decl) == VAR_DECL)
maybe_commonize_var (decl);
make_rtl_for_nonlocal_decl (decl, init, asmspec);
if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
abstract_virtuals_error (decl,
strip_array_types (TREE_TYPE (type)));
else
abstract_virtuals_error (decl, strip_array_types (type));
if (TREE_CODE (decl) == FUNCTION_DECL
|| TREE_TYPE (decl) == error_mark_node)
;
else if (DECL_EXTERNAL (decl)
&& ! (DECL_LANG_SPECIFIC (decl)
&& DECL_NOT_REALLY_EXTERN (decl)))
{
if (init)
DECL_INITIAL (decl) = init;
}
else
{
if (DECL_FUNCTION_SCOPE_P (decl))
{
if (doing_semantic_analysis_p ())
maybe_inject_for_scope_var (decl);
if (processing_template_decl)
{
if (init || DECL_INITIAL (decl) == error_mark_node)
DECL_INITIAL (decl) = init;
}
else if (!TREE_STATIC (decl))
initialize_local_var (decl, init);
}
if (TREE_STATIC (decl))
expand_static_init (decl, init);
}
finish_end0:
{
tree context = CP_DECL_CONTEXT (decl);
if (context
&& TYPE_P (context)
&& (TREE_CODE (decl) == VAR_DECL
|| TREE_CODE (decl) == FUNCTION_DECL)
&& COMPLETE_TYPE_P (context)
&& context == current_class_type)
pop_nested_class ();
}
}
finish_end:
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, 0);
}
tree
declare_global_var (name, type)
tree name;
tree type;
{
tree decl;
push_to_top_level ();
decl = build_decl (VAR_DECL, name, type);
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_ARTIFICIAL (decl) = 1;
pushdecl (decl);
cp_finish_decl (decl, NULL_TREE, NULL_TREE, 0);
pop_from_top_level ();
return decl;
}
static tree
get_atexit_node ()
{
tree atexit_fndecl;
tree arg_types;
tree fn_type;
tree fn_ptr_type;
const char *name;
if (atexit_node)
return atexit_node;
if (flag_use_cxa_atexit)
{
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
fn_type = build_function_type (void_type_node, arg_types);
fn_ptr_type = build_pointer_type (fn_type);
arg_types = tree_cons (NULL_TREE, ptr_type_node, void_list_node);
arg_types = tree_cons (NULL_TREE, ptr_type_node, arg_types);
arg_types = tree_cons (NULL_TREE, fn_ptr_type, arg_types);
fn_type = build_function_type (integer_type_node, arg_types);
fn_ptr_type = build_pointer_type (fn_type);
name = "__cxa_atexit";
}
else
{
fn_type = build_function_type (void_type_node, void_list_node);
fn_ptr_type = build_pointer_type (fn_type);
arg_types = tree_cons (NULL_TREE, fn_ptr_type, void_list_node);
fn_type = build_function_type (integer_type_node, arg_types);
name = "atexit";
}
push_lang_context (lang_name_c);
atexit_fndecl = build_library_fn_ptr (name, fn_type);
mark_used (atexit_fndecl);
pop_lang_context ();
atexit_node = default_conversion (atexit_fndecl);
return atexit_node;
}
static tree
get_dso_handle_node ()
{
if (dso_handle_node)
return dso_handle_node;
dso_handle_node = declare_global_var (get_identifier ("__dso_handle"),
ptr_type_node);
return dso_handle_node;
}
static tree
start_cleanup_fn ()
{
static int counter = 0;
int old_interface_only = interface_only;
int old_interface_unknown = interface_unknown;
char name[32];
tree parmtypes;
tree fntype;
tree fndecl;
push_to_top_level ();
push_lang_context (lang_name_c);
interface_only = 0;
interface_unknown = 1;
parmtypes = void_list_node;
if (flag_use_cxa_atexit)
parmtypes = tree_cons (NULL_TREE, ptr_type_node, parmtypes);
fntype = build_function_type (void_type_node, parmtypes);
sprintf (name, "__tcf_%d", counter++);
fndecl = build_lang_decl (FUNCTION_DECL, get_identifier (name), fntype);
TREE_PUBLIC (fndecl) = 0;
DECL_ARTIFICIAL (fndecl) = 1;
DECL_INLINE (fndecl) = 1;
if (flag_use_cxa_atexit)
{
tree parmdecl;
parmdecl = cp_build_parm_decl (NULL_TREE, ptr_type_node);
DECL_CONTEXT (parmdecl) = fndecl;
TREE_USED (parmdecl) = 1;
DECL_ARGUMENTS (fndecl) = parmdecl;
}
pushdecl (fndecl);
start_function (NULL_TREE, fndecl, NULL_TREE, SF_PRE_PARSED);
interface_unknown = old_interface_unknown;
interface_only = old_interface_only;
pop_lang_context ();
return current_function_decl;
}
static void
end_cleanup_fn ()
{
expand_body (finish_function (0));
pop_from_top_level ();
}
void
register_dtor_fn (decl)
tree decl;
{
tree cleanup;
tree compound_stmt;
tree args;
tree fcall;
int saved_flag_access_control;
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
build_cleanup (decl);
cleanup = start_cleanup_fn ();
saved_flag_access_control = flag_access_control;
flag_access_control = 0;
fcall = build_cleanup (decl);
flag_access_control = saved_flag_access_control;
compound_stmt = begin_compound_stmt (0);
finish_expr_stmt (fcall);
finish_compound_stmt (0, compound_stmt);
end_cleanup_fn ();
cxx_mark_addressable (cleanup);
cleanup = build_unary_op (ADDR_EXPR, cleanup, 0);
if (flag_use_cxa_atexit)
{
args = tree_cons (NULL_TREE,
build_unary_op (ADDR_EXPR, get_dso_handle_node (), 0),
NULL_TREE);
args = tree_cons (NULL_TREE, null_pointer_node, args);
args = tree_cons (NULL_TREE, cleanup, args);
}
else
args = tree_cons (NULL_TREE, cleanup, NULL_TREE);
finish_expr_stmt (build_function_call (get_atexit_node (), args));
}
static void
expand_static_init (decl, init)
tree decl;
tree init;
{
tree oldstatic;
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 20021010);
my_friendly_assert (TREE_STATIC (decl), 20021010);
if (!init
&& !TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl))
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
oldstatic = value_member (decl, static_aggregates);
if (oldstatic)
{
if (TREE_PURPOSE (oldstatic) && init != NULL_TREE)
error ("multiple initializations given for `%D'", decl);
}
else if (! toplevel_bindings_p ())
{
tree if_stmt;
tree then_clause;
tree assignment;
tree guard;
tree guard_init;
guard = get_guard (decl);
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (get_guard_cond (guard), if_stmt);
then_clause = begin_compound_stmt (0);
assignment = init ? init : NULL_TREE;
guard_init = set_guard (guard);
if (assignment)
{
assignment = tree_cons (NULL_TREE, assignment,
build_tree_list (NULL_TREE,
guard_init));
assignment = build_compound_expr (assignment);
}
else
assignment = guard_init;
finish_expr_stmt (assignment);
register_dtor_fn (decl);
finish_compound_stmt (0, then_clause);
finish_then_clause (if_stmt);
finish_if_stmt ();
}
else
static_aggregates = tree_cons (init, decl, static_aggregates);
}
tree
start_handler_parms (declspecs, declarator)
tree declspecs;
tree declarator;
{
tree decl;
if (declspecs)
{
decl = grokdeclarator (declarator, declspecs, CATCHPARM,
1, NULL);
if (decl == NULL_TREE)
error ("invalid catch parameter");
}
else
decl = NULL_TREE;
return decl;
}
int
complete_array_type (type, initial_value, do_default)
tree type, initial_value;
int do_default;
{
register tree maxindex = NULL_TREE;
int value = 0;
if (initial_value)
{
if (char_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (type)))
&& TREE_CODE (initial_value) == CONSTRUCTOR
&& CONSTRUCTOR_ELTS (initial_value)
&& (TREE_CODE (TREE_VALUE (CONSTRUCTOR_ELTS (initial_value)))
== STRING_CST)
&& TREE_CHAIN (CONSTRUCTOR_ELTS (initial_value)) == NULL_TREE)
initial_value = TREE_VALUE (CONSTRUCTOR_ELTS (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 = ssize_int (-1);
for (; elts; elts = TREE_CHAIN (elts))
{
if (TREE_PURPOSE (elts))
maxindex = TREE_PURPOSE (elts);
else
maxindex = size_binop (PLUS_EXPR, maxindex, ssize_int (1));
}
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;
}
layout_type (type);
return value;
}
static int
member_function_or_else (ctype, cur_type, flags)
tree ctype, cur_type;
enum overload_flags flags;
{
if (ctype && ctype != cur_type)
{
if (flags == DTOR_FLAG)
error ("destructor for alien class `%T' cannot be a member",
ctype);
else
error ("constructor for alien class `%T' cannot be a member",
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)
error ("`%D' declared as a `virtual' %s", object, type);
if (inlinep)
error ("`%D' declared as an `inline' %s", object, type);
if (quals)
error ("`const' and `volatile' function specifiers on `%D' invalid in %s declaration",
object, type);
if (friendp)
cp_error_at ("`%D' declared as a friend", object);
if (raises
&& (TREE_CODE (object) == TYPE_DECL
|| (!TYPE_PTRFN_P (TREE_TYPE (object))
&& !TYPE_REFFN_P (TREE_TYPE (object))
&& !TYPE_PTRMEMFUNC_P (TREE_TYPE (object)))))
cp_error_at ("`%D' declared with an exception specification", 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 decl;
int staticp = ctype && TREE_CODE (type) == FUNCTION_TYPE;
int has_default_arg = 0;
tree t;
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 (!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)
SET_DECL_LANGUAGE (decl, lang_c);
if (staticp)
{
DECL_STATIC_FUNCTION_P (decl) = 1;
DECL_CONTEXT (decl) = ctype;
}
if (ctype)
DECL_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");
if (!publicp)
error ("cannot declare `::main' to be static");
if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
integer_type_node))
error ("`main' must return `int'");
inlinep = 0;
publicp = 1;
}
if (ctype && (TYPE_ANONYMOUS_P (ctype)
|| decl_function_context (TYPE_MAIN_DECL (ctype))))
publicp = 0;
if (publicp)
{
t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (TYPE_ANONYMOUS_P (t))
{
if (DECL_EXTERN_C_P (decl))
;
else
{
pedwarn ("non-local function `%#D' uses anonymous type",
decl);
if (DECL_ORIGINAL_TYPE (TYPE_NAME (t)))
cp_pedwarn_at ("\
`%#D' does not refer to the unqualified type, so it is not used for linkage",
TYPE_NAME (t));
}
}
else
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_DECLARED_INLINE_P (decl) = 1;
if (DECL_DECLARED_INLINE_P (decl))
DECL_INLINE (decl) = 1;
if (flag_inline_trees == 2 && !DECL_INLINE (decl))
{
DID_INLINE_FUNC (decl) = 1;
DECL_INLINE (decl) = 1;
}
DECL_EXTERNAL (decl) = 1;
if (quals != NULL_TREE && TREE_CODE (type) == FUNCTION_TYPE)
{
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, friendp);
if (ctype && 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)
error
("defining explicit specialization `%D' in friend declaration",
orig_declarator);
else
{
tree fns = TREE_OPERAND (orig_declarator, 0);
tree args = TREE_OPERAND (orig_declarator, 1);
if (PROCESSING_REAL_TEMPLATE_DECL_P ())
{
error ("invalid use of template-id `%D' in declaration of primary template",
orig_declarator);
return NULL_TREE;
}
SET_DECL_IMPLICIT_INSTANTIATION (decl);
if (TREE_CODE (fns) == COMPONENT_REF)
{
my_friendly_assert (TREE_TYPE (TREE_OPERAND (fns, 0))
== current_class_type, 20001120);
fns = TREE_OPERAND (fns, 1);
}
my_friendly_assert (TREE_CODE (fns) == IDENTIFIER_NODE
|| TREE_CODE (fns) == LOOKUP_EXPR
|| TREE_CODE (fns) == OVERLOAD, 20001120);
DECL_TEMPLATE_INFO (decl) = tree_cons (fns, args, NULL_TREE);
if (has_default_arg)
{
error ("default arguments are not allowed in declaration of friend template specialization `%D'",
decl);
return NULL_TREE;
}
if (inlinep)
{
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 (funcdef_flag)
DECL_INITIAL (decl) = error_mark_node;
if (TYPE_NOTHROW_P (type) || nothrow_libfn_p (decl))
TREE_NOTHROW (decl) = 1;
if (check < 0)
return decl;
if (flags == NO_SPECIAL && ctype && constructor_name (ctype) == declarator)
DECL_CONSTRUCTOR_P (decl) = 1;
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)
{
tree old_decl;
old_decl = check_classfn (ctype, decl);
if (old_decl && TREE_CODE (old_decl) == TEMPLATE_DECL)
old_decl = DECL_TEMPLATE_RESULT (old_decl);
if (old_decl && DECL_STATIC_FUNCTION_P (old_decl)
&& TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE)
{
revert_static_member_fn (decl);
last_function_parms = TREE_CHAIN (last_function_parms);
}
if (old_decl && DECL_ARTIFICIAL (old_decl))
error ("definition of implicitly-declared `%D'", old_decl);
if (old_decl)
{
if (TREE_CODE (decl) == TEMPLATE_DECL)
decl = DECL_TEMPLATE_RESULT (decl);
if (!duplicate_decls (decl, old_decl))
error ("no `%#D' member function declared in class `%T'",
decl, ctype);
return old_decl;
}
}
if (DECL_CONSTRUCTOR_P (decl) && !grok_ctor_properties (ctype, decl))
return NULL_TREE;
if (ctype == NULL_TREE || check)
return decl;
if (virtualp)
DECL_VIRTUAL_P (decl) = 1;
return decl;
}
static tree
grokvardecl (type, name, specbits_in, initialized, constp, scope)
tree type;
tree name;
RID_BIT_TYPE *specbits_in;
int initialized;
int constp;
tree scope;
{
tree decl;
RID_BIT_TYPE specbits;
my_friendly_assert (!name || TREE_CODE (name) == IDENTIFIER_NODE,
20020808);
specbits = *specbits_in;
if (!scope)
{
if (RIDBIT_SETP (RID_EXTERN, specbits))
scope = current_namespace;
else if (!at_function_scope_p ())
{
scope = current_scope ();
if (!scope)
scope = current_namespace;
}
}
if (scope
&& (
(TREE_CODE (scope) == NAMESPACE_DECL && processing_template_decl)
|| (TREE_CODE (scope) == NAMESPACE_DECL
&& current_lang_name != lang_name_cplusplus)
|| TYPE_P (scope)))
decl = build_lang_decl (VAR_DECL, name, type);
else
decl = build_decl (VAR_DECL, name, type);
if (scope && TREE_CODE (scope) == NAMESPACE_DECL)
set_decl_namespace (decl, scope, 0);
else
DECL_CONTEXT (decl) = scope;
if (name && scope && current_lang_name != lang_name_c)
mangle_decl (decl);
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 (RIDBIT_SETP (RID_THREAD, specbits))
{
if (targetm.have_tls)
DECL_THREAD_LOCAL (decl) = 1;
else
error ("thread-local storage not supported for this target");
}
if (TREE_PUBLIC (decl))
{
tree t = no_linkage_check (TREE_TYPE (decl));
if (t)
{
if (TYPE_ANONYMOUS_P (t))
;
else
pedwarn ("non-local variable `%#D' uses local type `%T'",
decl, t);
}
}
return decl;
}
tree
build_ptrmemfunc_type (type)
tree type;
{
tree fields[4];
tree t;
tree unqualified_variant = NULL_TREE;
if (type == error_mark_node)
return type;
if ((t = TYPE_GET_PTRMEMFUNC_TYPE (type)))
return t;
if (cp_type_quals (type) != TYPE_UNQUALIFIED)
unqualified_variant
= build_ptrmemfunc_type (TYPE_MAIN_VARIANT (type));
if (flag_apple_kext)
{
tree u = make_aggr_type (UNION_TYPE);
SET_IS_AGGR_TYPE (u, 0);
fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_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_aggr_type (RECORD_TYPE);
TYPE_PTRMEMFUNC_FLAG (t) = 1;
SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_decl (FIELD_DECL, delta_identifier, delta_type_node);
fields[1] = build_decl (FIELD_DECL, index_identifier, delta_type_node);
fields[2] = build_decl (FIELD_DECL, pfn_or_delta2_identifier, u);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 2, ptr_type_node);
}
else
{
t = make_aggr_type (RECORD_TYPE);
TYPE_PTRMEMFUNC_FLAG (t) = 1;
SET_IS_AGGR_TYPE (t, 0);
fields[0] = build_decl (FIELD_DECL, pfn_identifier, type);
fields[1] = build_decl (FIELD_DECL, delta_identifier,
delta_type_node);
finish_builtin_type (t, "__ptrmemfunc_type", fields, 1, ptr_type_node);
}
TYPE_NAME (t) = NULL_TREE;
if (cp_type_quals (type) != TYPE_UNQUALIFIED)
{
t = build_qualified_type (t, cp_type_quals (type));
TYPE_MAIN_VARIANT (t) = unqualified_variant;
TYPE_NEXT_VARIANT (t) = TYPE_NEXT_VARIANT (unqualified_variant);
TYPE_NEXT_VARIANT (unqualified_variant) = t;
}
TYPE_SET_PTRMEMFUNC_TYPE (type, t);
CLASSTYPE_GOT_SEMICOLON (t) = 1;
return t;
}
tree
build_ptrmem_type (tree class_type, tree member_type)
{
return build_pointer_type (build_offset_type (class_type, member_type));
}
int
check_static_variable_definition (decl, type)
tree decl;
tree type;
{
if (!ARITHMETIC_TYPE_P (type) && TREE_CODE (type) != ENUMERAL_TYPE)
{
error ("invalid in-class initialization of static data member of non-integral type `%T'",
type);
return 1;
}
else if (!CP_TYPE_CONST_P (type))
error ("ISO C++ forbids in-class initialization of non-const static member `%D'",
decl);
else if (pedantic && !INTEGRAL_TYPE_P (type))
pedwarn ("ISO C++ forbids initialization of member constant `%D' of non-integral type `%T'", decl, type);
return 0;
}
tree
compute_array_index_type (name, size)
tree name;
tree size;
{
tree itype;
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;
}
return build_index_type (build_min (MINUS_EXPR, sizetype,
size, integer_one_node));
}
STRIP_TYPE_NOPS (size);
size = decl_constant_value (size);
if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE
&& TREE_CODE (TREE_TYPE (size)) != BOOLEAN_TYPE)
{
if (name)
error ("size of array `%D' has non-integer type", name);
else
error ("size of array has non-integer type");
size = integer_one_node;
}
if (TREE_CODE (size) == INTEGER_CST)
{
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))
{
if (name)
error ("size of array `%D' is negative", name);
else
error ("size of array is negative");
size = integer_one_node;
}
else if (integer_zerop (size) && pedantic && !in_system_header)
{
if (name)
pedwarn ("ISO C++ forbids zero-size array `%D'", name);
else
pedwarn ("ISO C++ forbids zero-size array");
}
}
else if (TREE_CONSTANT (size))
{
if (name)
error ("size of array `%D' is not an integral constant-expression",
name);
else
error ("size of array is not an integral constant-expression");
}
itype
= fold (cp_build_binary_op (MINUS_EXPR,
cp_convert (ssizetype, size),
cp_convert (ssizetype,
integer_one_node)));
if (!TREE_CONSTANT (itype))
{
if (pedantic)
{
if (name)
pedwarn ("ISO C++ forbids variable-size array `%D'",
name);
else
pedwarn ("ISO C++ forbids variable-size array");
}
itype = variable_size (itype);
}
else if (TREE_OVERFLOW (itype))
{
error ("overflow in array dimension");
TREE_OVERFLOW (itype) = 0;
}
return build_index_type (itype);
}
static tree
create_array_type_for_decl (name, type, size)
tree name;
tree type;
tree size;
{
tree itype = NULL_TREE;
const char* error_msg;
if (type == error_mark_node || size == error_mark_node)
return error_mark_node;
error_msg = NULL;
switch (TREE_CODE (type))
{
case VOID_TYPE:
error_msg = "array of void";
break;
case FUNCTION_TYPE:
error_msg = "array of functions";
break;
case REFERENCE_TYPE:
error_msg = "array of references";
break;
case OFFSET_TYPE:
error_msg = "array of data members";
break;
case METHOD_TYPE:
error_msg = "array of function members";
break;
default:
break;
}
if (error_msg)
{
if (name)
error ("declaration of `%D' as %s", name, error_msg);
else
error ("creating %s", error_msg);
return error_mark_node;
}
if (TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type))
{
if (name)
error ("declaration of `%D' as multidimensional array must have bounds for all dimensions except the first",
name);
else
error ("multidimensional array must have bounds for all dimensions except the first");
return error_mark_node;
}
if (size)
itype = compute_array_index_type (name, size);
return build_cplus_array_type (type, itype);
}
static tree
check_special_function_return_type (sfk, type, optype)
special_function_kind sfk;
tree type;
tree optype;
{
switch (sfk)
{
case sfk_constructor:
if (type)
error ("return type specification for constructor invalid");
type = void_type_node;
break;
case sfk_destructor:
if (type)
error ("return type specification for destructor invalid");
type = void_type_node;
break;
case sfk_conversion:
if (type && !same_type_p (type, optype))
error ("operator `%T' declared to return `%T'", optype, type);
else if (type)
pedwarn ("return type specified for `operator %T'", optype);
type = optype;
break;
default:
abort ();
break;
}
return type;
}
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 cw_asm_specbit = 0;
int nclasses = 0;
tree spec;
tree type = NULL_TREE;
int longlong = 0;
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 extern_langp = 0;
tree dependant_name = NULL_TREE;
tree typedef_decl = NULL_TREE;
const 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_attr = NULL_TREE;
#endif
tree init = NULL_TREE;
special_function_kind sfk = sfk_none;
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 returned_attrs = NULL_TREE;
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:
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;
sfk = sfk_destructor;
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)
{
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 (CALL_DECLARATOR_PARMS (decl)))
{
tree attributes;
if (decl_context != NORMAL)
{
error ("variable declaration is not allowed here");
return error_mark_node;
}
*next = TREE_OPERAND (decl, 0);
init = CALL_DECLARATOR_PARMS (decl);
if (attrlist)
{
attributes = *attrlist;
}
else
{
attributes = NULL_TREE;
}
decl = start_decl (declarator, declspecs, 1,
attributes, NULL_TREE);
decl_type_access_control (decl);
if (decl)
{
if (TREE_USED (TREE_TYPE (decl)))
TREE_USED (decl) = 1;
finish_decl (decl, init, NULL_TREE);
}
else
error ("invalid declarator");
return NULL_TREE;
}
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
&& constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 0)),
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))
{
sfk = sfk_constructor;
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 (C_IS_RESERVED_WORD (dname))
{
if (!ALTIVEC_IS_CONTEXT_KEYWORD (C_RID_CODE (dname)))
if (!flag_objc)
error ("declarator-id missing; using reserved word `%D'",
dname);
name = IDENTIFIER_POINTER (dname);
}
else if (!IDENTIFIER_TYPENAME_P (dname))
name = IDENTIFIER_POINTER (dname);
else
{
my_friendly_assert (flags == NO_SPECIAL, 154);
flags = TYPENAME_FLAG;
ctor_return_type = TREE_TYPE (dname);
sfk = sfk_conversion;
if (IDENTIFIER_GLOBAL_VALUE (dname)
&& (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (dname))
== TYPE_DECL))
name = IDENTIFIER_POINTER (dname);
else
name = "<invalid operator>";
}
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) == BOUND_TEMPLATE_TEMPLATE_PARM)
{
ctype = cname;
dependant_name = TREE_OPERAND (decl, 1);
}
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))
{
error ("type `%T' is not derived from type `%T'",
cname, ctype);
TREE_OPERAND (decl, 0) = NULL_TREE;
}
else
ctype = cname;
}
if (TREE_CODE (TREE_OPERAND (decl, 1)) == NAMESPACE_DECL)
TREE_OPERAND (decl, 1) = DECL_NAME (TREE_OPERAND (decl, 1));
if (ctype && TREE_CODE (TREE_OPERAND (decl, 1)) == TYPE_DECL
&& constructor_name_p (DECL_NAME (TREE_OPERAND (decl, 1)),
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)
{
sfk = sfk_constructor;
ctor_return_type = ctype;
}
else if (TREE_CODE (decl) == BIT_NOT_EXPR
&& TREE_CODE (TREE_OPERAND (decl, 0)) == IDENTIFIER_NODE
&& constructor_name_p (TREE_OPERAND (decl, 0),
ctype))
{
sfk = sfk_destructor;
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:
error ("`%T' specified as declarator-id", DECL_NAME (decl));
if (TREE_TYPE (decl) == current_class_type)
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 = tree_cons (NULL_TREE, integer_type_node, declspecs);
*next = dname;
next = 0;
break;
case BASELINK:
next = &BASELINK_FUNCTIONS (decl);
break;
case TEMPLATE_DECL:
error ("invalid use of template-name '%E' in a declarator", decl);
return error_mark_node;
break;
default:
my_friendly_assert (0, 20020917);
}
}
}
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))
{
error ("declaration of `%D' as non-function", dname);
return void_type_node;
}
if (decl_context == NORMAL && !toplevel_bindings_p ())
{
struct cp_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;
}
if (name == NULL)
name = decl_context == PARM ? "parameter" : "type name";
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 (!adding_implicit_members && id && TREE_DEPRECATED (id))
{
if (TREE_UNAVAILABLE (id))
{
if (deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("unavailable"),
NULL_TREE));
#endif
}
else
{
if (deprecated_state != DEPRECATED_SUPPRESS
&& deprecated_state != DEPRECATED_UNAVAILABLE_SUPPRESS)
warn_deprecated_use (id);
#if 0
returned_attrs
= chainon (returned_attrs,
build_tree_list (get_identifier ("deprecated"),
NULL_TREE));
#endif
}
}
if (TREE_CODE (id) == IDENTIFIER_NODE)
{
if (id != ridpointers[(int) RID_BOOL]
&& ALTIVEC_IS_CONTEXT_KEYWORD (C_RID_CODE (id)))
{
RIDBIT_SET ((int) C_RID_CODE (id), specbits);
goto found;
}
if (id == ridpointers[(int) RID_ASM])
{
++cw_asm_specbit;
goto found;
}
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_ALTIVEC_VECTOR, specbits))
{
if (id == ridpointers[(int) RID_BOOL])
error ("`bool' is now a keyword");
else
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_ALTIVEC_VECTOR, specbits)
|| id != ridpointers[(int) RID_BOOL])
type = TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (id));
}
goto found;
}
if (IDENTIFIER_HAS_TYPE_VALUE (id))
{
if (type)
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 ("ISO 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));
if (i == (int)RID_THREAD)
{
if (RIDBIT_SETP (RID_EXTERN, specbits))
error ("`__thread' before `extern'");
if (RIDBIT_SETP (RID_STATIC, specbits))
error ("`__thread' before `static'");
}
if (i == (int)RID_EXTERN
&& TREE_PURPOSE (spec) == error_mark_node)
extern_langp = 1;
RIDBIT_SET (i, specbits);
goto found;
}
}
}
else if (TREE_CODE (id) == TYPE_DECL)
{
if (type)
error ("multiple declarations `%T' and `%T'", type,
TREE_TYPE (id));
else
{
type = TREE_TYPE (id);
TREE_VALUE (spec) = type;
typedef_decl = id;
}
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);
typedef_decl = t;
}
}
else if (id != error_mark_node)
type = id;
found: ;
}
if (type == NULL_TREE
&& RIDBIT_SETP (RID_ALTIVEC_VECTOR, specbits)
&& (RIDBIT_SETP (RID_ALTIVEC_PIXEL, specbits) || explicit_bool))
type = integer_type_node;
#if 0
if (typedef_decl)
decl_attr = DECL_ATTRIBUTES (typedef_decl);
#endif
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 (sfk != sfk_none)
type = check_special_function_return_type (sfk, type,
ctor_return_type);
else if (type == NULL_TREE)
{
int is_main;
explicit_int = -1;
is_main = (funcdef_flag
&& dname && MAIN_NAME_P (dname)
&& ctype == NULL_TREE
&& in_namespace == NULL_TREE
&& current_namespace == global_namespace);
if (in_system_header || flag_ms_extensions)
;
else if (pedantic || ! is_main)
pedwarn ("ISO C++ forbids declaration of `%s' with no type",
name);
else if (warn_return_type)
warning ("ISO C++ forbids declaration of `%s' with no type",
name);
type = integer_type_node;
}
if (type && IMPLICIT_TYPENAME_P (type))
{
warning ("`%T' is implicitly a typename", type);
cp_deprecated ("implicit typename");
type = copy_node (type);
TREE_TYPE (type) = NULL_TREE;
}
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));
warn_about_long_double ();
}
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 (TREE_CODE (type) != INTEGER_TYPE)
error ("long, 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_ALTIVEC_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
&& RIDBIT_NOTSETP (RID_SIGNED, specbits)
&& !(typedef_decl
&& C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl))
&& (TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == CHAR_TYPE)
&& !same_type_p (TYPE_MAIN_VARIANT (type), wchar_type_node)))
{
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 = c_common_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);
}
type_quals = TYPE_UNQUALIFIED;
if (RIDBIT_SETP (RID_CONST, specbits))
type_quals |= TYPE_QUAL_CONST;
if (RIDBIT_SETP (RID_VOLATILE, specbits))
type_quals |= TYPE_QUAL_VOLATILE;
if (RIDBIT_SETP (RID_RESTRICT, specbits))
type_quals |= TYPE_QUAL_RESTRICT;
if (sfk == sfk_conversion && type_quals != TYPE_UNQUALIFIED)
error ("qualifiers are not allowed on declaration of `operator %T'",
ctor_return_type);
if (RIDBIT_SETP (RID_ALTIVEC_PIXEL, specbits)
&& RIDBIT_NOTSETP (RID_ALTIVEC_VECTOR, specbits))
{
error ("__pixel invalid for `%s'", name);
RIDBIT_RESET (RID_ALTIVEC_PIXEL, specbits);
}
if (RIDBIT_SETP (RID_ALTIVEC_VECTOR, specbits))
{
explicit_bool |= RIDBIT_SETP (RID_ALTIVEC_BOOL, specbits);
if ((type == integer_type_node || type == long_integer_type_node)
&& !explicit_bool && !explicit_int
&& RIDBIT_SETP (RID_ALTIVEC_PIXEL, specbits))
type = vector_pixel_type_node;
else if (type == long_unsigned_type_node)
{
type = vector_unsigned_long_type_node;
if (warn_altivec_long_deprecated)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
}
else if (type == unsigned_type_node)
type = vector_unsigned_long_type_node;
else if (explicit_bool
&& (type == long_integer_type_node || type == integer_type_node))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_boolean_long_type_node;
}
else if (RIDBIT_SETP (RID_SIGNED, specbits)
&& (type == long_integer_type_node || type == integer_type_node))
{
if (warn_altivec_long_deprecated && type == long_integer_type_node)
warning ("Use of 'long' in AltiVec types is deprecated; use 'int'");
type = vector_signed_long_type_node;
}
else if (type == short_unsigned_type_node)
type = vector_unsigned_short_type_node;
else if (type == short_integer_type_node)
type = (explicit_bool
? vector_boolean_short_type_node
: vector_signed_short_type_node);
else if (type == unsigned_char_type_node)
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_ALTIVEC_VECTOR, specbits);
RIDBIT_RESET (RID_ALTIVEC_PIXEL, specbits);
}
if (RIDBIT_SETP (RID_ALTIVEC_PIXEL, specbits) && type != vector_pixel_type_node)
{
error ("type modifiers do not apply to `vector pixel'");
type = vector_pixel_type_node;
}
}
type_quals |= cp_type_quals (type);
type = cp_build_qualified_type_real
(type, type_quals, ((typedef_decl && !DECL_ARTIFICIAL (typedef_decl)
? tf_ignore_bad_quals : 0) | tf_error | tf_warning));
type_quals = cp_type_quals (type);
staticp = 0;
inlinep = !! RIDBIT_SETP (RID_INLINE, specbits);
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)
{
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 (dependant_name && !friendp)
{
error ("`%T::%D' is not a valid declarator", ctype, dependant_name);
return void_type_node;
}
if (RIDBIT_ANY_SET (specbits))
{
if (RIDBIT_SETP (RID_STATIC, specbits)) nclasses++;
if (RIDBIT_SETP (RID_EXTERN, specbits) && !extern_langp) nclasses++;
if (RIDBIT_SETP (RID_THREAD, 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 (!nclasses && !friendp && extern_langp)
nclasses++;
}
if (virtualp
&& (current_class_name == NULL_TREE || decl_context != FIELD))
{
error ("virtual outside class declaration");
virtualp = 0;
}
if (staticp && decl_context == TYPENAME
&& TREE_CODE (declspecs) == TREE_LIST
&& ANON_AGGR_TYPE_P (TREE_VALUE (declspecs)))
decl_context = FIELD;
if (nclasses == 2
&& RIDBIT_SETP (RID_THREAD, specbits)
&& (RIDBIT_SETP (RID_EXTERN, specbits)
|| RIDBIT_SETP (RID_STATIC, specbits)))
nclasses = 1;
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
&& 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);
if (IDENTIFIER_TYPENAME_P (tmp))
{
if (IDENTIFIER_GLOBAL_VALUE (tmp)
&& (TREE_CODE (IDENTIFIER_GLOBAL_VALUE (tmp))
== TYPE_DECL))
name = IDENTIFIER_POINTER (tmp);
else
name = "<invalid operator>";
}
}
error ("storage class specified for %s `%s'",
op ? "member operator" : "field",
name);
}
else
{
if (decl_context == PARM || decl_context == CATCHPARM)
error ("storage class specified for parameter `%s'", name);
else
error ("storage class specified for typename");
}
RIDBIT_RESET (RID_REGISTER, specbits);
RIDBIT_RESET (RID_AUTO, specbits);
RIDBIT_RESET (RID_EXTERN, specbits);
RIDBIT_RESET (RID_THREAD, specbits);
}
}
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);
}
else if (RIDBIT_SETP (RID_THREAD, specbits)
&& !RIDBIT_SETP (RID_EXTERN, specbits)
&& !RIDBIT_SETP (RID_STATIC, specbits))
{
error ("function-scope `%s' implicitly auto and declared `__thread'",
name);
RIDBIT_RESET (RID_THREAD, specbits);
}
if (nclasses > 0 && friendp)
error ("storage class specifiers invalid in friend function declarations");
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);
grok_method_quals (ctype, dummy, quals);
type = TREE_TYPE (dummy);
ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (type)));
quals = NULL_TREE;
}
}
switch (TREE_CODE (declarator))
{
case TREE_LIST:
{
tree attrs = TREE_PURPOSE (declarator);
tree inner_decl;
int attr_flags;
declarator = TREE_VALUE (declarator);
inner_decl = declarator;
while (inner_decl != NULL_TREE
&& TREE_CODE (inner_decl) == TREE_LIST)
inner_decl = TREE_VALUE (inner_decl);
attr_flags = 0;
if (inner_decl == NULL_TREE
|| TREE_CODE (inner_decl) == IDENTIFIER_NODE)
attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
if (TREE_CODE (inner_decl) == CALL_EXPR)
attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
if (TREE_CODE (inner_decl) == ARRAY_REF)
attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
returned_attrs = decl_attributes (&type,
chainon (returned_attrs, attrs),
attr_flags);
}
break;
case ARRAY_REF:
{
register tree size;
size = TREE_OPERAND (declarator, 1);
if (size == NULL_TREE && decl_context == FIELD && ! staticp
&& ! RIDBIT_SETP (RID_TYPEDEF, specbits))
size = integer_zero_node;
declarator = TREE_OPERAND (declarator, 0);
type = create_array_type_for_decl (dname, type, size);
ctype = NULL_TREE;
}
break;
case CALL_EXPR:
{
tree arg_types;
int funcdecl_p;
tree inner_parms = CALL_DECLARATOR_PARMS (declarator);
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 = CALL_DECLARATOR_QUALS (declarator);
raises = CALL_DECLARATOR_EXCEPTION_SPEC (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 && sfk == sfk_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)
{
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,
flags))
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)
{
error ("constructors may not be `%s'",
IDENTIFIER_POINTER (TREE_VALUE (quals)));
quals = NULL_TREE;
}
{
RID_BIT_TYPE tmp_bits;
memcpy (&tmp_bits, &specbits, 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");
}
if (decl_context == FIELD)
{
if (! member_function_or_else (ctype,
current_class_type,
flags))
return void_type_node;
TYPE_HAS_CONSTRUCTOR (ctype) = 1;
if (sfk != sfk_constructor)
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)
error ("can't define friend function `%s' in a local class definition",
name);
}
declarator = TREE_OPERAND (declarator, 0);
arg_types = grokparms (inner_parms);
if (declarator && flags == DTOR_FLAG)
{
if (TREE_CODE (declarator) == BIT_NOT_EXPR)
declarator = TREE_OPERAND (declarator, 0);
if (arg_types != void_list_node)
{
error ("destructors may not have parameters");
arg_types = void_list_node;
last_function_parms = NULL_TREE;
}
}
type = build_function_type (type, arg_types);
{
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 (ctype
&& (TREE_CODE (type) == VOID_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE))
{
error (TREE_CODE (declarator) == ADDR_EXPR
? "cannot declare reference to `%#T'"
: "cannot declare pointer to `%#T'", type);
type = TREE_TYPE (type);
}
else if (VOID_TYPE_P (type)
&& (ctype || TREE_CODE (declarator) == ADDR_EXPR))
error (ctype ? "cannot declare pointer to `%#T' member"
: "cannot declare reference to `%#T'", type);
type_quals = TYPE_UNQUALIFIED;
if (TREE_CODE (declarator) == ADDR_EXPR)
{
if (!VOID_TYPE_P (type))
type = build_reference_type (type);
}
else if (TREE_CODE (type) == METHOD_TYPE)
type = build_ptrmemfunc_type (build_pointer_type (type));
else if (ctype)
type = build_ptrmem_type (ctype, type);
else
type = build_pointer_type (type);
if (TREE_TYPE (declarator))
{
register tree typemodlist;
int erred = 0;
int constp = 0;
int volatilep = 0;
int restrictp = 0;
for (typemodlist = TREE_TYPE (declarator); typemodlist;
typemodlist = TREE_CHAIN (typemodlist))
{
tree qualifier = TREE_VALUE (typemodlist);
if (qualifier == ridpointers[(int) RID_CONST])
{
constp++;
type_quals |= TYPE_QUAL_CONST;
}
else if (qualifier == ridpointers[(int) RID_VOLATILE])
{
volatilep++;
type_quals |= TYPE_QUAL_VOLATILE;
}
else if (qualifier == ridpointers[(int) RID_RESTRICT])
{
restrictp++;
type_quals |= TYPE_QUAL_RESTRICT;
}
else if (!erred)
{
erred = 1;
error ("invalid type modifier within pointer declarator");
}
}
if (constp > 1)
pedwarn ("duplicate `const'");
if (volatilep > 1)
pedwarn ("duplicate `volatile'");
if (restrictp > 1)
pedwarn ("duplicate `restrict'");
type = cp_build_qualified_type (type, type_quals);
type_quals = cp_type_quals (type);
}
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 (!TREE_OPERAND (declarator, 0)
|| !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, tf_error | tf_warning,
NULL_TREE);
}
pop_nested_class ();
TREE_COMPLEXITY (declarator) = current_class_depth;
}
else
abort ();
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_INSTANTIATION (t)
|| uses_template_parms (CLASSTYPE_TI_ARGS (t)))
&& PRIMARY_TEMPLATE_P (CLASSTYPE_TI_TEMPLATE (t)))
template_count += 1;
t = TYPE_MAIN_DECL (t);
t = DECL_CONTEXT (t);
}
if (sname == NULL_TREE)
goto done_scoping;
if (TREE_CODE (sname) == IDENTIFIER_NODE)
{
if (ctype == current_class_type)
{
if (pedantic)
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
{
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)
|| COMPLETE_TYPE_P (complete_type (ctype)))
{
if (current_class_type)
{
error ("cannot declare member `%T::%s' within `%T'",
ctype, name, current_class_type);
return void_type_node;
}
}
else
{
cxx_incomplete_type_error (NULL_TREE, ctype);
return error_mark_node;
}
declarator = sname;
}
else if (TREE_CODE (sname) == SCOPE_REF)
abort ();
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));
}
}
break;
case BIT_NOT_EXPR:
declarator = TREE_OPERAND (declarator, 0);
break;
case BASELINK:
declarator = BASELINK_FUNCTIONS (declarator);
break;
case RECORD_TYPE:
case UNION_TYPE:
case ENUMERAL_TYPE:
declarator = NULL_TREE;
break;
case ERROR_MARK:
declarator = NULL_TREE;
break;
default:
abort ();
}
}
if (returned_attrs)
{
if (attrlist)
*attrlist = chainon (returned_attrs, *attrlist);
else
attrlist = &returned_attrs;
}
if (TREE_CODE (type) == ARRAY_TYPE
&& COMPLETE_TYPE_P (type)
&& TREE_OVERFLOW (TYPE_SIZE (type)))
{
error ("size of array `%s' is too large", name);
type = error_mark_node;
}
if ((decl_context == FIELD || decl_context == PARM)
&& !processing_template_decl
&& variably_modified_type_p (type))
{
if (decl_context == FIELD)
error ("data member may not have variably modified type `%T'", type);
else
error ("parameter may not have variably modified type `%T'", type);
type = error_mark_node;
}
if (explicitp == 1 || (explicitp && friendp))
{
error ("only declarations of constructors can be `explicit'");
explicitp = 0;
}
if (RIDBIT_SETP (RID_MUTABLE, specbits))
{
if (current_class_name == NULL_TREE || decl_context == PARM || friendp)
{
error ("non-member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (decl_context == TYPENAME || RIDBIT_SETP (RID_TYPEDEF, specbits))
{
error ("non-object member `%s' cannot be declared `mutable'", name);
RIDBIT_RESET (RID_MUTABLE, specbits);
}
else if (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
{
error ("function `%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);
}
else if (type_quals & TYPE_QUAL_CONST)
{
error ("const `%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)
{
error ("template-id `%D' used as a declarator", declarator);
declarator = dname;
}
else
abort ();
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))
pedwarn ("ISO C++ forbids nested type `%D' with same name as enclosing class",
declarator);
decl = build_lang_decl (TYPE_DECL, declarator, type);
}
else
{
decl = build_decl (TYPE_DECL, declarator, type);
if (!current_function_decl)
DECL_CONTEXT (decl) = FROB_CONTEXT (current_namespace);
}
if (type != error_mark_node
&& declarator
&& TYPE_NAME (type)
&& TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
&& TYPE_ANONYMOUS_P (type)
&& (!attrlist || !*attrlist)
&& cp_type_quals (type) == TYPE_UNQUALIFIED)
{
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);
}
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-member function 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;
bad_specifiers (decl, "type", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
return decl;
}
if (type && typedef_type
&& TREE_CODE (type) == ARRAY_TYPE && !TYPE_DOMAIN (type)
&& TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (typedef_type))
type = build_cplus_array_type (TREE_TYPE (type), NULL_TREE);
if (type == typedef_type && TREE_CODE (type) == FUNCTION_TYPE)
{
tree decls = NULL_TREE;
tree args;
for (args = TYPE_ARG_TYPES (type); args; args = TREE_CHAIN (args))
{
tree decl = cp_build_parm_decl (NULL_TREE, TREE_VALUE (args));
TREE_CHAIN (decl) = decls;
decls = decl;
}
last_function_parms = nreverse (decls);
}
if (decl_context == TYPENAME)
{
if (type_quals != TYPE_UNQUALIFIED)
type_quals = TYPE_UNQUALIFIED;
if (friendp)
{
if (type_quals != TYPE_UNQUALIFIED)
{
error ("type qualifiers specified for friend class declaration");
type_quals = TYPE_UNQUALIFIED;
}
if (inlinep)
{
error ("`inline' specified for friend class declaration");
inlinep = 0;
}
if (!current_aggr)
{
if (TREE_CODE (type) == TEMPLATE_TYPE_PARM)
pedwarn ("template parameters cannot be friends");
else if (TREE_CODE (type) == TYPENAME_TYPE)
pedwarn ("friend declaration requires class-key, "
"i.e. `friend class %T::%D'",
TYPE_CONTEXT (type), TYPENAME_TYPE_FULLNAME (type));
else
pedwarn ("friend declaration requires class-key, "
"i.e. `friend %#T'",
type);
}
if (type != integer_type_node)
{
decl_type_access_control (TYPE_NAME (type));
if (current_class_type)
make_friend_class (current_class_type, TYPE_MAIN_VARIANT (type));
else
error ("trying to make class `%T' a friend of global scope",
type);
type = void_type_node;
}
}
else if (quals)
{
if (ctype == NULL_TREE)
{
if (TREE_CODE (type) != METHOD_TYPE)
error ("invalid qualifiers on non-member function type");
else
ctype = TYPE_METHOD_BASETYPE (type);
}
if (ctype)
{
tree dummy = build_decl (TYPE_DECL, declarator, 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)
{
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))
abort ();
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);
}
{
register tree decl;
if (decl_context == PARM)
{
decl = cp_build_parm_decl (declarator, type);
bad_specifiers (decl, "parameter", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
}
else if (decl_context == FIELD)
{
if (type == error_mark_node)
{
decl = NULL_TREE;
}
else if (in_namespace && !friendp)
{
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])
{
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)
{
error ("can't make `%D' into a method -- not in a class",
declarator);
return void_type_node;
}
if (virtualp && TREE_CODE (ctype) == UNION_TYPE)
{
error ("function `%D' declared virtual inside a union",
declarator);
return void_type_node;
}
if (declarator == ansi_opname (NEW_EXPR)
|| declarator == ansi_opname (VEC_NEW_EXPR)
|| declarator == ansi_opname (DELETE_EXPR)
|| declarator == ansi_opname (VEC_DELETE_EXPR))
{
if (virtualp)
{
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) ?
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_attr);
#endif
if (explicitp == 2)
DECL_NONCONVERTING_P (decl) = 1;
else if (DECL_CONSTRUCTOR_P (decl))
{
tree arg_types = FUNCTION_FIRST_USER_PARMTYPE (decl);
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
&& !COMPLETE_TYPE_P (complete_type (type))
&& (TREE_CODE (type) != ARRAY_TYPE || initialized == 0))
{
if (declarator)
error ("field `%D' has incomplete type", declarator);
else
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)
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 member function; 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)
{
pedwarn ("ISO C++ forbids initialization of member `%D'",
declarator);
pedwarn ("making `%D' static", declarator);
staticp = 1;
}
if (uses_template_parms (type))
;
else if (check_static_variable_definition (declarator,
type))
return void_type_node;
}
if (current_class_type && declarator == constructor_name (current_class_type)
&& staticp)
pedwarn ("ISO C++ forbids static data member `%D' with same name as enclosing class",
declarator);
if (staticp)
{
decl = build_lang_decl (VAR_DECL, declarator, type);
TREE_STATIC (decl) = 1;
TREE_PUBLIC (decl) = DECL_EXTERNAL (decl) = 1;
}
else
{
decl = build_decl (FIELD_DECL, declarator, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
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);
else if (RIDBIT_SETP (RID_THREAD, specbits))
error ("storage class `__thread' 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 invalid_static = 0;
if (TREE_CODE (type) == METHOD_TYPE)
{
pedwarn ("cannot declare member function `%D' to have static linkage", decl);
invalid_static = 1;
}
else if (current_function_decl)
{
error ("cannot declare static function inside another function");
invalid_static = 1;
}
if (invalid_static)
{
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
}
}
else
{
decl = grokvardecl (type, declarator, &specbits,
initialized,
(type_quals & TYPE_QUAL_CONST) != 0,
ctype ? ctype : in_namespace);
bad_specifiers (decl, "variable", virtualp, quals != NULL_TREE,
inlinep, friendp, raises != NULL_TREE);
if (ctype)
{
DECL_CONTEXT (decl) = ctype;
if (staticp == 1)
{
pedwarn ("`static' may not be used when defining (as opposed to declaring) a static data member");
staticp = 0;
RIDBIT_RESET (RID_STATIC, specbits);
}
if (RIDBIT_SETP (RID_REGISTER, specbits) && TREE_STATIC (decl))
{
error ("static member `%D' declared `register'", decl);
RIDBIT_RESET (RID_REGISTER, specbits);
}
if (RIDBIT_SETP (RID_EXTERN, specbits) && pedantic)
{
pedwarn ("cannot explicitly declare member `%#D' to have extern linkage",
decl);
RIDBIT_RESET (RID_EXTERN, specbits);
}
}
}
my_friendly_assert (!RIDBIT_SETP (RID_MUTABLE, specbits), 19990927);
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 (cw_asm_specbit)
{
if (flag_cw_asm_blocks)
{
DECL_CW_ASM_FUNCTION (decl) = 1;
DECL_CW_ASM_NORETURN (decl) = 0;
DECL_CW_ASM_FRAME_SIZE (decl) = -2;
}
else
error ("asm functions not enabled, use `-fasm-blocks'");
}
if (!processing_template_decl)
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;
{
for (; parms; parms = TREE_CHAIN (parms))
{
if (VOID_TYPE_P (TREE_TYPE (parms)))
TREE_TYPE (parms) = error_mark_node;
else if (complete_type_or_else (TREE_TYPE (parms), parms))
{
layout_decl (parms, 0);
DECL_ARG_TYPE (parms) = type_passed_as (TREE_TYPE (parms));
}
else
TREE_TYPE (parms) = error_mark_node;
}
}
int
local_variable_p (t)
tree t;
{
if ((TREE_CODE (t) == VAR_DECL
&& !TYPE_P (CP_DECL_CONTEXT (t))
&& !DECL_NAMESPACE_SCOPE_P (t))
|| (TREE_CODE (t) == PARM_DECL))
return 1;
return 0;
}
int
nonstatic_local_decl_p (t)
tree t;
{
return ((local_variable_p (t) && !TREE_STATIC (t))
|| TREE_CODE (t) == LABEL_DECL
|| TREE_CODE (t) == RESULT_DECL);
}
static tree
local_variable_p_walkfn (tp, walk_subtrees, data)
tree *tp;
int *walk_subtrees ATTRIBUTE_UNUSED;
void *data ATTRIBUTE_UNUSED;
{
return ((local_variable_p (*tp) && !DECL_ARTIFICIAL (*tp))
? *tp : 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)
error ("default argument for `%#D' has type `%T'",
decl, TREE_TYPE (arg));
else
error ("default argument for parameter of type `%T' has type `%T'",
decl_type, TREE_TYPE (arg));
return error_mark_node;
}
var = walk_tree_without_duplicates (&arg, local_variable_p_walkfn,
NULL);
if (var)
{
error ("default argument `%E' uses local variable `%D'",
arg, var);
return error_mark_node;
}
return arg;
}
tree
grokparms (first_parm)
tree first_parm;
{
tree result = NULL_TREE;
tree decls = NULL_TREE;
int ellipsis = !first_parm || PARMLIST_ELLIPSIS_P (first_parm);
tree parm, chain;
int any_error = 0;
my_friendly_assert (!first_parm || TREE_PARMLIST (first_parm), 20001115);
for (parm = first_parm; parm != NULL_TREE; parm = chain)
{
tree type = NULL_TREE;
tree decl = TREE_VALUE (parm);
tree init = TREE_PURPOSE (parm);
tree specs, attrs;
chain = TREE_CHAIN (parm);
if (TREE_CODE (decl) != VOID_TYPE
&& TREE_CODE (decl) != TREE_LIST)
{
if (TREE_CODE (decl) == STRING_CST)
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 (parm == void_list_node)
break;
split_specs_attrs (TREE_PURPOSE (decl), &specs, &attrs);
decl = grokdeclarator (TREE_VALUE (decl), specs,
PARM, init != NULL_TREE, &attrs);
if (! decl || TREE_TYPE (decl) == error_mark_node)
continue;
if (attrs)
cplus_decl_attributes (&decl, attrs, 0);
type = TREE_TYPE (decl);
if (VOID_TYPE_P (type))
{
if (same_type_p (type, void_type_node)
&& !DECL_NAME (decl) && !result && !chain && !ellipsis)
break;
cxx_incomplete_type_error (decl, type);
type = error_mark_node;
TREE_TYPE (decl) = error_mark_node;
}
if (type != error_mark_node)
{
type = TYPE_MAIN_VARIANT (type);
if (TREE_CODE (type) == METHOD_TYPE)
{
error ("parameter `%D' invalidly declared method type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (TREE_CODE (type) == OFFSET_TYPE)
{
error ("parameter `%D' invalidly declared offset type", decl);
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (abstract_virtuals_error (decl, type))
any_error = 1;
else if (POINTER_TYPE_P (type))
{
tree t = TREE_TYPE (type);
int ptr = TYPE_PTR_P (type);
while (1)
{
if (TYPE_PTR_P (t))
ptr = 1;
else if (TREE_CODE (t) != ARRAY_TYPE)
break;
else if (!TYPE_DOMAIN (t))
break;
t = TREE_TYPE (t);
}
if (TREE_CODE (t) == ARRAY_TYPE)
error ("parameter `%D' includes %s to array of unknown bound `%T'",
decl, ptr ? "pointer" : "reference", t);
}
if (!any_error && init)
init = check_default_argument (decl, init);
else
init = NULL_TREE;
}
TREE_CHAIN (decl) = decls;
decls = decl;
result = tree_cons (init, type, result);
}
decls = nreverse (decls);
result = nreverse (result);
if (!ellipsis)
result = chainon (result, void_list_node);
last_function_parms = decls;
return result;
}
int
copy_fn_p (d)
tree d;
{
tree args;
tree arg_type;
int result = 1;
my_friendly_assert (DECL_FUNCTION_MEMBER_P (d), 20011208);
if (DECL_TEMPLATE_INFO (d) && is_member_template (DECL_TI_TEMPLATE (d)))
return 0;
args = FUNCTION_FIRST_USER_PARMTYPE (d);
if (!args)
return 0;
arg_type = TREE_VALUE (args);
if (TYPE_MAIN_VARIANT (arg_type) == DECL_CONTEXT (d))
{
result = -1;
}
else if (TREE_CODE (arg_type) == REFERENCE_TYPE
&& TYPE_MAIN_VARIANT (TREE_TYPE (arg_type)) == DECL_CONTEXT (d))
{
if (CP_TYPE_CONST_P (TREE_TYPE (arg_type)))
result = 2;
}
else
return 0;
args = TREE_CHAIN (args);
if (args && args != void_list_node && !TREE_PURPOSE (args))
return 0;
return result;
}
void grok_special_member_properties (decl)
tree decl;
{
if (!DECL_NONSTATIC_MEMBER_FUNCTION_P(decl))
;
else if (DECL_CONSTRUCTOR_P (decl))
{
int ctor = copy_fn_p (decl);
if (ctor > 0)
{
TYPE_HAS_INIT_REF (DECL_CONTEXT (decl)) = 1;
if (ctor > 1)
TYPE_HAS_CONST_INIT_REF (DECL_CONTEXT (decl)) = 1;
}
else if (sufficient_parms_p (FUNCTION_FIRST_USER_PARMTYPE (decl)))
TYPE_HAS_DEFAULT_CONSTRUCTOR (DECL_CONTEXT (decl)) = 1;
}
else if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
{
int assop = copy_fn_p (decl);
if (assop)
{
TYPE_HAS_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
if (assop != 1)
TYPE_HAS_CONST_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
if (DECL_PURE_VIRTUAL_P (decl))
TYPE_HAS_ABSTRACT_ASSIGN_REF (DECL_CONTEXT (decl)) = 1;
}
}
}
int
grok_ctor_properties (ctype, decl)
tree ctype, decl;
{
int ctor_parm = copy_fn_p (decl);
if (ctor_parm < 0)
{
error ("invalid constructor; you probably meant `%T (const %T&)'",
ctype, ctype);
SET_IDENTIFIER_ERROR_LOCUS (DECL_NAME (decl), ctype);
return 0;
}
return 1;
}
static int
ambi_op_p (code)
enum tree_code code;
{
return (code == INDIRECT_REF
|| code == ADDR_EXPR
|| code == CONVERT_EXPR
|| code == NEGATE_EXPR
|| code == PREINCREMENT_EXPR
|| code == PREDECREMENT_EXPR);
}
static int
unary_op_p (code)
enum tree_code code;
{
return (code == TRUTH_NOT_EXPR
|| code == BIT_NOT_EXPR
|| code == COMPONENT_REF
|| code == TYPE_EXPR);
}
void
grok_op_properties (decl, friendp)
tree decl;
int friendp;
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
tree argtype;
int methodp = (TREE_CODE (TREE_TYPE (decl)) == METHOD_TYPE);
tree name = DECL_NAME (decl);
enum tree_code operator_code;
int arity;
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
argtype = TREE_CHAIN (argtype))
++arity;
if (current_class_type == NULL_TREE)
friendp = 1;
if (DECL_CONV_FN_P (decl))
operator_code = TYPE_EXPR;
else
do
{
#define DEF_OPERATOR(NAME, CODE, MANGLING, ARITY, ASSN_P) \
if (ansi_opname (CODE) == name) \
{ \
operator_code = (CODE); \
break; \
} \
else if (ansi_assopname (CODE) == name) \
{ \
operator_code = (CODE); \
DECL_ASSIGNMENT_OPERATOR_P (decl) = 1; \
break; \
}
#include "operators.def"
#undef DEF_OPERATOR
abort ();
}
while (0);
my_friendly_assert (operator_code != LAST_CPLUS_TREE_CODE, 20000526);
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if (! friendp)
{
switch (operator_code)
{
case CALL_EXPR:
TYPE_OVERLOADS_CALL_EXPR (current_class_type) = 1;
break;
case ARRAY_REF:
TYPE_OVERLOADS_ARRAY_REF (current_class_type) = 1;
break;
case COMPONENT_REF:
case MEMBER_REF:
TYPE_OVERLOADS_ARROW (current_class_type) = 1;
break;
case NEW_EXPR:
TYPE_HAS_NEW_OPERATOR (current_class_type) = 1;
break;
case DELETE_EXPR:
TYPE_GETS_DELETE (current_class_type) |= 1;
break;
case VEC_NEW_EXPR:
TYPE_HAS_ARRAY_NEW_OPERATOR (current_class_type) = 1;
break;
case VEC_DELETE_EXPR:
TYPE_GETS_DELETE (current_class_type) |= 2;
break;
default:
break;
}
}
if (operator_code == NEW_EXPR || operator_code == VEC_NEW_EXPR)
{
if (methodp)
revert_static_member_fn (decl);
TREE_TYPE (decl) = coerce_new_type (TREE_TYPE (decl));
}
else if (operator_code == DELETE_EXPR || operator_code == VEC_DELETE_EXPR)
{
if (methodp)
revert_static_member_fn (decl);
TREE_TYPE (decl) = coerce_delete_type (TREE_TYPE (decl));
}
else
{
if (! methodp || DECL_STATIC_FUNCTION_P (decl))
{
if (operator_code == TYPE_EXPR
|| operator_code == CALL_EXPR
|| operator_code == COMPONENT_REF
|| operator_code == ARRAY_REF
|| operator_code == NOP_EXPR)
error ("`%D' must be a nonstatic member function", decl);
else
{
tree p = argtypes;
if (DECL_STATIC_FUNCTION_P (decl))
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) == BOUND_TEMPLATE_TEMPLATE_PARM)
goto foundaggr;
}
error
("`%D' must have an argument of class or enumerated type",
decl);
foundaggr:
;
}
}
if (operator_code == CALL_EXPR)
return;
if (IDENTIFIER_TYPENAME_P (name) && ! DECL_TEMPLATE_INFO (decl))
{
tree t = TREE_TYPE (name);
if (! friendp)
{
int ref = (TREE_CODE (t) == REFERENCE_TYPE);
const char *what = 0;
if (ref)
t = TYPE_MAIN_VARIANT (TREE_TYPE (t));
if (TREE_CODE (t) == VOID_TYPE)
what = "void";
else if (t == current_class_type)
what = "the same type";
else if (IS_AGGR_TYPE (t)
&& COMPLETE_TYPE_P (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 (operator_code == COND_EXPR)
{
error ("ISO C++ prohibits overloading operator ?:");
}
else if (ambi_op_p (operator_code))
{
if (arity == 1)
;
else if (arity == 2)
{
switch (operator_code)
{
case INDIRECT_REF:
operator_code = MULT_EXPR;
break;
case ADDR_EXPR:
operator_code = BIT_AND_EXPR;
break;
case CONVERT_EXPR:
operator_code = PLUS_EXPR;
break;
case NEGATE_EXPR:
operator_code = MINUS_EXPR;
break;
case PREINCREMENT_EXPR:
operator_code = POSTINCREMENT_EXPR;
break;
case PREDECREMENT_EXPR:
operator_code = POSTDECREMENT_EXPR;
break;
default:
abort ();
}
SET_OVERLOADED_OPERATOR_CODE (decl, operator_code);
if ((operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
&& ! processing_template_decl
&& ! same_type_p (TREE_VALUE (TREE_CHAIN (argtypes)), integer_type_node))
{
if (methodp)
error ("postfix `%D' must take `int' as its argument",
decl);
else
error
("postfix `%D' must take `int' as its second argument",
decl);
}
}
else
{
if (methodp)
error ("`%D' must take either zero or one argument", decl);
else
error ("`%D' must take either one or two arguments", decl);
}
if (warn_ecpp
&& (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR
|| operator_code == PREINCREMENT_EXPR
|| operator_code == PREDECREMENT_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 (operator_code == PREINCREMENT_EXPR
|| operator_code == PREDECREMENT_EXPR)
{
if (TREE_CODE (ret) != REFERENCE_TYPE
|| !same_type_p (TYPE_MAIN_VARIANT (TREE_TYPE (ret)),
arg))
warning ("prefix `%D' should return `%T'", decl,
build_reference_type (arg));
}
else
{
if (!same_type_p (TYPE_MAIN_VARIANT (ret), arg))
warning ("postfix `%D' should return `%T'", decl, arg);
}
}
}
else if (unary_op_p (operator_code))
{
if (arity != 1)
{
if (methodp)
error ("`%D' must take `void'", decl);
else
error ("`%D' must take exactly one argument", decl);
}
}
else
{
if (arity != 2)
{
if (methodp)
error ("`%D' must take exactly one argument", decl);
else
error ("`%D' must take exactly two arguments", decl);
}
if (warn_ecpp
&& (operator_code == TRUTH_ANDIF_EXPR
|| operator_code == TRUTH_ORIF_EXPR
|| operator_code == COMPOUND_EXPR))
warning ("user-defined `%D' always evaluates both arguments",
decl);
}
if (warn_ecpp
&& arity == 2
&& !DECL_ASSIGNMENT_OPERATOR_P (decl)
&& (operator_code == PLUS_EXPR
|| operator_code == MINUS_EXPR
|| operator_code == TRUNC_DIV_EXPR
|| operator_code == MULT_EXPR
|| operator_code == TRUNC_MOD_EXPR)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (decl))) == REFERENCE_TYPE)
warning ("`%D' should return by value", decl);
for (; argtypes && argtypes != void_list_node;
argtypes = TREE_CHAIN (argtypes))
if (TREE_PURPOSE (argtypes))
{
TREE_PURPOSE (argtypes) = NULL_TREE;
if (operator_code == POSTINCREMENT_EXPR
|| operator_code == POSTDECREMENT_EXPR)
{
if (pedantic)
pedwarn ("`%D' cannot have default arguments", decl);
}
else
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";
default:
abort ();
}
}
tree
xref_tag (enum tag_types tag_code, tree name, tree attributes,
bool globalize)
{
enum tree_code code;
register tree ref, t;
struct cp_binding_level *b = current_binding_level;
tree context = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
switch (tag_code)
{
case record_type:
case class_type:
code = RECORD_TYPE;
break;
case union_type:
code = UNION_TYPE;
break;
case enum_type:
code = ENUMERAL_TYPE;
break;
default:
abort ();
}
if (TYPE_P (name))
{
t = name;
name = TYPE_IDENTIFIER (t);
}
else
t = IDENTIFIER_TYPE_VALUE (name);
if (t && globalize && TREE_CODE (t) == TYPENAME_TYPE)
{
static int explained;
tree shadowed;
warning ("`%s %T' declares a new type at namespace scope",
tag_name (tag_code), name);
if (!explained++)
warning (" names from dependent base classes are not visible to unqualified name lookup - to refer to the inherited type, say `%s %T::%T'",
tag_name (tag_code),
constructor_name (current_class_type),
TYPE_IDENTIFIER (t));
for (shadowed = b->class_shadowed;
shadowed;
shadowed = TREE_CHAIN (shadowed))
if (TREE_TYPE (shadowed) == TYPE_NAME (t))
{
TREE_PURPOSE (shadowed) = NULL_TREE;
break;
}
}
if (t && TREE_CODE (t) != code && TREE_CODE (t) != TEMPLATE_TYPE_PARM
&& TREE_CODE (t) != BOUND_TEMPLATE_TEMPLATE_PARM)
t = NULL_TREE;
if (! globalize)
{
ref = lookup_tag (code, name, b, 1);
}
else
{
if (t)
{
ref = follow_tag_typedef (t);
if (!ref)
{
pedwarn ("using typedef-name `%D' after `%s'",
TYPE_NAME (t), tag_name (tag_code));
ref = t;
}
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
error ("using template type parameter `%T' after `%s'",
t, tag_name (tag_code));
}
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_TEMPLATE_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;
}
}
if (! ref)
{
if (code == ENUMERAL_TYPE)
{
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);
TYPE_USER_ALIGN (ref) = 0;
TREE_UNSIGNED (ref) = 1;
TYPE_PRECISION (ref) = TYPE_PRECISION (unsigned_type_node);
TYPE_MIN_VALUE (ref) = TYPE_MIN_VALUE (unsigned_type_node);
TYPE_MAX_VALUE (ref) = TYPE_MAX_VALUE (unsigned_type_node);
pushtag (name, ref, globalize);
}
else
{
struct cp_binding_level *old_b = class_binding_level;
ref = make_aggr_type (code);
TYPE_CONTEXT (ref) = context;
#ifdef NONNESTED_CLASSES
class_binding_level = (struct cp_binding_level *)0;
#endif
pushtag (name, ref, globalize);
class_binding_level = old_b;
}
}
else
{
if (!globalize && processing_template_decl && IS_AGGR_TYPE (ref))
redeclare_class_template (ref, current_template_parms);
}
TYPE_ATTRIBUTES (ref) = attributes;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ref);
}
tree
xref_tag_from_type (old, id, globalize)
tree old, id;
int globalize;
{
enum tag_types tag_kind;
if (TREE_CODE (old) == RECORD_TYPE)
tag_kind = (CLASSTYPE_DECLARED_CLASS (old) ? class_type : record_type);
else
tag_kind = union_type;
if (id == NULL_TREE)
id = TYPE_IDENTIFIER (old);
return xref_tag (tag_kind, id, NULL_TREE, globalize);
}
void
xref_basetypes (ref, binfo)
tree ref;
tree binfo;
{
tree binfos;
tree base;
int i, len;
enum tag_types tag_code;
if (TREE_CODE (ref) == UNION_TYPE)
{
error ("derived union `%T' invalid", ref);
return;
}
tag_code = (CLASSTYPE_DECLARED_CLASS (ref) ? class_type : record_type);
len = list_length (binfo);
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) != BOUND_TEMPLATE_TEMPLATE_PARM))
{
error ("base type `%T' fails to be a struct or class type",
TREE_VALUE (binfo));
continue;
}
if (!COMPLETE_TYPE_P (basetype)
&& ! (current_template_parms && uses_template_parms (basetype)))
{
error ("base class `%T' has incomplete type", basetype);
continue;
}
else
{
if (CLASSTYPE_MARKED (basetype))
{
if (basetype == ref)
error ("recursive type `%T' undefined", basetype);
else
error ("duplicate base type `%T' invalid", basetype);
continue;
}
if (TYPE_FOR_JAVA (basetype)
&& (current_lang_depth () == 0))
TYPE_FOR_JAVA (ref) = 1;
base_binfo
= make_binfo (size_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_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
}
if (CLASS_TYPE_P (basetype))
{
TYPE_HAS_NEW_OPERATOR (ref)
|= TYPE_HAS_NEW_OPERATOR (basetype);
TYPE_HAS_ARRAY_NEW_OPERATOR (ref)
|= TYPE_HAS_ARRAY_NEW_OPERATOR (basetype);
TYPE_GETS_DELETE (ref) |= TYPE_GETS_DELETE (basetype);
TYPE_USES_MULTIPLE_INHERITANCE (ref)
|= TYPE_USES_MULTIPLE_INHERITANCE (basetype);
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref)
|= TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (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;
TYPE_BASE_CONVS_MAY_REQUIRE_CODE_P (ref) = 1;
}
while (--i >= 0)
CLEAR_CLASSTYPE_MARKED (BINFO_TYPE (TREE_VEC_ELT (binfos, i)));
CLEAR_CLASSTYPE_MARKED (ref);
get_vbase_types (ref);
}
tree
start_enum (name)
tree name;
{
register tree enumtype = NULL_TREE;
struct cp_binding_level *b = current_binding_level;
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)
{
error ("multiple definition of `%#T'", enumtype);
cp_error_at ("previous definition here", enumtype);
TYPE_VALUES (enumtype) = NULL_TREE;
}
else
{
enumtype = make_node (ENUMERAL_TYPE);
pushtag (name, enumtype, 0);
}
return enumtype;
}
void
finish_enum (enumtype)
tree enumtype;
{
tree pair;
tree minnode;
tree maxnode;
tree t;
bool unsignedp;
int lowprec;
int highprec;
int precision;
TYPE_VALUES (enumtype) = nreverse (TYPE_VALUES (enumtype));
if (processing_template_decl)
{
for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
TREE_TYPE (TREE_VALUE (pair)) = enumtype;
if (at_function_scope_p ())
add_stmt (build_min (TAG_DEFN, enumtype));
return;
}
if (TYPE_VALUES (enumtype))
{
minnode = maxnode = NULL_TREE;
for (pair = TYPE_VALUES (enumtype); pair; pair = TREE_CHAIN (pair))
{
tree decl = TREE_VALUE (pair);
tree value = DECL_INITIAL (decl);
TREE_TYPE (decl) = 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 (TREE_TYPE (value) != enumtype)
{
value = DECL_INITIAL (decl) = copy_node (value);
TREE_TYPE (value) = enumtype;
}
TREE_VALUE (pair) = value;
}
}
else
minnode = maxnode = integer_zero_node;
unsignedp = tree_int_cst_sgn (minnode) >= 0;
lowprec = min_precision (minnode, unsignedp);
highprec = min_precision (maxnode, unsignedp);
precision = MAX (lowprec, highprec);
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 (c_common_type_for_size
(precision, 1));
else
TYPE_PRECISION (enumtype) = TYPE_PRECISION (integer_type_node);
TYPE_SIZE (enumtype) = NULL_TREE;
layout_type (enumtype);
for (t = TYPE_MAIN_VARIANT (enumtype); t; t = TYPE_NEXT_VARIANT (t))
{
TYPE_VALUES (t) = TYPE_VALUES (enumtype);
TYPE_MIN_VALUE (t) = TYPE_MIN_VALUE (enumtype);
TYPE_MAX_VALUE (t) = TYPE_MAX_VALUE (enumtype);
TYPE_SIZE (t) = TYPE_SIZE (enumtype);
TYPE_SIZE_UNIT (t) = TYPE_SIZE_UNIT (enumtype);
TYPE_MODE (t) = TYPE_MODE (enumtype);
TYPE_PRECISION (t) = TYPE_PRECISION (enumtype);
TYPE_ALIGN (t) = TYPE_ALIGN (enumtype);
TYPE_USER_ALIGN (t) = TYPE_USER_ALIGN (enumtype);
TREE_UNSIGNED (t) = TREE_UNSIGNED (enumtype);
}
rest_of_type_compilation (enumtype, namespace_bindings_p ());
}
void
build_enumerator (name, value, enumtype)
tree name;
tree value;
tree enumtype;
{
tree decl;
tree context;
tree type;
if (value)
STRIP_TYPE_NOPS (value);
if (! processing_template_decl)
{
if (value != NULL_TREE)
{
value = decl_constant_value (value);
if (TREE_CODE (value) == INTEGER_CST)
{
value = default_conversion (value);
constant_expression_warning (value);
}
else
{
error ("enumerator value for `%D' not integer constant", name);
value = NULL_TREE;
}
}
if (value == NULL_TREE && ! processing_template_decl)
{
tree prev_value;
if (TYPE_VALUES (enumtype))
{
prev_value = DECL_INITIAL (TREE_VALUE (TYPE_VALUES (enumtype)));
value = cp_build_binary_op (PLUS_EXPR,
prev_value,
integer_one_node);
if (tree_int_cst_lt (value, prev_value))
error ("overflow in enumeration values at `%D'", name);
}
else
value = integer_zero_node;
}
STRIP_TYPE_NOPS (value);
}
context = current_scope ();
type = value ? TREE_TYPE (value) : NULL_TREE;
if (context && context == current_class_type)
decl = build_lang_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);
if (flag_gen_index)
gen_indexing_info (INDEX_ENUM, IDENTIFIER_POINTER (name), lineno);
TYPE_VALUES (enumtype) = tree_cons (name, decl, TYPE_VALUES (enumtype));
}
static void
check_function_type (decl, current_function_parms)
tree decl;
tree current_function_parms;
{
tree fntype = TREE_TYPE (decl);
tree return_type = complete_type (TREE_TYPE (fntype));
require_complete_types_for_parms (current_function_parms);
if (!COMPLETE_OR_VOID_TYPE_P (return_type))
{
error ("return type `%#T' is incomplete", TREE_TYPE (fntype));
if (TREE_CODE (fntype) == METHOD_TYPE)
{
tree ctype = TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (fntype)));
TREE_TYPE (decl)
= build_cplus_method_type (ctype,
void_type_node,
FUNCTION_ARG_CHAIN (decl));
}
else
TREE_TYPE (decl)
= build_function_type (void_type_node,
TYPE_ARG_TYPES (TREE_TYPE (decl)));
TREE_TYPE (decl)
= build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (fntype));
}
else
abstract_virtuals_error (decl, TREE_TYPE (fntype));
}
static void gen_start_function_index PARAMS ((tree));
static void
gen_start_function_index (decl)
tree decl;
{
int info_tag = INDEX_ERROR;
tree dc = NULL_TREE;
if (processing_template_decl
|| DECL_USE_TEMPLATE (decl)
|| DECL_ARTIFICIAL (decl))
return;
if (DECL_CONSTRUCTOR_P (decl))
{
info_tag = INDEX_CONSTRUCTOR_BEGIN;
if (DECL_BASE_CONSTRUCTOR_P (decl)
|| DECL_COMPLETE_CONSTRUCTOR_P (decl))
info_tag = INDEX_ERROR;
}
else if (DECL_DESTRUCTOR_P (decl))
{
info_tag = INDEX_DESTRUCTOR_BEGIN;
if (DECL_BASE_DESTRUCTOR_P (decl)
|| DECL_COMPLETE_DESTRUCTOR_P (decl))
info_tag = INDEX_ERROR;
}
else if (DECL_STATIC_FUNCTION_P (decl))
{
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
info_tag = INDEX_CLASS_OPERATOR_BEGIN;
else
info_tag = INDEX_CLASS_METHOD_BEGIN;
}
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
{
if (IDENTIFIER_OPNAME_P (DECL_NAME (decl)))
info_tag = INDEX_INSTANCE_OPERATOR_BEGIN;
else
info_tag = INDEX_INSTANCE_METHOD_BEGIN;
}
else
info_tag = INDEX_FUNCTION_BEGIN;
if (info_tag == INDEX_ERROR)
return;
gen_indexing_info (info_tag,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
if (DECL_CLASS_CONTEXT (decl))
dc = TYPE_NAME (DECL_CLASS_CONTEXT (decl));
else if (DECL_CONTEXT (decl))
dc = DECL_CONTEXT (decl);
if (dc != NULL_TREE)
gen_indexing_info (INDEX_CLASS_INHERITANCE,
IDENTIFIER_POINTER (DECL_NAME (dc)),
DECL_SOURCE_LINE (dc));
}
int
start_function (declspecs, declarator, attrs, flags)
tree declspecs, declarator, attrs;
int flags;
{
tree decl1;
tree ctype = NULL_TREE;
tree fntype;
tree restype;
int doing_friend = 0;
struct cp_binding_level *bl;
tree current_function_parms;
my_friendly_assert (TREE_CODE (TREE_VALUE (void_list_node)) == VOID_TYPE, 160);
my_friendly_assert (TREE_CHAIN (void_list_node) == NULL_TREE, 161);
if (have_extern_spec)
{
declspecs = tree_cons (NULL_TREE, get_identifier ("extern"), declspecs);
have_extern_spec = false;
}
if (flags & SF_PRE_PARSED)
{
decl1 = declarator;
fntype = TREE_TYPE (decl1);
if (TREE_CODE (fntype) == METHOD_TYPE)
ctype = TYPE_METHOD_BASETYPE (fntype);
if (!ctype && DECL_FRIEND_P (decl1))
{
ctype = DECL_FRIEND_CONTEXT (decl1);
if (ctype && TREE_CODE (ctype) != RECORD_TYPE)
ctype = NULL_TREE;
else
doing_friend = 1;
}
last_function_parms = DECL_ARGUMENTS (decl1);
}
else
{
decl1 = grokdeclarator (declarator, declspecs, FUNCDEF, 1, NULL);
if (decl1 == NULL_TREE || TREE_CODE (decl1) != FUNCTION_DECL)
return 0;
cplus_decl_attributes (&decl1, attrs, 0);
if (current_binding_level == global_binding_level)
maybe_apply_pragma_weak (decl1);
fntype = TREE_TYPE (decl1);
restype = TREE_TYPE (fntype);
if (CLASS_TYPE_P (restype) && !CLASSTYPE_GOT_SEMICOLON (restype))
{
error ("semicolon missing after declaration of `%#T'", restype);
shadow_tag (build_tree_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 (DECL_DECLARED_INLINE_P (decl1)
&& lookup_attribute ("noinline", attrs))
warning_with_decl (decl1,
"inline function `%s' given attribute noinline");
if (DECL_MAYBE_IN_CHARGE_CONSTRUCTOR_P (decl1))
adjust_clone_args (decl1);
if (ctype != NULL_TREE && DECL_STATIC_FUNCTION_P (decl1)
&& TREE_CODE (TREE_TYPE (decl1)) == METHOD_TYPE)
{
revert_static_member_fn (decl1);
last_function_parms = TREE_CHAIN (last_function_parms);
ctype = NULL_TREE;
}
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)));
if (ctype)
push_nested_class (ctype, 1);
else if (DECL_STATIC_FUNCTION_P (decl1))
push_nested_class (DECL_CONTEXT (decl1), 2);
if (flags & SF_INCLASS_INLINE)
maybe_begin_member_template_processing (decl1);
if (warn_ecpp
&& DECL_OVERLOADED_OPERATOR_P (decl1) == NOP_EXPR
&& TREE_CODE (TREE_TYPE (fntype)) == VOID_TYPE)
warning ("`operator=' should return a reference to `*this'");
if (!DECL_INITIAL (decl1))
DECL_INITIAL (decl1) = error_mark_node;
TREE_STATIC (decl1) = 1;
if (processing_template_decl)
decl1 = push_template_decl (decl1);
current_function_decl = decl1;
current_function_parms = last_function_parms;
if (! processing_template_decl)
check_function_type (decl1, current_function_parms);
restype = TREE_TYPE (fntype);
if (c_promoting_integer_type_p (restype))
restype = type_promotes_to (restype);
if (DECL_RESULT (decl1) == NULL_TREE)
{
DECL_RESULT (decl1)
= build_decl (RESULT_DECL, 0, TYPE_MAIN_VARIANT (restype));
c_apply_type_quals_to_decl (cp_type_quals (restype),
DECL_RESULT (decl1));
}
bl = current_binding_level;
init_function_start (decl1, input_filename, lineno);
current_binding_level = bl;
immediate_size_expand = 0;
cfun->x_dont_save_pending_sizes_p = 1;
begin_stmt_tree (&DECL_SAVED_TREE (decl1));
announce_function (decl1);
if (flag_gen_index)
gen_start_function_index (decl1);
if (!processing_template_decl && !(flags & SF_PRE_PARSED))
{
if (!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);
}
fntype = TREE_TYPE (decl1);
}
current_function_decl = decl1;
cfun->decl = decl1;
if (!DECL_PENDING_INLINE_P (decl1))
DECL_SAVED_FUNCTION_DATA (decl1) = NULL;
if (ctype && !doing_friend && !DECL_STATIC_FUNCTION_P (decl1))
{
tree t = DECL_ARGUMENTS (decl1);
my_friendly_assert (t != NULL_TREE && TREE_CODE (t) == PARM_DECL,
162);
my_friendly_assert (TREE_CODE (TREE_TYPE (t)) == POINTER_TYPE,
19990811);
cp_function_chain->x_current_class_ref
= build_indirect_ref (t, NULL);
cp_function_chain->x_current_class_ptr = t;
t = TREE_CHAIN (t);
if (DECL_HAS_IN_CHARGE_PARM_P (decl1))
{
current_in_charge_parm = t;
t = TREE_CHAIN (t);
}
if (DECL_HAS_VTT_PARM_P (decl1))
{
if (DECL_NAME (t) != vtt_parm_identifier)
abort ();
current_vtt_parm = t;
}
}
if (DECL_INTERFACE_KNOWN (decl1))
{
tree ctx = decl_function_context (decl1);
if (DECL_NOT_REALLY_EXTERN (decl1))
DECL_EXTERNAL (decl1) = 0;
if (ctx != NULL_TREE && DECL_DECLARED_INLINE_P (ctx)
&& TREE_PUBLIC (ctx))
comdat_linkage (decl1);
}
else if (interface_unknown == 0
&& (! DECL_TEMPLATE_INSTANTIATION (decl1)
|| flag_alt_external_templates))
{
if (DECL_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1)
|| processing_template_decl)
{
DECL_EXTERNAL (decl1)
= (interface_only
|| (DECL_DECLARED_INLINE_P (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_DECLARED_INLINE_P (decl1)
|| DECL_TEMPLATE_INSTANTIATION (decl1))
&& ! DECL_INTERFACE_KNOWN (decl1)
&& ! decl_function_context (decl1))
DECL_DEFER_OUTPUT (decl1) = 1;
else
DECL_INTERFACE_KNOWN (decl1) = 1;
}
pushlevel (0);
current_binding_level->parm_flag = 1;
cplus_decl_attributes (&decl1, attrs, (int)ATTR_FLAG_FUNCTION_DEF);
++function_depth;
if (DECL_DESTRUCTOR_P (decl1))
{
dtor_label = build_decl (LABEL_DECL, NULL_TREE, NULL_TREE);
DECL_CONTEXT (dtor_label) = current_function_decl;
}
if (DECL_CW_ASM_FUNCTION (current_function_decl))
{
cw_asm_state = cw_asm_decls;
cw_asm_in_decl = 0;
}
start_fname_decls ();
store_parm_decls (current_function_parms);
return 1;
}
void
store_parm_decls (current_function_parms)
tree current_function_parms;
{
register tree fndecl = current_function_decl;
register tree parm;
tree nonparms = NULL_TREE;
if (current_function_parms)
{
tree specparms = current_function_parms;
tree next;
storedecls (NULL_TREE);
specparms = nreverse (specparms);
for (parm = specparms; parm; parm = next)
{
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_DECL)
{
if (DECL_NAME (parm) == NULL_TREE
|| TREE_CODE (parm) != VOID_TYPE)
pushdecl (parm);
else
error ("parameter `%D' declared void", parm);
}
else
{
TREE_CHAIN (parm) = NULL_TREE;
nonparms = chainon (nonparms, parm);
}
}
DECL_ARGUMENTS (fndecl) = getdecls ();
storetags (gettags ());
}
else
DECL_ARGUMENTS (fndecl) = NULL_TREE;
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
current_eh_spec_block = begin_eh_spec_block ();
}
static void
save_function_data (decl)
tree decl;
{
struct language_function *f;
my_friendly_assert (!DECL_PENDING_INLINE_P (decl),
19990908);
f = ((struct language_function *)
ggc_alloc (sizeof (struct language_function)));
memcpy (f, cp_function_chain, sizeof (struct language_function));
DECL_SAVED_FUNCTION_DATA (decl) = f;
f->base.x_stmt_tree.x_last_stmt = NULL_TREE;
f->base.x_stmt_tree.x_last_expr_type = NULL_TREE;
f->x_named_label_uses = NULL;
f->bindings = NULL;
f->x_local_names = NULL;
f->x_expanding_p = 1;
if (current_function_cannot_inline)
{
f->cannot_inline = current_function_cannot_inline;
DECL_INLINE (decl) = 0;
}
}
static void
begin_constructor_body ()
{
}
static void
finish_constructor_body ()
{
}
static void
begin_destructor_body ()
{
tree if_stmt;
tree compound_stmt;
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (boolean_true_node, if_stmt);
compound_stmt = begin_compound_stmt (0);
initialize_vtbl_ptrs (current_class_ptr);
finish_compound_stmt (0, compound_stmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
push_base_cleanups ();
}
static void
finish_destructor_body ()
{
tree exprstmt;
add_stmt (build_stmt (LABEL_STMT, dtor_label));
if (DECL_VIRTUAL_P (current_function_decl))
{
tree if_stmt;
tree virtual_size = cxx_sizeof (current_class_type);
exprstmt = build_op_delete_call
(DELETE_EXPR, current_class_ptr, virtual_size,
LOOKUP_NORMAL | LOOKUP_SPECULATIVELY, NULL_TREE);
if_stmt = begin_if_stmt ();
finish_if_stmt_cond (build (BIT_AND_EXPR, integer_type_node,
current_in_charge_parm,
integer_one_node),
if_stmt);
finish_expr_stmt (exprstmt);
finish_then_clause (if_stmt);
finish_if_stmt ();
}
}
tree
begin_function_body ()
{
tree stmt;
if (processing_template_decl)
;
else
keep_next_level (1);
stmt = begin_compound_stmt (0);
COMPOUND_STMT_BODY_BLOCK (stmt) = 1;
if (processing_template_decl)
;
else if (DECL_CONSTRUCTOR_P (current_function_decl))
begin_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
begin_destructor_body ();
return stmt;
}
void
finish_function_body (compstmt)
tree compstmt;
{
finish_compound_stmt (0, compstmt);
if (processing_template_decl)
;
else if (DECL_CONSTRUCTOR_P (current_function_decl))
finish_constructor_body ();
else if (DECL_DESTRUCTOR_P (current_function_decl))
finish_destructor_body ();
}
tree
finish_function (flags)
int flags;
{
register tree fndecl = current_function_decl;
tree fntype, ctype = NULL_TREE;
int inclass_inline = (flags & 2) != 0;
int nested;
if (fndecl == NULL_TREE)
return error_mark_node;
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl)
&& DECL_VIRTUAL_P (fndecl)
&& !processing_template_decl)
{
tree fnclass = DECL_CONTEXT (fndecl);
if (fndecl == CLASSTYPE_KEY_METHOD (fnclass))
{
if (DECL_DECLARED_INLINE_P (fndecl))
CLASSTYPE_KEY_METHOD (fnclass) = NULL_TREE;
keyed_classes = tree_cons (NULL_TREE, fnclass, keyed_classes);
}
}
if (flag_gen_index)
{
if (!processing_template_decl
&& !DECL_USE_TEMPLATE (fndecl)
&& !DECL_ARTIFICIAL (fndecl)
&& !DECL_BASE_DESTRUCTOR_P (fndecl)
&& !DECL_COMPLETE_DESTRUCTOR_P (fndecl)
&& !DECL_BASE_CONSTRUCTOR_P (fndecl)
&& !DECL_COMPLETE_CONSTRUCTOR_P (fndecl))
{
int info_tag;
if (DECL_STATIC_FUNCTION_P (fndecl))
info_tag = INDEX_CLASS_METHOD_END;
else if (DECL_NONSTATIC_MEMBER_FUNCTION_P (fndecl))
info_tag = INDEX_INSTANCE_METHOD_END;
else
info_tag = INDEX_FUNCTION_END;
gen_indexing_info (info_tag, NULL, lineno);
}
}
nested = function_depth > 1;
fntype = TREE_TYPE (fndecl);
my_friendly_assert (building_stmt_tree (), 20000911);
finish_fname_decls ();
if (!DECL_CLONED_FUNCTION_P (fndecl))
{
if (DECL_MAIN_P (current_function_decl))
{
#if VMS_TARGET
finish_return_stmt (integer_one_node);
#else
finish_return_stmt (integer_zero_node);
#endif
}
if (flag_exceptions && !processing_template_decl
&& flag_enforce_eh_specs
&& TYPE_RAISES_EXCEPTIONS (TREE_TYPE (current_function_decl)))
finish_eh_spec_block (TYPE_RAISES_EXCEPTIONS
(TREE_TYPE (current_function_decl)),
current_eh_spec_block);
}
finish_stmt_tree (&DECL_SAVED_TREE (fndecl));
if (current_binding_level->parm_flag != 1)
{
if (errorcount == 0)
abort ();
DECL_SAVED_TREE (fndecl) = build_stmt (COMPOUND_STMT, NULL_TREE);
while (current_binding_level->parm_flag != 1)
{
if (current_binding_level->parm_flag == 2)
pop_nested_class ();
else
poplevel (0, 0, 0);
}
}
poplevel (1, 0, 1);
if (current_function_return_value)
{
tree r = current_function_return_value;
if (r != error_mark_node
&& aggregate_value_p (TREE_TYPE (TREE_TYPE (fndecl))))
{
DECL_ALIGN (r) = DECL_ALIGN (DECL_RESULT (fndecl));
walk_tree_without_duplicates (&DECL_SAVED_TREE (fndecl),
nullify_returns_r, r);
}
else
current_function_return_value = NULL_TREE;
}
if (current_class_name)
ctype = current_class_type;
DECL_CONTEXT (DECL_RESULT (fndecl)) = fndecl;
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
if (!processing_template_decl)
save_function_data (fndecl);
if (!processing_template_decl && calls_setjmp_p (fndecl))
DECL_UNINLINABLE (fndecl) = 1;
if (warn_return_type
&& !processing_template_decl
&& TREE_CODE (TREE_TYPE (fntype)) != VOID_TYPE
&& !current_function_returns_value && !current_function_returns_null
&& !current_function_returns_abnormally
&& !DECL_NAME (DECL_RESULT (fndecl))
&& DECL_INLINE (fndecl))
warning ("no return statement in function returning non-void");
free_after_parsing (cfun);
free_after_compilation (cfun);
cfun = NULL;
if (inclass_inline)
maybe_end_member_template_processing ();
if (ctype)
pop_nested_class ();
--function_depth;
if (! nested)
current_function_decl = NULL_TREE;
return fndecl;
}
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 (attrlist)
cplus_decl_attributes (&fndecl, attrlist, 0);
if (fndecl == void_type_node)
return fndecl;
if (TREE_CODE (fndecl) != FUNCTION_DECL)
return NULL_TREE;
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)
error ("`%D' is already defined in class `%T'", fndecl,
DECL_CONTEXT (fndecl));
}
return void_type_node;
}
check_template_shadow (fndecl);
DECL_DECLARED_INLINE_P (fndecl) = 1;
DID_INLINE_FUNC (fndecl) = 0;
if (flag_default_inline)
DECL_INLINE (fndecl) = 1;
if (processing_template_decl && !DECL_TEMPLATE_SPECIALIZATION (fndecl))
fndecl = push_template_decl (fndecl);
if (! DECL_FRIEND_P (fndecl))
{
if (TREE_CHAIN (fndecl))
{
fndecl = copy_node (fndecl);
TREE_CHAIN (fndecl) = NULL_TREE;
}
grok_special_member_properties (fndecl);
}
cp_finish_decl (fndecl, NULL_TREE, NULL_TREE, 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;
}
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
maybe_register_incomplete_var (var)
tree var;
{
my_friendly_assert (TREE_CODE (var) == VAR_DECL, 20020406);
if (!processing_template_decl && TREE_TYPE (var) != error_mark_node
&& DECL_EXTERNAL (var))
{
tree inner_type = TREE_TYPE (var);
while (TREE_CODE (inner_type) == ARRAY_TYPE)
inner_type = TREE_TYPE (inner_type);
inner_type = TYPE_MAIN_VARIANT (inner_type);
if ((!COMPLETE_TYPE_P (inner_type) && CLASS_TYPE_P (inner_type))
|| (TYPE_LANG_SPECIFIC (inner_type)
&& TYPE_BEING_DEFINED (inner_type)))
incomplete_vars = tree_cons (inner_type, var, incomplete_vars);
}
}
void
complete_vars (type)
tree type;
{
tree *list = &incomplete_vars;
my_friendly_assert (CLASS_TYPE_P (type), 20020406);
while (*list)
{
if (same_type_p (type, TREE_PURPOSE (*list)))
{
tree var = TREE_VALUE (*list);
complete_type (TREE_TYPE (var));
*list = TREE_CHAIN (*list);
}
else
list = &TREE_CHAIN (*list);
}
}
tree
cxx_maybe_build_cleanup (decl)
tree decl;
{
tree type = TREE_TYPE (decl);
if (type != error_mark_node && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
int flags = LOOKUP_NORMAL|LOOKUP_DESTRUCTOR;
tree rval;
special_function_kind dtor = sfk_complete_destructor;
if (flag_apple_kext
&& has_apple_kext_compatibility_attr_p (type))
{
if (! has_empty_operator_delete_p (type) || pedantic)
{
cp_warning_at ("'%D' is an instance of a class which does "
"not allow global or stack-based objects; it "
"does not have an empty `operator delete', and "
"so it will ** NOT ** be destructed.", decl);
return 0;
}
dtor = sfk_deleting_destructor;
}
if (TREE_CODE (type) == ARRAY_TYPE)
rval = decl;
else
{
cxx_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,
dtor, flags, 0);
if (TYPE_USES_VIRTUAL_BASECLASSES (type)
&& ! TYPE_HAS_DESTRUCTOR (type))
rval = build_compound_expr (tree_cons (NULL_TREE, rval,
build_tree_list (NULL_TREE, build_vbase_delete (type, decl))));
return rval;
}
return NULL_TREE;
}
void
finish_stmt ()
{
last_expr_type = NULL_TREE;
}
void
revert_static_member_fn (decl)
tree decl;
{
tree tmp;
tree function = TREE_TYPE (decl);
tree args = TYPE_ARG_TYPES (function);
if (cp_type_quals (TREE_TYPE (TREE_VALUE (args)))
!= TYPE_UNQUALIFIED)
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;
}
void
cxx_push_function_context (f)
struct function *f;
{
struct language_function *p
= ((struct language_function *)
ggc_alloc_cleared (sizeof (struct language_function)));
f->language = p;
expanding_p = 0;
current_stmt_tree ()->stmts_are_full_exprs_p = 1;
}
void
cxx_pop_function_context (f)
struct function *f;
{
f->language = 0;
}
enum cp_tree_node_structure_enum
cp_tree_node_structure (t)
union lang_tree_node *t;
{
switch (TREE_CODE (&t->generic))
{
case DEFAULT_ARG: return TS_CP_IDENTIFIER;
case IDENTIFIER_NODE: return TS_CP_IDENTIFIER;
case OVERLOAD: return TS_CP_OVERLOAD;
case TEMPLATE_PARM_INDEX: return TS_CP_TPI;
case PTRMEM_CST: return TS_CP_PTRMEM;
case WRAPPER: return TS_CP_WRAPPER;
case SRCLOC: return TS_CP_SRCLOC;
default: return TS_CP_GENERIC;
}
}
tree
identifier_global_value (t)
tree t;
{
return IDENTIFIER_GLOBAL_VALUE (t);
}
tree
build_void_list_node ()
{
tree t = build_tree_list (NULL_TREE, void_type_node);
TREE_PARMLIST (t) = 1;
return t;
}
static int
cp_missing_noreturn_ok_p (decl)
tree decl;
{
return DECL_MAIN_P (decl);
}
#include "gt-cp-decl.h"