#include "config.h"
#include "system.h"
#include "tree.h"
#include "cp-tree.h"
#include "except.h"
#include "lex.h"
#include "toplev.h"
#include "flags.h"
#define RECHAIN_STMTS(stmt, substmt, last) \
do { \
substmt = last; \
TREE_CHAIN (stmt) = NULL_TREE; \
last_tree = stmt; \
} while (0)
#define RECHAIN_STMTS_FROM_LAST(stmt, substmt) \
RECHAIN_STMTS (stmt, substmt, last_tree)
#define RECHAIN_STMTS_FROM_CHAIN(stmt, substmt) \
RECHAIN_STMTS (stmt, substmt, TREE_CHAIN (stmt))
void
finish_expr_stmt (expr)
tree expr;
{
if (expr != NULL_TREE)
{
if (!processing_template_decl)
{
emit_line_note (input_filename, lineno);
if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
expr = default_conversion (expr);
}
cplus_expand_expr_stmt (expr);
clear_momentary ();
}
finish_stmt ();
}
tree
begin_if_stmt ()
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
add_tree (r);
}
else
r = NULL_TREE;
do_pushlevel ();
return r;
}
void
finish_if_stmt_cond (cond, if_stmt)
tree cond;
tree if_stmt;
{
if (processing_template_decl)
{
if (last_tree != if_stmt)
RECHAIN_STMTS_FROM_LAST (if_stmt, IF_COND (if_stmt));
else
IF_COND (if_stmt) = copy_to_permanent (cond);
}
else
{
emit_line_note (input_filename, lineno);
expand_start_cond (condition_conversion (cond), 0);
}
}
tree
finish_then_clause (if_stmt)
tree if_stmt;
{
if (processing_template_decl)
{
RECHAIN_STMTS_FROM_CHAIN (if_stmt,
THEN_CLAUSE (if_stmt));
last_tree = if_stmt;
return if_stmt;
}
else
return NULL_TREE;
}
void
begin_else_clause ()
{
if (!processing_template_decl)
expand_start_else ();
}
void
finish_else_clause (if_stmt)
tree if_stmt;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (if_stmt, ELSE_CLAUSE (if_stmt));
}
void
finish_if_stmt ()
{
if (!processing_template_decl)
expand_end_cond ();
do_poplevel ();
finish_stmt ();
}
tree
begin_while_stmt ()
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (WHILE_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
}
else
{
emit_nop ();
emit_line_note (input_filename, lineno);
expand_start_loop (1);
r = NULL_TREE;
}
do_pushlevel ();
return r;
}
void
finish_while_stmt_cond (cond, while_stmt)
tree cond;
tree while_stmt;
{
if (processing_template_decl)
{
if (last_tree != while_stmt)
RECHAIN_STMTS_FROM_LAST (while_stmt,
WHILE_COND (while_stmt));
else
TREE_OPERAND (while_stmt, 0) = copy_to_permanent (cond);
}
else
{
emit_line_note (input_filename, lineno);
expand_exit_loop_if_false (0, condition_conversion (cond));
}
if (getdecls () == NULL_TREE)
{
do_poplevel ();
do_pushlevel ();
}
}
void
finish_while_stmt (while_stmt)
tree while_stmt;
{
do_poplevel ();
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (while_stmt, WHILE_BODY (while_stmt));
else
expand_end_loop ();
finish_stmt ();
}
tree
begin_do_stmt ()
{
if (processing_template_decl)
{
tree r = build_min_nt (DO_STMT, NULL_TREE, NULL_TREE);
add_tree (r);
return r;
}
else
{
emit_nop ();
emit_line_note (input_filename, lineno);
expand_start_loop_continue_elsewhere (1);
return NULL_TREE;
}
}
void
finish_do_body (do_stmt)
tree do_stmt;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (do_stmt, DO_BODY (do_stmt));
else
expand_loop_continue_here ();
}
void
finish_do_stmt (cond, do_stmt)
tree cond;
tree do_stmt;
{
if (processing_template_decl)
DO_COND (do_stmt) = copy_to_permanent (cond);
else
{
emit_line_note (input_filename, lineno);
expand_exit_loop_if_false (0, condition_conversion (cond));
expand_end_loop ();
}
clear_momentary ();
finish_stmt ();
}
void
finish_return_stmt (expr)
tree expr;
{
emit_line_note (input_filename, lineno);
c_expand_return (expr);
finish_stmt ();
}
tree
begin_for_stmt ()
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (FOR_STMT, NULL_TREE, NULL_TREE,
NULL_TREE, NULL_TREE);
add_tree (r);
}
else
r = NULL_TREE;
if (flag_new_for_scope > 0)
{
do_pushlevel ();
note_level_for_for ();
}
return r;
}
void
finish_for_init_stmt (for_stmt)
tree for_stmt;
{
if (processing_template_decl)
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_INIT_STMT (for_stmt));
}
else
{
emit_nop ();
emit_line_note (input_filename, lineno);
expand_start_loop_continue_elsewhere (1);
}
do_pushlevel ();
}
void
finish_for_cond (cond, for_stmt)
tree cond;
tree for_stmt;
{
if (processing_template_decl)
{
if (last_tree != for_stmt)
RECHAIN_STMTS_FROM_LAST (for_stmt, FOR_COND (for_stmt));
else
FOR_COND (for_stmt) = copy_to_permanent (cond);
}
else
{
emit_line_note (input_filename, lineno);
if (cond)
expand_exit_loop_if_false (0, condition_conversion (cond));
}
if (getdecls () == NULL_TREE)
{
do_poplevel ();
do_pushlevel ();
}
}
void
finish_for_expr (expr, for_stmt)
tree expr;
tree for_stmt;
{
if (processing_template_decl)
FOR_EXPR (for_stmt) = expr;
push_momentary ();
}
void
finish_for_stmt (expr, for_stmt)
tree expr;
tree for_stmt;
{
do_poplevel ();
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (for_stmt, FOR_BODY (for_stmt));
else
{
emit_line_note (input_filename, lineno);
expand_loop_continue_here ();
if (expr)
cplus_expand_expr_stmt (expr);
expand_end_loop ();
}
pop_momentary ();
if (flag_new_for_scope > 0)
do_poplevel ();
finish_stmt ();
}
void
finish_break_stmt ()
{
emit_line_note (input_filename, lineno);
if (processing_template_decl)
add_tree (build_min_nt (BREAK_STMT));
else if ( ! expand_exit_something ())
cp_error ("break statement not within loop or switch");
}
void
finish_continue_stmt ()
{
emit_line_note (input_filename, lineno);
if (processing_template_decl)
add_tree (build_min_nt (CONTINUE_STMT));
else if (! expand_continue_loop (0))
cp_error ("continue statement not within a loop");
}
void
begin_switch_stmt ()
{
do_pushlevel ();
}
tree
finish_switch_cond (cond)
tree cond;
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (SWITCH_STMT, cond, NULL_TREE);
add_tree (r);
}
else if (cond != error_mark_node)
{
emit_line_note (input_filename, lineno);
c_expand_start_case (cond);
r = NULL_TREE;
}
else
{
c_expand_start_case (boolean_false_node);
r = NULL_TREE;
}
push_switch ();
push_momentary ();
return r;
}
void
finish_switch_stmt (cond, switch_stmt)
tree cond;
tree switch_stmt;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (switch_stmt, SWITCH_BODY (switch_stmt));
else
expand_end_case (cond);
pop_momentary ();
pop_switch ();
do_poplevel ();
finish_stmt ();
}
void
finish_case_label (low_value, high_value)
tree low_value;
tree high_value;
{
do_case (low_value, high_value);
}
void
finish_goto_stmt (destination)
tree destination;
{
if (processing_template_decl)
add_tree (build_min_nt (GOTO_STMT, destination));
else
{
emit_line_note (input_filename, lineno);
if (TREE_CODE (destination) == IDENTIFIER_NODE)
{
tree decl = lookup_label (destination);
TREE_USED (decl) = 1;
expand_goto (decl);
}
else
expand_computed_goto (destination);
}
}
tree
begin_try_block ()
{
if (processing_template_decl)
{
tree r = build_min_nt (TRY_BLOCK, NULL_TREE,
NULL_TREE);
add_tree (r);
return r;
}
else
{
emit_line_note (input_filename, lineno);
expand_start_try_stmts ();
return NULL_TREE;
}
}
void
finish_try_block (try_block)
tree try_block;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_LAST (try_block, TRY_STMTS (try_block));
else
{
expand_start_all_catch ();
}
}
void
finish_handler_sequence (try_block)
tree try_block;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (try_block, TRY_HANDLERS (try_block));
else
{
expand_end_all_catch ();
}
}
tree
begin_handler ()
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (HANDLER, NULL_TREE, NULL_TREE);
add_tree (r);
}
else
r = NULL_TREE;
do_pushlevel ();
return r;
}
void
finish_handler_parms (handler)
tree handler;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_PARMS (handler));
}
void
finish_handler (handler)
tree handler;
{
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (handler, HANDLER_BODY (handler));
else
expand_end_catch_block ();
do_poplevel ();
}
tree
begin_compound_stmt (has_no_scope)
int has_no_scope;
{
tree r;
if (processing_template_decl)
{
r = build_min_nt (COMPOUND_STMT, NULL_TREE);
add_tree (r);
if (has_no_scope)
COMPOUND_STMT_NO_SCOPE (r) = 1;
}
else
r = NULL_TREE;
if (!has_no_scope)
do_pushlevel ();
return r;
}
tree
finish_compound_stmt (has_no_scope, compound_stmt)
int has_no_scope;
tree compound_stmt;
{
tree r;
if (!has_no_scope)
r = do_poplevel ();
else
r = NULL_TREE;
if (processing_template_decl)
RECHAIN_STMTS_FROM_CHAIN (compound_stmt,
COMPOUND_BODY (compound_stmt));
finish_stmt ();
return r;
}
void
finish_asm_stmt (cv_qualifier, string, output_operands,
input_operands, clobbers)
tree cv_qualifier;
tree string;
tree output_operands;
tree input_operands;
tree clobbers;
{
if (TREE_CHAIN (string))
string = combine_strings (string);
if (processing_template_decl)
{
tree r = build_min_nt (ASM_STMT, cv_qualifier, string,
output_operands, input_operands,
clobbers);
add_tree (r);
}
else
{
emit_line_note (input_filename, lineno);
if (output_operands != NULL_TREE || input_operands != NULL_TREE
|| clobbers != NULL_TREE)
{
tree t;
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
for (t = input_operands; t; t = TREE_CHAIN (t))
TREE_VALUE (t) = decay_conversion (TREE_VALUE (t));
c_expand_asm_operands (string, output_operands,
input_operands,
clobbers,
cv_qualifier
== ridpointers[(int) RID_VOLATILE],
input_filename, lineno);
}
else
{
if (cv_qualifier != NULL_TREE
&& cv_qualifier != ridpointers[(int) RID_VOLATILE])
cp_warning ("%s qualifier ignored on asm",
IDENTIFIER_POINTER (cv_qualifier));
expand_asm (string);
}
finish_stmt ();
}
}
tree
finish_parenthesized_expr (expr)
tree expr;
{
if (IS_EXPR_CODE_CLASS (TREE_CODE_CLASS (TREE_CODE (expr))))
C_SET_EXP_ORIGINAL_CODE (expr, ERROR_MARK);
return expr;
}
tree
begin_stmt_expr ()
{
keep_next_level ();
return processing_template_decl ? last_tree : expand_start_stmt_expr();
}
tree
finish_stmt_expr (rtl_expr, expr)
tree rtl_expr;
tree expr;
{
tree result;
if (!processing_template_decl)
{
rtl_expr = expand_end_stmt_expr (rtl_expr);
TREE_SIDE_EFFECTS (rtl_expr) = 1;
}
if (TREE_CODE (expr) == BLOCK)
{
if (processing_template_decl)
result = build_min_nt (BIND_EXPR, NULL_TREE, last_tree,
NULL_TREE);
else
result = build (BIND_EXPR, TREE_TYPE (rtl_expr),
NULL_TREE, rtl_expr, expr);
delete_block (expr);
}
else
result = expr;
if (processing_template_decl)
{
last_tree = rtl_expr;
TREE_CHAIN (last_tree) = NULL_TREE;
}
return result;
}
tree
finish_call_expr (fn, args, koenig)
tree fn;
tree args;
int koenig;
{
tree result;
if (koenig)
{
if (TREE_CODE (fn) == BIT_NOT_EXPR)
fn = build_x_unary_op (BIT_NOT_EXPR, TREE_OPERAND (fn, 0));
else if (TREE_CODE (fn) != TEMPLATE_ID_EXPR)
fn = do_identifier (fn, 2, args);
}
result = build_x_function_call (fn, args, current_class_ref);
if (TREE_CODE (result) == CALL_EXPR
&& (! TREE_TYPE (result)
|| TREE_CODE (TREE_TYPE (result)) != VOID_TYPE))
result = require_complete_type (result);
return result;
}
tree
finish_increment_expr (expr, code)
tree expr;
enum tree_code code;
{
if (TREE_CODE (expr) == OFFSET_REF)
expr = resolve_offset_ref (expr);
return build_x_unary_op (code, expr);
}
tree
finish_this_expr ()
{
tree result;
if (current_class_ptr)
{
#ifdef WARNING_ABOUT_CCD
TREE_USED (current_class_ptr) = 1;
#endif
result = current_class_ptr;
}
else if (current_function_decl
&& DECL_STATIC_FUNCTION_P (current_function_decl))
{
error ("`this' is unavailable for static member functions");
result = error_mark_node;
}
else
{
if (current_function_decl)
error ("invalid use of `this' in non-member function");
else
error ("invalid use of `this' at top level");
result = error_mark_node;
}
return result;
}
tree
finish_object_call_expr (fn, object, args)
tree fn;
tree object;
tree args;
{
#if 0
tree real_fn = build_component_ref (object, fn, NULL_TREE, 1);
return finish_call_expr (real_fn, args);
#else
if (TREE_CODE (fn) == TYPE_DECL)
{
if (processing_template_decl)
fn = DECL_NAME (fn);
else
{
cp_error ("calling type `%T' like a method", fn);
return error_mark_node;
}
}
return build_method_call (object, fn, args, NULL_TREE, LOOKUP_NORMAL);
#endif
}
tree
finish_qualified_object_call_expr (fn, object, args)
tree fn;
tree object;
tree args;
{
if (IS_SIGNATURE (TREE_OPERAND (fn, 0)))
{
warning ("signature name in scope resolution ignored");
return finish_object_call_expr (TREE_OPERAND (fn, 1), object, args);
}
else
return build_scoped_method_call (object, TREE_OPERAND (fn, 0),
TREE_OPERAND (fn, 1), args);
}
tree
finish_pseudo_destructor_call_expr (object, scope, destructor)
tree object;
tree scope;
tree destructor;
{
if (scope && scope != destructor)
cp_error ("destructor specifier `%T::~%T()' must have matching names",
scope, destructor);
if ((scope == NULL_TREE || IDENTIFIER_GLOBAL_VALUE (destructor))
&& (TREE_CODE (TREE_TYPE (object)) !=
TREE_CODE (TREE_TYPE (IDENTIFIER_GLOBAL_VALUE (destructor)))))
cp_error ("`%E' is not of type `%T'", object, destructor);
return cp_convert (void_type_node, object);
}
tree
finish_qualified_call_expr (fn, args)
tree fn;
tree args;
{
if (processing_template_decl)
return build_min_nt (CALL_EXPR, copy_to_permanent (fn), args,
NULL_TREE);
else
return build_member_call (TREE_OPERAND (fn, 0),
TREE_OPERAND (fn, 1),
args);
}
tree
finish_label_address_expr (label)
tree label;
{
tree result;
label = lookup_label (label);
if (label == NULL_TREE)
result = null_pointer_node;
else
{
TREE_USED (label) = 1;
result = build1 (ADDR_EXPR, ptr_type_node, label);
TREE_CONSTANT (result) = 1;
}
return result;
}
tree
finish_unary_op_expr (code, expr)
enum tree_code code;
tree expr;
{
tree result = build_x_unary_op (code, expr);
if (code == NEGATE_EXPR && TREE_CODE (expr) == INTEGER_CST)
TREE_NEGATED_INT (result) = 1;
overflow_warning (result);
return result;
}
tree
finish_id_expr (expr)
tree expr;
{
if (TREE_CODE (expr) == IDENTIFIER_NODE)
expr = do_identifier (expr, 1, NULL_TREE);
return expr;
}
int
begin_new_placement ()
{
return suspend_momentary ();
}
tree
finish_new_placement (args, cookie)
tree args;
int cookie;
{
resume_momentary (cookie);
return args;
}
int
begin_function_definition (decl_specs, declarator)
tree decl_specs;
tree declarator;
{
tree specs;
tree attrs;
split_specs_attrs (decl_specs, &specs, &attrs);
if (!start_function (specs, declarator, attrs, 0))
return 0;
reinit_parse_for_function ();
reset_specialization ();
return 1;
}
tree
begin_constructor_declarator (scope, name)
tree scope;
tree name;
{
tree result = build_parse_node (SCOPE_REF, scope, name);
enter_scope_of (result);
return result;
}
tree
finish_declarator (declarator, declspecs, attributes,
prefix_attributes, initialized)
tree declarator;
tree declspecs;
tree attributes;
tree prefix_attributes;
int initialized;
{
return start_decl (declarator, declspecs, initialized, attributes,
prefix_attributes);
}
void
finish_translation_unit ()
{
while (! toplevel_bindings_p ())
poplevel (0, 0, 0);
while (current_namespace != global_namespace)
pop_namespace ();
finish_file ();
}
tree
finish_template_type_parm (aggr, identifier)
tree aggr;
tree identifier;
{
if (aggr == signature_type_node)
sorry ("signature as template type parameter");
else if (aggr != class_type_node)
{
pedwarn ("template type parameters must use the keyword `class' or `typename'");
aggr = class_type_node;
}
return build_tree_list (aggr, identifier);
}
tree
finish_template_template_parm (aggr, identifier)
tree aggr;
tree identifier;
{
tree decl = build_decl (TYPE_DECL, identifier, NULL_TREE);
tree tmpl = build_lang_decl (TEMPLATE_DECL, identifier, NULL_TREE);
DECL_TEMPLATE_PARMS (tmpl) = current_template_parms;
DECL_TEMPLATE_RESULT (tmpl) = decl;
SET_DECL_ARTIFICIAL (decl);
end_template_decl ();
return finish_template_type_parm (aggr, tmpl);
}
tree
finish_parmlist (parms, ellipsis)
tree parms;
int ellipsis;
{
if (!ellipsis)
chainon (parms, void_list_node);
if (parms != NULL_TREE)
TREE_PARMLIST (parms) = 1;
return parms;
}
tree
begin_class_definition (t)
tree t;
{
push_obstacks_nochange ();
end_temporary_allocation ();
if ( flag_dump_symbols )
{
extern tree current_aggr;
int l_base_count = 0; tree typename = DECL_NAME (TYPE_NAME (t));
if (!ANON_AGGRNAME_P (typename) && !IDENTIFIER_TEMPLATE (typename))
{
if ( current_aggr == class_type_node ) {
tree base_typename;
printf ("+cm %s %u\n", IDENTIFIER_POINTER (typename), lineno);
for (l_base_count = 0; l_base_count < CLASSTYPE_N_BASECLASSES (t);
l_base_count++)
{
base_typename = TYPE_NAME (TYPE_BINFO_BASETYPE (t,l_base_count));
printf ("+ci %s %u\n",
IDENTIFIER_POINTER (DECL_NAME (base_typename)),
lineno);
}
}
else if (current_aggr == record_type_node)
printf ("+sh %s %u\n", IDENTIFIER_POINTER (typename), lineno);
else if (current_aggr == union_type_node)
printf ("+uh %s %u\n", IDENTIFIER_POINTER (typename), lineno);
}
}
if ( flag_gen_index )
{
extern tree current_aggr;
int l_base_count = 0; tree typename = DECL_NAME (TYPE_NAME (t));
if (!ANON_AGGRNAME_P (typename) && !IDENTIFIER_TEMPLATE (typename))
{
if ( current_aggr == class_type_node ) {
tree base_typename;
dump_symbol_info ("+cm ", IDENTIFIER_POINTER (typename), lineno);
for (l_base_count = 0; l_base_count < CLASSTYPE_N_BASECLASSES (t);
l_base_count++)
{
base_typename = TYPE_NAME (TYPE_BINFO_BASETYPE (t,l_base_count));
dump_symbol_info ("+ci ",
IDENTIFIER_POINTER (DECL_NAME (base_typename)),
lineno);
}
}
else if (current_aggr == record_type_node)
dump_symbol_info ("+sh ", IDENTIFIER_POINTER (typename), lineno);
else if (current_aggr == union_type_node)
dump_symbol_info ("+uh ", IDENTIFIER_POINTER (typename), lineno);
}
}
if (t == error_mark_node
|| ! IS_AGGR_TYPE (t))
{
t = make_lang_type (RECORD_TYPE);
pushtag (make_anon_name (), t, 0);
}
if (TREE_CODE (t) == TYPENAME_TYPE)
t = TREE_TYPE (t);
if (PARTIAL_INSTANTIATION_P (t))
{
if (!pedantic)
{
TYPE_BINFO_BASETYPES (t) = NULL_TREE;
TYPE_FIELDS (t) = NULL_TREE;
TYPE_METHODS (t) = NULL_TREE;
CLASSTYPE_TAGS (t) = NULL_TREE;
TYPE_SIZE (t) = NULL_TREE;
}
PARTIAL_INSTANTIATION_P (t) = 0;
}
else if (TYPE_SIZE (t))
duplicate_tag_error (t);
if (TYPE_BEING_DEFINED (t))
{
t = make_lang_type (TREE_CODE (t));
pushtag (TYPE_IDENTIFIER (t), t, 0);
}
maybe_process_partial_specialization (t);
pushclass (t, 1);
TYPE_BEING_DEFINED (t) = 1;
if (! IS_SIGNATURE (t))
{
int needs_writing;
tree name = TYPE_IDENTIFIER (t);
if (! ANON_AGGRNAME_P (name))
{
CLASSTYPE_INTERFACE_ONLY (t) = interface_only;
SET_CLASSTYPE_INTERFACE_UNKNOWN_X
(t, interface_unknown);
}
if (write_virtuals == 3)
needs_writing = ! CLASSTYPE_INTERFACE_ONLY (t)
&& CLASSTYPE_INTERFACE_KNOWN (t);
else
needs_writing = 1;
CLASSTYPE_VTABLE_NEEDS_WRITING (t) = needs_writing;
}
#if 0
tmp = TYPE_IDENTIFIER ($<ttype>0);
if (tmp && IDENTIFIER_TEMPLATE (tmp))
overload_template_name (tmp, 1);
#endif
reset_specialization();
begin_tree ();
build_self_reference ();
return t;
}
void
dump_declaration (declarator)
tree declarator;
{
char ch;
if (DECL_ARTIFICIAL (declarator))
return;
if (processing_template_decl)
return;
if (DECL_USE_TEMPLATE (declarator))
return;
switch (TREE_CODE (declarator)) {
case FUNCTION_DECL:
if (DECL_STATIC_FUNCTION_P (declarator))
ch = '+';
else
ch = '-';
if (DECL_DESTRUCTOR_P (declarator))
printf ("+%ch ~%s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
else if (IDENTIFIER_OPNAME_P (DECL_NAME (declarator)))
{
printf ("+%ch operator%s %u\n", ch,
operator_name_string (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
else
{
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_GLOBAL_", 8))
{
printf ("+%ch %s %u\n", ch,
IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
}
break;
case CONST_DECL:
printf ("+nh %s %u\n", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case FIELD_DECL:
if (DECL_NAME (declarator))
{
printf ("+dh %s %u\n", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
break;
default:
break;
}
}
void
gen_declaration_index (declarator)
tree declarator;
{
char fn_type;
char buf[15];
if (DECL_ARTIFICIAL (declarator) || processing_template_decl || DECL_USE_TEMPLATE (declarator))
return;
switch (TREE_CODE (declarator)) {
case FUNCTION_DECL:
if (DECL_STATIC_FUNCTION_P (declarator))
fn_type = '+';
else
fn_type = '-';
if (DECL_DESTRUCTOR_P (declarator)) {
sprintf (&buf[0], "+%ch ", fn_type);
dump_symbol_info (buf, NULL, -1);
dump_symbol_info (NULL, "~", -1);
dump_symbol_info (NULL,
IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
else if (IDENTIFIER_OPNAME_P (DECL_NAME (declarator)))
{
sprintf (&buf[0], "+%ch ", fn_type);
dump_symbol_info (buf, NULL, -1);
dump_symbol_info (NULL, "operator", -1);
dump_symbol_info (NULL,
operator_name_string (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
else
{
if (strncmp (IDENTIFIER_POINTER (DECL_NAME (declarator)), "_GLOBAL_", 8))
{
sprintf (&buf[0], "+%ch ", fn_type);
dump_symbol_info (buf,
IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
}
break;
case CONST_DECL:
dump_symbol_info ("+nh ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
break;
case FIELD_DECL:
if (DECL_NAME (declarator))
{
dump_symbol_info ("+dh ", IDENTIFIER_POINTER (DECL_NAME (declarator)),
DECL_SOURCE_LINE (declarator));
}
break;
default:
break;
}
}
void
finish_member_declaration (decl)
tree decl;
{
if (decl == error_mark_node || decl == NULL_TREE)
return;
if (decl == void_type_node)
return;
my_friendly_assert (TREE_CHAIN (decl) == NULL_TREE, 0);
if (flag_dump_symbols)
dump_declaration (decl);
if (flag_gen_index)
gen_declaration_index (decl);
TREE_PRIVATE (decl)
= (current_access_specifier == access_private_node);
TREE_PROTECTED (decl)
= (current_access_specifier == access_protected_node);
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
TREE_PRIVATE (DECL_RESULT (decl)) = TREE_PRIVATE (decl);
TREE_PROTECTED (DECL_RESULT (decl)) = TREE_PROTECTED (decl);
}
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
DECL_CLASS_CONTEXT (decl) = current_class_type;
else
DECL_CONTEXT (decl) = current_class_type;
if (TREE_CODE (decl) == FUNCTION_DECL
|| DECL_FUNCTION_TEMPLATE_P (decl))
{
add_method (current_class_type, 0, decl);
TREE_CHAIN (decl) = TYPE_METHODS (current_class_type);
TYPE_METHODS (current_class_type) = decl;
}
else
{
if (TREE_CODE (decl) == TYPE_DECL)
TYPE_FIELDS (current_class_type)
= chainon (TYPE_FIELDS (current_class_type), decl);
else
{
TREE_CHAIN (decl) = TYPE_FIELDS (current_class_type);
TYPE_FIELDS (current_class_type) = decl;
}
if (TREE_CODE (decl) != USING_DECL)
pushdecl_class_level (decl);
}
}
tree
finish_class_definition (t, attributes, semi, pop_scope_p)
tree t;
tree attributes;
int semi;
int pop_scope_p;
{
if (semi)
note_got_semicolon (t);
if (flag_dump_symbols)
{
extern tree current_aggr;
tree typename = DECL_NAME (TYPE_NAME (t));
if (!ANON_AGGRNAME_P (typename) && !IDENTIFIER_TEMPLATE (typename))
{
if (current_aggr == class_type_node)
printf ("-cm %u\n", lineno);
}
}
if (flag_gen_index)
{
extern tree current_aggr;
tree typename = DECL_NAME (TYPE_NAME (t));
if (!ANON_AGGRNAME_P (typename) && !IDENTIFIER_TEMPLATE (typename))
{
if (current_aggr == class_type_node)
dump_symbol_info ("-cm ", NULL, lineno);
}
}
attributes = chainon (TREE_TYPE (t), attributes);
TREE_TYPE (t) = NULL_TREE;
if (TREE_CODE (t) == ENUMERAL_TYPE)
;
else
{
t = finish_struct (t, attributes, semi);
if (semi)
note_got_semicolon (t);
}
pop_obstacks ();
if (! semi)
check_for_missing_semicolon (t);
if (pop_scope_p)
pop_scope (CP_DECL_CONTEXT (TYPE_MAIN_DECL (t)));
if (current_scope () == current_function_decl)
do_pending_defargs ();
return t;
}
void
begin_inline_definitions ()
{
if (pending_inlines
&& current_scope () == current_function_decl)
do_pending_inlines ();
}
void
finish_inline_definitions ()
{
if (current_class_type == NULL_TREE)
clear_inline_text_obstack ();
end_tree ();
}
tree
finish_member_class_template (types)
tree types;
{
tree t;
for (t = types; t != NULL_TREE; t = TREE_CHAIN (t))
if (IS_AGGR_TYPE_CODE (TREE_CODE (TREE_VALUE (t))))
maybe_process_partial_specialization (TREE_VALUE (t));
note_list_got_semicolon (types);
grok_x_components (types);
if (TYPE_CONTEXT (TREE_VALUE (types)) != current_class_type)
types = NULL_TREE;
finish_member_template_decl (types);
return NULL_TREE;
}
void
finish_template_decl (parms)
tree parms;
{
if (parms)
end_template_decl ();
else
end_specialization ();
}
tree
finish_template_type (name, args, entering_scope)
tree name;
tree args;
int entering_scope;
{
tree decl;
decl = lookup_template_class (name, args,
NULL_TREE, NULL_TREE, entering_scope);
if (decl != error_mark_node)
decl = TYPE_STUB_DECL (decl);
return decl;
}
void
enter_scope_of (sr)
tree sr;
{
tree scope = TREE_OPERAND (sr, 0);
if (TREE_CODE (scope) == NAMESPACE_DECL)
{
push_decl_namespace (scope);
TREE_COMPLEXITY (sr) = -1;
}
else if (scope != current_class_type)
{
if (TREE_CODE (scope) == TYPENAME_TYPE)
{
scope = TREE_TYPE (scope);
TREE_OPERAND (sr, 0) = scope;
}
push_nested_class (scope, 3);
TREE_COMPLEXITY (sr) = current_class_depth;
}
}
tree
finish_base_specifier (access_specifier, base_class,
current_aggr_is_signature)
tree access_specifier;
tree base_class;
int current_aggr_is_signature;
{
tree type;
tree result;
if (base_class == NULL_TREE)
{
error ("invalid base class");
type = error_mark_node;
}
else
type = TREE_TYPE (base_class);
if (current_aggr_is_signature && access_specifier)
error ("access and source specifiers not allowed in signature");
if (! is_aggr_type (type, 1))
result = NULL_TREE;
else if (current_aggr_is_signature
&& (! type) && (! IS_SIGNATURE (type)))
{
error ("class name not allowed as base signature");
result = NULL_TREE;
}
else if (current_aggr_is_signature)
{
sorry ("signature inheritance, base type `%s' ignored",
IDENTIFIER_POINTER (access_specifier));
result = build_tree_list (access_public_node, type);
}
else if (type && IS_SIGNATURE (type))
{
error ("signature name not allowed as base class");
result = NULL_TREE;
}
else
result = build_tree_list (access_specifier, type);
return result;
}
void
check_multiple_declarators ()
{
tree scope = current_scope ();
if (scope && TREE_CODE (scope) == FUNCTION_DECL)
return;
if (PROCESSING_REAL_TEMPLATE_DECL_P ()
|| processing_explicit_instantiation
|| processing_specialization)
cp_error ("multiple declarators in template declaration");
}
tree
finish_typeof (expr)
tree expr;
{
if (processing_template_decl)
{
tree t;
push_obstacks_nochange ();
end_temporary_allocation ();
t = make_lang_type (TYPEOF_TYPE);
TYPE_FIELDS (t) = expr;
pop_obstacks ();
return t;
}
return TREE_TYPE (expr);
}