#include <varargs.h>
#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#ifdef NEED_DECLARATION_FREE
+extern void free PROTO((void *));
+#endif
+
+extern void compiler_error ();
+
+static tree get_identifier_list PROTO((tree));
+static tree bot_manip PROTO((tree));
+static tree perm_manip PROTO((tree));
+static tree build_cplus_array_type_1 PROTO((tree, tree));
+static void list_hash_add PROTO((int, tree));
+static int list_hash PROTO((tree, tree, tree));
+static tree list_hash_lookup PROTO((int, int, int, int, tree, tree,
+ tree));
+
#define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Return nonzero if REF is an lvalue valid for this language.
case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return real_lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
case MIN_EXPR:
return (real_lvalue_p (TREE_OPERAND (ref, 0))
&& real_lvalue_p (TREE_OPERAND (ref, 1)));
+
+ default:
+ break;
}
return 0;
}
+/* This differs from real_lvalue_p in that class rvalues are considered
+ lvalues. */
int
lvalue_p (ref)
tree ref;
what they refer to are valid lvals. */
case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR:
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
case COMPONENT_REF:
case SAVE_EXPR:
+ case UNSAVE_EXPR:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
return lvalue_p (TREE_OPERAND (ref, 0));
case STRING_CST:
case MIN_EXPR:
return (lvalue_p (TREE_OPERAND (ref, 0))
&& lvalue_p (TREE_OPERAND (ref, 1)));
+
+ default:
+ break;
}
return 0;
tree slot;
tree rval;
- if (TREE_CODE (init) == TARGET_EXPR || init == error_mark_node)
+ if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return init;
slot = build (VAR_DECL, type);
+ DECL_ARTIFICIAL (slot) = 1;
layout_decl (slot, 0);
- rval = build (NEW_EXPR, type,
+ rval = build (AGGR_INIT_EXPR, type,
TREE_OPERAND (init, 0), TREE_OPERAND (init, 1), slot);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
rval = build (TARGET_EXPR, type, slot, rval, NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (rval) = 1;
- TREE_ADDRESSABLE (rval) = 1;
+
+ return rval;
+}
+
+/* Encapsulate the expression INIT in a TARGET_EXPR. */
+
+tree
+get_target_expr (init)
+ tree init;
+{
+ tree slot;
+ tree rval;
+
+ slot = build (VAR_DECL, TREE_TYPE (init));
+ DECL_ARTIFICIAL (slot) = 1;
+ layout_decl (slot, 0);
+ rval = build (TARGET_EXPR, TREE_TYPE (init), slot, init,
+ NULL_TREE, NULL_TREE);
+ TREE_SIDE_EFFECTS (rval) = 1;
return rval;
}
return t;
}
-tree
+static tree
build_cplus_array_type_1 (elt_type, index_type)
tree elt_type;
tree index_type;
them too. */
DECL_ASSEMBLER_NAME (decl) = get_identifier (VTABLE_BASE);
DECL_VIRTUAL_P (decl) = 1;
+ DECL_ARTIFICIAL (decl) = 1;
DECL_FIELD_CONTEXT (decl) = rec;
DECL_CLASS_CONTEXT (decl) = rec;
DECL_FCONTEXT (decl) = basetype;
BINFO_VPTR_FIELD (base_binfo) = decl;
vbase_decls = decl;
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s: virtual %s'",
- TYPE_NAME_STRING (rec),
- TYPE_NAME_STRING (basetype));
- }
got_it:
/* The space this decl occupies has already been accounted for. */
continue;
}
+ /* Effective C++ rule 14. We only need to check TYPE_VIRTUAL_P
+ here because the case of virtual functions but non-virtual
+ dtor is handled in finish_struct_1. */
+ if (warn_ecpp && ! TYPE_VIRTUAL_P (basetype)
+ && TYPE_HAS_DESTRUCTOR (basetype))
+ cp_warning ("base class `%#T' has a non-virtual destructor", basetype);
+
if (const_size == 0)
offset = integer_zero_node;
else
const_size = CEIL (const_size, TYPE_ALIGN (basetype))
* TYPE_ALIGN (basetype);
offset = size_int ((const_size + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
-
-#if 0
- /* bpk: Disabled this check until someone is willing to
- claim it as theirs and explain exactly what circumstances
- warrant the warning. */
- if (warn_nonvdtor && TYPE_HAS_DESTRUCTOR (basetype)
- && DECL_VINDEX (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1)) == NULL_TREE)
- {
- warning_with_decl (TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1),
- "destructor `%s' non-virtual");
- warning ("in inheritance relationship `%s:%s %s'",
- TYPE_NAME_STRING (rec),
- TREE_VIA_VIRTUAL (base_binfo) ? " virtual" : "",
- TYPE_NAME_STRING (basetype));
- }
-#endif
}
BINFO_OFFSET (base_binfo) = offset;
if (CLASSTYPE_VSIZE (basetype))
and the hash code is computed differently for each of these. */
#define TYPE_HASH_SIZE 59
-struct list_hash *list_hash_table[TYPE_HASH_SIZE];
+static struct list_hash *list_hash_table[TYPE_HASH_SIZE];
/* Compute a hash code for a list (chain of TREE_LIST nodes
with goodies in the TREE_PURPOSE, TREE_VALUE, and bits of the
TREE_COMMON slots), by adding the hash codes of the individual entries. */
-int
-list_hash (list)
- tree list;
+static int
+list_hash (purpose, value, chain)
+ tree purpose, value, chain;
{
register int hashcode = 0;
- if (TREE_CHAIN (list))
- hashcode += TYPE_HASH (TREE_CHAIN (list));
+ if (chain)
+ hashcode += TYPE_HASH (chain);
- if (TREE_VALUE (list))
- hashcode += TYPE_HASH (TREE_VALUE (list));
+ if (value)
+ hashcode += TYPE_HASH (value);
else
hashcode += 1007;
- if (TREE_PURPOSE (list))
- hashcode += TYPE_HASH (TREE_PURPOSE (list));
+ if (purpose)
+ hashcode += TYPE_HASH (purpose);
else
hashcode += 1009;
return hashcode;
/* Look in the type hash table for a type isomorphic to TYPE.
If one is found, return it. Otherwise return 0. */
-tree
-list_hash_lookup (hashcode, list)
- int hashcode;
- tree list;
+static tree
+list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain)
+ int hashcode, via_public, via_virtual, via_protected;
+ tree purpose, value, chain;
{
register struct list_hash *h;
+
for (h = list_hash_table[hashcode % TYPE_HASH_SIZE]; h; h = h->next)
if (h->hashcode == hashcode
- && TREE_VIA_VIRTUAL (h->list) == TREE_VIA_VIRTUAL (list)
- && TREE_VIA_PUBLIC (h->list) == TREE_VIA_PUBLIC (list)
- && TREE_VIA_PROTECTED (h->list) == TREE_VIA_PROTECTED (list)
- && TREE_PURPOSE (h->list) == TREE_PURPOSE (list)
- && TREE_VALUE (h->list) == TREE_VALUE (list)
- && TREE_CHAIN (h->list) == TREE_CHAIN (list))
- {
- my_friendly_assert (TREE_TYPE (h->list) == TREE_TYPE (list), 299);
- return h->list;
- }
+ && TREE_VIA_VIRTUAL (h->list) == via_virtual
+ && TREE_VIA_PUBLIC (h->list) == via_public
+ && TREE_VIA_PROTECTED (h->list) == via_protected
+ && TREE_PURPOSE (h->list) == purpose
+ && TREE_VALUE (h->list) == value
+ && TREE_CHAIN (h->list) == chain)
+ return h->list;
return 0;
}
/* Add an entry to the list-hash-table
for a list TYPE whose hash code is HASHCODE. */
-void
+static void
list_hash_add (hashcode, list)
int hashcode;
tree list;
static int debug_no_list_hash = 0;
-tree
-list_hash_canon (hashcode, list)
- int hashcode;
- tree list;
-{
- tree t1;
-
- if (debug_no_list_hash)
- return list;
-
- t1 = list_hash_lookup (hashcode, list);
- if (t1 != 0)
- {
- obstack_free (&class_obstack, list);
- return t1;
- }
-
- /* If this is a new list, record it for later reuse. */
- list_hash_add (hashcode, list);
-
- return list;
-}
-
tree
hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
int via_public, via_virtual, via_protected;
tree t;
int hashcode;
+ if (! debug_no_list_hash)
+ {
+ hashcode = list_hash (purpose, value, chain);
+ t = list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
+ purpose, value, chain);
+ if (t)
+ return t;
+ }
+
current_obstack = &class_obstack;
+
t = tree_cons (purpose, value, chain);
TREE_VIA_PUBLIC (t) = via_public;
TREE_VIA_PROTECTED (t) = via_protected;
TREE_VIA_VIRTUAL (t) = via_virtual;
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
+
+ /* If this is a new list, record it for later reuse. */
+ if (! debug_no_list_hash)
+ list_hash_add (hashcode, t);
+
current_obstack = ambient_obstack;
return t;
}
hash_tree_chain (value, chain)
tree value, chain;
{
- struct obstack *ambient_obstack = current_obstack;
- tree t;
- int hashcode;
-
- current_obstack = &class_obstack;
- t = tree_cons (NULL_TREE, value, chain);
- hashcode = list_hash (t);
- t = list_hash_canon (hashcode, t);
- current_obstack = ambient_obstack;
- return t;
+ return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
is_overloaded_fn (x)
tree x;
{
- if (TREE_CODE (x) == FUNCTION_DECL)
+ if (TREE_CODE (x) == FUNCTION_DECL
+ || TREE_CODE (x) == TEMPLATE_ID_EXPR
+ || DECL_FUNCTION_TEMPLATE_P (x))
return 1;
if (TREE_CODE (x) == TREE_LIST
&& (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
+ || DECL_FUNCTION_TEMPLATE_P (TREE_VALUE (x))))
return 1;
return 0;
really_overloaded_fn (x)
tree x;
{
- if (TREE_CODE (x) == TREE_LIST
- && (TREE_CODE (TREE_VALUE (x)) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (x)) == TEMPLATE_DECL))
- return 1;
-
- return 0;
+ return TREE_CODE (x) != FUNCTION_DECL
+ && is_overloaded_fn (x);
}
tree
get_first_fn (from)
tree from;
{
- if (TREE_CODE (from) == FUNCTION_DECL)
+ if (TREE_CODE (from) == FUNCTION_DECL
+ || TREE_CODE (from) == TEMPLATE_ID_EXPR
+ || DECL_FUNCTION_TEMPLATE_P (from))
return from;
my_friendly_assert (TREE_CODE (from) == TREE_LIST, 9);
return TREE_VALUE (from);
}
-tree
-fnaddr_from_vtable_entry (entry)
- tree entry;
-{
- if (flag_vtable_thunks)
- {
- tree func = entry;
- if (TREE_CODE (func) == ADDR_EXPR)
- func = TREE_OPERAND (func, 0);
- if (TREE_CODE (func) == THUNK_DECL)
- return DECL_INITIAL (func);
- else
- return entry;
- }
- else
- return TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (entry))));
-}
-
-tree
-function_arg_chain (t)
- tree t;
-{
- return TREE_CHAIN (TYPE_ARG_TYPES (TREE_TYPE (t)));
-}
-
-int
-promotes_to_aggr_type (t, code)
- tree t;
- enum tree_code code;
-{
- if (TREE_CODE (t) == code)
- t = TREE_TYPE (t);
- return IS_AGGR_TYPE (t);
-}
-
int
is_aggr_type_2 (t1, t2)
tree t1, t2;
return 0;
return IS_AGGR_TYPE (t1) && IS_AGGR_TYPE (t2);
}
-
-/* Give message using types TYPE1 and TYPE2 as arguments.
- PFN is the function which will print the message;
- S is the format string for PFN to use. */
-
-void
-message_2_types (pfn, s, type1, type2)
- void (*pfn) ();
- char *s;
- tree type1, type2;
-{
- tree name1 = TYPE_NAME (type1);
- tree name2 = TYPE_NAME (type2);
- if (TREE_CODE (name1) == TYPE_DECL)
- name1 = DECL_NAME (name1);
- if (TREE_CODE (name2) == TYPE_DECL)
- name2 = DECL_NAME (name2);
- (*pfn) (s, IDENTIFIER_POINTER (name1), IDENTIFIER_POINTER (name2));
-}
\f
#define PRINT_RING_SIZE 4
char *
-lang_printable_name (decl)
+lang_printable_name (decl, v)
tree decl;
+ int v;
{
static tree decl_ring[PRINT_RING_SIZE];
static char *print_ring[PRINT_RING_SIZE];
int i;
/* Only cache functions. */
- if (TREE_CODE (decl) != FUNCTION_DECL
+ if (v < 2
+ || TREE_CODE (decl) != FUNCTION_DECL
|| DECL_LANG_SPECIFIC (decl) == 0)
- return decl_as_string (decl, 1);
+ return lang_decl_name (decl, v);
/* See if this print name is lying around. */
for (i = 0; i < PRINT_RING_SIZE; i++)
if (print_ring[ring_counter])
free (print_ring[ring_counter]);
- {
- int print_ret_type_p
- = (!DECL_CONSTRUCTOR_P (decl)
- && !DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (decl)));
-
- char *name = (char *)decl_as_string (decl, print_ret_type_p);
- print_ring[ring_counter] = (char *)malloc (strlen (name) + 1);
- strcpy (print_ring[ring_counter], name);
- decl_ring[ring_counter] = decl;
- }
+ print_ring[ring_counter] = xstrdup (lang_decl_name (decl, v));
+ decl_ring[ring_counter] = decl;
return print_ring[ring_counter];
}
\f
return v;
}
+/* Given a TEMPLATE_TEMPLATE_PARM node T, create a new one together with its
+ lang_specific field and its corresponding TEMPLATE_DECL node */
+
+tree
+copy_template_template_parm (t)
+ tree t;
+{
+ tree template = TYPE_NAME (t);
+ tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ template = copy_node (template);
+ copy_lang_decl (template);
+ TREE_TYPE (template) = t2;
+ TYPE_NAME (t2) = template;
+ TYPE_STUB_DECL (t2) = template;
+
+ /* No need to copy these */
+ TYPE_FIELDS (t2) = TYPE_FIELDS (t);
+ CLASSTYPE_TEMPLATE_INFO (t2) = CLASSTYPE_TEMPLATE_INFO (t);
+ return t2;
+}
+
/* Subroutine of copy_to_permanent
Assuming T is a node build bottom-up, make it all exist on
tree
mapcar (t, func)
tree t;
- tree (*func)();
+ tree (*func) PROTO((tree));
{
tree tmp;
case VAR_DECL:
case FUNCTION_DECL:
case CONST_DECL:
- break;
+ /* Rather than aborting, return error_mark_node. This allows us
+ to report a sensible error message on code like this:
+
+ void g() { int i; f<i>(7); } */
+ return error_mark_node;
case PARM_DECL:
{
case COND_EXPR:
case TARGET_EXPR:
- case NEW_EXPR:
+ case AGGR_INIT_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
case PREINCREMENT_EXPR:
case POSTDECREMENT_EXPR:
case POSTINCREMENT_EXPR:
- case CALL_EXPR:
case ARRAY_REF:
case SCOPE_REF:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
return t;
- break;
- case RTL_EXPR:
+ case CALL_EXPR:
t = copy_node (t);
- if (RTL_EXPR_SEQUENCE (t))
- RTL_EXPR_SEQUENCE (t) = copy_rtx (RTL_EXPR_SEQUENCE (t));
- if (RTL_EXPR_RTL (t))
- RTL_EXPR_RTL (t) = copy_rtx (RTL_EXPR_RTL (t));
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ TREE_OPERAND (t, 1) = mapcar (TREE_OPERAND (t, 1), func);
+
+ /* tree.def says that operand two is RTL, but
+ build_call_declarator puts trees in there. */
+ if (TREE_OPERAND (t, 2)
+ && TREE_CODE (TREE_OPERAND (t, 2)) == TREE_LIST)
+ TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
+ else
+ TREE_OPERAND (t, 2) = NULL_TREE;
return t;
- break;
case CONVERT_EXPR:
case ADDR_EXPR:
case TRUTH_NOT_EXPR:
case NOP_EXPR:
case COMPONENT_REF:
+ case CLEANUP_POINT_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ case COMPLEX_CST:
+ t = copy_node (t);
+ TREE_REALPART (t) = mapcar (TREE_REALPART (t), func);
+ TREE_IMAGPART (t) = mapcar (TREE_REALPART (t), func);
+ return t;
+
case CONSTRUCTOR:
t = copy_node (t);
CONSTRUCTOR_ELTS (t) = mapcar (CONSTRUCTOR_ELTS (t), func);
return t;
+ case TEMPLATE_TEMPLATE_PARM:
+ return copy_template_template_parm (t);
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
void
print_lang_statistics ()
{
- extern struct obstack maybepermanent_obstack, decl_obstack;
+ extern struct obstack decl_obstack;
print_obstack_statistics ("class_obstack", &class_obstack);
print_obstack_statistics ("decl_obstack", &decl_obstack);
- print_obstack_statistics ("permanent_obstack", &permanent_obstack);
- print_obstack_statistics ("maybepermanent_obstack", &maybepermanent_obstack);
print_search_statistics ();
print_class_statistics ();
#ifdef GATHER_STATISTICS
return t;
else if (TREE_CODE (t) == TARGET_EXPR)
{
- if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR)
+ if (TREE_CODE (TREE_OPERAND (t, 1)) == AGGR_INIT_EXPR)
{
mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
return build_cplus_new
/* Obstack used for allocating nodes in template function and variable
definitions. */
-extern struct obstack *expression_obstack;
-
/* Similar to `build_nt', except we build
on the permanent_obstack, regardless. */
get_type_decl (t)
tree t;
{
- if (TREE_CODE (t) == IDENTIFIER_NODE)
- return identifier_typedecl_value (t);
if (TREE_CODE (t) == TYPE_DECL)
return t;
if (TREE_CODE_CLASS (TREE_CODE (t)) == 't')
return 0;
case TEMPLATE_CONST_PARM:
- return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2);
+ return TEMPLATE_CONST_IDX (t1) == TEMPLATE_CONST_IDX (t2)
+ && TEMPLATE_CONST_LEVEL (t1) == TEMPLATE_CONST_LEVEL (t2);
case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
if (TREE_CODE (TREE_OPERAND (t1, 0)) != TREE_CODE (TREE_OPERAND (t2, 0)))
return 0;
if (TREE_CODE_CLASS (TREE_CODE (TREE_OPERAND (t1, 0))) == 't')
return comptypes (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0), 1);
break;
+
+ default:
+ break;
}
switch (TREE_CODE_CLASS (code1))
int len;
{
register tree node;
- push_obstacks_nochange ();
- resume_temporary_allocation ();
+ register struct obstack *ambient_obstack = current_obstack;
+ current_obstack = expression_obstack;
node = make_tree_vec (len);
- pop_obstacks ();
+ current_obstack = ambient_obstack;
return node;
}
+void
+push_expression_obstack ()
+{
+ push_obstacks_nochange ();
+ current_obstack = expression_obstack;
+}
+
/* The type of ARG when used as an lvalue. */
tree
return type;
}
+
+/* Does FUNCTION use a variable-length argument list? */
+
+int
+varargs_function_p (function)
+ tree function;
+{
+ tree parm = TYPE_ARG_TYPES (TREE_TYPE (function));
+ for (; parm; parm = TREE_CHAIN (parm))
+ if (TREE_VALUE (parm) == void_type_node)
+ return 0;
+ return 1;
+}