summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/cp/tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/gcc/cp/tree.c')
-rw-r--r--contrib/gcc/cp/tree.c1067
1 files changed, 727 insertions, 340 deletions
diff --git a/contrib/gcc/cp/tree.c b/contrib/gcc/cp/tree.c
index 7c7768f..866aa27 100644
--- a/contrib/gcc/cp/tree.c
+++ b/contrib/gcc/cp/tree.c
@@ -1,5 +1,5 @@
/* Language-dependent node constructors for parse phase of GNU compiler.
- Copyright (C) 1987, 88, 92, 93, 94, 95, 1996 Free Software Foundation, Inc.
+ Copyright (C) 1987, 88, 92-98, 1999 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GNU CC.
@@ -28,40 +28,30 @@ Boston, MA 02111-1307, USA. */
#include "rtl.h"
#include "toplev.h"
-#ifdef __STDC__
-#include <stdarg.h>
-#else
-#include <varargs.h>
-#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));
+static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree));
-static void unshare_base_binfos PROTO((tree));
static int avoid_overlap PROTO((tree, tree));
+static int lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree));
+static tree no_linkage_helper PROTO((tree));
+static tree build_srcloc PROTO((char *, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y))
-/* Return nonzero if REF is an lvalue valid for this language.
- Lvalues can be assigned, unless they have TREE_READONLY.
- Lvalues can have their address taken, unless they have DECL_REGISTER. */
+/* Returns non-zero if REF is an lvalue. If
+ TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type
+ are considered lvalues. */
-int
-real_lvalue_p (ref)
+static int
+lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref;
+ int treat_class_rvalues_as_lvalues;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1;
@@ -79,7 +69,11 @@ real_lvalue_p (ref)
case UNSAVE_EXPR:
case TRY_CATCH_EXPR:
case WITH_CLEANUP_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 0));
+ case REALPART_EXPR:
+ case IMAGPART_EXPR:
+ case NOP_EXPR:
+ return lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues);
case STRING_CST:
return 1;
@@ -93,9 +87,7 @@ real_lvalue_p (ref)
case ARRAY_REF:
case PARM_DECL:
case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
+ if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1;
break;
@@ -105,24 +97,43 @@ real_lvalue_p (ref)
case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1;
- return real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
break;
case COND_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 1))
- && real_lvalue_p (TREE_OPERAND (ref, 2)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 2),
+ treat_class_rvalues_as_lvalues));
case MODIFY_EXPR:
return 1;
case COMPOUND_EXPR:
- return real_lvalue_p (TREE_OPERAND (ref, 1));
+ return lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
- return (real_lvalue_p (TREE_OPERAND (ref, 0))
- && real_lvalue_p (TREE_OPERAND (ref, 1)));
+ return (lvalue_p_1 (TREE_OPERAND (ref, 0),
+ treat_class_rvalues_as_lvalues)
+ && lvalue_p_1 (TREE_OPERAND (ref, 1),
+ treat_class_rvalues_as_lvalues));
+
+ case TARGET_EXPR:
+ return treat_class_rvalues_as_lvalues;
+
+ case CALL_EXPR:
+ return (treat_class_rvalues_as_lvalues
+ && IS_AGGR_TYPE (TREE_TYPE (ref)));
+
+ case FUNCTION_DECL:
+ /* All functions (except non-static-member functions) are
+ lvalues. */
+ return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref);
default:
break;
@@ -131,92 +142,26 @@ real_lvalue_p (ref)
return 0;
}
+/* Return nonzero if REF is an lvalue valid for this language.
+ Lvalues can be assigned, unless they have TREE_READONLY, or unless
+ they are FUNCTION_DECLs. Lvalues can have their address taken,
+ unless they have DECL_REGISTER. */
+
+int
+real_lvalue_p (ref)
+ tree ref;
+{
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
+}
+
/* This differs from real_lvalue_p in that class rvalues are considered
lvalues. */
+
int
lvalue_p (ref)
tree ref;
{
- if (! language_lvalue_valid (ref))
- return 0;
-
- if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
- return 1;
-
- if (ref == current_class_ptr && flag_this_is_variable <= 0)
- return 0;
-
- switch (TREE_CODE (ref))
- {
- /* preincrements and predecrements are valid lvals, provided
- 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:
- return 1;
-
- case VAR_DECL:
- if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
- && DECL_LANG_SPECIFIC (ref)
- && DECL_IN_AGGR_P (ref))
- return 0;
- case INDIRECT_REF:
- case ARRAY_REF:
- case PARM_DECL:
- case RESULT_DECL:
- case ERROR_MARK:
- if (TREE_CODE (TREE_TYPE (ref)) != FUNCTION_TYPE
- && TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
- return 1;
- break;
-
- case TARGET_EXPR:
- return 1;
-
- case CALL_EXPR:
- if (IS_AGGR_TYPE (TREE_TYPE (ref)))
- return 1;
- break;
-
- /* A currently unresolved scope ref. */
- case SCOPE_REF:
- my_friendly_abort (103);
- case OFFSET_REF:
- if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
- return 1;
- return lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1));
- break;
-
- case COND_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 1))
- && lvalue_p (TREE_OPERAND (ref, 2)));
-
- case MODIFY_EXPR:
- return 1;
-
- case COMPOUND_EXPR:
- return lvalue_p (TREE_OPERAND (ref, 1));
-
- case MAX_EXPR:
- case MIN_EXPR:
- return (lvalue_p (TREE_OPERAND (ref, 0))
- && lvalue_p (TREE_OPERAND (ref, 1)));
-
- default:
- break;
- }
-
- return 0;
+ return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1);
}
/* Return nonzero if REF is an lvalue valid for this language;
@@ -225,7 +170,7 @@ lvalue_p (ref)
int
lvalue_or_else (ref, string)
tree ref;
- char *string;
+ const char *string;
{
int win = lvalue_p (ref);
if (! win)
@@ -249,7 +194,7 @@ build_cplus_new (type, init)
tree rval;
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
- return init;
+ return convert (type, init);
slot = build (VAR_DECL, type);
DECL_ARTIFICIAL (slot) = 1;
@@ -431,9 +376,7 @@ build_cplus_method_type (basetype, rettype, argtypes)
TYPE_METHOD_BASETYPE (t) = TYPE_MAIN_VARIANT (basetype);
TREE_TYPE (t) = rettype;
if (IS_SIGNATURE (basetype))
- ptype = build_signature_pointer_type (TYPE_MAIN_VARIANT (basetype),
- TYPE_READONLY (basetype),
- TYPE_VOLATILE (basetype));
+ ptype = build_signature_pointer_type (basetype);
else
ptype = build_pointer_type (basetype);
@@ -473,7 +416,8 @@ build_cplus_array_type_1 (elt_type, index_type)
saveable_obstack = &permanent_obstack;
}
- if (processing_template_decl
+ if (processing_template_decl
+ || uses_template_parms (elt_type)
|| uses_template_parms (index_type))
{
t = make_node (ARRAY_TYPE);
@@ -498,14 +442,14 @@ build_cplus_array_type (elt_type, index_type)
tree index_type;
{
tree t;
- int constp = TYPE_READONLY (elt_type);
- int volatilep = TYPE_VOLATILE (elt_type);
+ int type_quals = CP_TYPE_QUALS (elt_type);
+
elt_type = TYPE_MAIN_VARIANT (elt_type);
t = build_cplus_array_type_1 (elt_type, index_type);
- if (constp || volatilep)
- t = cp_build_type_variant (t, constp, volatilep);
+ if (type_quals != TYPE_UNQUALIFIED)
+ t = cp_build_qualified_type (t, type_quals);
return t;
}
@@ -514,21 +458,32 @@ build_cplus_array_type (elt_type, index_type)
down to the element type of an array. */
tree
-cp_build_type_variant (type, constp, volatilep)
+cp_build_qualified_type (type, type_quals)
tree type;
- int constp, volatilep;
+ int type_quals;
{
if (type == error_mark_node)
return type;
+ /* A restrict-qualified pointer type must be a pointer (or reference)
+ to object or incomplete type. */
+ if ((type_quals & TYPE_QUAL_RESTRICT)
+ && (!POINTER_TYPE_P (type)
+ || TYPE_PTRMEM_P (type)
+ || TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE))
+ {
+ cp_error ("`%T' cannot be `restrict'-qualified", type);
+ type_quals &= ~TYPE_QUAL_RESTRICT;
+ }
+
if (TREE_CODE (type) == ARRAY_TYPE)
{
tree real_main_variant = TYPE_MAIN_VARIANT (type);
push_obstacks (TYPE_OBSTACK (real_main_variant),
TYPE_OBSTACK (real_main_variant));
- type = build_cplus_array_type_1 (cp_build_type_variant
- (TREE_TYPE (type), constp, volatilep),
+ type = build_cplus_array_type_1 (cp_build_qualified_type
+ (TREE_TYPE (type), type_quals),
TYPE_DOMAIN (type));
/* TYPE must be on same obstack as REAL_MAIN_VARIANT. If not,
@@ -545,7 +500,7 @@ cp_build_type_variant (type, constp, volatilep)
pop_obstacks ();
return type;
}
- return build_type_variant (type, constp, volatilep);
+ return build_qualified_type (type, type_quals);
}
/* Returns the canonical version of TYPE. In other words, if TYPE is
@@ -557,18 +512,7 @@ tree
canonical_type_variant (t)
tree t;
{
- int constp, volatilep;
- if (TREE_CODE (t) == ARRAY_TYPE)
- {
- constp = TYPE_READONLY (TREE_TYPE (t));
- volatilep = TYPE_VOLATILE (TREE_TYPE (t));
- }
- else
- {
- constp = TYPE_READONLY (t);
- volatilep = TYPE_VOLATILE (t);
- }
- return cp_build_type_variant (TYPE_MAIN_VARIANT (t), constp, volatilep);
+ return cp_build_qualified_type (TYPE_MAIN_VARIANT (t), CP_TYPE_QUALS (t));
}
/* Add OFFSET to all base types of T.
@@ -618,7 +562,7 @@ propagate_binfo_offsets (binfo, offset)
BINFO_OFFSET (base_binfo) = offset;
#endif
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, offset);
/* Go to our next class that counts for offset propagation. */
i = j;
@@ -628,40 +572,35 @@ propagate_binfo_offsets (binfo, offset)
}
}
-/* Makes new binfos for the indirect bases under BASE_BINFO, and updates
+/* Makes new binfos for the indirect bases under BINFO, and updates
BINFO_OFFSET for them and their bases. */
-static void
-unshare_base_binfos (base_binfo)
- tree base_binfo;
+void
+unshare_base_binfos (binfo)
+ tree binfo;
{
- if (BINFO_BASETYPES (base_binfo))
- {
- tree base_binfos = BINFO_BASETYPES (base_binfo);
- tree chain = NULL_TREE;
- int j;
+ tree binfos = BINFO_BASETYPES (binfo);
+ tree new_binfo;
+ int j;
- /* Now unshare the structure beneath BASE_BINFO. */
- for (j = TREE_VEC_LENGTH (base_binfos)-1;
- j >= 0; j--)
- {
- tree base_base_binfo = TREE_VEC_ELT (base_binfos, j);
- if (! TREE_VIA_VIRTUAL (base_base_binfo))
- TREE_VEC_ELT (base_binfos, j)
- = make_binfo (BINFO_OFFSET (base_base_binfo),
- base_base_binfo,
- BINFO_VTABLE (base_base_binfo),
- BINFO_VIRTUALS (base_base_binfo),
- chain);
- chain = TREE_VEC_ELT (base_binfos, j);
- TREE_VIA_PUBLIC (chain) = TREE_VIA_PUBLIC (base_base_binfo);
- TREE_VIA_PROTECTED (chain) = TREE_VIA_PROTECTED (base_base_binfo);
- BINFO_INHERITANCE_CHAIN (chain) = base_binfo;
- }
+ if (binfos == NULL_TREE)
+ return;
- /* Completely unshare potentially shared data, and
- update what is ours. */
- propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
+ /* Now unshare the structure beneath BINFO. */
+ for (j = TREE_VEC_LENGTH (binfos)-1;
+ j >= 0; j--)
+ {
+ tree base_binfo = TREE_VEC_ELT (binfos, j);
+ new_binfo = TREE_VEC_ELT (binfos, j)
+ = make_binfo (BINFO_OFFSET (base_binfo),
+ base_binfo,
+ BINFO_VTABLE (base_binfo),
+ BINFO_VIRTUALS (base_binfo));
+ TREE_VIA_PUBLIC (new_binfo) = TREE_VIA_PUBLIC (base_binfo);
+ TREE_VIA_PROTECTED (new_binfo) = TREE_VIA_PROTECTED (base_binfo);
+ TREE_VIA_VIRTUAL (new_binfo) = TREE_VIA_VIRTUAL (base_binfo);
+ BINFO_INHERITANCE_CHAIN (new_binfo) = binfo;
+ unshare_base_binfos (new_binfo);
}
}
@@ -681,9 +620,7 @@ layout_basetypes (rec, max)
tree binfos = TYPE_BINFO_BASETYPES (rec);
int i, n_baseclasses = binfos ? TREE_VEC_LENGTH (binfos) : 0;
- /* Get all the virtual base types that this type uses.
- The TREE_VALUE slot holds the virtual baseclass type. */
- tree vbase_types = get_vbase_types (rec);
+ tree vbase_types;
unsigned int record_align = MAX (BITS_PER_UNIT, TYPE_ALIGN (rec));
unsigned int desired_align;
@@ -698,7 +635,11 @@ layout_basetypes (rec, max)
record_align = MAX (record_align, STRUCTURE_SIZE_BOUNDARY);
#endif
- CLASSTYPE_VBASECLASSES (rec) = vbase_types;
+ /* Get all the virtual base types that this type uses. The
+ TREE_VALUE slot holds the virtual baseclass type. Note that
+ get_vbase_types makes copies of the virtual base BINFOs, so that
+ the vbase_types are unshared. */
+ vbase_types = CLASSTYPE_VBASECLASSES (rec);
my_friendly_assert (TREE_CODE (TYPE_SIZE (rec)) == INTEGER_CST, 19970302);
const_size = TREE_INT_CST_LOW (TYPE_SIZE (rec));
@@ -764,10 +705,15 @@ layout_basetypes (rec, max)
continue;
my_friendly_assert (TREE_TYPE (field) == basetype, 23897);
+
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("direct base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+
BINFO_OFFSET (base_binfo)
= size_int (CEIL (TREE_INT_CST_LOW (DECL_FIELD_BITPOS (field)),
BITS_PER_UNIT));
- unshare_base_binfos (base_binfo);
+ propagate_binfo_offsets (base_binfo, BINFO_OFFSET (base_binfo));
TYPE_FIELDS (rec) = TREE_CHAIN (field);
}
@@ -776,6 +722,15 @@ layout_basetypes (rec, max)
{
BINFO_INHERITANCE_CHAIN (vbase_types) = TYPE_BINFO (rec);
unshare_base_binfos (vbase_types);
+ propagate_binfo_offsets (vbase_types, BINFO_OFFSET (vbase_types));
+
+ if (extra_warnings)
+ {
+ tree basetype = BINFO_TYPE (vbase_types);
+ if (get_base_distance (basetype, rec, 0, (tree*)0) == -2)
+ cp_warning ("virtual base `%T' inaccessible in `%T' due to ambiguity",
+ basetype, rec);
+ }
}
return max;
@@ -851,7 +806,7 @@ build_base_fields (rec)
base_align = MAX (base_align, DECL_ALIGN (decl));
DECL_SIZE (decl)
= size_int (MAX (TREE_INT_CST_LOW (DECL_SIZE (decl)),
- base_align));
+ (int) base_align));
}
else if (DECL_SIZE (decl) == integer_zero_node)
saw_empty = 1;
@@ -925,8 +880,7 @@ build_vbase_pointer_fields (rec)
if (TREE_VIA_VIRTUAL (base_binfo))
{
int j;
- char *name = (char *)alloca (TYPE_NAME_LENGTH (basetype)
- + sizeof (VBASE_NAME) + 1);
+ const char *name;
/* The offset for a virtual base class is only used in computing
virtual function tables and for initializing virtual base
@@ -946,7 +900,7 @@ build_vbase_pointer_fields (rec)
))
goto got_it;
}
- sprintf (name, VBASE_NAME_FORMAT, TYPE_NAME_STRING (basetype));
+ FORMAT_VBASE_NAME (name, basetype);
decl = build_lang_field_decl (FIELD_DECL, get_identifier (name),
build_pointer_type (basetype));
/* If you change any of the below, take a look at all the
@@ -1024,18 +978,14 @@ list_hash (purpose, value, chain)
If one is found, return it. Otherwise return 0. */
static tree
-list_hash_lookup (hashcode, via_public, via_protected, via_virtual,
- purpose, value, chain)
- int hashcode, via_public, via_virtual, via_protected;
+list_hash_lookup (hashcode, purpose, value, chain)
+ int hashcode;
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) == 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)
@@ -1060,24 +1010,16 @@ list_hash_add (hashcode, list)
list_hash_table[hashcode % TYPE_HASH_SIZE] = h;
}
-/* Given TYPE, and HASHCODE its hash code, return the canonical
- object for an identical list if one already exists.
- Otherwise, return TYPE, and record it as the canonical object
- if it is a permanent object.
-
- To use this function, first create a list of the sort you want.
- Then compute its hash code from the fields of the list that
- make it different from other similar lists.
- Then call this function and use the value.
- This function frees the list you pass in if it is a duplicate. */
+/* Given list components PURPOSE, VALUE, AND CHAIN, return the canonical
+ object for an identical list if one already exists. Otherwise, build a
+ new one, and record it as the canonical object. */
/* Set to 1 to debug without canonicalization. Never set by program. */
static int debug_no_list_hash = 0;
tree
-hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
- int via_public, via_virtual, via_protected;
+hash_tree_cons (purpose, value, chain)
tree purpose, value, chain;
{
struct obstack *ambient_obstack = current_obstack;
@@ -1087,8 +1029,7 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
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);
+ t = list_hash_lookup (hashcode, purpose, value, chain);
if (t)
return t;
}
@@ -1096,9 +1037,6 @@ hash_tree_cons (via_public, via_virtual, via_protected, purpose, value, chain)
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;
/* If this is a new list, record it for later reuse. */
if (! debug_no_list_hash)
@@ -1114,7 +1052,7 @@ tree
hash_tree_chain (value, chain)
tree value, chain;
{
- return hash_tree_cons (0, 0, 0, NULL_TREE, value, chain);
+ return hash_tree_cons (NULL_TREE, value, chain);
}
/* Similar, but used for concatenating two lists. */
@@ -1132,60 +1070,6 @@ hash_chainon (list1, list2)
return hash_tree_chain (TREE_VALUE (list1),
hash_chainon (TREE_CHAIN (list1), list2));
}
-
-static tree
-get_identifier_list (value)
- tree value;
-{
- tree list = IDENTIFIER_AS_LIST (value);
- if (list != NULL_TREE
- && (TREE_CODE (list) != TREE_LIST
- || TREE_VALUE (list) != value))
- list = NULL_TREE;
- else if (IDENTIFIER_HAS_TYPE_VALUE (value)
- && TREE_CODE (IDENTIFIER_TYPE_VALUE (value)) == RECORD_TYPE
- && IDENTIFIER_TYPE_VALUE (value)
- == TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (value)))
- {
- tree type = IDENTIFIER_TYPE_VALUE (value);
-
- if (TYPE_PTRMEMFUNC_P (type))
- list = NULL_TREE;
- else if (type == current_class_type)
- /* Don't mess up the constructor name. */
- list = tree_cons (NULL_TREE, value, NULL_TREE);
- else
- {
- if (! CLASSTYPE_ID_AS_LIST (type))
- CLASSTYPE_ID_AS_LIST (type)
- = perm_tree_cons (NULL_TREE, TYPE_IDENTIFIER (type), NULL_TREE);
- list = CLASSTYPE_ID_AS_LIST (type);
- }
- }
- return list;
-}
-
-tree
-get_decl_list (value)
- tree value;
-{
- tree list = NULL_TREE;
-
- if (TREE_CODE (value) == IDENTIFIER_NODE)
- list = get_identifier_list (value);
- else if (TREE_CODE (value) == RECORD_TYPE
- && TYPE_LANG_SPECIFIC (value)
- && value == TYPE_MAIN_VARIANT (value))
- list = CLASSTYPE_AS_LIST (value);
-
- if (list != NULL_TREE)
- {
- my_friendly_assert (TREE_CHAIN (list) == NULL_TREE, 301);
- return list;
- }
-
- return build_decl_list (NULL_TREE, value);
-}
/* Build an association between TYPE and some parameters:
@@ -1200,15 +1084,12 @@ get_decl_list (value)
VTABLE is the virtual function table with which to initialize
sub-objects of type TYPE.
- VIRTUALS are the virtual functions sitting in VTABLE.
-
- CHAIN are more associations we must retain. */
+ VIRTUALS are the virtual functions sitting in VTABLE. */
tree
-make_binfo (offset, binfo, vtable, virtuals, chain)
+make_binfo (offset, binfo, vtable, virtuals)
tree offset, binfo;
tree vtable, virtuals;
- tree chain;
{
tree new_binfo = make_tree_vec (7);
tree type;
@@ -1218,13 +1099,9 @@ make_binfo (offset, binfo, vtable, virtuals, chain)
else
{
type = binfo;
- binfo = TYPE_BINFO (binfo);
+ binfo = CLASS_TYPE_P (type) ? TYPE_BINFO (binfo) : NULL_TREE;
}
- TREE_CHAIN (new_binfo) = chain;
- if (chain)
- TREE_USED (new_binfo) = TREE_USED (chain);
-
TREE_TYPE (new_binfo) = TYPE_MAIN_VARIANT (type);
BINFO_OFFSET (new_binfo) = offset;
BINFO_VTABLE (new_binfo) = vtable;
@@ -1253,17 +1130,24 @@ binfo_value (elem, type)
return get_binfo (elem, type, 0);
}
+/* Return a reversed copy of the BINFO-chain given by PATH. (If the
+ BINFO_INHERITANCE_CHAIN points from base classes to derived
+ classes, it will instead point from derived classes to base
+ classes.) Returns the first node in the reversed chain. */
+
tree
reverse_path (path)
tree path;
{
- register tree prev = 0, tmp, next;
- for (tmp = path; tmp; tmp = next)
+ register tree prev = NULL_TREE, cur;
+ push_expression_obstack ();
+ for (cur = path; cur; cur = BINFO_INHERITANCE_CHAIN (cur))
{
- next = BINFO_INHERITANCE_CHAIN (tmp);
- BINFO_INHERITANCE_CHAIN (tmp) = prev;
- prev = tmp;
+ tree r = copy_node (cur);
+ BINFO_INHERITANCE_CHAIN (r) = prev;
+ prev = r;
}
+ pop_obstacks ();
return prev;
}
@@ -1286,7 +1170,7 @@ debug_binfo (elem)
fprintf (stderr, "virtuals:\n");
virtuals = BINFO_VIRTUALS (elem);
- n = skip_rtti_stuff (&virtuals);
+ n = skip_rtti_stuff (&virtuals, BINFO_TYPE (elem));
while (virtuals)
{
@@ -1340,15 +1224,11 @@ int
is_overloaded_fn (x)
tree x;
{
- /* XXX A baselink is also considered an overloaded function.
- As is a placeholder from push_class_decls. */
- if (TREE_CODE (x) == TREE_LIST)
- {
- my_friendly_assert (TREE_CODE (TREE_PURPOSE (x)) == TREE_VEC
- || TREE_CODE (TREE_PURPOSE (x)) == IDENTIFIER_NODE,
- 388);
- x = TREE_VALUE (x);
- }
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
+ x = TREE_VALUE (x);
return (TREE_CODE (x) == FUNCTION_DECL
|| TREE_CODE (x) == TEMPLATE_ID_EXPR
|| DECL_FUNCTION_TEMPLATE_P (x)
@@ -1359,9 +1239,10 @@ int
really_overloaded_fn (x)
tree x;
{
- /* A baselink is also considered an overloaded function.
- This might also be an ambiguous class member. */
- if (TREE_CODE (x) == TREE_LIST)
+ /* A baselink is also considered an overloaded function. */
+ if (TREE_CODE (x) == OFFSET_REF)
+ x = TREE_OPERAND (x, 1);
+ if (BASELINK_P (x))
x = TREE_VALUE (x);
return (TREE_CODE (x) == OVERLOAD
&& (TREE_CHAIN (x) != NULL_TREE
@@ -1374,11 +1255,22 @@ get_first_fn (from)
{
my_friendly_assert (is_overloaded_fn (from), 9);
/* A baselink is also considered an overloaded function. */
- if (TREE_CODE (from) == TREE_LIST)
+ if (BASELINK_P (from))
from = TREE_VALUE (from);
return OVL_CURRENT (from);
}
+/* Returns nonzero if T is a ->* or .* expression that refers to a
+ member function. */
+
+int
+bound_pmf_p (t)
+ tree t;
+{
+ return (TREE_CODE (t) == OFFSET_REF
+ && TYPE_PTRMEMFUNC_P (TREE_TYPE (TREE_OPERAND (t, 1))));
+}
+
/* Return a new OVL node, concatenating it with the old one. */
tree
@@ -1417,9 +1309,9 @@ build_overload (decl, chain)
tree decl;
tree chain;
{
- if (!chain)
+ if (! chain && TREE_CODE (decl) != TEMPLATE_DECL)
return decl;
- if (TREE_CODE (chain) != OVERLOAD)
+ if (chain && TREE_CODE (chain) != OVERLOAD)
chain = ovl_cons (chain, NULL_TREE);
return ovl_cons (decl, chain);
}
@@ -1518,21 +1410,26 @@ build_exception_variant (type, raises)
tree raises;
{
tree v = TYPE_MAIN_VARIANT (type);
- int constp = TYPE_READONLY (type);
- int volatilep = TYPE_VOLATILE (type);
+ int type_quals = TYPE_QUALS (type);
for (; v; v = TYPE_NEXT_VARIANT (v))
{
- if (TYPE_READONLY (v) != constp
- || TYPE_VOLATILE (v) != volatilep)
+ tree t;
+ tree u;
+
+ if (TYPE_QUALS (v) != type_quals)
continue;
- /* @@ This should do set equality, not exact match. */
- if (simple_cst_list_equal (TYPE_RAISES_EXCEPTIONS (v), raises))
- /* List of exceptions raised matches previously found list.
+ for (t = TYPE_RAISES_EXCEPTIONS (v), u = raises;
+ t != NULL_TREE && u != NULL_TREE;
+ t = TREE_CHAIN (t), u = TREE_CHAIN (u))
+ if (((TREE_VALUE (t) != NULL_TREE)
+ != (TREE_VALUE (u) != NULL_TREE))
+ || !same_type_p (TREE_VALUE (t), TREE_VALUE (u)))
+ break;
- @@ Nice to free up storage used in consing up the
- @@ list of exceptions raised. */
+ if (!t && !u)
+ /* There's a memory leak here; RAISES is not freed. */
return v;
}
@@ -1540,12 +1437,7 @@ build_exception_variant (type, raises)
v = build_type_copy (type);
if (raises && ! TREE_PERMANENT (raises))
- {
- push_obstacks_nochange ();
- end_temporary_allocation ();
- raises = copy_list (raises);
- pop_obstacks ();
- }
+ raises = copy_to_permanent (raises);
TYPE_RAISES_EXCEPTIONS (v) = raises;
return v;
@@ -1559,29 +1451,39 @@ copy_template_template_parm (t)
tree t;
{
tree template = TYPE_NAME (t);
- tree t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
+ tree t2;
+
+ /* Make sure these end up on the permanent_obstack. */
+ push_obstacks_nochange ();
+ end_temporary_allocation ();
+
+ t2 = make_lang_type (TEMPLATE_TEMPLATE_PARM);
template = copy_node (template);
copy_lang_decl (template);
+
+ pop_obstacks ();
+
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);
+ TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t2)
+ = TEMPLATE_TEMPLATE_PARM_TEMPLATE_INFO (t);
return t2;
}
-/* Subroutine of copy_to_permanent
-
- Assuming T is a node build bottom-up, make it all exist on
- permanent obstack, if it is not permanent already. */
+/* Walk through the tree structure T, applying func. If func ever returns
+ non-null, return that value. */
tree
-mapcar (t, func)
+search_tree (t, func)
tree t;
tree (*func) PROTO((tree));
{
+#define TRY(ARG) if (tmp=search_tree (ARG, func), tmp != NULL_TREE) return tmp
+
tree tmp;
if (t == NULL_TREE)
@@ -1593,6 +1495,259 @@ mapcar (t, func)
switch (TREE_CODE (t))
{
case ERROR_MARK:
+ break;
+
+ case IDENTIFIER_NODE:
+ break;
+
+ case VAR_DECL:
+ case FUNCTION_DECL:
+ case CONST_DECL:
+ case TEMPLATE_DECL:
+ case NAMESPACE_DECL:
+ break;
+
+ case TYPE_DECL:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case PARM_DECL:
+ TRY (TREE_TYPE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case TREE_LIST:
+ TRY (TREE_PURPOSE (t));
+ TRY (TREE_VALUE (t));
+ TRY (TREE_CHAIN (t));
+ break;
+
+ case OVERLOAD:
+ TRY (OVL_FUNCTION (t));
+ TRY (OVL_CHAIN (t));
+ break;
+
+ case TREE_VEC:
+ {
+ int len = TREE_VEC_LENGTH (t);
+
+ t = copy_node (t);
+ while (len--)
+ TRY (TREE_VEC_ELT (t, len));
+ }
+ break;
+
+ case INTEGER_CST:
+ case REAL_CST:
+ case STRING_CST:
+ case DEFAULT_ARG:
+ break;
+
+ case PTRMEM_CST:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case COND_EXPR:
+ case TARGET_EXPR:
+ case AGGR_INIT_EXPR:
+ case NEW_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ TRY (TREE_OPERAND (t, 2));
+ break;
+
+ case MODIFY_EXPR:
+ case PLUS_EXPR:
+ case MINUS_EXPR:
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case TRUNC_MOD_EXPR:
+ case MIN_EXPR:
+ case MAX_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_IOR_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_ANDTC_EXPR:
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ case LT_EXPR:
+ case LE_EXPR:
+ case GT_EXPR:
+ case GE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case CEIL_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case ROUND_MOD_EXPR:
+ case COMPOUND_EXPR:
+ case PREDECREMENT_EXPR:
+ case PREINCREMENT_EXPR:
+ case POSTDECREMENT_EXPR:
+ case POSTINCREMENT_EXPR:
+ case ARRAY_REF:
+ case SCOPE_REF:
+ case TRY_CATCH_EXPR:
+ case WITH_CLEANUP_EXPR:
+ case CALL_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ TRY (TREE_OPERAND (t, 1));
+ break;
+
+ case SAVE_EXPR:
+ case CONVERT_EXPR:
+ case ADDR_EXPR:
+ case INDIRECT_REF:
+ case NEGATE_EXPR:
+ case BIT_NOT_EXPR:
+ case TRUTH_NOT_EXPR:
+ case NOP_EXPR:
+ case NON_LVALUE_EXPR:
+ case COMPONENT_REF:
+ case CLEANUP_POINT_EXPR:
+ case LOOKUP_EXPR:
+ case SIZEOF_EXPR:
+ case ALIGNOF_EXPR:
+ TRY (TREE_OPERAND (t, 0));
+ break;
+
+ case MODOP_EXPR:
+ case CAST_EXPR:
+ case REINTERPRET_CAST_EXPR:
+ case CONST_CAST_EXPR:
+ case STATIC_CAST_EXPR:
+ case DYNAMIC_CAST_EXPR:
+ case ARROW_EXPR:
+ case DOTSTAR_EXPR:
+ case TYPEID_EXPR:
+ break;
+
+ case COMPLEX_CST:
+ TRY (TREE_REALPART (t));
+ TRY (TREE_IMAGPART (t));
+ break;
+
+ case CONSTRUCTOR:
+ TRY (CONSTRUCTOR_ELTS (t));
+ break;
+
+ case TEMPLATE_TEMPLATE_PARM:
+ case TEMPLATE_PARM_INDEX:
+ case TEMPLATE_TYPE_PARM:
+ break;
+
+ case BIND_EXPR:
+ break;
+
+ case REAL_TYPE:
+ case COMPLEX_TYPE:
+ case VOID_TYPE:
+ case BOOLEAN_TYPE:
+ case TYPENAME_TYPE:
+ case UNION_TYPE:
+ case ENUMERAL_TYPE:
+ case TYPEOF_TYPE:
+ break;
+
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ TRY (TREE_TYPE (t));
+ break;
+
+ case FUNCTION_TYPE:
+ case METHOD_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_ARG_TYPES (t));
+ break;
+
+ case ARRAY_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_DOMAIN (t));
+ break;
+
+ case INTEGER_TYPE:
+ TRY (TYPE_MAX_VALUE (t));
+ break;
+
+ case OFFSET_TYPE:
+ TRY (TREE_TYPE (t));
+ TRY (TYPE_OFFSET_BASETYPE (t));
+ break;
+
+ case RECORD_TYPE:
+ if (TYPE_PTRMEMFUNC_P (t))
+ TRY (TYPE_PTRMEMFUNC_FN_TYPE (t));
+ break;
+
+ /* This list is incomplete, but should suffice for now.
+ It is very important that `sorry' not call
+ `report_error_function'. That could cause an infinite loop. */
+ default:
+ sorry ("initializer contains unrecognized tree code");
+ return error_mark_node;
+
+ }
+
+ return NULL_TREE;
+
+#undef TRY
+}
+
+/* Passed to search_tree. Checks for the use of types with no linkage. */
+
+static tree
+no_linkage_helper (t)
+ tree t;
+{
+ if (TYPE_P (t)
+ && (IS_AGGR_TYPE (t) || TREE_CODE (t) == ENUMERAL_TYPE)
+ && (decl_function_context (TYPE_MAIN_DECL (t))
+ || ANON_AGGRNAME_P (TYPE_IDENTIFIER (t))))
+ return t;
+ return NULL_TREE;
+}
+
+/* Check if the type T depends on a type with no linkage and if so, return
+ it. */
+
+tree
+no_linkage_check (t)
+ tree t;
+{
+ t = search_tree (t, no_linkage_helper);
+ if (t != error_mark_node)
+ return t;
+ return NULL_TREE;
+}
+
+
+/* Make copies of all the nodes below T. If FUNC is non-NULL, call it
+ for each node. */
+
+tree
+mapcar (t, func)
+ tree t;
+ tree (*func) PROTO((tree));
+{
+ tree tmp;
+
+ if (t == NULL_TREE)
+ return t;
+
+ if (func)
+ {
+ tmp = func (t);
+ if (tmp)
+ return tmp;
+ }
+
+ switch (TREE_CODE (t))
+ {
+ case ERROR_MARK:
return error_mark_node;
case VAR_DECL:
@@ -1608,11 +1763,13 @@ mapcar (t, func)
void g() { const int i = 7; f<i>(7); }
however, we must actually return the constant initializer. */
- tmp = decl_constant_value (t);
- if (tmp != t)
- return mapcar (tmp, func);
- else
- return error_mark_node;
+ if (TREE_READONLY_DECL_P (t))
+ {
+ tmp = decl_constant_value (t);
+ if (tmp != t)
+ return mapcar (tmp, func);
+ }
+ return error_mark_node;
case PARM_DECL:
{
@@ -1659,6 +1816,12 @@ mapcar (t, func)
case STRING_CST:
return copy_node (t);
+ case PTRMEM_CST:
+ t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
+ PTRMEM_CST_MEMBER (t) = mapcar (PTRMEM_CST_MEMBER (t), func);
+ return t;
+
case COND_EXPR:
case TARGET_EXPR:
case AGGR_INIT_EXPR:
@@ -1722,7 +1885,7 @@ mapcar (t, 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. */
+ make_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);
@@ -1739,37 +1902,39 @@ mapcar (t, func)
case NOP_EXPR:
case COMPONENT_REF:
case CLEANUP_POINT_EXPR:
+ case NON_LVALUE_EXPR:
t = copy_node (t);
+ TREE_TYPE (t) = mapcar (TREE_TYPE (t), func);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;
case POINTER_TYPE:
tmp = build_pointer_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case REFERENCE_TYPE:
tmp = build_reference_type (mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case FUNCTION_TYPE:
tmp = build_function_type (mapcar (TREE_TYPE (t), func),
mapcar (TYPE_ARG_TYPES (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case ARRAY_TYPE:
tmp = build_cplus_array_type (mapcar (TREE_TYPE (t), func),
mapcar (TYPE_DOMAIN (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, CP_TYPE_QUALS (t));
case INTEGER_TYPE:
tmp = build_index_type (mapcar (TYPE_MAX_VALUE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case OFFSET_TYPE:
tmp = build_offset_type (mapcar (TYPE_OFFSET_BASETYPE (t), func),
mapcar (TREE_TYPE (t), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case METHOD_TYPE:
tmp = build_cplus_method_type
(mapcar (TREE_TYPE (TREE_VALUE (TYPE_ARG_TYPES (t))), func),
mapcar (TREE_TYPE (t), func),
mapcar (TREE_CHAIN (TYPE_ARG_TYPES (t)), func));
- return cp_build_type_variant (tmp, TYPE_READONLY (t), TYPE_VOLATILE (t));
+ return cp_build_qualified_type (tmp, TYPE_QUALS (t));
case COMPLEX_CST:
t = copy_node (t);
@@ -1799,6 +1964,11 @@ mapcar (t, func)
TREE_OPERAND (t, 2) = mapcar (TREE_OPERAND (t, 2), func);
return t;
+ case LOOKUP_EXPR:
+ t = copy_node (t);
+ TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
+ return t;
+
case RECORD_TYPE:
if (TYPE_PTRMEMFUNC_P (t))
return build_ptrmemfunc_type
@@ -1818,6 +1988,16 @@ mapcar (t, func)
return NULL_TREE;
}
+/* Returns T if T is allocated on the permanent obstack, NULL_TREE
+ otherwise. */
+
+tree
+permanent_p (t)
+ tree t;
+{
+ return TREE_PERMANENT (t) ? t : NULL_TREE;
+}
+
static tree
perm_manip (t)
tree t;
@@ -1885,17 +2065,10 @@ print_lang_statistics ()
void
__eprintf (string, expression, line, filename)
-#ifdef __STDC__
const char *string;
const char *expression;
unsigned line;
const char *filename;
-#else
- char *string;
- char *expression;
- unsigned line;
- char *filename;
-#endif
{
fprintf (stderr, string, expression, line, filename);
fflush (stderr);
@@ -2037,7 +2210,7 @@ build_min VPROTO((enum tree_code code, tree tt, ...))
t = make_node (code);
length = tree_code_length[(int) code];
- TREE_TYPE (t) = tt;
+ TREE_TYPE (t) = copy_to_permanent (tt);
TREE_COMPLEXITY (t) = lineno;
for (i = 0; i < length; i++)
@@ -2114,7 +2287,7 @@ vec_binfo_member (elem, vec)
if (vec)
for (i = 0; i < TREE_VEC_LENGTH (vec); ++i)
- if (comptypes (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i)), 1))
+ if (same_type_p (elem, BINFO_TYPE (TREE_VEC_ELT (vec, i))))
return TREE_VEC_ELT (vec, i);
return NULL_TREE;
@@ -2134,6 +2307,24 @@ hack_decl_function_context (decl)
return decl_function_context (decl);
}
+/* Returns the namespace that contains DECL, whether directly or
+ indirectly. */
+
+tree
+decl_namespace_context (decl)
+ tree decl;
+{
+ while (1)
+ {
+ if (TREE_CODE (decl) == NAMESPACE_DECL)
+ return decl;
+ else if (TYPE_P (decl))
+ decl = CP_DECL_CONTEXT (TYPE_MAIN_DECL (decl));
+ else
+ decl = CP_DECL_CONTEXT (decl);
+ }
+}
+
/* Return truthvalue of whether T1 is the same tree structure as T2.
Return 1 if they are the same.
Return 0 if they are understandably different.
@@ -2187,7 +2378,7 @@ cp_tree_equal (t1, t2)
/* We need to do this when determining whether or not two
non-type pointer to member function template arguments
are the same. */
- if (!(comptypes (TREE_TYPE (t1), TREE_TYPE (t2), 1)
+ if (!(same_type_p (TREE_TYPE (t1), TREE_TYPE (t2))
/* The first operand is RTL. */
&& TREE_OPERAND (t1, 0) == TREE_OPERAND (t2, 0)))
return 0;
@@ -2255,9 +2446,15 @@ cp_tree_equal (t1, t2)
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);
+ return same_type_p (TREE_OPERAND (t1, 0), TREE_OPERAND (t2, 0));
break;
+ case PTRMEM_CST:
+ /* Two pointer-to-members are the same if they point to the same
+ field or function in the same class. */
+ return (PTRMEM_CST_MEMBER (t1) == PTRMEM_CST_MEMBER (t2)
+ && same_type_p (PTRMEM_CST_CLASS (t1), PTRMEM_CST_CLASS (t2)));
+
default:
break;
}
@@ -2284,17 +2481,17 @@ cp_tree_equal (t1, t2)
return -1;
}
-/* Similar to make_tree_vec, but build on a temporary obstack. */
+/* Similar to make_tree_vec, but build on the momentary_obstack.
+ Thus, these vectors are really and truly temporary. */
tree
make_temp_vec (len)
int len;
{
register tree node;
- register struct obstack *ambient_obstack = current_obstack;
- current_obstack = expression_obstack;
+ push_expression_obstack ();
node = make_tree_vec (len);
- current_obstack = ambient_obstack;
+ pop_obstacks ();
return node;
}
@@ -2333,7 +2530,7 @@ build_int_wrapper (i)
return t;
}
-tree
+static tree
build_srcloc (file, line)
char *file;
int line;
@@ -2378,8 +2575,7 @@ lvalue_type (arg)
tree type = TREE_TYPE (arg);
if (TREE_CODE (arg) == OVERLOAD)
type = unknown_type_node;
- return cp_build_type_variant
- (type, TREE_READONLY (arg), TREE_THIS_VOLATILE (arg));
+ return type;
}
/* The type of ARG for printing error messages; denote lvalues with
@@ -2422,3 +2618,194 @@ member_p (decl)
tree ctx = DECL_CONTEXT (decl);
return (ctx && TREE_CODE_CLASS (TREE_CODE (ctx)) == 't');
}
+
+/* Create a placeholder for member access where we don't actually have an
+ object that the access is against. */
+
+tree
+build_dummy_object (type)
+ tree type;
+{
+ tree decl = build1 (NOP_EXPR, build_pointer_type (type), void_zero_node);
+ return build_indirect_ref (decl, NULL_PTR);
+}
+
+/* We've gotten a reference to a member of TYPE. Return *this if appropriate,
+ or a dummy object otherwise. If BINFOP is non-0, it is filled with the
+ binfo path from current_class_type to TYPE, or 0. */
+
+tree
+maybe_dummy_object (type, binfop)
+ tree type;
+ tree *binfop;
+{
+ tree decl, context;
+
+ if (current_class_type
+ && get_base_distance (type, current_class_type, 0, binfop) != -1)
+ context = current_class_type;
+ else
+ {
+ /* Reference from a nested class member function. */
+ context = type;
+ if (binfop)
+ *binfop = TYPE_BINFO (type);
+ }
+
+ if (current_class_ref && context == current_class_type)
+ decl = current_class_ref;
+ else
+ decl = build_dummy_object (context);
+
+ return decl;
+}
+
+/* Returns 1 if OB is a placeholder object, or a pointer to one. */
+
+int
+is_dummy_object (ob)
+ tree ob;
+{
+ if (TREE_CODE (ob) == INDIRECT_REF)
+ ob = TREE_OPERAND (ob, 0);
+ return (TREE_CODE (ob) == NOP_EXPR
+ && TREE_OPERAND (ob, 0) == void_zero_node);
+}
+
+/* Returns 1 iff type T is a POD type, as defined in [basic.types]. */
+
+int
+pod_type_p (t)
+ tree t;
+{
+ tree f;
+
+ while (TREE_CODE (t) == ARRAY_TYPE)
+ t = TREE_TYPE (t);
+
+ if (! IS_AGGR_TYPE (t))
+ return 1;
+
+ if (CLASSTYPE_NON_AGGREGATE (t)
+ || TYPE_HAS_COMPLEX_ASSIGN_REF (t)
+ || TYPE_HAS_DESTRUCTOR (t))
+ return 0;
+
+ for (f = TYPE_FIELDS (t); f; f = TREE_CHAIN (f))
+ {
+ if (TREE_CODE (f) != FIELD_DECL)
+ continue;
+
+ if (TREE_CODE (TREE_TYPE (f)) == REFERENCE_TYPE
+ || TYPE_PTRMEMFUNC_P (TREE_TYPE (f))
+ || TYPE_PTRMEM_P (TREE_TYPE (f)))
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Return a 1 if ATTR_NAME and ATTR_ARGS denote a valid C++-specific
+ attribute for either declaration DECL or type TYPE and 0 otherwise.
+ Plugged into valid_lang_attribute. */
+
+int
+cp_valid_lang_attribute (attr_name, attr_args, decl, type)
+ tree attr_name;
+ tree attr_args ATTRIBUTE_UNUSED;
+ tree decl ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+{
+ if (is_attribute_p ("com_interface", attr_name))
+ {
+ if (! flag_vtable_thunks)
+ {
+ error ("`com_interface' only supported with -fvtable-thunks");
+ return 0;
+ }
+
+ if (attr_args != NULL_TREE
+ || decl != NULL_TREE
+ || ! CLASS_TYPE_P (type)
+ || type != TYPE_MAIN_VARIANT (type))
+ {
+ warning ("`com_interface' attribute can only be applied to class definitions");
+ return 0;
+ }
+
+ CLASSTYPE_COM_INTERFACE (type) = 1;
+ return 1;
+ }
+ else if (is_attribute_p ("init_priority", attr_name))
+ {
+ tree initp_expr = (attr_args ? TREE_VALUE (attr_args): NULL_TREE);
+ int pri;
+
+ if (initp_expr)
+ STRIP_NOPS (initp_expr);
+
+ if (!initp_expr || TREE_CODE (initp_expr) != INTEGER_CST)
+ {
+ error ("requested init_priority is not an integer constant");
+ return 0;
+ }
+
+ pri = TREE_INT_CST_LOW (initp_expr);
+
+ while (TREE_CODE (type) == ARRAY_TYPE)
+ type = TREE_TYPE (type);
+
+ if (decl == NULL_TREE
+ || TREE_CODE (decl) != VAR_DECL
+ || ! TREE_STATIC (decl)
+ || DECL_EXTERNAL (decl)
+ || (TREE_CODE (type) != RECORD_TYPE
+ && TREE_CODE (type) != UNION_TYPE)
+ /* Static objects in functions are initialized the
+ first time control passes through that
+ function. This is not precise enough to pin down an
+ init_priority value, so don't allow it. */
+ || current_function_decl)
+ {
+ error ("can only use init_priority attribute on file-scope definitions of objects of class type");
+ return 0;
+ }
+
+ if (pri > MAX_INIT_PRIORITY || pri <= 0)
+ {
+ error ("requested init_priority is out of range");
+ return 0;
+ }
+
+ /* Check for init_priorities that are reserved for
+ language and runtime support implementations.*/
+ if (pri <= MAX_RESERVED_INIT_PRIORITY)
+ {
+ warning
+ ("requested init_priority is reserved for internal use");
+ }
+
+ DECL_INIT_PRIORITY (decl) = pri;
+ return 1;
+ }
+
+ return 0;
+}
+
+/* Return a new PTRMEM_CST of the indicated TYPE. The MEMBER is the
+ thing pointed to by the constant. */
+
+tree
+make_ptrmem_cst (type, member)
+ tree type;
+ tree member;
+{
+ tree ptrmem_cst = make_node (PTRMEM_CST);
+ /* If would seem a great convenience if make_node would set
+ TREE_CONSTANT for things of class `c', but it does not. */
+ TREE_CONSTANT (ptrmem_cst) = 1;
+ TREE_TYPE (ptrmem_cst) = type;
+ PTRMEM_CST_MEMBER (ptrmem_cst) = member;
+ return ptrmem_cst;
+}
+
OpenPOWER on IntegriCloud