#include "config.h"
#include "system.h"
#include "tree.h"
#include "rtl.h"
#include "expr.h"
#include "flags.h"
#include "cp-tree.h"
#include "decl.h"
#include "lex.h"
#include "output.h"
#include "except.h"
#include "toplev.h"
#include "timevar.h"
#include "cpplib.h"
#include "target.h"
#include "objc/objc-act.h"
#include "genindex.h"
#include "c-common.h"
#include "timevar.h"
extern cpp_reader *parse_in;
typedef struct priority_info_s {
int initializations_p;
int destructions_p;
} *priority_info;
static void mark_vtable_entries PARAMS ((tree));
static void grok_function_init PARAMS ((tree, tree));
static int maybe_emit_vtables (tree);
static int is_namespace_ancestor PARAMS ((tree, tree));
static void add_using_namespace PARAMS ((tree, tree, int));
static cxx_binding *ambiguous_decl (tree, cxx_binding *, cxx_binding *,int);
static tree build_anon_union_vars PARAMS ((tree, tree*, int, int));
static int acceptable_java_type PARAMS ((tree));
static void output_vtable_inherit PARAMS ((tree));
static tree start_objects PARAMS ((int, int));
static void finish_objects PARAMS ((int, int, tree));
static tree merge_functions PARAMS ((tree, tree));
static tree decl_namespace PARAMS ((tree));
static tree validate_nonmember_using_decl PARAMS ((tree, tree *, tree *));
static void do_nonmember_using_decl PARAMS ((tree, tree, tree, tree,
tree *, tree *));
static tree start_static_storage_duration_function PARAMS ((void));
static void finish_static_storage_duration_function PARAMS ((tree));
static priority_info get_priority_info PARAMS ((int));
static void do_static_initialization PARAMS ((tree, tree));
static void do_static_destruction PARAMS ((tree));
static tree start_static_initialization_or_destruction PARAMS ((tree, int));
static void finish_static_initialization_or_destruction PARAMS ((tree));
static void generate_ctor_or_dtor_function PARAMS ((int, int));
static int generate_ctor_and_dtor_functions_for_priority
PARAMS ((splay_tree_node, void *));
static tree prune_vars_needing_no_initialization PARAMS ((tree *));
static void write_out_vars PARAMS ((tree));
static void import_export_class PARAMS ((tree));
static tree get_guard_bits PARAMS ((tree));
static GTY(()) varray_type pending_statics;
#define pending_statics_used \
(pending_statics ? pending_statics->elements_used : 0)
static GTY(()) varray_type deferred_fns;
#define deferred_fns_used \
(deferred_fns ? deferred_fns->elements_used : 0)
extern int spew_debug;
int at_eof;
tree static_ctors;
tree static_dtors;
tree global_namespace;
int
grok_method_quals (ctype, function, quals)
tree ctype, function, quals;
{
tree fntype = TREE_TYPE (function);
tree raises = TYPE_RAISES_EXCEPTIONS (fntype);
int type_quals = TYPE_UNQUALIFIED;
int dup_quals = TYPE_UNQUALIFIED;
int this_quals = TYPE_UNQUALIFIED;
do
{
int tq = cp_type_qual_from_rid (TREE_VALUE (quals));
if ((type_quals | this_quals) & tq)
dup_quals |= tq;
else if (tq & TYPE_QUAL_RESTRICT)
this_quals |= tq;
else
type_quals |= tq;
quals = TREE_CHAIN (quals);
}
while (quals);
if (dup_quals != TYPE_UNQUALIFIED)
error ("duplicate type qualifiers in %s declaration",
TREE_CODE (function) == FUNCTION_DECL
? "member function" : "type");
ctype = cp_build_qualified_type (ctype, type_quals);
fntype = build_cplus_method_type (ctype, TREE_TYPE (fntype),
(TREE_CODE (fntype) == METHOD_TYPE
? TREE_CHAIN (TYPE_ARG_TYPES (fntype))
: TYPE_ARG_TYPES (fntype)));
if (raises)
fntype = build_exception_variant (fntype, raises);
TREE_TYPE (function) = fntype;
return this_quals;
}
void
warn_if_unknown_interface (decl)
tree decl;
{
static int already_warned = 0;
if (already_warned++)
return;
if (flag_alt_external_templates)
{
tree til = tinst_for_decl ();
int sl = lineno;
const char *sf = input_filename;
if (til)
{
lineno = TINST_LINE (til);
input_filename = TINST_FILE (til);
}
warning ("template `%#D' instantiated in file without #pragma interface",
decl);
lineno = sl;
input_filename = sf;
}
else
cp_warning_at ("template `%#D' defined in file without #pragma interface",
decl);
}
void
grok_x_components (specs)
tree specs;
{
tree t;
specs = strip_attrs (specs);
check_tag_decl (specs);
t = groktypename (build_tree_list (specs, NULL_TREE));
if (t == NULL_TREE || !ANON_AGGR_TYPE_P (t))
return;
fixup_anonymous_aggr (t);
finish_member_declaration (build_decl (FIELD_DECL, NULL_TREE, t));
}
tree
cp_build_parm_decl (name, type)
tree name;
tree type;
{
tree parm = build_decl (PARM_DECL, name, type);
DECL_ARG_TYPE (parm) = type_passed_as (type);
return parm;
}
tree
build_artificial_parm (name, type)
tree name;
tree type;
{
tree parm = cp_build_parm_decl (name, type);
DECL_ARTIFICIAL (parm) = 1;
TREE_READONLY (parm) = 1;
return parm;
}
void
maybe_retrofit_in_chrg (fn)
tree fn;
{
tree basetype, arg_types, parms, parm, fntype;
if (DECL_HAS_IN_CHARGE_PARM_P (fn))
return;
if (uses_template_parms (fn))
return;
if (DECL_CONSTRUCTOR_P (fn)
&& !TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
return;
arg_types = TYPE_ARG_TYPES (TREE_TYPE (fn));
basetype = TREE_TYPE (TREE_VALUE (arg_types));
arg_types = TREE_CHAIN (arg_types);
parms = TREE_CHAIN (DECL_ARGUMENTS (fn));
if (TYPE_USES_VIRTUAL_BASECLASSES (DECL_CONTEXT (fn)))
{
parm = build_artificial_parm (vtt_parm_identifier, vtt_parm_type);
TREE_CHAIN (parm) = parms;
parms = parm;
arg_types = hash_tree_chain (vtt_parm_type, arg_types);
DECL_HAS_VTT_PARM_P (fn) = 1;
}
parm = build_artificial_parm (in_charge_identifier, integer_type_node);
TREE_CHAIN (parm) = parms;
parms = parm;
arg_types = hash_tree_chain (integer_type_node, arg_types);
TREE_CHAIN (DECL_ARGUMENTS (fn)) = parms;
fntype = build_cplus_method_type (basetype, TREE_TYPE (TREE_TYPE (fn)),
arg_types);
if (TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)))
fntype = build_exception_variant (fntype,
TYPE_RAISES_EXCEPTIONS (TREE_TYPE (fn)));
TREE_TYPE (fn) = fntype;
DECL_HAS_IN_CHARGE_PARM_P (fn) = 1;
}
void
grokclassfn (ctype, function, flags, quals)
tree ctype, function;
enum overload_flags flags;
tree quals;
{
tree fn_name = DECL_NAME (function);
int this_quals = TYPE_UNQUALIFIED;
SET_DECL_LANGUAGE (function, lang_cplusplus);
if (fn_name == NULL_TREE)
{
error ("name missing for member function");
fn_name = get_identifier ("<anonymous>");
DECL_NAME (function) = fn_name;
}
if (quals)
this_quals = grok_method_quals (ctype, function, quals);
if (TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
{
tree type = TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (function)));
tree qual_type;
tree parm;
this_quals |= TYPE_QUAL_CONST;
qual_type = cp_build_qualified_type (type, this_quals);
parm = build_artificial_parm (this_identifier, qual_type);
c_apply_type_quals_to_decl (this_quals, parm);
TREE_CHAIN (parm) = last_function_parms;
last_function_parms = parm;
}
DECL_ARGUMENTS (function) = last_function_parms;
DECL_CONTEXT (function) = ctype;
if (flags == DTOR_FLAG)
DECL_DESTRUCTOR_P (function) = 1;
if (flags == DTOR_FLAG || DECL_CONSTRUCTOR_P (function))
maybe_retrofit_in_chrg (function);
if (flags == DTOR_FLAG)
{
DECL_DESTRUCTOR_P (function) = 1;
TYPE_HAS_DESTRUCTOR (ctype) = 1;
}
}
tree
grok_array_decl (array_expr, index_exp)
tree array_expr, index_exp;
{
tree type = TREE_TYPE (array_expr);
tree p1, p2, i1, i2;
if (type == error_mark_node || index_exp == error_mark_node)
return error_mark_node;
if (processing_template_decl)
return build_min (ARRAY_REF, type ? TREE_TYPE (type) : NULL_TREE,
array_expr, index_exp);
if (type == NULL_TREE)
{
error ("parser may be lost: is there a '{' missing somewhere?");
return NULL_TREE;
}
if (TREE_CODE (type) == OFFSET_TYPE
|| TREE_CODE (type) == REFERENCE_TYPE)
type = TREE_TYPE (type);
if (IS_AGGR_TYPE (type) || IS_AGGR_TYPE (TREE_TYPE (index_exp)))
return build_opfncall (ARRAY_REF, LOOKUP_NORMAL,
array_expr, index_exp, NULL_TREE);
if (TREE_CODE (type) == ARRAY_TYPE)
p1 = array_expr;
else
p1 = build_expr_type_conversion (WANT_POINTER, array_expr, 0);
if (TREE_CODE (TREE_TYPE (index_exp)) == ARRAY_TYPE)
p2 = index_exp;
else
p2 = build_expr_type_conversion (WANT_POINTER, index_exp, 0);
i1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, array_expr, 0);
i2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, index_exp, 0);
if ((p1 && i2) && (i1 && p2))
error ("ambiguous conversion for array subscript");
if (p1 && i2)
array_expr = p1, index_exp = i2;
else if (i1 && p2)
array_expr = p2, index_exp = i1;
else
{
error ("invalid types `%T[%T]' for array subscript",
type, TREE_TYPE (index_exp));
return error_mark_node;
}
if (array_expr == error_mark_node || index_exp == error_mark_node)
error ("ambiguous conversion for array subscript");
return build_array_ref (array_expr, index_exp);
}
tree
delete_sanity (exp, size, doing_vec, use_global_delete)
tree exp, size;
int doing_vec, use_global_delete;
{
tree t, type;
tree maxindex = NULL_TREE;
if (exp == error_mark_node)
return exp;
if (processing_template_decl)
{
t = build_min (DELETE_EXPR, void_type_node, exp, size);
DELETE_EXPR_USE_GLOBAL (t) = use_global_delete;
DELETE_EXPR_USE_VEC (t) = doing_vec;
return t;
}
if (TREE_CODE (exp) == OFFSET_REF)
exp = resolve_offset_ref (exp);
exp = convert_from_reference (exp);
t = stabilize_reference (exp);
t = build_expr_type_conversion (WANT_POINTER, t, 1);
if (t == NULL_TREE || t == error_mark_node)
{
error ("type `%#T' argument given to `delete', expected pointer",
TREE_TYPE (exp));
return error_mark_node;
}
if (doing_vec == 2)
{
maxindex = cp_build_binary_op (MINUS_EXPR, size, integer_one_node);
pedwarn ("anachronistic use of array size in vector delete");
}
type = TREE_TYPE (t);
if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
error ("cannot delete a function. Only pointer-to-objects are valid arguments to `delete'");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (type)) == VOID_TYPE)
{
warning ("deleting `%T' is undefined", type);
doing_vec = 0;
}
if (TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == VAR_DECL
&& TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == ARRAY_TYPE)
warning ("deleting array `%#D'", TREE_OPERAND (t, 0));
if (integer_zerop (t))
return build1 (NOP_EXPR, void_type_node, t);
if (doing_vec)
return build_vec_delete (t, maxindex, sfk_deleting_destructor,
use_global_delete);
else
return build_delete (type, t, sfk_deleting_destructor,
LOOKUP_NORMAL, use_global_delete);
}
void
check_member_template (tmpl)
tree tmpl;
{
tree decl;
my_friendly_assert (TREE_CODE (tmpl) == TEMPLATE_DECL, 0);
decl = DECL_TEMPLATE_RESULT (tmpl);
if (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == TYPE_DECL
&& IS_AGGR_TYPE (TREE_TYPE (decl))))
{
if (current_function_decl)
error ("invalid declaration of member template `%#D' in local class",
decl);
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_VIRTUAL_P (decl))
{
error
("invalid use of `virtual' in template declaration of `%#D'",
decl);
DECL_VIRTUAL_P (decl) = 0;
}
DECL_IGNORED_P (tmpl) = 1;
}
else
error ("template declaration of `%#D'", decl);
}
static int
acceptable_java_type (type)
tree type;
{
if (TREE_CODE (type) == VOID_TYPE || TYPE_FOR_JAVA (type))
return 1;
if (TREE_CODE (type) == POINTER_TYPE || TREE_CODE (type) == REFERENCE_TYPE)
{
type = TREE_TYPE (type);
if (TREE_CODE (type) == RECORD_TYPE)
{
tree args; int i;
if (! TYPE_FOR_JAVA (type))
return 0;
if (! CLASSTYPE_TEMPLATE_INFO (type))
return 1;
args = CLASSTYPE_TI_ARGS (type);
i = TREE_VEC_LENGTH (args);
while (--i >= 0)
{
type = TREE_VEC_ELT (args, i);
if (TREE_CODE (type) == POINTER_TYPE)
type = TREE_TYPE (type);
if (! TYPE_FOR_JAVA (type))
return 0;
}
return 1;
}
}
return 0;
}
int
check_java_method (method)
tree method;
{
int jerr = 0;
tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (method));
tree ret_type = TREE_TYPE (TREE_TYPE (method));
if (! acceptable_java_type (ret_type))
{
error ("Java method '%D' has non-Java return type `%T'",
method, ret_type);
jerr++;
}
for (; arg_types != NULL_TREE; arg_types = TREE_CHAIN (arg_types))
{
tree type = TREE_VALUE (arg_types);
if (! acceptable_java_type (type))
{
error ("Java method '%D' has non-Java parameter type `%T'",
method, type);
jerr++;
}
}
return jerr ? 0 : 1;
}
tree
check_classfn (ctype, function)
tree ctype, function;
{
int ix;
if (DECL_USE_TEMPLATE (function)
&& !(TREE_CODE (function) == TEMPLATE_DECL
&& DECL_TEMPLATE_SPECIALIZATION (function))
&& is_member_template (DECL_TI_TEMPLATE (function)))
return NULL_TREE;
ix = lookup_fnfields_1 (complete_type (ctype),
DECL_CONSTRUCTOR_P (function) ? ctor_identifier :
DECL_DESTRUCTOR_P (function) ? dtor_identifier :
DECL_NAME (function));
if (ix >= 0)
{
tree methods = CLASSTYPE_METHOD_VEC (ctype);
tree fndecls, fndecl = 0;
bool is_conv_op;
const char *format = NULL;
for (fndecls = TREE_VEC_ELT (methods, ix);
fndecls; fndecls = OVL_NEXT (fndecls))
{
tree p1, p2;
fndecl = OVL_CURRENT (fndecls);
p1 = TYPE_ARG_TYPES (TREE_TYPE (function));
p2 = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
if (DECL_STATIC_FUNCTION_P (fndecl)
&& TREE_CODE (TREE_TYPE (function)) == METHOD_TYPE)
p1 = TREE_CHAIN (p1);
if (same_type_p (TREE_TYPE (TREE_TYPE (function)),
TREE_TYPE (TREE_TYPE (fndecl)))
&& compparms (p1, p2)
&& (DECL_TEMPLATE_SPECIALIZATION (function)
== DECL_TEMPLATE_SPECIALIZATION (fndecl))
&& (!DECL_TEMPLATE_SPECIALIZATION (function)
|| (DECL_TI_TEMPLATE (function)
== DECL_TI_TEMPLATE (fndecl))))
return fndecl;
}
error ("prototype for `%#D' does not match any in class `%T'",
function, ctype);
is_conv_op = DECL_CONV_FN_P (fndecl);
if (is_conv_op)
ix = CLASSTYPE_FIRST_CONVERSION_SLOT;
fndecls = TREE_VEC_ELT (methods, ix);
while (fndecls)
{
fndecl = OVL_CURRENT (fndecls);
fndecls = OVL_NEXT (fndecls);
if (!fndecls && is_conv_op)
{
if (TREE_VEC_LENGTH (methods) > ix)
{
ix++;
fndecls = TREE_VEC_ELT (methods, ix);
if (!DECL_CONV_FN_P (OVL_CURRENT (fndecls)))
{
fndecls = NULL_TREE;
is_conv_op = false;
}
}
else
is_conv_op = false;
}
if (format)
format = " %#D";
else if (fndecls)
format = "candidates are: %#D";
else
format = "candidate is: %#D";
cp_error_at (format, fndecl);
}
}
else if (!COMPLETE_TYPE_P (ctype))
cxx_incomplete_type_error (function, ctype);
else
error ("no `%#D' member function declared in class `%T'",
function, ctype);
if (COMPLETE_TYPE_P (ctype))
add_method (ctype, function, 1);
return NULL_TREE;
}
void
finish_static_data_member_decl (decl, init, asmspec_tree, flags)
tree decl;
tree init;
tree asmspec_tree;
int flags;
{
my_friendly_assert (TREE_PUBLIC (decl), 0);
DECL_CONTEXT (decl) = current_class_type;
if (!asmspec_tree && current_class_type)
DECL_INITIAL (decl) = error_mark_node;
if (! processing_template_decl)
{
if (!pending_statics)
VARRAY_TREE_INIT (pending_statics, 32, "pending_statics");
VARRAY_PUSH_TREE (pending_statics, decl);
}
if (LOCAL_CLASS_P (current_class_type))
pedwarn ("local class `%#T' shall not have static data member `%#D'",
current_class_type, decl);
if (init != NULL_TREE && TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (decl)))
{
static int explained = 0;
error ("initializer invalid for static member with constructor");
if (!explained)
{
error ("(an out of class initialization is required)");
explained = 1;
}
init = NULL_TREE;
}
if (CP_TYPE_CONST_P (TREE_TYPE (decl)) && init == 0)
TREE_USED (decl) = 1;
DECL_INITIAL (decl) = init;
DECL_IN_AGGR_P (decl) = 1;
cp_finish_decl (decl, init, asmspec_tree, flags);
if (flag_gen_index)
gen_indexing_info (INDEX_DATA_DECL,
IDENTIFIER_POINTER (DECL_NAME (decl)),
DECL_SOURCE_LINE (decl));
}
tree
grokfield (declarator, declspecs, init, asmspec_tree, attrlist)
tree declarator, declspecs, init, asmspec_tree, attrlist;
{
tree value;
const char *asmspec = 0;
int flags = LOOKUP_ONLYCONVERTING;
if (init == NULL_TREE && declarator != NULL_TREE
&& TREE_CODE (declarator) == CALL_EXPR
&& TREE_OPERAND (declarator, 0)
&& (TREE_CODE (TREE_OPERAND (declarator, 0)) == IDENTIFIER_NODE
|| TREE_CODE (TREE_OPERAND (declarator, 0)) == SCOPE_REF)
&& parmlist_is_exprlist (CALL_DECLARATOR_PARMS (declarator)))
{
static int explained;
error ("invalid data member initialization");
if (!explained)
{
error ("(use `=' to initialize static data members)");
explained = 1;
}
declarator = TREE_OPERAND (declarator, 0);
flags = 0;
}
if (declspecs == NULL_TREE
&& TREE_CODE (declarator) == SCOPE_REF
&& TREE_CODE (TREE_OPERAND (declarator, 1)) == IDENTIFIER_NODE)
{
if (! IS_AGGR_TYPE_CODE (TREE_CODE (TREE_OPERAND (declarator, 0))))
;
else if (TREE_COMPLEXITY (declarator) == current_class_depth)
pop_nested_class ();
return do_class_using_decl (declarator);
}
if (init
&& TREE_CODE (init) == TREE_LIST
&& TREE_VALUE (init) == error_mark_node
&& TREE_CHAIN (init) == NULL_TREE)
init = NULL_TREE;
value = grokdeclarator (declarator, declspecs, FIELD, init != 0, &attrlist);
if (! value || value == error_mark_node)
return value;
if (TREE_TYPE (value) == error_mark_node)
return error_mark_node;
if (TREE_CODE (value) == TYPE_DECL && init)
{
error ("typedef `%D' is initialized (use __typeof__ instead)", value);
init = NULL_TREE;
}
if (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
if (DECL_NAME (value) != NULL_TREE
&& IDENTIFIER_POINTER (DECL_NAME (value))[0] == '_'
&& ! strcmp (IDENTIFIER_POINTER (DECL_NAME (value)), "_vptr"))
error ("member `%D' conflicts with virtual function table field name",
value);
if (TREE_CODE (value) == TYPE_DECL)
{
DECL_NONLOCAL (value) = 1;
DECL_CONTEXT (value) = current_class_type;
if (CLASS_TYPE_P (TREE_TYPE (value)))
CLASSTYPE_GOT_SEMICOLON (TREE_TYPE (value)) = 1;
if (processing_template_decl)
value = push_template_decl (value);
return value;
}
if (DECL_IN_AGGR_P (value))
{
error ("`%D' is already defined in `%T'", value,
DECL_CONTEXT (value));
return void_type_node;
}
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
if (init)
{
if (TREE_CODE (value) == FUNCTION_DECL)
{
grok_function_init (value, init);
init = NULL_TREE;
}
else if (pedantic && TREE_CODE (value) != VAR_DECL)
init = NULL_TREE;
else
{
if (TREE_CODE (init) == TREE_LIST)
{
if (TREE_CHAIN (init) == NULL_TREE)
init = TREE_VALUE (init);
else
init = digest_init (TREE_TYPE (value), init, (tree *)0);
}
if (!processing_template_decl)
{
if (TREE_CODE (init) == CONST_DECL)
init = DECL_INITIAL (init);
else if (TREE_READONLY_DECL_P (init))
init = decl_constant_value (init);
else if (TREE_CODE (init) == CONSTRUCTOR)
init = digest_init (TREE_TYPE (value), init, (tree *)0);
if (init == error_mark_node)
init = build1 (NOP_EXPR, TREE_TYPE (value), init);
else if (! TREE_CONSTANT (init))
{
if (TREE_CODE (TREE_TYPE (value)) != REFERENCE_TYPE
|| (TREE_STATIC (init) == 0
&& (!DECL_P (init) || DECL_EXTERNAL (init) == 0)))
{
error ("field initializer is not constant");
init = error_mark_node;
}
}
}
}
}
if (processing_template_decl && ! current_function_decl
&& (TREE_CODE (value) == VAR_DECL || TREE_CODE (value) == FUNCTION_DECL))
value = push_template_decl (value);
if (attrlist)
cplus_decl_attributes (&value, attrlist, 0);
if (TREE_CODE (value) == VAR_DECL)
{
finish_static_data_member_decl (value, init, asmspec_tree,
flags);
return value;
}
if (TREE_CODE (value) == FIELD_DECL)
{
if (asmspec)
error ("`asm' specifiers are not permitted on non-static data members");
if (DECL_INITIAL (value) == error_mark_node)
init = error_mark_node;
cp_finish_decl (value, init, NULL_TREE, flags);
DECL_INITIAL (value) = init;
DECL_IN_AGGR_P (value) = 1;
return value;
}
if (TREE_CODE (value) == FUNCTION_DECL)
{
if (asmspec)
{
SET_DECL_RTL (value, NULL_RTX);
SET_DECL_ASSEMBLER_NAME (value, get_identifier (asmspec));
}
if (!DECL_FRIEND_P (value))
grok_special_member_properties (value);
cp_finish_decl (value, init, asmspec_tree, flags);
if (DECL_FRIEND_P (value))
return void_type_node;
DECL_IN_AGGR_P (value) = 1;
return value;
}
abort ();
return NULL_TREE;
}
tree
grokbitfield (declarator, declspecs, width)
tree declarator, declspecs, width;
{
register tree value = grokdeclarator (declarator, declspecs, BITFIELD,
0, NULL);
if (! value) return NULL_TREE;
if (TREE_CODE (value) == VOID_TYPE)
return void_type_node;
if (TREE_CODE (value) == TYPE_DECL)
{
error ("cannot declare `%D' to be a bit-field type", value);
return NULL_TREE;
}
if (TREE_CODE (value) == FUNCTION_DECL)
{
error ("cannot declare bit-field `%D' with function type",
DECL_NAME (value));
return NULL_TREE;
}
if (DECL_IN_AGGR_P (value))
{
error ("`%D' is already defined in the class %T", value,
DECL_CONTEXT (value));
return void_type_node;
}
if (TREE_STATIC (value))
{
error ("static member `%D' cannot be a bit-field", value);
return NULL_TREE;
}
cp_finish_decl (value, NULL_TREE, NULL_TREE, 0);
if (width != error_mark_node)
{
constant_expression_warning (width);
DECL_INITIAL (value) = width;
SET_DECL_C_BIT_FIELD (value);
}
DECL_IN_AGGR_P (value) = 1;
return value;
}
tree
grokoptypename (declspecs, declarator, scope)
tree declspecs, declarator;
tree scope;
{
tree t = grokdeclarator (declarator, declspecs, TYPENAME, 0, NULL);
if (scope && current_template_parms
&& uses_template_parms (t)
&& uses_template_parms (scope))
{
tree args = current_template_args ();
push_scope (scope);
t = tsubst (t, args, tf_error | tf_warning, NULL_TREE);
pop_scope (scope);
}
return mangle_conv_op_name_for_type (t);
}
static void
grok_function_init (decl, init)
tree decl;
tree init;
{
tree type = TREE_TYPE (decl);
if (TREE_CODE (type) == FUNCTION_TYPE)
error ("initializer specified for non-member function `%D'", decl);
else if (integer_zerop (init))
DECL_PURE_VIRTUAL_P (decl) = 1;
else
error ("invalid initializer for virtual method `%D'", decl);
}
void
cplus_decl_attributes (decl, attributes, flags)
tree *decl, attributes;
int flags;
{
if (*decl == NULL_TREE || *decl == void_type_node)
return;
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
decl_attributes (decl, attributes, flags);
if (TREE_CODE (*decl) == TYPE_DECL)
SET_IDENTIFIER_TYPE_VALUE (DECL_NAME (*decl), TREE_TYPE (*decl));
}
tree
constructor_name_full (thing)
tree thing;
{
if (TREE_CODE (thing) == TEMPLATE_TYPE_PARM
|| TREE_CODE (thing) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (thing) == TYPENAME_TYPE)
thing = TYPE_NAME (thing);
else if (IS_AGGR_TYPE_CODE (TREE_CODE (thing)))
{
if (TYPE_WAS_ANONYMOUS (thing) && TYPE_HAS_CONSTRUCTOR (thing))
thing = DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (thing), 0)));
else
thing = TYPE_NAME (thing);
}
if (TREE_CODE (thing) == TYPE_DECL
|| (TREE_CODE (thing) == TEMPLATE_DECL
&& TREE_CODE (DECL_TEMPLATE_RESULT (thing)) == TYPE_DECL))
thing = DECL_NAME (thing);
my_friendly_assert (TREE_CODE (thing) == IDENTIFIER_NODE, 197);
return thing;
}
tree
constructor_name (thing)
tree thing;
{
tree t;
thing = constructor_name_full (thing);
t = IDENTIFIER_TEMPLATE (thing);
if (!t)
return thing;
return t;
}
bool
constructor_name_p (tree name, tree type)
{
return (name == constructor_name (type)
|| name == constructor_name_full (type));
}
void
defer_fn (fn)
tree fn;
{
if (DECL_DEFERRED_FN (fn))
return;
DECL_DEFERRED_FN (fn) = 1;
if (!deferred_fns)
VARRAY_TREE_INIT (deferred_fns, 32, "deferred_fns");
if (! DECL_ARTIFICIAL (fn)
&& ! DECL_SAVED_TREE (fn)
&& (! DECL_DECLARED_INLINE_P (fn) || ! TREE_USED (fn)))
abort ();
VARRAY_PUSH_TREE (deferred_fns, fn);
}
static tree
build_anon_union_vars (anon_decl, elems, static_p, external_p)
tree anon_decl;
tree* elems;
int static_p;
int external_p;
{
tree type = TREE_TYPE (anon_decl);
tree main_decl = NULL_TREE;
tree field;
if (TREE_CODE (type) != UNION_TYPE)
error ("anonymous struct not inside named type");
for (field = TYPE_FIELDS (type);
field != NULL_TREE;
field = TREE_CHAIN (field))
{
tree decl;
if (DECL_ARTIFICIAL (field))
continue;
if (TREE_CODE (field) != FIELD_DECL)
{
cp_pedwarn_at ("`%#D' invalid; an anonymous union can only have non-static data members",
field);
continue;
}
if (TREE_PRIVATE (field))
cp_pedwarn_at ("private member `%#D' in anonymous union", field);
else if (TREE_PROTECTED (field))
cp_pedwarn_at ("protected member `%#D' in anonymous union", field);
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
{
decl = build_anon_union_vars (field, elems, static_p, external_p);
if (!decl)
continue;
}
else if (DECL_NAME (field) == NULL_TREE)
continue;
else
{
decl = build_decl (VAR_DECL, DECL_NAME (field), TREE_TYPE (field));
DECL_INITIAL (decl) = error_mark_node;
TREE_PUBLIC (decl) = 0;
TREE_STATIC (decl) = static_p;
DECL_EXTERNAL (decl) = external_p;
decl = pushdecl (decl);
DECL_INITIAL (decl) = NULL_TREE;
}
if (main_decl == NULL_TREE
|| tree_int_cst_lt (DECL_SIZE (main_decl), DECL_SIZE (decl)))
{
if (main_decl)
TREE_ASM_WRITTEN (main_decl) = 1;
main_decl = decl;
}
else
TREE_ASM_WRITTEN (decl) = 1;
if (DECL_NAME (field) == NULL_TREE
&& ANON_AGGR_TYPE_P (TREE_TYPE (field)))
continue;
*elems = tree_cons (NULL_TREE, decl, *elems);
TREE_TYPE (*elems) = type;
}
return main_decl;
}
void
finish_anon_union (anon_union_decl)
tree anon_union_decl;
{
tree type = TREE_TYPE (anon_union_decl);
tree main_decl;
int public_p = TREE_PUBLIC (anon_union_decl);
int static_p = TREE_STATIC (anon_union_decl);
int external_p = DECL_EXTERNAL (anon_union_decl);
DECL_CONTEXT (anon_union_decl) = DECL_CONTEXT (TYPE_NAME (type));
if (TYPE_FIELDS (type) == NULL_TREE)
return;
if (public_p)
{
error ("namespace-scope anonymous aggregates must be static");
return;
}
if (!processing_template_decl)
{
main_decl
= build_anon_union_vars (anon_union_decl,
&DECL_ANON_UNION_ELEMS (anon_union_decl),
static_p, external_p);
if (main_decl == NULL_TREE)
{
warning ("anonymous aggregate with no members");
return;
}
if (static_p)
{
make_decl_rtl (main_decl, 0);
COPY_DECL_RTL (main_decl, anon_union_decl);
expand_anon_union_decl (anon_union_decl,
NULL_TREE,
DECL_ANON_UNION_ELEMS (anon_union_decl));
return;
}
}
add_decl_stmt (anon_union_decl);
}
void
finish_builtin_type (type, name, fields, len, align_type)
tree type;
const char *name;
tree fields[];
int len;
tree align_type;
{
register int i;
TYPE_FIELDS (type) = fields[0];
for (i = 0; i < len; i++)
{
layout_type (TREE_TYPE (fields[i]));
DECL_FIELD_CONTEXT (fields[i]) = type;
TREE_CHAIN (fields[i]) = fields[i+1];
}
DECL_FIELD_CONTEXT (fields[i]) = type;
TYPE_ALIGN (type) = TYPE_ALIGN (align_type);
TYPE_USER_ALIGN (type) = TYPE_USER_ALIGN (align_type);
layout_type (type);
#if 0
TYPE_NAME (type) = make_type_decl (get_identifier (name), type);
#else
TYPE_NAME (type) = build_decl (TYPE_DECL, get_identifier (name), type);
#endif
TYPE_STUB_DECL (type) = TYPE_NAME (type);
layout_decl (TYPE_NAME (type), 0);
}
tree
coerce_new_type (type)
tree type;
{
int e = 0;
tree args = TYPE_ARG_TYPES (type);
my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
if (!same_type_p (TREE_TYPE (type), ptr_type_node))
e = 1, error ("`operator new' must return type `%T'", ptr_type_node);
if (!args || args == void_list_node
|| !same_type_p (TREE_VALUE (args), size_type_node))
{
e = 2;
if (args && args != void_list_node)
args = TREE_CHAIN (args);
pedwarn ("`operator new' takes type `size_t' (`%T') as first parameter", size_type_node);
}
switch (e)
{
case 2:
args = tree_cons (NULL_TREE, size_type_node, args);
case 1:
type = build_exception_variant
(build_function_type (ptr_type_node, args),
TYPE_RAISES_EXCEPTIONS (type));
default:;
}
return type;
}
tree
coerce_delete_type (type)
tree type;
{
int e = 0;
tree args = TYPE_ARG_TYPES (type);
my_friendly_assert (TREE_CODE (type) == FUNCTION_TYPE, 20001107);
if (!same_type_p (TREE_TYPE (type), void_type_node))
e = 1, error ("`operator delete' must return type `%T'", void_type_node);
if (!args || args == void_list_node
|| !same_type_p (TREE_VALUE (args), ptr_type_node))
{
e = 2;
if (args && args != void_list_node)
args = TREE_CHAIN (args);
error ("`operator delete' takes type `%T' as first parameter", ptr_type_node);
}
switch (e)
{
case 2:
args = tree_cons (NULL_TREE, ptr_type_node, args);
case 1:
type = build_exception_variant
(build_function_type (void_type_node, args),
TYPE_RAISES_EXCEPTIONS (type));
default:;
}
return type;
}
static void
mark_vtable_entries (decl)
tree decl;
{
tree entries = CONSTRUCTOR_ELTS (DECL_INITIAL (decl));
for (; entries; entries = TREE_CHAIN (entries))
{
tree fnaddr = TREE_VALUE (entries);
tree fn;
if (TREE_CODE (fnaddr) != ADDR_EXPR
&& TREE_CODE (fnaddr) != FDESC_EXPR)
continue;
fn = TREE_OPERAND (fnaddr, 0);
TREE_ADDRESSABLE (fn) = 1;
if (DECL_THUNK_P (fn))
use_thunk (fn, 0);
mark_used (fn);
}
}
void
comdat_linkage (decl)
tree decl;
{
if (flag_weak)
make_decl_one_only (decl);
else if (TREE_CODE (decl) == FUNCTION_DECL
|| (TREE_CODE (decl) == VAR_DECL && DECL_ARTIFICIAL (decl)))
TREE_PUBLIC (decl) = 0;
else
{
if (DECL_INITIAL (decl) == 0
|| DECL_INITIAL (decl) == error_mark_node)
DECL_COMMON (decl) = 1;
else if (EMPTY_CONSTRUCTOR_P (DECL_INITIAL (decl)))
{
DECL_COMMON (decl) = 1;
DECL_INITIAL (decl) = error_mark_node;
}
# ifndef MAKE_DECL_COALESCED
else
{
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
}
# endif MAKE_DECL_COALESCED
}
if (DECL_LANG_SPECIFIC (decl))
DECL_COMDAT (decl) = 1;
}
void
maybe_make_one_only (decl)
tree decl;
{
if (! flag_weak)
return;
make_decl_one_only (decl);
if (TREE_CODE (decl) == VAR_DECL)
{
DECL_COMDAT (decl) = 1;
TREE_SYMBOL_REFERENCED (DECL_ASSEMBLER_NAME (decl)) = 1;
}
}
void
import_export_vtable (decl, type, final)
tree decl, type;
int final;
{
if (DECL_INTERFACE_KNOWN (decl))
return;
if (TYPE_FOR_JAVA (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
DECL_INTERFACE_KNOWN (decl) = 1;
}
else if (CLASSTYPE_INTERFACE_KNOWN (type))
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = CLASSTYPE_INTERFACE_ONLY (type);
DECL_INTERFACE_KNOWN (decl) = 1;
}
else
{
int found = (CLASSTYPE_TEMPLATE_INSTANTIATION (type)
|| CLASSTYPE_KEY_METHOD (type) != NULL_TREE);
if (final || ! found)
{
comdat_linkage (decl);
DECL_EXTERNAL (decl) = 0;
}
else
{
TREE_PUBLIC (decl) = 1;
DECL_EXTERNAL (decl) = 1;
}
}
}
static void
import_export_class (ctype)
tree ctype;
{
int import_export = 0;
my_friendly_assert (at_eof, 20000226);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
return;
if (CLASSTYPE_INTERFACE_ONLY (ctype))
return;
if (lookup_attribute ("dllimport", TYPE_ATTRIBUTES (ctype)))
import_export = -1;
else if (lookup_attribute ("dllexport", TYPE_ATTRIBUTES (ctype)))
import_export = 1;
if (import_export == 0
&& CLASSTYPE_IMPLICIT_INSTANTIATION (ctype)
&& ! flag_implicit_templates)
import_export = -1;
if (import_export == 0
&& TYPE_POLYMORPHIC_P (ctype))
{
tree method = CLASSTYPE_KEY_METHOD (ctype);
if (method)
import_export = (DECL_REALLY_EXTERN (method) ? -1 : 1);
}
#ifdef MULTIPLE_SYMBOL_SPACES
if (import_export == -1)
import_export = 0;
#endif
if (import_export)
{
SET_CLASSTYPE_INTERFACE_KNOWN (ctype);
CLASSTYPE_INTERFACE_ONLY (ctype) = (import_export < 0);
}
}
static void
output_vtable_inherit (vars)
tree vars;
{
tree parent;
rtx child_rtx, parent_rtx;
child_rtx = XEXP (DECL_RTL (vars), 0);
parent = binfo_for_vtable (vars);
if (parent == TYPE_BINFO (DECL_CONTEXT (vars)))
parent_rtx = const0_rtx;
else if (parent)
{
parent = get_vtbl_decl_for_binfo (TYPE_BINFO (BINFO_TYPE (parent)));
parent_rtx = XEXP (DECL_RTL (parent), 0);
}
else
abort ();
assemble_vtable_inherit (child_rtx, parent_rtx);
}
static int
maybe_emit_vtables (tree ctype)
{
tree vtbl;
tree primary_vtbl;
primary_vtbl = CLASSTYPE_VTABLES (ctype);
if (TREE_ASM_WRITTEN (primary_vtbl))
return 0;
if (TREE_TYPE (primary_vtbl) == void_type_node)
return 0;
import_export_class (ctype);
import_export_vtable (primary_vtbl, ctype, 1);
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
if (!DECL_EXTERNAL (vtbl) && DECL_NEEDED_P (vtbl))
break;
if (!vtbl)
{
if (DECL_COMDAT (primary_vtbl)
&& CLASSTYPE_DEBUG_REQUESTED (ctype))
note_debug_info_needed (ctype);
return 0;
}
for (vtbl = CLASSTYPE_VTABLES (ctype); vtbl; vtbl = TREE_CHAIN (vtbl))
{
import_export_vtable (vtbl, ctype, 1);
mark_vtable_entries (vtbl);
if (TREE_TYPE (DECL_INITIAL (vtbl)) == 0)
store_init_value (vtbl, DECL_INITIAL (vtbl));
if (write_symbols == DWARF_DEBUG || write_symbols == DWARF2_DEBUG)
{
DECL_IGNORED_P (vtbl) = 1;
}
if (flag_weak)
comdat_linkage (vtbl);
rest_of_decl_compilation (vtbl, NULL, 1, 1);
if (flag_vtable_gc)
output_vtable_inherit (vtbl);
if (flag_syntax_only)
TREE_ASM_WRITTEN (vtbl) = 1;
}
note_debug_info_needed (ctype);
return 1;
}
void
import_export_decl (decl)
tree decl;
{
if (DECL_INTERFACE_KNOWN (decl))
return;
if (DECL_TEMPLATE_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
if ((DECL_IMPLICIT_INSTANTIATION (decl)
|| DECL_FRIEND_PSEUDO_TEMPLATE_INSTANTIATION (decl))
&& (flag_implicit_templates
|| (flag_implicit_inline_templates
&& DECL_DECLARED_INLINE_P (decl))))
{
if (!TREE_PUBLIC (decl))
;
else
comdat_linkage (decl);
}
else
{
DECL_EXTERNAL (decl) = 1;
DECL_NOT_REALLY_EXTERN (decl) = 0;
}
}
else if (DECL_FUNCTION_MEMBER_P (decl))
{
if (!DECL_DECLARED_INLINE_P (decl))
{
tree ctype = DECL_CONTEXT (decl);
import_export_class (ctype);
if (CLASSTYPE_INTERFACE_KNOWN (ctype))
{
DECL_NOT_REALLY_EXTERN (decl)
= ! (CLASSTYPE_INTERFACE_ONLY (ctype)
|| (DECL_DECLARED_INLINE_P (decl)
&& ! flag_implement_inlines
&& !DECL_VINDEX (decl)));
if (!DECL_NOT_REALLY_EXTERN (decl))
DECL_EXTERNAL (decl) = 1;
if (DECL_ARTIFICIAL (decl) && flag_weak)
comdat_linkage (decl);
else
maybe_make_one_only (decl);
}
}
else
comdat_linkage (decl);
#ifdef MAKE_DECL_COALESCED
if (DECL_DECLARED_INLINE_P (decl))
{
MAKE_DECL_COALESCED (decl);
}
#endif
}
else
{
comdat_linkage (decl);
#ifdef MAKE_DECL_COALESCED
MAKE_DECL_COALESCED(decl);
#endif
}
DECL_INTERFACE_KNOWN (decl) = 1;
}
void
import_export_tinfo (decl, type, is_in_library)
tree decl;
tree type;
int is_in_library;
{
if (DECL_INTERFACE_KNOWN (decl))
return;
if (IS_AGGR_TYPE (type))
import_export_class (type);
if (IS_AGGR_TYPE (type) && CLASSTYPE_INTERFACE_KNOWN (type)
&& TYPE_POLYMORPHIC_P (type)
&& flag_rtti
&& abi_version_at_least (1))
{
DECL_NOT_REALLY_EXTERN (decl) = !CLASSTYPE_INTERFACE_ONLY (type);
DECL_COMDAT (decl) = 0;
}
else
{
DECL_NOT_REALLY_EXTERN (decl) = 1;
DECL_COMDAT (decl) = 1;
#ifdef MAKE_DECL_COALESCED
TREE_PUBLIC (decl) = 1;
if (! is_in_library)
MAKE_DECL_COALESCED (decl);
#endif
}
if (flag_weak)
DECL_COMDAT (decl) = 1;
else if (is_in_library)
DECL_COMDAT (decl) = 0;
DECL_INTERFACE_KNOWN (decl) = 1;
}
tree
build_cleanup (decl)
tree decl;
{
tree temp;
tree type = TREE_TYPE (decl);
my_friendly_assert (!TYPE_HAS_TRIVIAL_DESTRUCTOR (type), 20030106);
mark_used (decl);
if (TREE_CODE (type) == ARRAY_TYPE)
temp = decl;
else
{
cxx_mark_addressable (decl);
temp = build1 (ADDR_EXPR, build_pointer_type (type), decl);
}
temp = build_delete (TREE_TYPE (temp), temp,
sfk_complete_destructor,
LOOKUP_NORMAL|LOOKUP_NONVIRTUAL|LOOKUP_DESTRUCTOR, 0);
return temp;
}
tree
get_guard (decl)
tree decl;
{
tree sname;
tree guard;
sname = mangle_guard_variable (decl);
guard = IDENTIFIER_GLOBAL_VALUE (sname);
if (! guard)
{
tree guard_type;
guard_type = long_long_integer_type_node;
guard = build_decl (VAR_DECL, sname, guard_type);
TREE_PUBLIC (guard) = TREE_PUBLIC (decl);
TREE_STATIC (guard) = TREE_STATIC (decl);
DECL_COMMON (guard) = DECL_COMMON (decl);
DECL_ONE_ONLY (guard) = DECL_ONE_ONLY (decl);
if (TREE_PUBLIC (decl))
DECL_WEAK (guard) = DECL_WEAK (decl);
#ifdef MAKE_DECL_COALESCED
if (TREE_PUBLIC (decl) || DECL_COALESCED (decl))
MAKE_DECL_COALESCED (guard);
#endif
DECL_ARTIFICIAL (guard) = 1;
TREE_USED (guard) = 1;
pushdecl_top_level (guard);
cp_finish_decl (guard, NULL_TREE, NULL_TREE, 0);
}
return guard;
}
static tree
get_guard_bits (guard)
tree guard;
{
guard = build1 (ADDR_EXPR,
build_pointer_type (TREE_TYPE (guard)),
guard);
guard = build1 (NOP_EXPR,
build_pointer_type (char_type_node),
guard);
guard = build1 (INDIRECT_REF, char_type_node, guard);
return guard;
}
tree
get_guard_cond (guard)
tree guard;
{
tree guard_value;
guard = get_guard_bits (guard);
guard_value = integer_zero_node;
if (!same_type_p (TREE_TYPE (guard_value), TREE_TYPE (guard)))
guard_value = convert (TREE_TYPE (guard), guard_value);
return cp_build_binary_op (EQ_EXPR, guard, guard_value);
}
tree
set_guard (guard)
tree guard;
{
tree guard_init;
guard = get_guard_bits (guard);
guard_init = integer_one_node;
if (!same_type_p (TREE_TYPE (guard_init), TREE_TYPE (guard)))
guard_init = convert (TREE_TYPE (guard), guard_init);
return build_modify_expr (guard, NOP_EXPR, guard_init);
}
static tree
start_objects (method_type, initp)
int method_type, initp;
{
tree fnname;
tree body;
char type[10];
if (initp != DEFAULT_INIT_PRIORITY)
{
char joiner;
#ifdef JOINER
joiner = JOINER;
#else
joiner = '_';
#endif
sprintf (type, "%c%c%.5u", method_type, joiner, initp);
}
else
sprintf (type, "%c", method_type);
fnname = get_file_function_name_long (type);
start_function (void_list_node,
make_call_declarator (fnname, void_list_node, NULL_TREE,
NULL_TREE),
NULL_TREE, SF_DEFAULT);
TREE_PUBLIC (current_function_decl) = ! targetm.have_ctors_dtors;
TREE_USED (current_function_decl) = 1;
if (method_type == 'I')
DECL_GLOBAL_CTOR_P (current_function_decl) = 1;
else
DECL_GLOBAL_DTOR_P (current_function_decl) = 1;
DECL_LANG_SPECIFIC (current_function_decl)->decl_flags.u2sel = 1;
#ifdef STATIC_INIT_SECTION
if ( ! flag_apple_kext)
DECL_SECTION_NAME (current_function_decl) =
build_string (strlen (STATIC_INIT_SECTION), STATIC_INIT_SECTION);
#endif
body = begin_compound_stmt (0);
current_function_cannot_inline
= "static constructors and destructors cannot be inlined";
return body;
}
static void
finish_objects (method_type, initp, body)
int method_type, initp;
tree body;
{
tree fn;
finish_compound_stmt (0, body);
fn = finish_function (0);
expand_body (fn);
if (flag_syntax_only)
return;
if (targetm.have_ctors_dtors)
{
rtx fnsym = XEXP (DECL_RTL (fn), 0);
if (method_type == 'I')
(* targetm.asm_out.constructor) (fnsym, initp);
else
(* targetm.asm_out.destructor) (fnsym, initp);
}
}
#define INITIALIZE_P_IDENTIFIER "__initialize_p"
#define PRIORITY_IDENTIFIER "__priority"
#define SSDF_IDENTIFIER "__static_initialization_and_destruction"
static GTY(()) tree initialize_p_decl;
static GTY(()) tree priority_decl;
static GTY(()) tree ssdf_decl;
static GTY(()) varray_type ssdf_decls;
static splay_tree priority_info_map;
static tree
start_static_storage_duration_function ()
{
static unsigned ssdf_number;
tree parm_types;
tree type;
tree body;
char id[sizeof (SSDF_IDENTIFIER) + 1 + 32];
sprintf (id, "%s_%u", SSDF_IDENTIFIER, ssdf_number++);
if (ssdf_number == 0)
{
sorry ("too many initialization functions required");
abort ();
}
parm_types = void_list_node;
parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
parm_types = tree_cons (NULL_TREE, integer_type_node, parm_types);
type = build_function_type (void_type_node, parm_types);
ssdf_decl = build_lang_decl (FUNCTION_DECL,
get_identifier (id),
type);
TREE_PUBLIC (ssdf_decl) = 0;
DECL_ARTIFICIAL (ssdf_decl) = 1;
#ifdef STATIC_INIT_SECTION
if ( ! flag_apple_kext)
DECL_SECTION_NAME (ssdf_decl) = build_string (strlen (STATIC_INIT_SECTION),
STATIC_INIT_SECTION);
#endif
if (!ssdf_decls)
{
VARRAY_TREE_INIT (ssdf_decls, 32, "ssdf_decls");
priority_info_map = splay_tree_new (splay_tree_compare_ints,
0,
(splay_tree_delete_value_fn) &free);
get_priority_info (DEFAULT_INIT_PRIORITY);
}
VARRAY_PUSH_TREE (ssdf_decls, ssdf_decl);
initialize_p_decl = cp_build_parm_decl
(get_identifier (INITIALIZE_P_IDENTIFIER), integer_type_node);
DECL_CONTEXT (initialize_p_decl) = ssdf_decl;
TREE_USED (initialize_p_decl) = 1;
priority_decl = cp_build_parm_decl
(get_identifier (PRIORITY_IDENTIFIER), integer_type_node);
DECL_CONTEXT (priority_decl) = ssdf_decl;
TREE_USED (priority_decl) = 1;
TREE_CHAIN (initialize_p_decl) = priority_decl;
DECL_ARGUMENTS (ssdf_decl) = initialize_p_decl;
pushdecl (ssdf_decl);
start_function (NULL_TREE,
ssdf_decl,
NULL_TREE,
SF_PRE_PARSED);
body = begin_compound_stmt (0);
current_function_cannot_inline
= "static storage duration functions cannot be inlined";
return body;
}
static void
finish_static_storage_duration_function (body)
tree body;
{
finish_compound_stmt (0, body);
expand_body (finish_function (0));
}
static priority_info
get_priority_info (priority)
int priority;
{
priority_info pi;
splay_tree_node n;
n = splay_tree_lookup (priority_info_map,
(splay_tree_key) priority);
if (!n)
{
pi = (priority_info) xmalloc (sizeof (struct priority_info_s));
pi->initializations_p = 0;
pi->destructions_p = 0;
splay_tree_insert (priority_info_map,
(splay_tree_key) priority,
(splay_tree_value) pi);
}
else
pi = (priority_info) n->value;
return pi;
}
static tree
start_static_initialization_or_destruction (decl, initp)
tree decl;
int initp;
{
tree guard_if_stmt = NULL_TREE;
int priority;
tree cond;
tree guard;
tree init_cond;
priority_info pi;
priority = DECL_INIT_PRIORITY (decl);
if (!priority)
priority = DEFAULT_INIT_PRIORITY;
pi = get_priority_info (priority);
if (initp)
pi->initializations_p = 1;
else
pi->destructions_p = 1;
input_filename = DECL_SOURCE_FILE (decl);
lineno = DECL_SOURCE_LINE (decl);
if (member_p (decl))
{
DECL_CONTEXT (current_function_decl) = DECL_CONTEXT (decl);
DECL_STATIC_FUNCTION_P (current_function_decl) = 1;
}
guard_if_stmt = begin_if_stmt ();
cond = cp_build_binary_op (EQ_EXPR,
priority_decl,
build_int_2 (priority, 0));
init_cond = initp ? integer_one_node : integer_zero_node;
init_cond = cp_build_binary_op (EQ_EXPR,
initialize_p_decl,
init_cond);
cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, init_cond);
guard = NULL_TREE;
if ((TREE_PUBLIC (decl) && (DECL_COMMON (decl)
|| DECL_ONE_ONLY (decl)
|| DECL_WEAK (decl)))
|| DECL_COALESCED (decl))
{
tree guard_cond;
guard = get_guard (decl);
if (flag_use_cxa_atexit)
{
my_friendly_assert (initp, 20000629);
guard_cond = get_guard_cond (guard);
}
else if (initp)
guard_cond
= cp_build_binary_op (EQ_EXPR,
build_unary_op (PREINCREMENT_EXPR,
guard,
1),
integer_one_node);
else
guard_cond
= cp_build_binary_op (EQ_EXPR,
build_unary_op (PREDECREMENT_EXPR,
guard,
1),
integer_zero_node);
cond = cp_build_binary_op (TRUTH_ANDIF_EXPR, cond, guard_cond);
}
finish_if_stmt_cond (cond, guard_if_stmt);
if (guard && initp && flag_use_cxa_atexit)
finish_expr_stmt (set_guard (guard));
return guard_if_stmt;
}
static void
finish_static_initialization_or_destruction (guard_if_stmt)
tree guard_if_stmt;
{
finish_then_clause (guard_if_stmt);
finish_if_stmt ();
DECL_CONTEXT (current_function_decl) = NULL_TREE;
DECL_STATIC_FUNCTION_P (current_function_decl) = 0;
}
static void
do_static_initialization (decl, init)
tree decl;
tree init;
{
tree guard_if_stmt;
guard_if_stmt
= start_static_initialization_or_destruction (decl,
1);
if (init)
finish_expr_stmt (init);
if (flag_use_cxa_atexit)
register_dtor_fn (decl);
finish_static_initialization_or_destruction (guard_if_stmt);
}
static void
do_static_destruction (decl)
tree decl;
{
tree guard_if_stmt;
my_friendly_assert (!flag_use_cxa_atexit, 20000121);
if (TYPE_HAS_TRIVIAL_DESTRUCTOR (TREE_TYPE (decl)))
return;
guard_if_stmt = start_static_initialization_or_destruction (decl,
0);
finish_expr_stmt (build_cleanup (decl));
finish_static_initialization_or_destruction (guard_if_stmt);
}
static tree
prune_vars_needing_no_initialization (vars)
tree *vars;
{
tree *var = vars;
tree result = NULL_TREE;
while (*var)
{
tree t = *var;
tree decl = TREE_VALUE (t);
tree init = TREE_PURPOSE (t);
if (decl == error_mark_node)
{
var = &TREE_CHAIN (t);
continue;
}
my_friendly_assert (TREE_CODE (decl) == VAR_DECL, 19990420);
if (DECL_EXTERNAL (decl))
{
var = &TREE_CHAIN (t);
continue;
}
if (init && TREE_CODE (init) == TREE_LIST
&& value_member (error_mark_node, init))
{
var = &TREE_CHAIN (t);
continue;
}
*var = TREE_CHAIN (t);
TREE_CHAIN (t) = result;
result = t;
}
return result;
}
static void
write_out_vars (vars)
tree vars;
{
tree v;
for (v = vars; v; v = TREE_CHAIN (v))
if (! TREE_ASM_WRITTEN (TREE_VALUE (v)))
rest_of_decl_compilation (TREE_VALUE (v), 0, 1, 1);
}
static void
generate_ctor_or_dtor_function (constructor_p, priority)
int constructor_p;
int priority;
{
char function_key;
tree arguments;
tree body;
size_t i;
if (constructor_p)
function_key = 'I';
else
function_key = 'D';
body = start_objects (function_key, priority);
for (i = 0; i < ssdf_decls->elements_used; ++i)
{
arguments = tree_cons (NULL_TREE, build_int_2 (priority, 0),
NULL_TREE);
arguments = tree_cons (NULL_TREE, build_int_2 (constructor_p, 0),
arguments);
finish_expr_stmt (build_function_call (VARRAY_TREE (ssdf_decls, i),
arguments));
}
if (priority == DEFAULT_INIT_PRIORITY)
{
tree fns;
for (fns = constructor_p ? static_ctors : static_dtors;
fns;
fns = TREE_CHAIN (fns))
finish_expr_stmt (build_function_call (TREE_VALUE (fns), NULL_TREE));
}
finish_objects (function_key, priority, body);
}
static int
generate_ctor_and_dtor_functions_for_priority (n, data)
splay_tree_node n;
void *data ATTRIBUTE_UNUSED;
{
int priority = (int) n->key;
priority_info pi = (priority_info) n->value;
if (pi->initializations_p
|| (priority == DEFAULT_INIT_PRIORITY && static_ctors))
generate_ctor_or_dtor_function (1,
priority);
if (pi->destructions_p
|| (priority == DEFAULT_INIT_PRIORITY && static_dtors))
generate_ctor_or_dtor_function (0,
priority);
return 0;
}
int
cxx_finish_file_start ()
{
at_eof = 1;
if (! global_bindings_p () || current_class_type || decl_namespace_list)
return 0;
if (pch_file)
c_common_write_pch ();
if (dbg_dir)
c_common_write_context ();
return 1;
}
void
cxx_finish_file_rest ()
{
tree vars;
int reconsider;
size_t i;
lineno -= 1;
interface_unknown = 1;
interface_only = 0;
timevar_push (TV_VARCONST);
emit_support_tinfos ();
do
{
tree t;
size_t n_old, n_new;
reconsider = 0;
instantiate_pending_templates ();
while (keyed_classes != NULL_TREE
&& maybe_emit_vtables (TREE_VALUE (keyed_classes)))
{
reconsider = 1;
keyed_classes = TREE_CHAIN (keyed_classes);
}
t = keyed_classes;
if (t != NULL_TREE)
{
tree next = TREE_CHAIN (t);
while (next)
{
if (maybe_emit_vtables (TREE_VALUE (next)))
{
reconsider = 1;
TREE_CHAIN (t) = TREE_CHAIN (next);
}
else
t = next;
next = TREE_CHAIN (t);
}
}
n_old = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls);
for (i = 0; i < n_old; ++i)
{
tree tinfo_decl = VARRAY_TREE (unemitted_tinfo_decls, i);
if (emit_tinfo_decl (tinfo_decl))
reconsider = 1;
else
VARRAY_PUSH_TREE (unemitted_tinfo_decls, tinfo_decl);
}
n_new = VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) - n_old;
memmove (&VARRAY_TREE (unemitted_tinfo_decls, 0),
&VARRAY_TREE (unemitted_tinfo_decls, n_old),
n_new * sizeof (tree));
memset (&VARRAY_TREE (unemitted_tinfo_decls, n_new),
0,
n_old * sizeof (tree));
VARRAY_ACTIVE_SIZE (unemitted_tinfo_decls) = n_new;
vars = prune_vars_needing_no_initialization (&static_aggregates);
if (vars)
{
tree v;
tree ssdf_body = start_static_storage_duration_function ();
write_out_vars (vars);
for (v = vars; v; v = TREE_CHAIN (v))
do_static_initialization (TREE_VALUE (v),
TREE_PURPOSE (v));
if (!flag_use_cxa_atexit)
{
vars = nreverse (vars);
for (v = vars; v; v = TREE_CHAIN (v))
do_static_destruction (TREE_VALUE (v));
}
else
vars = NULL_TREE;
finish_static_storage_duration_function (ssdf_body);
reconsider = 1;
}
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
if (DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
&& TREE_USED (decl)
&& (! DECL_REALLY_EXTERN (decl) || DECL_INLINE (decl)))
{
push_to_top_level ();
synthesize_method (decl);
pop_from_top_level ();
reconsider = 1;
}
if (!DECL_SAVED_TREE (decl))
continue;
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl)
&& DECL_INITIAL (decl)
&& DECL_NEEDED_P (decl))
DECL_EXTERNAL (decl) = 0;
if (!DECL_EXTERNAL (decl)
&& DECL_NEEDED_P (decl)
&& DECL_SAVED_TREE (decl)
&& !TREE_ASM_WRITTEN (decl))
{
int saved_not_really_extern;
saved_not_really_extern = DECL_NOT_REALLY_EXTERN (decl);
expand_body (decl);
DECL_EXTERNAL (decl) = 0;
DECL_NOT_REALLY_EXTERN (decl) = saved_not_really_extern;
if (flag_syntax_only)
TREE_ASM_WRITTEN (decl) = 1;
reconsider = 1;
}
}
if (deferred_fns_used
&& wrapup_global_declarations (&VARRAY_TREE (deferred_fns, 0),
deferred_fns_used))
reconsider = 1;
if (walk_namespaces (wrapup_globals_for_namespace, 0))
reconsider = 1;
for (i = 0; i < pending_statics_used; ++i)
{
tree decl = VARRAY_TREE (pending_statics, i);
if (TREE_ASM_WRITTEN (decl))
continue;
import_export_decl (decl);
if (DECL_NOT_REALLY_EXTERN (decl) && ! DECL_IN_AGGR_P (decl))
DECL_EXTERNAL (decl) = 0;
#ifdef MACHOPIC_VAR_REFERRED_TO_P
else
if (TREE_USED (decl) && DECL_INITIAL (decl) != 0
&& DECL_INITIAL (decl) != error_mark_node
&& TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR
&& DECL_EXTERNAL (decl)
&& MACHOPIC_VAR_REFERRED_TO_P (IDENTIFIER_POINTER (
DECL_ASSEMBLER_NAME (decl))))
{
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
}
#endif
}
if (pending_statics
&& wrapup_global_declarations (&VARRAY_TREE (pending_statics, 0),
pending_statics_used))
reconsider = 1;
}
while (reconsider);
for (i = 0; i < deferred_fns_used; ++i)
{
tree decl = VARRAY_TREE (deferred_fns, i);
if (TREE_USED (decl) && DECL_DECLARED_INLINE_P (decl)
&& !(TREE_ASM_WRITTEN (decl) || DECL_SAVED_TREE (decl)))
cp_warning_at ("inline function `%D' used but never defined", decl);
}
push_lang_context (lang_name_c);
if (priority_info_map)
splay_tree_foreach (priority_info_map,
generate_ctor_and_dtor_functions_for_priority,
0);
if (priority_info_map)
splay_tree_delete (priority_info_map);
pop_lang_context ();
walk_namespaces (wrapup_globals_for_namespace, &reconsider);
if (pending_statics)
check_global_declarations (&VARRAY_TREE (pending_statics, 0),
pending_statics_used);
finish_repo ();
{
int flags;
FILE *stream = dump_begin (TDI_all, &flags);
if (stream)
{
dump_node (global_namespace, flags & ~TDF_SLIM, stream);
dump_end (TDI_all, stream);
}
}
timevar_pop (TV_VARCONST);
if (flag_detailed_statistics)
{
dump_tree_statistics ();
dump_time_statistics ();
}
}
tree
reparse_absdcl_as_expr (type, decl)
tree type, decl;
{
if (TREE_OPERAND (decl, 0) == NULL_TREE)
return build_functional_cast (type, NULL_TREE);
decl = reparse_absdcl_as_expr (type, TREE_OPERAND (decl, 0));
return finish_call_expr (decl, NULL_TREE, false);
}
tree
reparse_absdcl_as_casts (decl, expr)
tree decl, expr;
{
tree type;
int non_void_p = 0, vector_p = 0;
if (TREE_CODE (expr) == CONSTRUCTOR
&& TREE_TYPE (expr) == 0)
{
type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
if (processing_template_decl)
TREE_TYPE (expr) = type;
else
{
expr = digest_init (type, expr, (tree *) 0);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
{
int failure = complete_array_type (type, expr, 1);
my_friendly_assert (!failure, 78);
}
}
}
while (decl)
{
type = groktypename (TREE_VALUE (CALL_DECLARATOR_PARMS (decl)));
decl = TREE_OPERAND (decl, 0);
if (!VOID_TYPE_P (type))
non_void_p = 1;
if (TREE_CODE (type) == VECTOR_TYPE
&& (vector_p = 1,
!TREE_TYPE (expr)
|| TREE_CODE (TREE_TYPE (expr)) != VECTOR_TYPE))
expr = altivec_vector_constant (type, expr);
else
expr = build_c_cast (type, expr);
}
if (warn_old_style_cast && ! in_system_header && !vector_p
&& non_void_p && current_lang_name != lang_name_c)
warning ("use of old-style cast");
return expr;
}
tree
build_expr_from_tree (t)
tree t;
{
if (t == NULL_TREE || t == error_mark_node)
return t;
switch (TREE_CODE (t))
{
case IDENTIFIER_NODE:
return do_identifier (t, 0, NULL_TREE);
case LOOKUP_EXPR:
if (LOOKUP_EXPR_GLOBAL (t))
{
tree token = TREE_OPERAND (t, 0);
return do_scoped_id (token, IDENTIFIER_GLOBAL_VALUE (token));
}
else
return do_identifier (TREE_OPERAND (t, 0), 0, NULL_TREE);
case TEMPLATE_ID_EXPR:
{
tree template;
tree args;
tree object;
template = build_expr_from_tree (TREE_OPERAND (t, 0));
args = build_expr_from_tree (TREE_OPERAND (t, 1));
if (TREE_CODE (template) == COMPONENT_REF)
{
object = TREE_OPERAND (template, 0);
template = TREE_OPERAND (template, 1);
}
else
object = NULL_TREE;
template = lookup_template_function (template, args);
if (object)
return build (COMPONENT_REF, TREE_TYPE (template),
object, template);
else
return template;
}
case INDIRECT_REF:
return build_x_indirect_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)), "unary *");
case CAST_EXPR:
return build_functional_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case REINTERPRET_CAST_EXPR:
return build_reinterpret_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case CONST_CAST_EXPR:
return build_const_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case DYNAMIC_CAST_EXPR:
return build_dynamic_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case STATIC_CAST_EXPR:
return build_static_cast
(TREE_TYPE (t), build_expr_from_tree (TREE_OPERAND (t, 0)));
case PREDECREMENT_EXPR:
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
case NEGATE_EXPR:
case BIT_NOT_EXPR:
case ABS_EXPR:
case TRUTH_NOT_EXPR:
case ADDR_EXPR:
case CONVERT_EXPR:
case REALPART_EXPR:
case IMAGPART_EXPR:
if (TREE_TYPE (t))
return t;
return build_x_unary_op (TREE_CODE (t),
build_expr_from_tree (TREE_OPERAND (t, 0)));
case PLUS_EXPR:
case MINUS_EXPR:
case MULT_EXPR:
case TRUNC_DIV_EXPR:
case CEIL_DIV_EXPR:
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
case BIT_AND_EXPR:
case BIT_ANDTC_EXPR:
case BIT_IOR_EXPR:
case BIT_XOR_EXPR:
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
case TRUTH_ANDIF_EXPR:
case TRUTH_ORIF_EXPR:
case TRUTH_AND_EXPR:
case TRUTH_OR_EXPR:
case RSHIFT_EXPR:
case LSHIFT_EXPR:
case RROTATE_EXPR:
case LROTATE_EXPR:
case EQ_EXPR:
case NE_EXPR:
case MAX_EXPR:
case MIN_EXPR:
case LE_EXPR:
case GE_EXPR:
case LT_EXPR:
case GT_EXPR:
case MEMBER_REF:
return build_x_binary_op
(TREE_CODE (t),
build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case DOTSTAR_EXPR:
return build_m_component_ref
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case SCOPE_REF:
return build_offset_ref (TREE_OPERAND (t, 0), TREE_OPERAND (t, 1));
case ARRAY_REF:
if (TREE_OPERAND (t, 0) == NULL_TREE)
return build_nt (ARRAY_REF, NULL_TREE,
build_expr_from_tree (TREE_OPERAND (t, 1)));
return grok_array_decl (build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)));
case SIZEOF_EXPR:
case ALIGNOF_EXPR:
{
tree r = build_expr_from_tree (TREE_OPERAND (t, 0));
if (!TYPE_P (r))
return TREE_CODE (t) == SIZEOF_EXPR ? expr_sizeof (r) : c_alignof_expr (r);
else
return cxx_sizeof_or_alignof_type (r, TREE_CODE (t), true);
}
case MODOP_EXPR:
return build_x_modify_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_CODE (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)));
case ARROW_EXPR:
return build_x_arrow
(build_expr_from_tree (TREE_OPERAND (t, 0)));
case NEW_EXPR:
return build_new
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)),
NEW_EXPR_USE_GLOBAL (t));
case DELETE_EXPR:
return delete_sanity
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
DELETE_EXPR_USE_VEC (t), DELETE_EXPR_USE_GLOBAL (t));
case COMPOUND_EXPR:
if (TREE_OPERAND (t, 1) == NULL_TREE)
return build_x_compound_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)));
else
abort ();
case METHOD_CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
return build_scoped_method_call
(build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (ref, 0)),
name,
build_expr_from_tree (TREE_OPERAND (t, 2)));
}
else
{
tree fn = TREE_OPERAND (t, 0);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
fn = lookup_template_function
(TREE_OPERAND (fn, 0),
build_expr_from_tree (TREE_OPERAND (fn, 1)));
return build_method_call
(build_expr_from_tree (TREE_OPERAND (t, 1)),
fn,
build_expr_from_tree (TREE_OPERAND (t, 2)),
NULL_TREE, LOOKUP_NORMAL);
}
case CALL_EXPR:
if (TREE_CODE (TREE_OPERAND (t, 0)) == SCOPE_REF)
{
tree ref = TREE_OPERAND (t, 0);
tree name = TREE_OPERAND (ref, 1);
tree fn, scope, args;
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = build_nt (TEMPLATE_ID_EXPR,
TREE_OPERAND (name, 0),
build_expr_from_tree (TREE_OPERAND (name, 1)));
scope = build_expr_from_tree (TREE_OPERAND (ref, 0));
args = build_expr_from_tree (TREE_OPERAND (t, 1));
fn = resolve_scoped_fn_name (scope, name);
return build_call_from_tree (fn, args, 1);
}
else
{
tree name = TREE_OPERAND (t, 0);
tree id;
tree args = build_expr_from_tree (TREE_OPERAND (t, 1));
if (args != NULL_TREE && TREE_CODE (name) == LOOKUP_EXPR
&& !LOOKUP_EXPR_GLOBAL (name)
&& TREE_CODE ((id = TREE_OPERAND (name, 0))) == IDENTIFIER_NODE
&& (!current_class_type
|| !lookup_member (current_class_type, id, 0, 0)))
{
name = do_identifier (id, 0, args);
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| ! really_overloaded_fn (name))
name = build_expr_from_tree (name);
if (TREE_CODE (name) == OFFSET_REF)
return build_offset_ref_call_from_tree (name, args);
if (TREE_CODE (name) == COMPONENT_REF)
return finish_object_call_expr (TREE_OPERAND (name, 1),
TREE_OPERAND (name, 0),
args);
name = convert_from_reference (name);
return build_call_from_tree (name, args,
false);
}
case MESSAGE_SEND_EXPR:
return finish_message_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_OPERAND (t, 1),
build_expr_from_tree (TREE_OPERAND (t, 2)));
case CLASS_REFERENCE_EXPR:
return get_class_reference
(build_expr_from_tree (TREE_OPERAND (t, 0)));
case COND_EXPR:
return build_x_conditional_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2)));
case PSEUDO_DTOR_EXPR:
return (finish_pseudo_destructor_call_expr
(build_expr_from_tree (TREE_OPERAND (t, 0)),
build_expr_from_tree (TREE_OPERAND (t, 1)),
build_expr_from_tree (TREE_OPERAND (t, 2))));
case TREE_LIST:
{
tree purpose, value, chain;
if (t == void_list_node)
return t;
purpose = TREE_PURPOSE (t);
if (purpose)
purpose = build_expr_from_tree (purpose);
value = TREE_VALUE (t);
if (value)
value = build_expr_from_tree (value);
chain = TREE_CHAIN (t);
if (chain && chain != void_type_node)
chain = build_expr_from_tree (chain);
return tree_cons (purpose, value, chain);
}
case COMPONENT_REF:
{
tree object = build_expr_from_tree (TREE_OPERAND (t, 0));
return finish_class_member_access_expr (object,
TREE_OPERAND (t, 1));
}
case THROW_EXPR:
return build_throw (build_expr_from_tree (TREE_OPERAND (t, 0)));
case CONSTRUCTOR:
{
tree r;
tree elts;
tree type = TREE_TYPE (t);
bool purpose_p;
if (type && TYPE_PTRMEMFUNC_P (type))
return t;
r = NULL_TREE;
purpose_p = !(type && IS_AGGR_TYPE (type));
for (elts = CONSTRUCTOR_ELTS (t); elts; elts = TREE_CHAIN (elts))
{
tree purpose = TREE_PURPOSE (elts);
tree value = TREE_VALUE (elts);
if (purpose && purpose_p)
purpose = build_expr_from_tree (purpose);
value = build_expr_from_tree (value);
r = tree_cons (purpose, value, r);
}
r = build_nt (CONSTRUCTOR, NULL_TREE, nreverse (r));
TREE_HAS_CONSTRUCTOR (r) = TREE_HAS_CONSTRUCTOR (t);
if (type)
return digest_init (type, r, 0);
return r;
}
case TYPEID_EXPR:
if (TYPE_P (TREE_OPERAND (t, 0)))
return get_typeid (TREE_OPERAND (t, 0));
return build_typeid (build_expr_from_tree (TREE_OPERAND (t, 0)));
case VAR_DECL:
return convert_from_reference (t);
case VA_ARG_EXPR:
return build_va_arg (build_expr_from_tree (TREE_OPERAND (t, 0)),
TREE_TYPE (t));
default:
return t;
}
}
tree
build_offset_ref_call_from_tree (tree fn, tree args)
{
tree object_addr;
my_friendly_assert (TREE_CODE (fn) == OFFSET_REF, 20020725);
if (TREE_CODE (TREE_OPERAND (fn, 1)) == FIELD_DECL)
fn = resolve_offset_ref (fn);
else
{
object_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (fn, 0), 0);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn);
args = tree_cons (NULL_TREE, object_addr, args);
}
return build_function_call (fn, args);
}
tree
build_call_from_tree (tree fn, tree args, bool disallow_virtual)
{
tree template_args;
tree template_id;
tree f;
my_friendly_assert (TREE_CODE (fn) != OFFSET_REF, 20020725);
my_friendly_assert (TREE_CODE (fn) != SCOPE_REF, 20020725);
if (TREE_CODE (fn) == TEMPLATE_ID_EXPR)
{
template_id = fn;
template_args = TREE_OPERAND (fn, 1);
fn = TREE_OPERAND (fn, 0);
}
else
{
template_id = NULL_TREE;
template_args = NULL_TREE;
}
f = (TREE_CODE (fn) == OVERLOAD) ? get_first_fn (fn) : fn;
if (current_class_type
&& ((TREE_CODE (f) == FUNCTION_DECL
&& DECL_FUNCTION_MEMBER_P (f))
|| (DECL_FUNCTION_TEMPLATE_P (f)
&& DECL_FUNCTION_MEMBER_P (f))))
{
f = lookup_member (current_class_type, DECL_NAME (f),
1, 0);
if (f)
fn = f;
}
if (template_id)
{
if (BASELINK_P (fn))
BASELINK_FUNCTIONS (fn) = build_nt (TEMPLATE_ID_EXPR,
BASELINK_FUNCTIONS (fn),
template_args);
else
fn = template_id;
}
return finish_call_expr (fn, args, disallow_virtual);
}
tree
reparse_decl_as_expr (type, decl)
tree type, decl;
{
decl = build_expr_from_tree (decl);
if (type)
return build_functional_cast (type, build_tree_list (NULL_TREE, decl));
else
return decl;
}
tree
finish_decl_parsing (decl)
tree decl;
{
switch (TREE_CODE (decl))
{
case IDENTIFIER_NODE:
return decl;
case INDIRECT_REF:
return make_pointer_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case ADDR_EXPR:
return make_reference_declarator
(NULL_TREE, finish_decl_parsing (TREE_OPERAND (decl, 0)));
case BIT_NOT_EXPR:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
case SCOPE_REF:
push_nested_class (TREE_TYPE (TREE_OPERAND (decl, 0)), 3);
TREE_COMPLEXITY (decl) = current_class_depth;
return decl;
case ARRAY_REF:
TREE_OPERAND (decl, 0) = finish_decl_parsing (TREE_OPERAND (decl, 0));
return decl;
case TREE_LIST:
TREE_VALUE (decl) = finish_decl_parsing (TREE_VALUE (decl));
return decl;
case TEMPLATE_ID_EXPR:
return decl;
default:
abort ();
return NULL_TREE;
}
}
static int
is_namespace_ancestor (root, child)
tree root, child;
{
if (root == child)
return 1;
if (root == global_namespace)
return 1;
if (child == global_namespace)
return 0;
return is_namespace_ancestor (root, CP_DECL_CONTEXT (child));
}
tree
namespace_ancestor (ns1, ns2)
tree ns1, ns2;
{
timevar_push (TV_NAME_LOOKUP);
if (is_namespace_ancestor (ns1, ns2))
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, ns1);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
namespace_ancestor (CP_DECL_CONTEXT (ns1), ns2));
}
static void
add_using_namespace (user, used, indirect)
tree user;
tree used;
int indirect;
{
tree t;
timevar_push (TV_NAME_LOOKUP);
if (user == used)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
my_friendly_assert (TREE_CODE (user) == NAMESPACE_DECL, 380);
my_friendly_assert (TREE_CODE (used) == NAMESPACE_DECL, 380);
t = purpose_member (used, DECL_NAMESPACE_USING (user));
if (t != NULL_TREE)
{
if (!indirect)
TREE_INDIRECT_USING (t) = 0;
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, (void)0);
}
DECL_NAMESPACE_USING (user)
= tree_cons (used, namespace_ancestor (user, used),
DECL_NAMESPACE_USING (user));
TREE_INDIRECT_USING (DECL_NAMESPACE_USING (user)) = indirect;
DECL_NAMESPACE_USERS (used)
= tree_cons (user, 0, DECL_NAMESPACE_USERS (used));
for (t = DECL_NAMESPACE_USING (used); t; t = TREE_CHAIN (t))
add_using_namespace (user, TREE_PURPOSE (t), 1);
for (t = DECL_NAMESPACE_USERS (user); t; t = TREE_CHAIN (t))
add_using_namespace (TREE_PURPOSE (t), used, 1);
timevar_pop (TV_NAME_LOOKUP);
}
static tree
merge_functions (s1, s2)
tree s1;
tree s2;
{
for (; s2; s2 = OVL_NEXT (s2))
{
tree fn2 = OVL_CURRENT (s2);
tree fns1;
for (fns1 = s1; fns1; fns1 = OVL_NEXT (fns1))
{
tree fn1 = OVL_CURRENT (fns1);
if (fn1 == fn2
|| (DECL_EXTERN_C_P (fn1) && DECL_EXTERN_C_P (fn2)
&& DECL_NAME (fn1) == DECL_NAME (fn2)))
break;
}
if (!fns1)
s1 = build_overload (fn2, s1);
}
return s1;
}
static cxx_binding *
ambiguous_decl (tree name, cxx_binding *old, cxx_binding *new, int flags)
{
tree val, type;
my_friendly_assert (old != NULL, 393);
val = BINDING_VALUE (new);
if (val)
switch (TREE_CODE (val))
{
case TEMPLATE_DECL:
if (LOOKUP_QUALIFIERS_ONLY (flags)
&& !DECL_CLASS_TEMPLATE_P (val))
val = NULL_TREE;
break;
case TYPE_DECL:
if (LOOKUP_NAMESPACES_ONLY (flags))
val = NULL_TREE;
break;
case NAMESPACE_DECL:
if (LOOKUP_TYPES_ONLY (flags))
val = NULL_TREE;
break;
case FUNCTION_DECL:
if (LOOKUP_QUALIFIERS_ONLY (flags) || DECL_ANTICIPATED (val))
val = NULL_TREE;
break;
default:
if (LOOKUP_QUALIFIERS_ONLY (flags))
val = NULL_TREE;
}
if (!BINDING_VALUE (old))
BINDING_VALUE (old) = val;
else if (val && val != BINDING_VALUE (old))
{
if (is_overloaded_fn (BINDING_VALUE (old))
&& is_overloaded_fn (val))
{
BINDING_VALUE (old) = merge_functions (BINDING_VALUE (old),
val);
}
else
{
if (flags & LOOKUP_COMPLAIN)
{
if (BINDING_VALUE (old) != error_mark_node)
{
error ("use of `%D' is ambiguous", name);
cp_error_at (" first declared as `%#D' here",
BINDING_VALUE (old));
}
cp_error_at (" also declared as `%#D' here", val);
}
BINDING_VALUE (old) = error_mark_node;
}
}
type = BINDING_TYPE (new);
if (LOOKUP_NAMESPACES_ONLY (flags))
type = NULL_TREE;
if (!BINDING_TYPE (old))
BINDING_TYPE (old) = type;
else if (type && BINDING_TYPE (old) != type)
{
if (flags & LOOKUP_COMPLAIN)
{
error ("`%D' denotes an ambiguous type",name);
cp_error_at (" first type here", BINDING_TYPE (old));
cp_error_at (" other type here", type);
}
}
return old;
}
bool
lookup_using_namespace (tree name, cxx_binding *val, tree usings,
tree scope, int flags, tree *spacesp)
{
tree iter;
cxx_binding *val1;
timevar_push (TV_NAME_LOOKUP);
for (iter = usings; iter; iter = TREE_CHAIN (iter))
if (TREE_VALUE (iter) == scope)
{
if (spacesp)
*spacesp = tree_cons (TREE_PURPOSE (iter), NULL_TREE,
*spacesp);
val1 = cxx_scope_find_binding_for_name (TREE_PURPOSE (iter), name);
if (val1)
val = ambiguous_decl (name, val, val1, flags);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP,
BINDING_VALUE (val) != error_mark_node);
}
bool
qualified_lookup_using_namespace (tree name, tree scope, cxx_binding *result,
int flags)
{
tree seen = NULL_TREE;
tree todo = NULL_TREE;
tree usings;
timevar_push (TV_NAME_LOOKUP);
scope = ORIGINAL_NAMESPACE (scope);
while (scope && result->value != error_mark_node)
{
cxx_binding *b = cxx_scope_find_binding_for_name (scope, name);
if (b)
{
seen = tree_cons (scope, NULL_TREE, seen);
result = ambiguous_decl (name, result, b, flags);
}
if (!BINDING_VALUE (result) && !BINDING_TYPE (result))
for (usings = DECL_NAMESPACE_USING (scope); usings;
usings = TREE_CHAIN (usings))
if (!TREE_INDIRECT_USING (usings)
&& !purpose_member (TREE_PURPOSE (usings), seen))
todo = tree_cons (TREE_PURPOSE (usings), NULL_TREE, todo);
if (todo)
{
scope = TREE_PURPOSE (todo);
todo = TREE_CHAIN (todo);
}
else
scope = NULL_TREE;
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, result->value != error_mark_node);
}
void
set_decl_namespace (decl, scope, friendp)
tree decl;
tree scope;
int friendp;
{
tree old;
scope = ORIGINAL_NAMESPACE (scope);
if (!friendp && !is_namespace_ancestor (current_namespace, scope))
error ("declaration of `%D' not in a namespace surrounding `%D'",
decl, scope);
DECL_CONTEXT (decl) = FROB_CONTEXT (scope);
if (scope != current_namespace)
{
old = namespace_binding (DECL_NAME (decl), scope);
if (!old)
goto complain;
if (processing_explicit_instantiation)
return;
if (!is_overloaded_fn (decl))
return;
if (!is_overloaded_fn (old))
goto complain;
if (processing_template_decl || processing_specialization)
return;
for (; old; old = OVL_NEXT (old))
if (decls_match (decl, OVL_CURRENT (old)))
return;
}
else
return;
complain:
error ("`%D' should have been declared inside `%D'",
decl, scope);
}
static tree
decl_namespace (decl)
tree decl;
{
timevar_push (TV_NAME_LOOKUP);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
while (DECL_CONTEXT (decl))
{
decl = DECL_CONTEXT (decl);
if (TREE_CODE (decl) == NAMESPACE_DECL)
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, decl);
if (TYPE_P (decl))
decl = TYPE_STUB_DECL (decl);
my_friendly_assert (DECL_P (decl), 390);
}
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, global_namespace);
}
tree
current_decl_namespace ()
{
tree result;
if (decl_namespace_list)
return TREE_PURPOSE (decl_namespace_list);
if (current_class_type)
result = decl_namespace (TYPE_STUB_DECL (current_class_type));
else if (current_function_decl)
result = decl_namespace (current_function_decl);
else
result = current_namespace;
return result;
}
void
push_decl_namespace (decl)
tree decl;
{
if (TREE_CODE (decl) != NAMESPACE_DECL)
decl = decl_namespace (decl);
decl_namespace_list = tree_cons (ORIGINAL_NAMESPACE (decl),
NULL_TREE, decl_namespace_list);
}
void
pop_decl_namespace ()
{
decl_namespace_list = TREE_CHAIN (decl_namespace_list);
}
void
push_scope (t)
tree t;
{
if (TREE_CODE (t) == NAMESPACE_DECL)
push_decl_namespace (t);
else if (CLASS_TYPE_P (t))
pushclass (t, 2);
}
void
pop_scope (t)
tree t;
{
if (TREE_CODE (t) == NAMESPACE_DECL)
pop_decl_namespace ();
else if (CLASS_TYPE_P (t))
popclass ();
}
struct arg_lookup
{
tree name;
tree namespaces;
tree classes;
tree functions;
};
static int arg_assoc PARAMS ((struct arg_lookup*, tree));
static int arg_assoc_args PARAMS ((struct arg_lookup*, tree));
static int arg_assoc_type PARAMS ((struct arg_lookup*, tree));
static int add_function PARAMS ((struct arg_lookup *, tree));
static int arg_assoc_namespace PARAMS ((struct arg_lookup *, tree));
static int arg_assoc_class PARAMS ((struct arg_lookup *, tree));
static int arg_assoc_template_arg PARAMS ((struct arg_lookup*, tree));
static int
add_function (k, fn)
struct arg_lookup *k;
tree fn;
{
if (!k->functions)
k->functions = fn;
else if (is_overloaded_fn (k->functions) && is_overloaded_fn (fn))
k->functions = build_overload (fn, k->functions);
else
{
tree f1 = OVL_CURRENT (k->functions);
tree f2 = fn;
if (is_overloaded_fn (f1))
{
fn = f1; f1 = f2; f2 = fn;
}
cp_error_at ("`%D' is not a function,", f1);
cp_error_at (" conflict with `%D'", f2);
error (" in call to `%D'", k->name);
return 1;
}
return 0;
}
static int
arg_assoc_namespace (k, scope)
struct arg_lookup *k;
tree scope;
{
tree value;
if (purpose_member (scope, k->namespaces))
return 0;
k->namespaces = tree_cons (scope, NULL_TREE, k->namespaces);
value = namespace_binding (k->name, scope);
if (!value)
return 0;
for (; value; value = OVL_NEXT (value))
if (add_function (k, OVL_CURRENT (value)))
return 1;
return 0;
}
static int
arg_assoc_template_arg (k, arg)
struct arg_lookup* k;
tree arg;
{
if (TREE_CODE (arg) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (arg) == UNBOUND_CLASS_TEMPLATE)
return 0;
else if (TREE_CODE (arg) == TEMPLATE_DECL)
{
tree ctx = CP_DECL_CONTEXT (arg);
if (TREE_CODE (ctx) == NAMESPACE_DECL)
return arg_assoc_namespace (k, ctx);
else
return arg_assoc_class (k, ctx);
}
else if (TYPE_P (arg))
return arg_assoc_type (k, arg);
else
return 0;
}
static int
arg_assoc_class (k, type)
struct arg_lookup* k;
tree type;
{
tree list, friends, context;
int i;
if (!CLASS_TYPE_P (type))
return 0;
if (purpose_member (type, k->classes))
return 0;
k->classes = tree_cons (type, NULL_TREE, k->classes);
context = decl_namespace (TYPE_MAIN_DECL (type));
if (arg_assoc_namespace (k, context))
return 1;
for (i = 0; i < CLASSTYPE_N_BASECLASSES (type); i++)
if (arg_assoc_class (k, TYPE_BINFO_BASETYPE (type, i)))
return 1;
for (list = DECL_FRIENDLIST (TYPE_MAIN_DECL (type)); list;
list = TREE_CHAIN (list))
if (k->name == TREE_PURPOSE (list))
for (friends = TREE_VALUE (list); friends;
friends = TREE_CHAIN (friends))
if (TREE_PURPOSE (friends) == error_mark_node && TREE_VALUE (friends)
&& decl_namespace (TREE_VALUE (friends)) == context)
if (add_function (k, TREE_VALUE (friends)))
return 1;
if (CLASSTYPE_TEMPLATE_INFO (type))
{
list = INNERMOST_TEMPLATE_ARGS (CLASSTYPE_TI_ARGS (type));
for (i = 0; i < TREE_VEC_LENGTH (list); ++i)
arg_assoc_template_arg (k, TREE_VEC_ELT (list, i));
}
return 0;
}
static int
arg_assoc_type (k, type)
struct arg_lookup *k;
tree type;
{
switch (TREE_CODE (type))
{
case VOID_TYPE:
case INTEGER_TYPE:
case REAL_TYPE:
case COMPLEX_TYPE:
case VECTOR_TYPE:
case CHAR_TYPE:
case BOOLEAN_TYPE:
return 0;
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (type))
return arg_assoc_type (k, TYPE_PTRMEMFUNC_FN_TYPE (type));
return arg_assoc_class (k, type);
case POINTER_TYPE:
case REFERENCE_TYPE:
case ARRAY_TYPE:
return arg_assoc_type (k, TREE_TYPE (type));
case UNION_TYPE:
case ENUMERAL_TYPE:
return arg_assoc_namespace (k, decl_namespace (TYPE_MAIN_DECL (type)));
case OFFSET_TYPE:
if (arg_assoc_type (k, TYPE_OFFSET_BASETYPE (type)))
return 1;
return arg_assoc_type (k, TREE_TYPE (type));
case METHOD_TYPE:
case FUNCTION_TYPE:
if (arg_assoc_args (k, TYPE_ARG_TYPES (type)))
return 1;
return arg_assoc_type (k, TREE_TYPE (type));
case TEMPLATE_TYPE_PARM:
case BOUND_TEMPLATE_TEMPLATE_PARM:
return 0;
case TYPENAME_TYPE:
return 0;
case LANG_TYPE:
if (type == unknown_type_node)
return 0;
default:
abort ();
}
return 0;
}
static int
arg_assoc_args (k, args)
struct arg_lookup* k;
tree args;
{
for (; args; args = TREE_CHAIN (args))
if (arg_assoc (k, TREE_VALUE (args)))
return 1;
return 0;
}
static int
arg_assoc (k, n)
struct arg_lookup* k;
tree n;
{
if (n == error_mark_node)
return 0;
if (TYPE_P (n))
return arg_assoc_type (k, n);
if (! type_unknown_p (n))
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == ADDR_EXPR)
n = TREE_OPERAND (n, 0);
if (TREE_CODE (n) == COMPONENT_REF)
n = TREE_OPERAND (n, 1);
if (TREE_CODE (n) == OFFSET_REF)
n = TREE_OPERAND (n, 1);
while (TREE_CODE (n) == TREE_LIST)
n = TREE_VALUE (n);
if (TREE_CODE (n) == BASELINK)
n = BASELINK_FUNCTIONS (n);
if (TREE_CODE (n) == FUNCTION_DECL)
return arg_assoc_type (k, TREE_TYPE (n));
if (TREE_CODE (n) == TEMPLATE_ID_EXPR)
{
tree template = TREE_OPERAND (n, 0);
tree args = TREE_OPERAND (n, 1);
tree ctx;
tree arg;
if (TREE_CODE (template) == COMPONENT_REF)
template = TREE_OPERAND (template, 1);
template = OVL_CURRENT (template);
ctx = CP_DECL_CONTEXT (template);
if (TREE_CODE (ctx) == NAMESPACE_DECL)
{
if (arg_assoc_namespace (k, ctx) == 1)
return 1;
}
else if (arg_assoc_class (k, ctx) == 1)
return 1;
for (arg = args; arg != NULL_TREE; arg = TREE_CHAIN (arg))
if (arg_assoc_template_arg (k, TREE_VALUE (arg)) == 1)
return 1;
}
else
{
my_friendly_assert (TREE_CODE (n) == OVERLOAD, 980715);
for (; n; n = OVL_CHAIN (n))
if (arg_assoc_type (k, TREE_TYPE (OVL_FUNCTION (n))))
return 1;
}
return 0;
}
tree
lookup_arg_dependent (name, fns, args)
tree name;
tree fns;
tree args;
{
struct arg_lookup k;
tree fn = NULL_TREE;
timevar_push (TV_NAME_LOOKUP);
k.name = name;
k.functions = fns;
k.classes = NULL_TREE;
if (fns)
fn = OVL_CURRENT (fns);
if (fn && TREE_CODE (fn) == FUNCTION_DECL && DECL_LOCAL_FUNCTION_P (fn))
k.namespaces = NULL_TREE;
else
unqualified_namespace_lookup (name, 0, &k.namespaces);
arg_assoc_args (&k, args);
POP_TIMEVAR_AND_RETURN (TV_NAME_LOOKUP, k.functions);
}
void
do_namespace_alias (alias, namespace)
tree alias, namespace;
{
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
error ("unknown namespace `%D'", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
alias = build_lang_decl (NAMESPACE_DECL, alias, void_type_node);
DECL_NAMESPACE_ALIAS (alias) = namespace;
pushdecl (alias);
}
static tree
validate_nonmember_using_decl (decl, scope, name)
tree decl;
tree *scope;
tree *name;
{
if (TREE_CODE (decl) == SCOPE_REF)
{
*scope = TREE_OPERAND (decl, 0);
*name = TREE_OPERAND (decl, 1);
if (!processing_template_decl)
{
if(TREE_CODE (*scope) != NAMESPACE_DECL)
{
if (TYPE_P (*scope))
error ("`%T' is not a namespace", *scope);
else
error ("`%D' is not a namespace", *scope);
return NULL_TREE;
}
if (TREE_CODE (*name) == TEMPLATE_ID_EXPR)
{
*name = TREE_OPERAND (*name, 0);
error ("a using-declaration cannot specify a template-id. Try `using %D'", *name);
return NULL_TREE;
}
}
}
else if (TREE_CODE (decl) == IDENTIFIER_NODE
|| TREE_CODE (decl) == TYPE_DECL
|| TREE_CODE (decl) == TEMPLATE_DECL)
{
*scope = global_namespace;
*name = decl;
}
else if (TREE_CODE (decl) == NAMESPACE_DECL)
{
error ("namespace `%D' not allowed in using-declaration", decl);
return NULL_TREE;
}
else
abort ();
if (DECL_P (*name))
*name = DECL_NAME (*name);
return push_using_decl (*scope, *name);
}
static void
do_nonmember_using_decl (scope, name, oldval, oldtype, newval, newtype)
tree scope, name;
tree oldval, oldtype;
tree *newval, *newtype;
{
cxx_binding decls;
*newval = *newtype = NULL_TREE;
cxx_binding_clear (&decls);
if (!qualified_lookup_using_namespace (name, scope, &decls, 0))
return;
if (!decls.value && !decls.type)
{
error ("`%D' not declared", name);
return;
}
if (decls.value && is_overloaded_fn (decls.value))
{
tree tmp, tmp1;
if (oldval && !is_overloaded_fn (oldval))
{
duplicate_decls (OVL_CURRENT (decls.value), oldval);
oldval = NULL_TREE;
}
*newval = oldval;
for (tmp = decls.value; tmp; tmp = OVL_NEXT (tmp))
{
tree new_fn = OVL_CURRENT (tmp);
for (tmp1 = oldval; tmp1; tmp1 = OVL_NEXT (tmp1))
{
tree old_fn = OVL_CURRENT (tmp1);
if (new_fn == old_fn)
break;
else if (OVL_USED (tmp1))
continue;
else if (compparms (TYPE_ARG_TYPES (TREE_TYPE (new_fn)),
TYPE_ARG_TYPES (TREE_TYPE (old_fn))))
{
if (DECL_ANTICIPATED (old_fn))
{
DECL_ANTICIPATED (old_fn) = 0;
break;
}
if (!decls_match (new_fn, old_fn))
error ("`%D' is already declared in this scope", name);
break;
}
}
if (tmp1)
continue;
*newval = build_overload (OVL_CURRENT (tmp), *newval);
if (TREE_CODE (*newval) != OVERLOAD)
*newval = ovl_cons (*newval, NULL_TREE);
OVL_USED (*newval) = 1;
}
}
else
{
*newval = decls.value;
if (oldval)
duplicate_decls (*newval, oldval);
}
*newtype = decls.type;
if (oldtype && *newtype && oldtype != *newtype)
{
error ("using declaration `%D' introduced ambiguous type `%T'",
name, oldtype);
return;
}
}
void
do_toplevel_using_decl (decl)
tree decl;
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
cxx_binding *binding;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
binding = binding_for_name (name, current_namespace);
oldval = BINDING_VALUE (binding);
oldtype = BINDING_TYPE (binding);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
BINDING_VALUE (binding) = newval;
if (newtype)
BINDING_TYPE (binding) = newtype;
return;
}
void
do_local_using_decl (decl)
tree decl;
{
tree scope, name;
tree oldval, oldtype, newval, newtype;
decl = validate_nonmember_using_decl (decl, &scope, &name);
if (decl == NULL_TREE)
return;
if (building_stmt_tree ()
&& at_function_scope_p ())
add_decl_stmt (decl);
oldval = lookup_name_current_level (name);
oldtype = lookup_type_current_level (name);
do_nonmember_using_decl (scope, name, oldval, oldtype, &newval, &newtype);
if (newval)
{
if (is_overloaded_fn (newval))
{
tree fn, term;
if (oldval && TREE_CODE (oldval) == OVERLOAD)
term = OVL_FUNCTION (oldval);
else
term = oldval;
for (fn = newval; fn && OVL_CURRENT (fn) != term;
fn = OVL_NEXT (fn))
push_overloaded_decl (OVL_CURRENT (fn),
PUSH_LOCAL | PUSH_USING);
}
else
push_local_binding (name, newval, PUSH_USING);
}
if (newtype)
set_identifier_type_value (name, newtype);
}
tree
do_class_using_decl (decl)
tree decl;
{
tree name, value;
if (TREE_CODE (decl) != SCOPE_REF
|| !TYPE_P (TREE_OPERAND (decl, 0)))
{
error ("using-declaration for non-member at class scope");
return NULL_TREE;
}
name = TREE_OPERAND (decl, 1);
if (TREE_CODE (name) == BIT_NOT_EXPR)
{
error ("using-declaration for destructor");
return NULL_TREE;
}
else if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
{
name = TREE_OPERAND (name, 0);
error ("a using-declaration cannot specify a template-id. Try `using %T::%D'", TREE_OPERAND (decl, 0), name);
return NULL_TREE;
}
if (TREE_CODE (name) == TYPE_DECL || TREE_CODE (name) == TEMPLATE_DECL)
name = DECL_NAME (name);
else if (BASELINK_P (name))
{
name = BASELINK_FUNCTIONS (name);
if (TREE_CODE (name) == TEMPLATE_ID_EXPR)
name = TREE_OPERAND (name, 0);
name = DECL_NAME (get_first_fn (name));
}
my_friendly_assert (TREE_CODE (name) == IDENTIFIER_NODE, 980716);
value = build_lang_decl (USING_DECL, name, void_type_node);
DECL_INITIAL (value) = TREE_OPERAND (decl, 0);
return value;
}
void
do_using_directive (namespace)
tree namespace;
{
if (building_stmt_tree ())
add_stmt (build_stmt (USING_STMT, namespace));
if (TREE_CODE (namespace) == SCOPE_REF)
namespace = TREE_OPERAND (namespace, 1);
if (TREE_CODE (namespace) == IDENTIFIER_NODE)
{
if (!processing_template_decl)
error ("namespace `%T' undeclared", namespace);
return;
}
if (TREE_CODE (namespace) != NAMESPACE_DECL)
{
if (!processing_template_decl)
error ("`%T' is not a namespace", namespace);
return;
}
namespace = ORIGINAL_NAMESPACE (namespace);
if (!toplevel_bindings_p ())
push_using_directive (namespace);
else
add_using_namespace (current_namespace, namespace, 0);
}
void
check_default_args (x)
tree x;
{
tree arg = TYPE_ARG_TYPES (TREE_TYPE (x));
int saw_def = 0, i = 0 - (TREE_CODE (TREE_TYPE (x)) == METHOD_TYPE);
for (; arg && arg != void_list_node; arg = TREE_CHAIN (arg), ++i)
{
if (TREE_PURPOSE (arg))
saw_def = 1;
else if (saw_def)
{
cp_error_at ("default argument missing for parameter %P of `%+#D'",
i, x);
break;
}
}
}
void
mark_used (decl)
tree decl;
{
TREE_USED (decl) = 1;
if (processing_template_decl)
return;
if (TREE_CODE (decl) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (decl)
&& !TREE_ASM_WRITTEN (decl))
defer_fn (decl);
if (!skip_evaluation)
assemble_external (decl);
if (TREE_CODE (decl) == FUNCTION_DECL
&& DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
&& DECL_ARTIFICIAL (decl)
&& ! DECL_INITIAL (decl)
&& current_function_decl)
{
synthesize_method (decl);
return;
}
if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
&& DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
&& (!DECL_EXPLICIT_INSTANTIATION (decl)
|| (TREE_CODE (decl) == FUNCTION_DECL && DECL_INLINE (decl))))
instantiate_decl (decl, 1);
}
tree
handle_class_head (tag_kind, scope, id, attributes, defn_p, new_type_p)
enum tag_types tag_kind;
tree scope, id, attributes;
int defn_p;
int *new_type_p;
{
tree decl = NULL_TREE;
tree type;
tree current = current_scope ();
bool xrefd_p = false;
if (current == NULL_TREE)
current = current_namespace;
*new_type_p = 0;
if (scope)
{
if (TREE_CODE (id) == TYPE_DECL)
decl = TYPE_MAIN_DECL (TREE_TYPE (id));
else if (DECL_CLASS_TEMPLATE_P (id))
decl = DECL_TEMPLATE_RESULT (id);
else
{
if (TYPE_P (scope))
{
decl = make_typename_type (scope, id, tf_error);
if (decl != error_mark_node)
decl = TYPE_MAIN_DECL (decl);
else
decl = NULL_TREE;
}
else if (scope == current)
{
if (pedantic)
pedwarn ("extra qualification `%T::' on member `%D' ignored",
scope, id);
}
else
error ("`%T' does not have a class or union named `%D'",
scope, id);
}
}
if (!decl)
{
decl = xref_tag (tag_kind, id, attributes, !defn_p);
if (decl == error_mark_node)
return error_mark_node;
decl = TYPE_MAIN_DECL (decl);
xrefd_p = true;
}
type = TREE_TYPE (decl);
if (!TYPE_BINFO (type))
{
error ("`%T' is not a class or union type", decl);
return error_mark_node;
}
if (TREE_CODE (type) == RECORD_TYPE
&& CLASSTYPE_IS_TEMPLATE (type)
&& processing_template_decl <= template_class_depth (current)
&& ! is_base_of_enclosing_class (type, current_class_type))
{
error ("template argument is required for `%T'", type);
return error_mark_node;
}
if (defn_p)
{
tree context = CP_DECL_CONTEXT (decl);
if (IMPLICIT_TYPENAME_P (context))
context = TREE_TYPE (context);
*new_type_p = (current != context
&& TREE_CODE (context) != TEMPLATE_TYPE_PARM
&& TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
if (*new_type_p)
push_scope (context);
if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
= (tag_kind == class_type);
if (!xrefd_p && PROCESSING_REAL_TEMPLATE_DECL_P ())
decl = push_template_decl (decl);
}
return decl;
}
tree
handle_class_head_apparent_template (decl, new_type_p)
tree decl;
int *new_type_p;
{
tree context;
tree current;
if (decl == error_mark_node)
return decl;
current = current_scope ();
if (current == NULL_TREE)
current = current_namespace;
*new_type_p = 0;
context = CP_DECL_CONTEXT (decl);
if (IMPLICIT_TYPENAME_P (context))
context = TREE_TYPE (context);
*new_type_p = (current != context
&& TREE_CODE (context) != TEMPLATE_TYPE_PARM
&& TREE_CODE (context) != BOUND_TEMPLATE_TEMPLATE_PARM);
if (*new_type_p)
push_scope (context);
if (TREE_CODE (TREE_TYPE (decl)) == RECORD_TYPE)
CLASSTYPE_DECLARED_CLASS (TREE_TYPE (decl))
= (current_aggr == class_type_node);
return decl;
}
#include "gt-cp-decl2.h"