X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=13ec6dda6664dfc54875aa33a106af615322e7a4;hp=c3fdb798d6bd136a1fec6d76697f45967918175f;hb=8f623a2a6b835f5136f75e973564bae48b1cda2c;hpb=e4ce2dc45f1338aff005b5039938ccf13fff83d7 diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index c3fdb798d6b..13ec6dda666 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1,5 +1,5 @@ /* Build expressions with type checking for C++ compiler. - Copyright (C) 1987, 88, 89, 92, 93, 94, 1995 Free Software Foundation, Inc. + Copyright (C) 1987, 88, 89, 92, 93, 94, 95, 1996 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) This file is part of GNU CC. @@ -40,20 +40,21 @@ extern void warning (); #include "flags.h" #include "output.h" -int mark_addressable (); -static tree convert_for_assignment (); -/* static */ tree convert_for_initialization (); +int mark_addressable PROTO((tree)); +static tree convert_for_assignment PROTO((tree, tree, char*, tree, int)); +/* static */ tree convert_for_initialization PROTO((tree, tree, tree, int, char*, tree, int)); extern tree shorten_compare (); -extern void binary_op_error (); -static tree pointer_int_sum (); -static tree pointer_diff (); +static tree pointer_int_sum PROTO((enum tree_code, register tree, register tree)); +static tree pointer_diff PROTO((register tree, register tree)); +static int comp_target_parms PROTO((tree, tree, int)); +static int comp_ptr_ttypes_const PROTO((tree, tree)); +static int comp_ptr_ttypes_reinterpret PROTO((tree, tree)); +#if 0 static tree convert_sequence (); -/* static */ tree unary_complex_lvalue (); +#endif +/* static */ tree unary_complex_lvalue PROTO((enum tree_code, tree)); static tree get_delta_difference PROTO((tree, tree, int)); -extern rtx original_result_rtx; -extern int warn_synth; - /* Return the target type of TYPE, which meas return T for: T*, T&, T[], T (...), and otherwise, just T. */ @@ -81,7 +82,7 @@ require_complete_type (value) { tree type; - if (current_template_parms) + if (processing_template_decl) return value; type = TREE_TYPE (value); @@ -98,13 +99,13 @@ require_complete_type (value) not been laid out. Try to avoid an error by interpreting it as this->X::Y, if reasonable. */ if (TREE_CODE (value) == OFFSET_REF - && C_C_D != 0 - && TREE_OPERAND (value, 0) == C_C_D) + && current_class_ref != 0 + && TREE_OPERAND (value, 0) == current_class_ref) { tree base, member = TREE_OPERAND (value, 1); tree basetype = TYPE_OFFSET_BASETYPE (type); my_friendly_assert (TREE_CODE (member) == FIELD_DECL, 305); - base = convert_pointer_to (basetype, current_class_decl); + base = convert_pointer_to (basetype, current_class_ptr); value = build (COMPONENT_REF, TREE_TYPE (member), build_indirect_ref (base, NULL_PTR), member); return require_complete_type (value); @@ -112,7 +113,7 @@ require_complete_type (value) if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) { - instantiate_class_template (type); + instantiate_class_template (TYPE_MAIN_VARIANT (type)); if (TYPE_SIZE (type) != 0) return value; } @@ -125,13 +126,17 @@ tree complete_type (type) tree type; { - if (TYPE_SIZE (type) != NULL_TREE) + if (type == error_mark_node || TYPE_SIZE (type) != NULL_TREE) ; - else if (TREE_CODE (type) == ARRAY_TYPE) + else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type)) { tree t = complete_type (TREE_TYPE (type)); - if (TYPE_SIZE (t) != NULL_TREE) - type = build_cplus_array_type (t, TYPE_DOMAIN (type)); + if (TYPE_SIZE (t) != NULL_TREE && ! processing_template_decl) + layout_type (type); + TYPE_NEEDS_CONSTRUCTING (type) + = TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t)); + TYPE_NEEDS_DESTRUCTOR (type) + = TYPE_NEEDS_DESTRUCTOR (TYPE_MAIN_VARIANT (t)); } else if (IS_AGGR_TYPE (type) && CLASSTYPE_TEMPLATE_INSTANTIATION (type)) instantiate_class_template (TYPE_MAIN_VARIANT (type)); @@ -140,6 +145,7 @@ complete_type (type) } /* Return truthvalue of whether type of EXP is instantiated. */ + int type_unknown_p (exp) tree exp; @@ -151,6 +157,7 @@ type_unknown_p (exp) } /* Return truthvalue of whether T is function (or pfn) type. */ + int fntype_p (t) tree t; @@ -164,6 +171,7 @@ fntype_p (t) /* Do `exp = require_instantiated_type (type, exp);' to make sure EXP does not have an uninstantiated type. TYPE is type to instantiate with, if uninstantiated. */ + tree require_instantiated_type (type, exp, errval) tree type, exp, errval; @@ -347,6 +355,24 @@ common_type (t1, t2) code1 = TREE_CODE (t1); code2 = TREE_CODE (t2); + /* If one type is complex, form the common type of the non-complex + components, then make that complex. Use T1 or T2 if it is the + required type. */ + if (code1 == COMPLEX_TYPE || code2 == COMPLEX_TYPE) + { + tree subtype1 = code1 == COMPLEX_TYPE ? TREE_TYPE (t1) : t1; + tree subtype2 = code2 == COMPLEX_TYPE ? TREE_TYPE (t2) : t2; + tree subtype = common_type (subtype1, subtype2); + + if (code1 == COMPLEX_TYPE && TREE_TYPE (t1) == subtype) + return build_type_attribute_variant (t1, attributes); + else if (code2 == COMPLEX_TYPE && TREE_TYPE (t2) == subtype) + return build_type_attribute_variant (t2, attributes); + else + return build_type_attribute_variant (build_complex_type (subtype), + attributes); + } + switch (code1) { case INTEGER_TYPE: @@ -442,7 +468,8 @@ common_type (t1, t2) if (elt == TREE_TYPE (t2) && TYPE_DOMAIN (t2)) return build_type_attribute_variant (t2, attributes); /* Merge the element types, and have a size if either arg has one. */ - t1 = build_cplus_array_type (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); + t1 = build_cplus_array_type + (elt, TYPE_DOMAIN (TYPE_DOMAIN (t1) ? t1 : t2)); return build_type_attribute_variant (t1, attributes); } @@ -538,7 +565,8 @@ common_type (t1, t2) tree b1 = TYPE_OFFSET_BASETYPE (t1); tree b2 = TYPE_OFFSET_BASETYPE (t2); - if (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2)) + if (comptypes (b1, b2, 1) + || (DERIVED_FROM_P (b1, b2) && binfo_or_else (b1, b2))) return build_type_attribute_variant (t2, attributes); else if (binfo_or_else (b2, b1)) return build_type_attribute_variant (t1, attributes); @@ -551,6 +579,7 @@ common_type (t1, t2) } /* Return 1 if TYPE1 and TYPE2 raise the same exceptions. */ + int compexcepttypes (t1, t2) tree t1, t2; @@ -613,6 +642,7 @@ comp_array_types (cmp, t1, t2, strict) pointer to a base classes. These allowances do not commute. In this case, TYPE1 is assumed to be the base class, and TYPE2 is assumed to be the derived class. */ + int comptypes (type1, type2, strict) tree type1, type2; @@ -761,7 +791,7 @@ comptypes (type1, type2, strict) { int rval; look_hard: - rval = t1 == t2 || UNIQUELY_DERIVED_FROM_P (t1, t2); + rval = t1 == t2 || DERIVED_FROM_P (t1, t2); if (rval) { @@ -770,7 +800,7 @@ comptypes (type1, type2, strict) } if (strict < 0) { - val = UNIQUELY_DERIVED_FROM_P (t2, t1); + val = DERIVED_FROM_P (t2, t1); break; } } @@ -928,7 +958,8 @@ comp_target_types (ttl, ttr, nptrs) /* If two types share a common base type, return that basetype. If there is not a unique most-derived base type, this function returns ERROR_MARK_NODE. */ -tree + +static tree common_base_type (tt1, tt2) tree tt1, tt2; { @@ -987,6 +1018,7 @@ common_base_type (tt1, tt2) C++: See comment above about TYPE1, TYPE2, STRICT. If STRICT == 3, it means checking is strict, but do not compare default parameter values. */ + int compparms (parms1, parms2, strict) tree parms1, parms2; @@ -1033,7 +1065,8 @@ compparms (parms1, parms2, strict) /* This really wants return whether or not parameter type lists would make their owning functions assignment compatible or not. */ -int + +static int comp_target_parms (parms1, parms2, strict) tree parms1, parms2; int strict; @@ -1194,7 +1227,8 @@ unsigned_type (type) return unsigned_intHI_type_node; if (type1 == intQI_type_node) return unsigned_intQI_type_node; - return type; + + return signed_or_unsigned_type (1, type); } /* Return a signed type the same as TYPE in other respects. */ @@ -1222,7 +1256,8 @@ signed_type (type) return intHI_type_node; if (type1 == unsigned_intQI_type_node) return intQI_type_node; - return type; + + return signed_or_unsigned_type (0, type); } /* Return a type the same as TYPE except unsigned or @@ -1233,8 +1268,10 @@ signed_or_unsigned_type (unsignedp, type) int unsignedp; tree type; { - if (! INTEGRAL_TYPE_P (type)) + if (! INTEGRAL_TYPE_P (type) + || TREE_UNSIGNED (type) == unsignedp) return type; + if (TYPE_PRECISION (type) == TYPE_PRECISION (signed_char_type_node)) return unsignedp ? unsigned_char_type_node : signed_char_type_node; if (TYPE_PRECISION (type) == TYPE_PRECISION (integer_type_node)) @@ -1258,7 +1295,7 @@ c_sizeof (type) enum tree_code code = TREE_CODE (type); tree t; - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, type); if (code == FUNCTION_TYPE) @@ -1324,7 +1361,7 @@ tree expr_sizeof (e) tree e; { - if (current_template_parms) + if (processing_template_decl) return build_min (SIZEOF_EXPR, sizetype, e); if (TREE_CODE (e) == COMPONENT_REF @@ -1422,13 +1459,19 @@ decay_conversion (exp) register tree type = TREE_TYPE (exp); register enum tree_code code = TREE_CODE (type); - if (code == OFFSET_TYPE /* || TREE_CODE (exp) == OFFSET_REF */ ) + if (code == OFFSET_TYPE) { if (TREE_CODE (exp) == OFFSET_REF) return decay_conversion (resolve_offset_ref (exp)); type = TREE_TYPE (type); code = TREE_CODE (type); + + if (type == unknown_type_node) + { + cp_pedwarn ("assuming & on overloaded member function"); + return build_unary_op (ADDR_EXPR, exp, 0); + } } if (code == REFERENCE_TYPE) @@ -1462,14 +1505,7 @@ decay_conversion (exp) } if (code == METHOD_TYPE) { - if (TREE_CODE (exp) == OFFSET_REF) - { - /* FIXME: We should emit an error here about using a ptrmemfunc - for something other than a function call. */ - my_friendly_assert (TREE_CODE (TREE_OPERAND (exp, 1)) == FUNCTION_DECL, - 308); - return build_unary_op (ADDR_EXPR, TREE_OPERAND (exp, 1), 0); - } + cp_pedwarn ("assuming & on `%E'", exp); return build_unary_op (ADDR_EXPR, exp, 0); } if (code == ARRAY_TYPE) @@ -1489,9 +1525,9 @@ decay_conversion (exp) inner = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (inner))), inner); - TREE_REFERENCE_EXPR (inner) = 1; + TREE_CONSTANT (inner) = TREE_CONSTANT (TREE_OPERAND (inner, 0)); } - return convert (build_pointer_type (TREE_TYPE (type)), inner); + return cp_convert (build_pointer_type (TREE_TYPE (type)), inner); } if (TREE_CODE (exp) == COMPOUND_EXPR) @@ -1540,7 +1576,7 @@ decay_conversion (exp) /* This way is better for a COMPONENT_REF since it can simplify the offset for a component. */ adr = build_unary_op (ADDR_EXPR, exp, 1); - return convert (ptrtype, adr); + return cp_convert (ptrtype, adr); } return exp; @@ -1562,14 +1598,27 @@ default_conversion (exp) { tree t = type_promotes_to (type); if (t != type) - return convert (t, exp); + return cp_convert (t, exp); } - if (flag_traditional - && TYPE_MAIN_VARIANT (type) == float_type_node) - return convert (double_type_node, exp); return exp; } + +/* Take the address of an inline function without setting TREE_ADDRESSABLE + or TREE_USED. */ + +tree +inline_conversion (exp) + tree exp; +{ + if (TREE_CODE (exp) == FUNCTION_DECL) + { + tree type = build_type_variant + (TREE_TYPE (exp), TREE_READONLY (exp), TREE_THIS_VOLATILE (exp)); + exp = build1 (ADDR_EXPR, build_pointer_type (type), exp); + } + return exp; +} tree build_object_ref (datum, basetype, field) @@ -1597,78 +1646,21 @@ build_object_ref (datum, basetype, field) { tree binfo = binfo_or_else (basetype, dtype); if (binfo) - return build_component_ref (build_scoped_ref (datum, basetype), - field, binfo, 1); + return build_x_component_ref (build_scoped_ref (datum, basetype), + field, binfo, 1); } return error_mark_node; } /* Like `build_component_ref, but uses an already found field. - Must compute access for C_C_D. Otherwise, ok. */ + Must compute access for current_class_ref. Otherwise, ok. */ + tree build_component_ref_1 (datum, field, protect) tree datum, field; int protect; { - register tree basetype = TREE_TYPE (datum); - register enum tree_code code = TREE_CODE (basetype); - register tree ref; - - if (code == REFERENCE_TYPE) - { - datum = convert_from_reference (datum); - basetype = TREE_TYPE (datum); - code = TREE_CODE (basetype); - } - - if (! IS_AGGR_TYPE_CODE (code)) - { - if (code != ERROR_MARK) - cp_error ("request for member `%D' in `%E', which is of non-aggregate type `%T'", - field, datum, basetype); - return error_mark_node; - } - - if (TYPE_SIZE (basetype) == 0) - { - incomplete_type_error (0, basetype); - return error_mark_node; - } - - /* Look up component name in the structure type definition. */ - - if (field == error_mark_node) - my_friendly_abort (115); - - if (TREE_STATIC (field)) - return field; - - if (datum == C_C_D) - { - tree access = compute_access (TYPE_BINFO (current_class_type), field); - - if (access == access_private_node) - { - cp_error ("field `%D' is private", field); - return error_mark_node; - } - else if (access == access_protected_node) - { - cp_error ("field `%D' is protected", field); - return error_mark_node; - } - } - - ref = build (COMPONENT_REF, TREE_TYPE (field), datum, field); - - if (TREE_READONLY (datum) || TREE_READONLY (field)) - TREE_READONLY (ref) = 1; - if (TREE_THIS_VOLATILE (datum) || TREE_THIS_VOLATILE (field)) - TREE_THIS_VOLATILE (ref) = 1; - if (DECL_MUTABLE_P (field)) - TREE_READONLY (ref) = 0; - - return ref; + return build_component_ref (datum, field, NULL_TREE, protect); } /* Given a COND_EXPR in T, return it in a form that we can, for @@ -1677,6 +1669,7 @@ build_component_ref_1 (datum, field, protect) we're dealing with aggregates. So, we now call this in unary_complex_lvalue, and in build_modify_expr. The case (in particular) that led to this was with CODE == ADDR_EXPR, since it's not an lvalue when we'd get it there. */ + static tree rationalize_conditional_expr (code, t) enum tree_code code; @@ -1692,6 +1685,7 @@ rationalize_conditional_expr (code, t) FIELD_DECL for the field. If not found return NULL_TREE. Because anonymous unions can nest, we must also search all anonymous unions that are directly reachable. */ + static tree lookup_anon_field (t, type) tree t, type; @@ -1727,6 +1721,7 @@ lookup_anon_field (t, type) /* Build a COMPONENT_REF for a given DATUM, and it's member COMPONENT. COMPONENT can be an IDENTIFIER_NODE that is the name of the member that we are interested in, or it can be a FIELD_DECL. */ + tree build_component_ref (datum, component, basetype_path, protect) tree datum, component, basetype_path; @@ -1737,10 +1732,11 @@ build_component_ref (datum, component, basetype_path, protect) register tree field = NULL; register tree ref; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPONENT_REF, datum, component); - /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference inside it. */ + /* If DATUM is a COMPOUND_EXPR or COND_EXPR, move our reference + inside it. */ switch (TREE_CODE (datum)) { case COMPOUND_EXPR: @@ -1767,8 +1763,14 @@ build_component_ref (datum, component, basetype_path, protect) basetype = TREE_TYPE (datum); code = TREE_CODE (basetype); } + if (TREE_CODE (datum) == OFFSET_REF) + { + datum = resolve_offset_ref (datum); + basetype = TREE_TYPE (datum); + code = TREE_CODE (basetype); + } - /* First, see if there is a field or component with name COMPONENT. */ + /* First, see if there is a field or component with name COMPONENT. */ if (TREE_CODE (component) == TREE_LIST) { my_friendly_assert (!(TREE_CHAIN (component) == NULL_TREE @@ -1803,7 +1805,7 @@ build_component_ref (datum, component, basetype_path, protect) cp_error ("type `%T' has no destructor", basetype); return error_mark_node; } - return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 0); + return TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (basetype), 1); } /* Look up component name in the structure type definition. */ @@ -1813,16 +1815,20 @@ build_component_ref (datum, component, basetype_path, protect) hierarchy, the compiler will abort (because vptr lookups are not supposed to be ambiguous. */ field = CLASSTYPE_VFIELD (basetype); - else if (TREE_CODE (component) == FIELD_DECL) + else if (TREE_CODE (component) == FIELD_DECL + || TREE_CODE (component) == TYPE_DECL) { field = component; } else { + tree name = component; + if (TREE_CODE (component) == VAR_DECL) + name = DECL_NAME (component); if (basetype_path == NULL_TREE) basetype_path = TYPE_BINFO (basetype); - field = lookup_field (basetype_path, component, - protect && ! VFIELD_NAME_P (component), 0); + field = lookup_field (basetype_path, name, + protect && !VFIELD_NAME_P (name), 0); if (field == error_mark_node) return error_mark_node; @@ -1831,7 +1837,7 @@ build_component_ref (datum, component, basetype_path, protect) /* Not found as a data field, look for it as a method. If found, then if this is the only possible one, return it, else report ambiguity error. */ - tree fndecls = lookup_fnfields (basetype_path, component, 1); + tree fndecls = lookup_fnfields (basetype_path, name, 1); if (fndecls == error_mark_node) return error_mark_node; if (fndecls) @@ -1851,13 +1857,17 @@ build_component_ref (datum, component, basetype_path, protect) && ! resolves_to_fixed_type_p (datum, 0)) { tree addr = build_unary_op (ADDR_EXPR, datum, 0); + tree fntype = TREE_TYPE (fndecl); + addr = convert_pointer_to (DECL_CONTEXT (fndecl), addr); datum = build_indirect_ref (addr, NULL_PTR); my_friendly_assert (datum != error_mark_node, 310); fndecl = build_vfn_ref (&addr, datum, DECL_VINDEX (fndecl)); + TREE_TYPE (fndecl) = build_pointer_type (fntype); } - mark_used (fndecl); - return fndecl; + else + mark_used (fndecl); + return build (OFFSET_REF, TREE_TYPE (fndecl), datum, fndecl); } if (access == access_protected_node) cp_error ("member function `%D' is protected", fndecl); @@ -1878,7 +1888,7 @@ build_component_ref (datum, component, basetype_path, protect) } } - cp_error ("`%#T' has no member named `%D'", basetype, component); + cp_error ("`%#T' has no member named `%D'", basetype, name); return error_mark_node; } else if (TREE_TYPE (field) == error_mark_node) @@ -1905,7 +1915,8 @@ build_component_ref (datum, component, basetype_path, protect) { tree context = DECL_FIELD_CONTEXT (field); tree base = context; - while (base != basetype && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base))) + while (base != basetype && TYPE_NAME (base) + && ANON_AGGRNAME_P (TYPE_IDENTIFIER (base))) { base = TYPE_CONTEXT (base); } @@ -1935,7 +1946,7 @@ build_component_ref (datum, component, basetype_path, protect) basetype = base; /* Handle things from anon unions here... */ - if (ANON_AGGRNAME_P (TYPE_IDENTIFIER (context))) + if (TYPE_NAME (context) && ANON_AGGRNAME_P (TYPE_IDENTIFIER (context))) { tree subfield = lookup_anon_field (basetype, context); tree subdatum = build_component_ref (datum, subfield, @@ -1956,6 +1967,22 @@ build_component_ref (datum, component, basetype_path, protect) return ref; } + +/* Variant of build_component_ref for use in expressions, which should + never have REFERENCE_TYPE. */ + +tree +build_x_component_ref (datum, component, basetype_path, protect) + tree datum, component, basetype_path; + int protect; +{ + tree t = build_component_ref (datum, component, basetype_path, protect); + + if (! processing_template_decl) + t = convert_from_reference (t); + + return t; +} /* Given an expression PTR for a pointer, return an expression for the value pointed to. @@ -1971,7 +1998,7 @@ build_x_indirect_ref (ptr, errorstring) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (INDIRECT_REF, ptr); rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, NULL_TREE); @@ -1985,12 +2012,17 @@ build_indirect_ref (ptr, errorstring) tree ptr; char *errorstring; { - register tree pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE ? - ptr : default_conversion (ptr)); - register tree type = TREE_TYPE (pointer); + register tree pointer, type; + + if (ptr == error_mark_node) + return error_mark_node; - if (ptr == current_class_decl) - return C_C_D; + pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE + ? ptr : default_conversion (ptr)); + type = TREE_TYPE (pointer); + + if (ptr == current_class_ptr) + return current_class_ref; if (IS_AGGR_TYPE (type)) { @@ -2057,16 +2089,6 @@ build_indirect_ref (ptr, errorstring) will inherit the type of the array, which will be some pointer type. */ tree -build_x_array_ref (array, index) - tree array, index; -{ - tree rval = build_opfncall (ARRAY_REF, LOOKUP_NORMAL, array, index, NULL_TREE); - if (rval) - return rval; - return build_array_ref (array, index); -} - -tree build_array_ref (array, idx) tree array, idx; { @@ -2195,8 +2217,9 @@ build_array_ref (array, idx) /* Build a function call to function FUNCTION with parameters PARAMS. PARAMS is a list--a chain of TREE_LIST nodes--in which the - TREE_VALUE of each node is a parameter-expression. - FUNCTION's data type may be a function type or a pointer-to-function. + TREE_VALUE of each node is a parameter-expression. The PARAMS do + not include any object pointer that may be required. FUNCTION's + data type may be a function type or a pointer-to-function. For C++: If FUNCTION's data type is a TREE_LIST, then the tree list is the list of possible methods that FUNCTION could conceivably @@ -2211,12 +2234,11 @@ build_array_ref (array, idx) In the second case, TREE_PURPOSE (function) is the function's name directly. - DECL is the class instance variable, usually CURRENT_CLASS_DECL. */ + DECL is the class instance variable, usually CURRENT_CLASS_REF. + + When calling a TEMPLATE_DECL, we don't require a complete return + type. */ -/* - * [eichin:19911015.1726EST] actually return a possibly incomplete - * type - */ tree build_x_function_call (function, params, decl) tree function, params, decl; @@ -2227,10 +2249,27 @@ build_x_function_call (function, params, decl) if (function == error_mark_node) return error_mark_node; - if (current_template_parms) - return build_min_nt (CALL_EXPR, function, params, 0); + if (processing_template_decl) + return build_min_nt (CALL_EXPR, function, params, NULL_TREE); type = TREE_TYPE (function); + + if (TREE_CODE (type) == OFFSET_TYPE + && TREE_TYPE (type) == unknown_type_node + && TREE_CODE (function) == TREE_LIST + && TREE_CHAIN (function) == NULL_TREE) + { + /* Undo (Foo:bar)()... */ + type = TYPE_OFFSET_BASETYPE (type); + function = TREE_VALUE (function); + my_friendly_assert (TREE_CODE (function) == TREE_LIST, 999); + my_friendly_assert (TREE_CHAIN (function) == NULL_TREE, 999); + function = TREE_VALUE (function); + my_friendly_assert (TREE_CODE (function) == FUNCTION_DECL, 999); + function = DECL_NAME (function); + return build_method_call (decl, function, params, TYPE_BINFO (type), LOOKUP_NORMAL); + } + is_method = ((TREE_CODE (function) == TREE_LIST && current_class_type != NULL_TREE && IDENTIFIER_CLASS_VALUE (TREE_PURPOSE (function)) == function) @@ -2238,11 +2277,20 @@ build_x_function_call (function, params, decl) || TREE_CODE (type) == METHOD_TYPE || TYPE_PTRMEMFUNC_P (type)); + if (TREE_CODE (function) == FUNCTION_DECL + && DECL_STATIC_FUNCTION_P (function)) + return build_member_call + (DECL_CONTEXT (function), DECL_NAME (function), params); + /* Handle methods, friends, and overloaded functions, respectively. */ if (is_method) { + tree basetype = NULL_TREE; + if (TREE_CODE (function) == FUNCTION_DECL) { + basetype = DECL_CLASS_CONTEXT (function); + if (DECL_NAME (function)) function = DECL_NAME (function); else @@ -2251,6 +2299,7 @@ build_x_function_call (function, params, decl) else if (TREE_CODE (function) == TREE_LIST) { my_friendly_assert (TREE_CODE (TREE_VALUE (function)) == FUNCTION_DECL, 312); + basetype = DECL_CLASS_CONTEXT (TREE_VALUE (function)); function = TREE_PURPOSE (function); } else if (TREE_CODE (function) != IDENTIFIER_NODE) @@ -2278,6 +2327,10 @@ build_x_function_call (function, params, decl) must go through here in case it is a virtual function. @@ Perhaps this could be optimized. */ + if (basetype && (! current_class_type + || ! DERIVED_FROM_P (basetype, current_class_type))) + return build_member_call (basetype, function, params); + if (decl == NULL_TREE) { if (current_class_type == NULL_TREE) @@ -2300,7 +2353,7 @@ build_x_function_call (function, params, decl) { /* Should we undo what was done in build_component_ref? */ if (TREE_CODE (TREE_PURPOSE (TREE_OPERAND (function, 1))) == TREE_VEC) - /* Get the name that build_component_ref hid. */ + /* Get the name that build_component_ref hid. */ function = DECL_NAME (TREE_VALUE (TREE_OPERAND (function, 1))); else function = TREE_PURPOSE (TREE_OPERAND (function, 1)); @@ -2319,12 +2372,15 @@ build_x_function_call (function, params, decl) { tree val = TREE_VALUE (function); + if (flag_ansi_overloading) + return build_new_function_call (function, params, NULL_TREE); + if (TREE_CODE (val) == TEMPLATE_DECL) - return build_overload_call_maybe - (function, params, LOOKUP_COMPLAIN, (struct candidate *)0); + return build_overload_call_real + (function, params, LOOKUP_COMPLAIN, (struct candidate *)0, 0); else if (DECL_CHAIN (val) != NULL_TREE) return build_overload_call - (function, params, LOOKUP_COMPLAIN, (struct candidate *)0); + (function, params, LOOKUP_COMPLAIN); else my_friendly_abort (360); } @@ -2340,7 +2396,7 @@ build_x_function_call (function, params, decl) if (TREE_OPERAND (function, 0)) decl = TREE_OPERAND (function, 0); else - decl = C_C_D; + decl = current_class_ref; decl_addr = build_unary_op (ADDR_EXPR, decl, 0); function = get_member_function_from_ptrfunc (&decl_addr, @@ -2355,8 +2411,7 @@ build_x_function_call (function, params, decl) if (TREE_CODE (type) == REFERENCE_TYPE) type = TREE_TYPE (type); - if (TYPE_LANG_SPECIFIC (type) - && TYPE_OVERLOADS_CALL_EXPR (complete_type (type))) + if (IS_AGGR_TYPE (type)) return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, function, params, NULL_TREE); } @@ -2395,7 +2450,7 @@ build_x_function_call (function, params, decl) decl = convert_pointer_to (TREE_TYPE (ctypeptr), decl); } else - decl = build_c_cast (ctypeptr, decl, 0); + decl = build_c_cast (ctypeptr, decl); params = tree_cons (NULL_TREE, decl, params); } @@ -2417,7 +2472,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) if (TYPE_PTRMEMFUNC_P (TREE_TYPE (function))) { - tree fntype, index, e1, delta, delta2, e2, e3, aref, vtbl; + tree fntype, idx, e1, delta, delta2, e2, e3, aref, vtbl; tree instance; tree instance_ptr = *instance_ptrptr; @@ -2429,42 +2484,37 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) function = save_expr (function); fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)); - index = save_expr (build_component_ref (function, - index_identifier, - 0, 0)); - e1 = build (GT_EXPR, boolean_type_node, index, - convert (delta_type_node, integer_zero_node)); - delta = convert (ptrdiff_type_node, - build_component_ref (function, delta_identifier, 0, 0)); + idx = save_expr (build_component_ref (function, + index_identifier, + NULL_TREE, 0)); + e1 = fold (build (GT_EXPR, boolean_type_node, idx, + cp_convert (delta_type_node, integer_zero_node))); + delta = cp_convert (ptrdiff_type_node, + build_component_ref (function, delta_identifier, NULL_TREE, 0)); delta2 = DELTA2_FROM_PTRMEMFUNC (function); - /* convert down to the right base, before using the instance. */ + /* Convert down to the right base, before using the instance. */ instance = convert_pointer_to_real (TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)), instance_ptr); - if (instance == error_mark_node) + if (instance == error_mark_node && instance_ptr != error_mark_node) return instance; vtbl = convert_pointer_to (ptr_type_node, instance); vtbl = build (PLUS_EXPR, build_pointer_type (build_pointer_type (vtable_entry_type)), - vtbl, convert (ptrdiff_type_node, delta2)); + vtbl, cp_convert (ptrdiff_type_node, delta2)); vtbl = build_indirect_ref (vtbl, NULL_PTR); aref = build_array_ref (vtbl, build_binary_op (MINUS_EXPR, - index, + idx, integer_one_node, 1)); if (! flag_vtable_thunks) { aref = save_expr (aref); - /* Save the intermediate result in a SAVE_EXPR so we don't have to - compute each component of the virtual function pointer twice. */ - if (TREE_CODE (aref) == INDIRECT_REF) - TREE_OPERAND (aref, 0) = save_expr (TREE_OPERAND (aref, 0)); - delta = build_binary_op (PLUS_EXPR, - build_conditional_expr (e1, build_component_ref (aref, delta_identifier, 0, 0), integer_zero_node), + build_conditional_expr (e1, build_component_ref (aref, delta_identifier, NULL_TREE, 0), integer_zero_node), delta, 1); } @@ -2473,11 +2523,18 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) if (flag_vtable_thunks) e2 = aref; else - e2 = build_component_ref (aref, pfn_identifier, 0, 0); + e2 = build_component_ref (aref, pfn_identifier, NULL_TREE, 0); e3 = PFN_FROM_PTRMEMFUNC (function); TREE_TYPE (e2) = TREE_TYPE (e3); - function = build_conditional_expr (e1, e2, e3); + e1 = build_conditional_expr (e1, e2, e3); + + if (instance_ptr == error_mark_node + && TREE_CODE (e1) != ADDR_EXPR + && TREE_CODE (TREE_OPERAND (e1, 0)) != FUNCTION_DECL) + cp_error ("object missing in `%E'", function); + + function = e1; /* Make sure this doesn't get evaluated first inside one of the branches of the COND_EXPR. */ @@ -2537,38 +2594,27 @@ build_function_call_real (function, params, require_complete, flags) needs to be separately compiled). */ if (DECL_INLINE (function)) - { - /* Is it a synthesized method that needs to be synthesized? */ - if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function) - /* Kludge: don't synthesize for default args. */ - && current_function_decl) - synthesize_method (function); - - fntype = build_type_variant (TREE_TYPE (function), - TREE_READONLY (function), - TREE_THIS_VOLATILE (function)); - function = build1 (ADDR_EXPR, build_pointer_type (fntype), function); - } + function = inline_conversion (function); else - function = default_conversion (function); + function = build_addr_func (function); } else { fndecl = NULL_TREE; - /* Convert anything with function type to a pointer-to-function. */ - if (function == error_mark_node) - return error_mark_node; - function = default_conversion (function); + function = build_addr_func (function); } + if (function == error_mark_node) + return error_mark_node; + fntype = TREE_TYPE (function); if (TYPE_PTRMEMFUNC_P (fntype)) { - tree instance_ptr = build_unary_op (ADDR_EXPR, C_C_D, 0); - fntype = TYPE_PTRMEMFUNC_FN_TYPE (fntype); - function = get_member_function_from_ptrfunc (&instance_ptr, function); + cp_error ("must use .* or ->* to call pointer-to-member function in `%E (...)'", + function); + return error_mark_node; } is_method = (TREE_CODE (fntype) == POINTER_TYPE @@ -2626,17 +2672,17 @@ build_function_call_real (function, params, require_complete, flags) /* C++ */ value_type = TREE_TYPE (fntype) ? TREE_TYPE (fntype) : void_type_node; { - register tree result = - build (CALL_EXPR, value_type, - function, coerced_params, NULL_TREE); - - TREE_SIDE_EFFECTS (result) = 1; + register tree result + = build_call (function, value_type, coerced_params); - if (! require_complete) - return convert_from_reference (result); - if (value_type == void_type_node) - return result; - result = require_complete_type (result); + if (require_complete) + { + if (value_type == void_type_node) + return result; + result = require_complete_type (result); + } + if (IS_AGGR_TYPE (value_type)) + result = build_cplus_new (value_type, result); return convert_from_reference (result); } } @@ -2684,6 +2730,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) if (! flag_elide_constructors) return_loc = 0; + /* Argument passing is always copy-initialization. */ + flags |= LOOKUP_ONLYCONVERTING; + if (fndecl) { if (TREE_CODE (TREE_TYPE (fndecl)) == METHOD_TYPE) @@ -2712,9 +2761,8 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) { if (fndecl) { - char *buf = (char *)alloca (40 + strlen (called_thing)); - sprintf (buf, "too many arguments to %s `%%s'", called_thing); - error_with_decl (fndecl, buf); + cp_error_at ("too many arguments to %s `%+D'", called_thing, + fndecl); error ("at this point in file"); } else @@ -2753,7 +2801,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) else if (TREE_CODE (val) == OFFSET_REF && TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE) { - /* This is unclean. Should be handled elsewhere. */ + /* This is unclean. Should be handled elsewhere. */ val = build_unary_op (ADDR_EXPR, val, 0); } else if (TREE_CODE (val) == OFFSET_REF) @@ -2791,9 +2839,9 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) } else { - parmval = convert_for_initialization (return_loc, type, val, - flags|INDIRECT_BIND, - "argument passing", fndecl, i); + parmval = convert_for_initialization + (return_loc, type, val, flags, + "argument passing", fndecl, i); #ifdef PROMOTE_PROTOTYPES if ((TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) @@ -2816,7 +2864,7 @@ convert_arguments (return_loc, typelist, values, fndecl, flags) && (TYPE_PRECISION (TREE_TYPE (val)) < TYPE_PRECISION (double_type_node))) /* Convert `float' to `double'. */ - result = tree_cons (NULL_TREE, convert (double_type_node, val), result); + result = tree_cons (NULL_TREE, cp_convert (double_type_node, val), result); else if (TYPE_LANG_SPECIFIC (TREE_TYPE (val)) && ! TYPE_HAS_TRIVIAL_INIT_REF (TREE_TYPE (val))) { @@ -2906,9 +2954,12 @@ build_x_binary_op (code, arg1, arg2) { tree rval; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, arg1, arg2); + if (flag_ansi_overloading) + return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, arg1, arg2, NULL_TREE); if (rval) @@ -3107,8 +3158,10 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) case FLOOR_DIV_EXPR: case ROUND_DIV_EXPR: case EXACT_DIV_EXPR: - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == COMPLEX_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE)) { if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) cp_warning ("division by zero in `%E / 0'", op0); @@ -3217,7 +3270,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -3239,7 +3292,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1); /* Avoid converting op1 to result_type later. */ converted = 1; } @@ -3264,15 +3317,17 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) /* Convert the shift-count to an integer, regardless of size of value being shifted. */ if (TYPE_MAIN_VARIANT (TREE_TYPE (op1)) != integer_type_node) - op1 = convert (integer_type_node, op1); + op1 = cp_convert (integer_type_node, op1); } break; case EQ_EXPR: case NE_EXPR: build_type = boolean_type_node; - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE + || code0 == COMPLEX_TYPE) + && (code1 == INTEGER_TYPE || code1 == REAL_TYPE + || code1 == COMPLEX_TYPE)) short_compare = 1; else if (code0 == POINTER_TYPE && code1 == POINTER_TYPE) { @@ -3321,14 +3376,14 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1)) { - op0 = build_component_ref (op0, index_identifier, 0, 0); + op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0); op1 = integer_zero_node; result_type = TREE_TYPE (op0); } else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST && integer_zerop (op0)) { - op0 = build_component_ref (op1, index_identifier, 0, 0); + op0 = build_component_ref (op1, index_identifier, NULL_TREE, 0); op1 = integer_zero_node; result_type = TREE_TYPE (op0); } @@ -3342,8 +3397,8 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) && ((op1.index != -1 && op0.delta2 == op1.delta2) || op0.pfn == op1.pfn)) */ - tree index0 = build_component_ref (op0, index_identifier, 0, 0); - tree index1 = save_expr (build_component_ref (op1, index_identifier, 0, 0)); + tree index0 = build_component_ref (op0, index_identifier, NULL_TREE, 0); + tree index1 = save_expr (build_component_ref (op1, index_identifier, NULL_TREE, 0)); tree pfn0 = PFN_FROM_PTRMEMFUNC (op0); tree pfn1 = PFN_FROM_PTRMEMFUNC (op1); tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0); @@ -3364,7 +3419,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (TYPE_PTRMEMFUNC_P (type0) && TYPE_PTRMEMFUNC_FN_TYPE (type0) == type1) { - tree index0 = build_component_ref (op0, index_identifier, 0, 0); + tree index0 = build_component_ref (op0, index_identifier, NULL_TREE, 0); tree index1; tree pfn0 = PFN_FROM_PTRMEMFUNC (op0); tree delta20 = DELTA2_FROM_PTRMEMFUNC (op0); @@ -3454,25 +3509,22 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE) { result_type = type0; - if (pedantic) - pedwarn ("ANSI C++ forbids comparison between pointer and integer"); - else if (! flag_traditional) - warning ("comparison between pointer and integer"); + pedwarn ("ANSI C++ forbids comparison between pointer and integer"); } else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE) { result_type = type1; - if (pedantic) - pedwarn ("ANSI C++ forbids comparison between pointer and integer"); - else if (! flag_traditional) - warning ("comparison between pointer and integer"); + pedwarn ("ANSI C++ forbids comparison between pointer and integer"); } break; } - if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE) - && (code1 == INTEGER_TYPE || code1 == REAL_TYPE)) + if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE || code0 == COMPLEX_TYPE) + && + (code1 == INTEGER_TYPE || code1 == REAL_TYPE || code1 == COMPLEX_TYPE)) { + int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE); + if (shorten || common || short_compare) result_type = common_type (type0, type1); @@ -3487,7 +3539,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) Eg, (short)-1 | (unsigned short)-1 is (int)-1 but calculated in (unsigned short) it would be (unsigned short)-1. */ - if (shorten) + if (shorten && none_complex) { int unsigned0, unsigned1; tree arg0 = get_narrower (op0, &unsigned0); @@ -3582,7 +3634,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) TREE_TYPE (arg0)); /* Convert value-to-be-shifted to that type. */ if (TREE_TYPE (op0) != result_type) - op0 = convert (result_type, op0); + op0 = cp_convert (result_type, op0); converted = 1; } } @@ -3601,7 +3653,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) tree val = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode); if (val != 0) - return convert (boolean_type_node, val); + return cp_convert (boolean_type_node, val); op0 = xop0, op1 = xop1; converted = 1; resultcode = xresultcode; @@ -3616,7 +3668,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) tree primop0 = get_narrower (op0, &unsignedp0); tree primop1 = get_narrower (op1, &unsignedp1); - /* Check for comparison of different enum types. */ + /* Check for comparison of different enum types. */ if (flag_int_enum_equivalence == 0 && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE @@ -3732,9 +3784,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if (! converted) { if (TREE_TYPE (op0) != result_type) - op0 = convert (result_type, op0); + op0 = cp_convert (result_type, op0); if (TREE_TYPE (op1) != result_type) - op1 = convert (result_type, op1); + op1 = cp_convert (result_type, op1); } if (build_type == NULL_TREE) @@ -3748,7 +3800,7 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code) if (folded == result) TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1); if (final_type != 0) - return convert (final_type, folded); + return cp_convert (final_type, folded); return folded; } } @@ -3825,15 +3877,15 @@ pointer_int_sum (resultcode, ptrop, intop) so the multiply won't overflow spuriously. */ if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)) - intop = convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop); + intop = cp_convert (type_for_size (TYPE_PRECISION (sizetype), 0), intop); /* Replace the integer argument with a suitable product by the object size. Do this multiplication as signed, then convert to the appropriate pointer type (actually unsigned integral). */ - intop = convert (result_type, - build_binary_op (MULT_EXPR, intop, - convert (TREE_TYPE (intop), size_exp), 1)); + intop = cp_convert (result_type, + build_binary_op (MULT_EXPR, intop, + cp_convert (TREE_TYPE (intop), size_exp), 1)); /* Create the sum or difference. */ @@ -3872,7 +3924,7 @@ pointer_diff (op0, op1) then drop through to build the divide operator. */ op0 = build_binary_op (MINUS_EXPR, - convert (restype, op0), convert (restype, op1), 1); + cp_convert (restype, op0), cp_convert (restype, op1), 1); /* This generates an error if op1 is a pointer to an incomplete type. */ if (TYPE_SIZE (TREE_TYPE (TREE_TYPE (op1))) == 0) @@ -3887,7 +3939,7 @@ pointer_diff (op0, op1) /* Do the division. */ - result = build (EXACT_DIV_EXPR, restype, op0, convert (restype, op1)); + result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1)); folded = fold (result); if (folded == result) @@ -3938,7 +3990,7 @@ build_component_addr (arg, argtype, msg) size_int (BITS_PER_UNIT)); int flag = TREE_CONSTANT (rval); rval = fold (build (PLUS_EXPR, argtype, - rval, convert (argtype, offset))); + rval, cp_convert (argtype, offset))); TREE_CONSTANT (rval) = flag; } return rval; @@ -3953,11 +4005,11 @@ build_x_unary_op (code, xarg) enum tree_code code; tree xarg; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (code, xarg, NULL_TREE); /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an - error message. */ + error message. */ if (code == ADDR_EXPR && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg))) && TYPE_SIZE (TREE_TYPE (xarg)) == NULL_TREE) @@ -3965,12 +4017,31 @@ build_x_unary_op (code, xarg) /* don't look for a function */; else { - tree rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, - NULL_TREE, NULL_TREE); - if (rval) - return build_opfncall (code, LOOKUP_NORMAL, xarg, + tree rval; + + if (flag_ansi_overloading) + { + rval = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE); + if (rval || code != ADDR_EXPR) + return rval; + } + else + { + rval = build_opfncall (code, LOOKUP_SPECULATIVELY, xarg, + NULL_TREE, NULL_TREE); + if (rval) + return build_opfncall (code, LOOKUP_NORMAL, xarg, + NULL_TREE, NULL_TREE); + } + } + + if (code == ADDR_EXPR) + { + if (TREE_CODE (xarg) == TARGET_EXPR) + warning ("taking address of temporary"); } + return build_unary_op (code, xarg, 0); } @@ -3981,9 +4052,9 @@ condition_conversion (expr) tree expr; { tree t; - if (current_template_parms) + if (processing_template_decl) return expr; - t = convert (boolean_type_node, expr); + t = cp_convert (boolean_type_node, expr); t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); return t; } @@ -3996,6 +4067,7 @@ condition_conversion (expr) NOCONVERT nonzero suppresses the default promotions (such as from short to int). */ + tree build_unary_op (code, xarg, noconvert) enum tree_code code; @@ -4036,7 +4108,14 @@ build_unary_op (code, xarg, noconvert) break; case BIT_NOT_EXPR: - if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, arg, 1))) + if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + { + code = CONJ_EXPR; + if (!noconvert) + arg = default_conversion (arg); + } + else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, + arg, 1))) errstring = "wrong type argument to bit-complement"; else if (!noconvert) arg = default_conversion (arg); @@ -4049,8 +4128,16 @@ build_unary_op (code, xarg, noconvert) arg = default_conversion (arg); break; + case CONJ_EXPR: + /* Conjugating a real value is a no-op, but allow it anyway. */ + if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1))) + errstring = "wrong type argument to conjugation"; + else if (!noconvert) + arg = default_conversion (arg); + break; + case TRUTH_NOT_EXPR: - arg = convert (boolean_type_node, arg); + arg = cp_convert (boolean_type_node, arg); val = invert_truthvalue (arg); if (arg != error_mark_node) return val; @@ -4060,6 +4147,22 @@ build_unary_op (code, xarg, noconvert) case NOP_EXPR: break; + case REALPART_EXPR: + if (TREE_CODE (arg) == COMPLEX_CST) + return TREE_REALPART (arg); + else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + return fold (build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + else + return arg; + + case IMAGPART_EXPR: + if (TREE_CODE (arg) == COMPLEX_CST) + return TREE_IMAGPART (arg); + else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + return fold (build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg)); + else + return cp_convert (TREE_TYPE (arg), integer_zero_node); + case PREINCREMENT_EXPR: case POSTINCREMENT_EXPR: case PREDECREMENT_EXPR: @@ -4071,6 +4174,19 @@ build_unary_op (code, xarg, noconvert) if (val != 0) return val; + /* Increment or decrement the real part of the value, + and don't change the imaginary part. */ + if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE) + { + tree real, imag; + + arg = stabilize_reference (arg); + real = build_unary_op (REALPART_EXPR, arg, 1); + imag = build_unary_op (IMAGPART_EXPR, arg, 1); + return build (COMPLEX_EXPR, TREE_TYPE (arg), + build_unary_op (code, real, 1), imag); + } + /* Report invalid types. */ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER, @@ -4130,7 +4246,7 @@ build_unary_op (code, xarg, noconvert) else inc = integer_one_node; - inc = convert (argtype, inc); + inc = cp_convert (argtype, inc); /* Handle incrementing a cast-expression. */ @@ -4161,7 +4277,7 @@ build_unary_op (code, xarg, noconvert) modify = build_modify_expr (arg, NOP_EXPR, incremented); compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value); - /* Eliminate warning about unused result of + or -. */ + /* Eliminate warning about unused result of + or -. */ TREE_NO_UNUSED_WARNING (compound) = 1; return compound; } @@ -4205,7 +4321,7 @@ build_unary_op (code, xarg, noconvert) val = build (code, TREE_TYPE (arg), arg, inc); TREE_SIDE_EFFECTS (val) = 1; - return convert (result_type, val); + return cp_convert (result_type, val); } case ADDR_EXPR: @@ -4215,8 +4331,10 @@ build_unary_op (code, xarg, noconvert) argtype = TREE_TYPE (arg); if (TREE_CODE (argtype) == REFERENCE_TYPE) { - arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); - TREE_REFERENCE_EXPR (arg) = 1; + arg = build1 + (CONVERT_EXPR, + build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); + TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0)); return arg; } else if (pedantic @@ -4232,21 +4350,17 @@ build_unary_op (code, xarg, noconvert) /* Let &* cancel out to simplify resulting code. */ if (TREE_CODE (arg) == INDIRECT_REF) { - /* We don't need to have `current_class_decl' wrapped in a + /* We don't need to have `current_class_ptr' wrapped in a NON_LVALUE_EXPR node. */ - if (arg == C_C_D) - return current_class_decl; + if (arg == current_class_ref) + return current_class_ptr; - /* Keep `default_conversion' from converting if - ARG is of REFERENCE_TYPE. */ arg = TREE_OPERAND (arg, 0); if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE) { - if (TREE_CODE (arg) == VAR_DECL && DECL_INITIAL (arg) - && !TREE_SIDE_EFFECTS (DECL_INITIAL (arg))) - arg = DECL_INITIAL (arg); - arg = build1 (CONVERT_EXPR, build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); - TREE_REFERENCE_EXPR (arg) = 1; + arg = build1 + (CONVERT_EXPR, + build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg); TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0)); } else if (lvalue_p (arg)) @@ -4352,6 +4466,14 @@ build_unary_op (code, xarg, noconvert) function counts as a constant */ if (staticp (arg)) TREE_CONSTANT (addr) = 1; + + if (TREE_CODE (argtype) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) + { + build_ptrmemfunc_type (argtype); + addr = build_ptrmemfunc (argtype, addr, 0); + } + return addr; } } @@ -4386,9 +4508,9 @@ convert_sequence (conversions, arg) case FIX_FLOOR_EXPR: case FIX_ROUND_EXPR: case FIX_CEIL_EXPR: - return convert (TREE_TYPE (conversions), - convert_sequence (TREE_OPERAND (conversions, 0), - arg)); + return cp_convert (TREE_TYPE (conversions), + convert_sequence (TREE_OPERAND (conversions, 0), + arg)); default: return arg; @@ -4434,7 +4556,9 @@ unary_complex_lvalue (code, arg) || TREE_CODE (arg) == INIT_EXPR) { tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0); - return build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); + arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result); + TREE_NO_UNUSED_WARNING (arg) = 1; + return arg; } if (TREE_CODE (TREE_TYPE (arg)) == FUNCTION_TYPE @@ -4445,7 +4569,6 @@ unary_complex_lvalue (code, arg) is really the representation of a pointer to it. Here give the representation its true type. */ tree t; - tree offset; my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313); @@ -4454,12 +4577,15 @@ unary_complex_lvalue (code, arg) t = TREE_OPERAND (arg, 1); - if (TREE_CODE (t) == FUNCTION_DECL) /* Check all this code for right semantics. */ + if (TREE_CODE (t) == FUNCTION_DECL) /* Check all this code for right semantics. */ return build_unary_op (ADDR_EXPR, t, 0); if (TREE_CODE (t) == VAR_DECL) return build_unary_op (ADDR_EXPR, t, 0); else { + tree type; + tree offset = integer_zero_node; + if (TREE_OPERAND (arg, 0) && (TREE_CODE (TREE_OPERAND (arg, 0)) != NOP_EXPR || TREE_OPERAND (TREE_OPERAND (arg, 0), 0) != error_mark_node)) @@ -4471,38 +4597,40 @@ unary_complex_lvalue (code, arg) return error_mark_node; } - offset = get_delta_difference (DECL_FIELD_CONTEXT (t), - TREE_TYPE (TREE_OPERAND (arg, 0)), - 0); + type = TREE_TYPE (TREE_OPERAND (arg, 0)); + + if (TREE_CODE (TREE_TYPE (arg)) == OFFSET_TYPE) + { + /* Add in the offset to the intermediate subobject, if any. */ + offset = get_delta_difference (TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)), + type, + 0); + type = TYPE_OFFSET_BASETYPE (TREE_TYPE (arg)); + } + + /* Now in the offset to the final subobject. */ + offset = size_binop (PLUS_EXPR, + offset, + get_delta_difference (DECL_FIELD_CONTEXT (t), + type, + 0)); + + /* Add in the offset to the field. */ offset = size_binop (PLUS_EXPR, offset, size_binop (EASY_DIV_EXPR, DECL_FIELD_BITPOS (t), size_int (BITS_PER_UNIT))); - return convert (build_pointer_type (TREE_TYPE (arg)), offset); - } - } - - if (TREE_CODE (arg) == OFFSET_REF) - { - tree left = TREE_OPERAND (arg, 0), left_addr; - tree right_addr = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 1), 0); - if (left == 0) - if (current_class_decl) - left_addr = current_class_decl; - else - { - error ("no `this' for pointer to member"); - return error_mark_node; - } - else - left_addr = build_unary_op (ADDR_EXPR, left, 0); + /* We offset all pointer to data memebers by 1 so that we can + distinguish between a null pointer to data member and the first + data member of a structure. */ + offset = size_binop (PLUS_EXPR, offset, size_int (1)); - return build (PLUS_EXPR, build_pointer_type (TREE_TYPE (arg)), - build1 (NOP_EXPR, integer_type_node, left_addr), - build1 (NOP_EXPR, integer_type_node, right_addr)); + return cp_convert (build_pointer_type (TREE_TYPE (arg)), offset); + } } + /* We permit compiler to make function calls returning objects of aggregate type look like lvalues. */ { @@ -4533,7 +4661,7 @@ unary_complex_lvalue (code, arg) address of it; it should not be allocated in a register. Value is 1 if successful. - C++: we do not allow `current_class_decl' to be addressable. */ + C++: we do not allow `current_class_ptr' to be addressable. */ int mark_addressable (exp) @@ -4550,13 +4678,16 @@ mark_addressable (exp) case ADDR_EXPR: case COMPONENT_REF: case ARRAY_REF: + case REALPART_EXPR: + case IMAGPART_EXPR: x = TREE_OPERAND (x, 0); break; case PARM_DECL: - if (x == current_class_decl) + if (x == current_class_ptr) { - error ("address of `this' not available"); + if (! flag_this_is_variable) + error ("address of `this' not available"); TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */ put_var_into_stack (x); return 1; @@ -4589,8 +4720,10 @@ mark_addressable (exp) case CONST_DECL: case RESULT_DECL: - /* For C++, we don't warn about taking the address of a register - variable for CONST_DECLs; ARM p97 explicitly says it's okay. */ + if (DECL_REGISTER (x) && !TREE_ADDRESSABLE (x) + && !DECL_ARTIFICIAL (x) && extra_warnings) + cp_warning ("address requested for `%D', which is declared `register'", + x); put_var_into_stack (x); TREE_ADDRESSABLE (x) = 1; return 1; @@ -4614,6 +4747,15 @@ mark_addressable (exp) TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1; return 1; + case CONSTRUCTOR: + TREE_ADDRESSABLE (x) = 1; + return 1; + + case TARGET_EXPR: + TREE_ADDRESSABLE (x) = 1; + mark_addressable (TREE_OPERAND (x, 0)); + return 1; + default: return 1; } @@ -4627,9 +4769,12 @@ build_x_conditional_expr (ifexp, op1, op2) { tree rval = NULL_TREE; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COND_EXPR, ifexp, op1, op2); + if (flag_ansi_overloading) + return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2); + /* See comments in `build_x_binary_op'. */ if (op1 != 0) rval = build_opfncall (COND_EXPR, LOOKUP_SPECULATIVELY, ifexp, op1, op2); @@ -4648,7 +4793,6 @@ build_conditional_expr (ifexp, op1, op2) register enum tree_code code1; register enum tree_code code2; register tree result_type = NULL_TREE; - tree orig_op1 = op1, orig_op2 = op2; /* If second operand is omitted, it is the same as the first one; make sure it is calculated only once. */ @@ -4659,7 +4803,7 @@ build_conditional_expr (ifexp, op1, op2) ifexp = op1 = save_expr (ifexp); } - ifexp = convert (boolean_type_node, ifexp); + ifexp = cp_convert (boolean_type_node, ifexp); if (TREE_CODE (ifexp) == ERROR_MARK) return error_mark_node; @@ -4724,6 +4868,15 @@ build_conditional_expr (ifexp, op1, op2) result = fold (build (COND_EXPR, type1, ifexp, op1, op2)); if (TREE_TYPE (result) != type1) result = build1 (NOP_EXPR, type1, result); + /* Expand both sides into the same slot, + hopefully the target of the ?: expression. */ + if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR) + { + tree slot = build (VAR_DECL, TREE_TYPE (result)); + layout_decl (slot, 0); + result = build (TARGET_EXPR, TREE_TYPE (result), + slot, result, NULL_TREE, NULL_TREE); + } return result; } @@ -4797,16 +4950,14 @@ build_conditional_expr (ifexp, op1, op2) pedwarn ("ANSI C++ forbids conditional expr with only one void side"); result_type = void_type_node; } + else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2)) + result_type = qualify_type (type1, type2); + else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1)) + result_type = qualify_type (type2, type1); else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE) { if (comp_target_types (type1, type2, 1)) result_type = common_type (type1, type2); - else if (integer_zerop (op1) && TREE_TYPE (type1) == void_type_node - && TREE_CODE (orig_op1) != NOP_EXPR) - result_type = qualify_type (type2, type1); - else if (integer_zerop (op2) && TREE_TYPE (type2) == void_type_node - && TREE_CODE (orig_op2) != NOP_EXPR) - result_type = qualify_type (type1, type2); else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node) { if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE) @@ -4851,20 +5002,12 @@ build_conditional_expr (ifexp, op1, op2) } else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE) { - if (!integer_zerop (op2)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else - op2 = null_pointer_node; - + pedwarn ("pointer/integer type mismatch in conditional expression"); result_type = type1; } else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE) { - if (!integer_zerop (op1)) - pedwarn ("pointer/integer type mismatch in conditional expression"); - else - op1 = null_pointer_node; - + pedwarn ("pointer/integer type mismatch in conditional expression"); result_type = type2; } @@ -4877,30 +5020,52 @@ build_conditional_expr (ifexp, op1, op2) cp_error ("aggregate mismatch in conditional expression: `%T' vs `%T'", type1, type2); return error_mark_node; } + /* Warning: this code assumes that conversion between cv-variants of + a type is done using NOP_EXPRs. */ if (code1 == RECORD_TYPE && TYPE_HAS_CONVERSION (type1)) { - tree tmp = build_type_conversion (CONVERT_EXPR, type2, op1, 0); + /* There are other types besides pointers and records. */ + tree tmp; + if (code2 == POINTER_TYPE) + tmp = build_pointer_type + (build_type_variant (TREE_TYPE (type2), 1, 1)); + else + tmp = type2; + tmp = build_type_conversion (CONVERT_EXPR, tmp, op1, 0); if (tmp == NULL_TREE) { - cp_error ("aggregate type `%T' could not convert on lhs of `:'", type1); + cp_error ("incompatible types `%T' and `%T' in `?:'", + type1, type2); return error_mark_node; } if (tmp == error_mark_node) error ("ambiguous pointer conversion"); - result_type = type2; + else + STRIP_NOPS (tmp); + result_type = common_type (type2, TREE_TYPE (tmp)); op1 = tmp; } else if (code2 == RECORD_TYPE && TYPE_HAS_CONVERSION (type2)) { - tree tmp = build_type_conversion (CONVERT_EXPR, type1, op2, 0); + tree tmp; + if (code1 == POINTER_TYPE) + tmp = build_pointer_type + (build_type_variant (TREE_TYPE (type1), 1, 1)); + else + tmp = type1; + + tmp = build_type_conversion (CONVERT_EXPR, tmp, op2, 0); if (tmp == NULL_TREE) { - cp_error ("aggregate type `%T' could not convert on rhs of `:'", type2); + cp_error ("incompatible types `%T' and `%T' in `?:'", + type1, type2); return error_mark_node; } if (tmp == error_mark_node) error ("ambiguous pointer conversion"); - result_type = type1; + else + STRIP_NOPS (tmp); + result_type = common_type (type1, TREE_TYPE (tmp)); op2 = tmp; } else if (flag_cond_mismatch) @@ -4930,6 +5095,7 @@ build_conditional_expr (ifexp, op1, op2) /* Handle overloading of the ',' operator when needed. Otherwise, this function just builds an expression list. */ + tree build_x_compound_expr (list) tree list; @@ -4937,7 +5103,7 @@ build_x_compound_expr (list) tree rest = TREE_CHAIN (list); tree result; - if (current_template_parms) + if (processing_template_decl) return build_min_nt (COMPOUND_EXPR, list, NULL_TREE); if (rest == NULL_TREE) @@ -5004,124 +5170,251 @@ build_compound_expr (list) break_out_cleanups (TREE_VALUE (list)), rest); } -tree build_static_cast (type, expr) +tree +build_static_cast (type, expr) tree type, expr; { - return build_c_cast (type, expr, 0); + tree intype, binfo; + int ok; + + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; + + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); + + if (processing_template_decl) + { + tree t = build_min (STATIC_CAST_EXPR, type, expr); + return t; + } + + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (type) != REFERENCE_TYPE + && TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); + + if (TREE_CODE (type) == VOID_TYPE) + return build1 (CONVERT_EXPR, type, expr); + + if (type_unknown_p (expr)) + { + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; + } + + if (TREE_CODE (type) == REFERENCE_TYPE) + return (convert_from_reference + (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT, + LOOKUP_COMPLAIN, NULL_TREE))); + + if (IS_AGGR_TYPE (type)) + return build_cplus_new + (type, (build_method_call + (NULL_TREE, ctor_identifier, build_tree_list (NULL_TREE, expr), + TYPE_BINFO (type), LOOKUP_NORMAL))); + + expr = decay_conversion (expr); + intype = TREE_TYPE (expr); + + /* FIXME handle casting to array type. */ + + ok = 0; + if (can_convert_arg (type, intype, expr)) + ok = 1; + else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype)) + { + tree binfo; + if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype)) + && (TYPE_READONLY (TREE_TYPE (type)) + >= TYPE_READONLY (TREE_TYPE (intype))) + && (TYPE_VOLATILE (TREE_TYPE (type)) + >= TYPE_VOLATILE (TREE_TYPE (intype))) + && (binfo = get_binfo (TREE_TYPE (intype), TREE_TYPE (type), 0)) + && ! TREE_VIA_VIRTUAL (binfo)) + ok = 1; + } + else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + { + if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type))), + TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (intype))), 1) + && (TYPE_READONLY (TREE_TYPE (TREE_TYPE (type))) + >= TYPE_READONLY (TREE_TYPE (TREE_TYPE (intype)))) + && (TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (type))) + >= TYPE_VOLATILE (TREE_TYPE (TREE_TYPE (intype)))) + && (binfo = get_binfo (TYPE_OFFSET_BASETYPE (intype), + TYPE_OFFSET_BASETYPE (type), 0)) + && ! TREE_VIA_VIRTUAL (binfo)) + ok = 1; + } + else if (TREE_CODE (intype) != BOOLEAN_TYPE + && TREE_CODE (type) != ARRAY_TYPE + && TREE_CODE (type) != FUNCTION_TYPE + && can_convert (intype, type)) + ok = 1; + + if (ok) + return build_c_cast (type, expr); + + cp_error ("static_cast from `%T' to `%T'", intype, type); + return error_mark_node; } -tree build_reinterpret_cast (type, expr) +tree +build_reinterpret_cast (type, expr) tree type, expr; { - tree intype = TREE_TYPE (expr); + tree intype; - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); + if (type == error_mark_node || expr == error_mark_node) + return error_mark_node; - if (current_template_parms) + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); + + if (processing_template_decl) { tree t = build_min (REINTERPRET_CAST_EXPR, type, expr); return t; } - if (TYPE_PTRMEMFUNC_P (intype)) - intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + if (TREE_CODE (type) != REFERENCE_TYPE) + { + expr = decay_conversion (expr); + + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); + } - if (! POINTER_TYPE_P (type) && ! TREE_CODE (type) == INTEGER_TYPE) + if (type_unknown_p (expr)) { - cp_error ("reinterpret_cast cannot convert to type `%T'", type); - return error_mark_node; + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; } - if (! POINTER_TYPE_P (intype) && ! TREE_CODE (intype) == INTEGER_TYPE) + + intype = TREE_TYPE (expr); + + if (TREE_CODE (type) == REFERENCE_TYPE) { - cp_error ("reinterpret_cast cannot convert from type `%T'", type); - return error_mark_node; + if (! real_lvalue_p (expr)) + { + cp_error ("reinterpret_cast from `%T' rvalue to `%T'", intype, type); + return error_mark_node; + } + expr = build_unary_op (ADDR_EXPR, expr, 0); + if (expr != error_mark_node) + expr = build_reinterpret_cast + (build_pointer_type (TREE_TYPE (type)), expr); + if (expr != error_mark_node) + expr = build_indirect_ref (expr, 0); + return expr; } - if (TREE_CODE (type) == INTEGER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + else if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1)) + return build_static_cast (type, expr); + + if (TYPE_PTR_P (type) && (TREE_CODE (intype) == INTEGER_TYPE + || TREE_CODE (intype) == ENUMERAL_TYPE)) + /* OK */; + else if (TREE_CODE (type) == INTEGER_TYPE && TYPE_PTR_P (intype)) { - cp_error ("reinterpret_cast cannot convert non-pointer type `%T' to `%T'", - intype, type); - return error_mark_node; + if (TYPE_PRECISION (type) < TYPE_PRECISION (intype)) + cp_pedwarn ("reinterpret_cast from `%T' to `%T' loses precision", + intype, type); } - if (TREE_CODE (intype) == INTEGER_TYPE && TREE_CODE (type) != POINTER_TYPE) + else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype)) + || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype))) { - cp_error ("reinterpret_cast cannot convert `%T' to non-pointer type `%T'", - intype, type); - return error_mark_node; + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return fold (build1 (NOP_EXPR, type, expr)); } + else if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype)) + || (TYPE_PTROBV_P (type) && TYPE_PTROBV_P (intype))) + { + if (! comp_ptr_ttypes_reinterpret (TREE_TYPE (type), TREE_TYPE (intype))) + cp_pedwarn ("reinterpret_cast from `%T' to `%T' casts away const (or volatile)", + intype, type); - if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) == POINTER_TYPE) - expr = convert (ptr_type_node, expr); - - return build_c_cast (type, expr, 0); + if (TREE_READONLY_DECL_P (expr)) + expr = decl_constant_value (expr); + return fold (build1 (NOP_EXPR, type, expr)); + } + else + { + cp_error ("reinterpret_cast from `%T' to `%T'", intype, type); + return error_mark_node; + } + + return cp_convert (type, expr); } -tree build_const_cast (type, expr) +tree +build_const_cast (type, expr) tree type, expr; { - tree intype = TREE_TYPE (expr); - tree t1, t2; + tree intype; if (type == error_mark_node || expr == error_mark_node) return error_mark_node; - if (TYPE_PTRMEMFUNC_P (type)) - type = TYPE_PTRMEMFUNC_FN_TYPE (type); - if (TYPE_PTRMEMFUNC_P (intype)) - intype = TYPE_PTRMEMFUNC_FN_TYPE (intype); + if (TREE_CODE (expr) == OFFSET_REF) + expr = resolve_offset_ref (expr); - if (! POINTER_TYPE_P (type)) - { - cp_error ("const_cast cannot convert to non-pointer type `%T'", type); - return error_mark_node; - } - if (TREE_CODE (type) == REFERENCE_TYPE && ! real_lvalue_p (expr)) + if (processing_template_decl) { - cp_error ("const_cast cannot convert rvalue to type `%T'", type); - return error_mark_node; + tree t = build_min (CONST_CAST_EXPR, type, expr); + return t; } - if (TREE_CODE (type) == POINTER_TYPE && TREE_CODE (intype) != POINTER_TYPE) + + if (TREE_CODE (type) != REFERENCE_TYPE) { - cp_error ("const_cast cannot convert non-pointer type `%T' to type `%T'", - intype, type); - return error_mark_node; + expr = decay_conversion (expr); + + /* build_c_cast puts on a NOP_EXPR to make the result not an lvalue. + Strip such NOP_EXPRs if VALUE is being used in non-lvalue context. */ + if (TREE_CODE (expr) == NOP_EXPR + && TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0))) + expr = TREE_OPERAND (expr, 0); } - if (TREE_CODE (type) == REFERENCE_TYPE) + if (type_unknown_p (expr)) { - t1 = TREE_TYPE (type); - t2 = intype; + expr = instantiate_type (type, expr, 1); + if (expr == error_mark_node) + return error_mark_node; } - else - { - t1 = TREE_TYPE (type); - t2 = TREE_TYPE (intype); - for (; TREE_CODE (t1) == POINTER_TYPE && TREE_CODE (t2) == POINTER_TYPE; - t1 = TREE_TYPE (t1), t2 = TREE_TYPE (t2)) - ; - } + intype = TREE_TYPE (expr); - if (TREE_CODE (t1) == OFFSET_TYPE && TREE_CODE (t2) == OFFSET_TYPE) + if (comptypes (TYPE_MAIN_VARIANT (intype), TYPE_MAIN_VARIANT (type), 1)) + return build_static_cast (type, expr); + else if (TREE_CODE (type) == REFERENCE_TYPE) { - if (TYPE_OFFSET_BASETYPE (t1) != TYPE_OFFSET_BASETYPE (t2)) + if (! real_lvalue_p (expr)) { - cp_error ("const_cast cannot convert between pointers to members of different types `%T' and `%T'", - TYPE_OFFSET_BASETYPE (t2), TYPE_OFFSET_BASETYPE (t1)); + cp_error ("const_cast from `%T' rvalue to `%T'", intype, type); return error_mark_node; } - t1 = TREE_TYPE (t1); - t2 = TREE_TYPE (t2); - } - if (TYPE_MAIN_VARIANT (t1) != TYPE_MAIN_VARIANT (t2)) - { - cp_error ("const_cast cannot convert unrelated type `%T' to `%T'", - t2, t1); - return error_mark_node; + if (comp_ptr_ttypes_const (TREE_TYPE (type), intype)) + return (convert_from_reference + (convert_to_reference (type, expr, CONV_CONST|CONV_IMPLICIT, + LOOKUP_COMPLAIN, NULL_TREE))); } + else if (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (intype) == POINTER_TYPE + && comp_ptr_ttypes_const (TREE_TYPE (type), TREE_TYPE (intype))) + return cp_convert (type, expr); - return build_c_cast (type, expr, 0); + cp_error ("const_cast from `%T' to `%T'", intype, type); + return error_mark_node; } /* Build an expression representing a cast to type TYPE of expression EXPR. @@ -5130,10 +5423,8 @@ tree build_const_cast (type, expr) when doing the cast. */ tree -build_c_cast (type, expr, allow_nonconverting) - register tree type; - tree expr; - int allow_nonconverting; +build_c_cast (type, expr) + tree type, expr; { register tree value = expr; @@ -5183,13 +5474,7 @@ build_c_cast (type, expr, allow_nonconverting) return error_mark_node; } - /* If there's only one function in the overloaded space, - just take it. */ - if (TREE_CODE (value) == TREE_LIST - && TREE_CHAIN (value) == NULL_TREE) - value = TREE_VALUE (value); - - if (current_template_parms) + if (processing_template_decl) { tree t = build_min (CAST_EXPR, type, min_tree_cons (NULL_TREE, value, NULL_TREE)); @@ -5209,13 +5494,16 @@ build_c_cast (type, expr, allow_nonconverting) else { tree otype; - int flag; /* Convert functions and arrays to pointers and convert references to their expanded types, but don't convert any other types. */ if (TREE_CODE (TREE_TYPE (value)) == FUNCTION_TYPE - || TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE + || (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE + /* Don't do the default conversion if we want a + pointer to a function. */ + && ! (TREE_CODE (type) == POINTER_TYPE + && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) value = default_conversion (value); @@ -5263,11 +5551,9 @@ build_c_cast (type, expr, allow_nonconverting) warning ("cast to pointer from integer of different size"); #endif - flag = allow_nonconverting ? CONV_NONCONVERTING : 0; - if (TREE_CODE (type) == REFERENCE_TYPE) value = (convert_from_reference - (convert_to_reference (type, value, CONV_OLD_CONVERT|flag, + (convert_to_reference (type, value, CONV_C_CAST, LOOKUP_COMPLAIN, NULL_TREE))); else { @@ -5277,7 +5563,7 @@ build_c_cast (type, expr, allow_nonconverting) value = decl_constant_value (value); ovalue = value; - value = convert_force (type, value, flag); + value = convert_force (type, value, CONV_C_CAST); /* Ignore any integer overflow caused by the cast. */ if (TREE_CODE (value) == INTEGER_CST) @@ -5289,15 +5575,9 @@ build_c_cast (type, expr, allow_nonconverting) } /* Always produce some operator for an explicit cast, - so we can tell (for -pedantic) that the cast is no lvalue. - Also, pedantically, don't let (void *) (FOO *) 0 be a null - pointer constant. */ - if (TREE_CODE (type) != REFERENCE_TYPE - && (value == expr - || (pedantic - && TREE_CODE (value) == INTEGER_CST - && TREE_CODE (expr) == INTEGER_CST - && TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE))) + so we can tell (for -pedantic) that the cast is no lvalue. */ + if (TREE_CODE (type) != REFERENCE_TYPE && value == expr + && real_lvalue_p (value)) value = non_lvalue (value); return value; @@ -5323,7 +5603,7 @@ expand_target_expr (t) do_pending_stack_adjust (); start_sequence_for_rtl_expr (xval); emit_note (0, -1); - rtxval = expand_expr (t, NULL, VOIDmode, 0); + rtxval = expand_expr (t, NULL_RTX, VOIDmode, 0); do_pending_stack_adjust (); TREE_SIDE_EFFECTS (xval) = 1; RTL_EXPR_SEQUENCE (xval) = get_insns (); @@ -5342,8 +5622,8 @@ expand_target_expr (t) to combine the old value of LHS with RHS to get the new value. Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. - C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. -*/ + C++: If MODIFYCODE is INIT_EXPR, then leave references unbashed. */ + tree build_modify_expr (lhs, modifycode, rhs) tree lhs; @@ -5357,7 +5637,7 @@ build_modify_expr (lhs, modifycode, rhs) tree olhs = lhs; /* Avoid duplicate error messages from operands that had errors. */ - if (TREE_CODE (lhs) == ERROR_MARK || TREE_CODE (rhs) == ERROR_MARK) + if (lhs == error_mark_node || rhs == error_mark_node) return error_mark_node; /* Types that aren't fully specified cannot be used in assignments. */ @@ -5367,8 +5647,8 @@ build_modify_expr (lhs, modifycode, rhs) /* Handle assignment to signature pointers/refs. */ - if (TYPE_LANG_SPECIFIC (lhstype) && - (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype))) + if (TYPE_LANG_SPECIFIC (lhstype) + && (IS_SIGNATURE_POINTER (lhstype) || IS_SIGNATURE_REFERENCE (lhstype))) { return build_signature_pointer_constructor (lhs, rhs); } @@ -5382,7 +5662,8 @@ build_modify_expr (lhs, modifycode, rhs) case PREINCREMENT_EXPR: if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs), - stabilize_reference (TREE_OPERAND (lhs, 0))); + stabilize_reference (TREE_OPERAND (lhs, 0)), + TREE_OPERAND (lhs, 1)); return build (COMPOUND_EXPR, lhstype, lhs, build_modify_expr (TREE_OPERAND (lhs, 0), @@ -5392,14 +5673,14 @@ build_modify_expr (lhs, modifycode, rhs) case COMPOUND_EXPR: newrhs = build_modify_expr (TREE_OPERAND (lhs, 1), modifycode, rhs); - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; return build (COMPOUND_EXPR, lhstype, TREE_OPERAND (lhs, 0), newrhs); case MODIFY_EXPR: newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; return build (COMPOUND_EXPR, lhstype, lhs, newrhs); @@ -5412,18 +5693,18 @@ build_modify_expr (lhs, modifycode, rhs) so the code to compute it is only emitted once. */ tree cond = build_conditional_expr (TREE_OPERAND (lhs, 0), - build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)), + build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 1)), modifycode, rhs), - build_modify_expr (convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)), + build_modify_expr (cp_convert (TREE_TYPE (lhs), TREE_OPERAND (lhs, 2)), modifycode, rhs)); - if (TREE_CODE (cond) == ERROR_MARK) + if (cond == error_mark_node) return cond; /* Make sure the code to compute the rhs comes out before the split. */ return build (COMPOUND_EXPR, TREE_TYPE (lhs), /* Case to void to suppress warning from warn_if_unused_value. */ - convert (void_type_node, rhs), cond); + cp_convert (void_type_node, rhs), cond); } } @@ -5471,9 +5752,9 @@ build_modify_expr (lhs, modifycode, rhs) /* Do the default thing */; else { - result = build_method_call (lhs, constructor_name_full (lhstype), + result = build_method_call (lhs, ctor_identifier, build_tree_list (NULL_TREE, rhs), - NULL_TREE, LOOKUP_NORMAL); + TYPE_BINFO (lhstype), LOOKUP_NORMAL); if (result == NULL_TREE) return error_mark_node; return result; @@ -5492,10 +5773,8 @@ build_modify_expr (lhs, modifycode, rhs) else if (TYPE_HAS_TRIVIAL_ASSIGN_REF (lhstype) && TYPE_MAIN_VARIANT (lhstype) == TYPE_MAIN_VARIANT (TREE_TYPE (newrhs))) { - if (warn_synth) - /* If we care about this, do overload resolution. */ - build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, - lhs, rhs, make_node (NOP_EXPR)); + build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, + lhs, rhs, make_node (NOP_EXPR)); /* Do the default thing */; } @@ -5524,7 +5803,7 @@ build_modify_expr (lhs, modifycode, rhs) } else { - cp_error ("no match for `%O(%#T, %#T)'", modifycode, + cp_error ("no match for `%Q(%#T, %#T)'", modifycode, TREE_TYPE (lhs), TREE_TYPE (rhs)); return error_mark_node; } @@ -5533,6 +5812,12 @@ build_modify_expr (lhs, modifycode, rhs) { lhs = stabilize_reference (lhs); newrhs = build_binary_op (modifycode, lhs, rhs, 1); + if (newrhs == error_mark_node) + { + cp_error (" in evaluation of `%Q(%#T, %#T)'", modifycode, + TREE_TYPE (lhs), TREE_TYPE (rhs)); + return error_mark_node; + } } /* Handle a cast used as an "lvalue". @@ -5559,15 +5844,18 @@ build_modify_expr (lhs, modifycode, rhs) { tree inner_lhs = TREE_OPERAND (lhs, 0); tree result; - if (! lvalue_p (lhs) && pedantic) - pedwarn ("cast to non-reference type used as lvalue"); + + /* WP 5.4.1: The result is an lvalue if T is a reference type, + otherwise the result is an rvalue. */ + if (! lvalue_p (lhs)) + pedwarn ("ANSI C++ forbids cast to non-reference type used as lvalue"); result = build_modify_expr (inner_lhs, NOP_EXPR, - convert (TREE_TYPE (inner_lhs), - convert (lhstype, newrhs))); - if (TREE_CODE (result) == ERROR_MARK) + cp_convert (TREE_TYPE (inner_lhs), + cp_convert (lhstype, newrhs))); + if (result == error_mark_node) return result; - return convert (TREE_TYPE (lhs), result); + return cp_convert (TREE_TYPE (lhs), result); } } @@ -5618,7 +5906,7 @@ build_modify_expr (lhs, modifycode, rhs) } /* check to see if there is an assignment to `this' */ - if (lhs == current_class_decl) + if (lhs == current_class_ptr) { if (flag_this_is_variable > 0 && DECL_NAME (current_function_decl) != NULL_TREE @@ -5728,7 +6016,7 @@ build_modify_expr (lhs, modifycode, rhs) } else { - /* Avoid warnings on enum bit fields. */ + /* Avoid warnings on enum bit fields. */ if (TREE_CODE (olhstype) == ENUMERAL_TYPE && TREE_CODE (lhstype) == INTEGER_TYPE) { @@ -5749,10 +6037,10 @@ build_modify_expr (lhs, modifycode, rhs) expanded without a target. */ if (TREE_CODE (newrhs) == TARGET_EXPR) newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs, - TREE_VALUE (newrhs)); + TREE_OPERAND (newrhs, 0)); } - if (TREE_CODE (newrhs) == ERROR_MARK) + if (newrhs == error_mark_node) return error_mark_node; if (TREE_CODE (newrhs) == COND_EXPR) @@ -5783,11 +6071,11 @@ build_modify_expr (lhs, modifycode, rhs) result = build (COND_EXPR, result_type, cond, build_modify_expr (lhs, modifycode, - convert (result_type, - TREE_OPERAND (newrhs, 1))), + cp_convert (result_type, + TREE_OPERAND (newrhs, 1))), build_modify_expr (lhs1, modifycode, - convert (result_type, - TREE_OPERAND (newrhs, 2)))); + cp_convert (result_type, + TREE_OPERAND (newrhs, 2)))); } } else @@ -5804,7 +6092,7 @@ build_modify_expr (lhs, modifycode, rhs) if (olhstype == TREE_TYPE (result)) return result; /* Avoid warnings converting integral types back into enums - for enum bit fields. */ + for enum bit fields. */ if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE && TREE_CODE (olhstype) == ENUMERAL_TYPE) { @@ -5822,9 +6110,9 @@ build_x_modify_expr (lhs, modifycode, rhs) enum tree_code modifycode; tree rhs; { - if (current_template_parms) + if (processing_template_decl) return build_min_nt (MODOP_EXPR, lhs, - build_min_nt (modifycode, 0, 0), rhs); + build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs); if (modifycode != NOP_EXPR) { @@ -5849,6 +6137,7 @@ language_lvalue_valid (exp) /* Get difference in deltas for different pointer to member function types. Return integer_zero_node, if FROM cannot be converted to a TO type. If FORCE is true, then allow reverse conversions as well. */ + static tree get_delta_difference (from, to, force) tree from, to; @@ -5868,7 +6157,7 @@ get_delta_difference (from, to, force) binfo = get_binfo (from, to, 1); if (binfo == error_mark_node) { - error (" in pointer to member function conversion"); + error (" in pointer to member function conversiona"); return delta; } if (binfo == 0) @@ -5876,27 +6165,34 @@ get_delta_difference (from, to, force) if (!force) { error_not_base_type (from, to); - error (" in pointer to member function conversion"); + error (" in pointer to member conversion"); return delta; } binfo = get_binfo (to, from, 1); if (binfo == error_mark_node) { - error (" in pointer to member function conversion"); + if (!force) + error (" in pointer to member conversion"); return delta; } if (binfo == 0) { - error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); + if (!force) + cp_error ("cannot convert pointer to member of type %T to unrelated pointer to member of type %T", from, to); return delta; } if (TREE_VIA_VIRTUAL (binfo)) { + binfo = binfo_member (BINFO_TYPE (binfo), + CLASSTYPE_VBASECLASSES (from)); warning ("pointer to member conversion to virtual base class will only work if you are very careful"); } + delta = BINFO_OFFSET (binfo); + delta = cp_convert (ptrdiff_type_node, delta); + return build_binary_op (MINUS_EXPR, integer_zero_node, - BINFO_OFFSET (binfo), 1); + delta, 1); } if (TREE_VIA_VIRTUAL (binfo)) { @@ -5905,6 +6201,79 @@ get_delta_difference (from, to, force) return BINFO_OFFSET (binfo); } +static tree +build_ptrmemfunc1 (type, delta, idx, pfn, delta2) + tree type, delta, idx, pfn, delta2; +{ + tree u; + +#if 0 + /* This is the old way we did it. We want to avoid calling + digest_init, so that it can give an error if we use { } when + initializing a pointer to member function. */ + + if (pfn) + { + u = build_nt (CONSTRUCTOR, NULL_TREE, + tree_cons (pfn_identifier, pfn, NULL_TREE)); + } + else + { + u = build_nt (CONSTRUCTOR, NULL_TREE, + tree_cons (delta2_identifier, delta2, NULL_TREE)); + } + + u = build_nt (CONSTRUCTOR, NULL_TREE, + tree_cons (NULL_TREE, delta, + tree_cons (NULL_TREE, idx, + tree_cons (NULL_TREE, u, NULL_TREE)))); + + return digest_init (type, u, (tree*)0); +#else + tree delta_field, idx_field, pfn_or_delta2_field, pfn_field, delta2_field; + tree subtype; + int allconstant, allsimple; + + delta_field = TYPE_FIELDS (type); + idx_field = TREE_CHAIN (delta_field); + pfn_or_delta2_field = TREE_CHAIN (idx_field); + subtype = TREE_TYPE (pfn_or_delta2_field); + pfn_field = TYPE_FIELDS (subtype); + delta2_field = TREE_CHAIN (pfn_field); + + if (pfn) + { + allconstant = TREE_CONSTANT (pfn); + allsimple = initializer_constant_valid_p (pfn, TREE_TYPE (pfn)); + u = tree_cons (pfn_field, pfn, NULL_TREE); + } + else + { + delta2 = convert_and_check (delta_type_node, delta2); + allconstant = TREE_CONSTANT (delta2); + allsimple = initializer_constant_valid_p (delta2, TREE_TYPE (delta2)); + u = tree_cons (delta2_field, delta2, NULL_TREE); + } + + delta = convert_and_check (delta_type_node, delta); + idx = convert_and_check (delta_type_node, idx); + + allconstant = allconstant && TREE_CONSTANT (delta) && TREE_CONSTANT (idx); + allsimple = allsimple + && initializer_constant_valid_p (delta, TREE_TYPE (delta)) + && initializer_constant_valid_p (idx, TREE_TYPE (idx)); + + u = build (CONSTRUCTOR, subtype, NULL_TREE, u); + u = tree_cons (delta_field, delta, + tree_cons (idx_field, idx, + tree_cons (pfn_or_delta2_field, u, NULL_TREE))); + u = build (CONSTRUCTOR, type, NULL_TREE, u); + TREE_CONSTANT (u) = allconstant; + TREE_STATIC (u) = allconstant && allsimple; + return u; +#endif +} + /* Build a constructor for a pointer to member function. It can be used to initialize global variables, local variable, or used as a value in expressions. TYPE is the POINTER to METHOD_TYPE we @@ -5921,117 +6290,81 @@ build_ptrmemfunc (type, pfn, force) tree type, pfn; int force; { - tree index = integer_zero_node; + tree idx = integer_zero_node; tree delta = integer_zero_node; tree delta2 = integer_zero_node; tree vfield_offset; - tree npfn; - tree u; + tree npfn = NULL_TREE; - /* Handle multiple conversions of pointer to member functions. */ + /* Handle multiple conversions of pointer to member functions. */ if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) { - tree ndelta, ndelta2, nindex; + tree ndelta, ndelta2; + tree e1, e2, e3, n; + /* Is is already the right type? */ if (type == TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn))) return pfn; - if (TREE_CODE (pfn) != CONSTRUCTOR) - { - tree e1, e2, e3; - ndelta = convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, 0, 0)); - ndelta2 = convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn)); - index = build_component_ref (pfn, index_identifier, 0, 0); - delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))), - TYPE_METHOD_BASETYPE (TREE_TYPE (type)), - force); - delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1); - delta2 = build_binary_op (PLUS_EXPR, ndelta2, delta2, 1); - e1 = fold (build (GT_EXPR, boolean_type_node, index, integer_zero_node)); + ndelta = cp_convert (ptrdiff_type_node, build_component_ref (pfn, delta_identifier, NULL_TREE, 0)); + ndelta2 = cp_convert (ptrdiff_type_node, DELTA2_FROM_PTRMEMFUNC (pfn)); + idx = build_component_ref (pfn, index_identifier, NULL_TREE, 0); + + n = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))), + TYPE_METHOD_BASETYPE (TREE_TYPE (type)), + force); + + delta = build_binary_op (PLUS_EXPR, ndelta, n, 1); + delta2 = build_binary_op (PLUS_EXPR, ndelta2, n, 1); + e1 = fold (build (GT_EXPR, boolean_type_node, idx, integer_zero_node)); - u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE)); - u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, index, - tree_cons (NULL_TREE, u, NULL_TREE)))); - e2 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); + e2 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, + NULL_TREE, delta2); - pfn = PFN_FROM_PTRMEMFUNC (pfn); - npfn = build1 (NOP_EXPR, type, pfn); - TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn); + pfn = PFN_FROM_PTRMEMFUNC (pfn); + npfn = build1 (NOP_EXPR, type, pfn); + TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn); - u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE)); - u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, index, - tree_cons (NULL_TREE, u, NULL_TREE)))); - e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); - return build_conditional_expr (e1, e2, e3); - } - - ndelta = TREE_VALUE (CONSTRUCTOR_ELTS (pfn)); - nindex = TREE_VALUE (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn))); - npfn = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (CONSTRUCTOR_ELTS (pfn)))); - npfn = TREE_VALUE (CONSTRUCTOR_ELTS (npfn)); - if (integer_zerop (nindex)) - pfn = integer_zero_node; - else if (integer_zerop (fold (size_binop (PLUS_EXPR, nindex, integer_one_node)))) - { - tree e3; - delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (pfn)))), - TYPE_METHOD_BASETYPE (TREE_TYPE (type)), - force); - delta = build_binary_op (PLUS_EXPR, delta, ndelta, 1); - pfn = build1 (NOP_EXPR, type, npfn); - TREE_CONSTANT (pfn) = TREE_CONSTANT (npfn); - - u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE)); - u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, nindex, - tree_cons (NULL_TREE, u, NULL_TREE)))); - e3 = digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); - return e3; - } - else - { - sorry ("value casting of variable nonnull pointer to member functions not supported"); - return error_mark_node; - } + e3 = build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, + NULL_TREE); + return build_conditional_expr (e1, e2, e3); } - /* Handle null pointer to member function conversions. */ + /* Handle null pointer to member function conversions. */ if (integer_zerop (pfn)) { - pfn = build_c_cast (type, integer_zero_node, 0); - u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, pfn, NULL_TREE)); - u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, integer_zero_node, - tree_cons (NULL_TREE, integer_zero_node, - tree_cons (NULL_TREE, u, NULL_TREE)))); - return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); + pfn = build_c_cast (type, integer_zero_node); + return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), + integer_zero_node, integer_zero_node, + pfn, NULL_TREE); } if (TREE_CODE (pfn) == TREE_LIST || (TREE_CODE (pfn) == ADDR_EXPR && TREE_CODE (TREE_OPERAND (pfn, 0)) == TREE_LIST)) - { - pfn = instantiate_type (type, pfn, 1); - if (pfn == error_mark_node) - return error_mark_node; - if (TREE_CODE (pfn) != ADDR_EXPR) - pfn = build_unary_op (ADDR_EXPR, pfn, 0); - } + return instantiate_type (type, pfn, 1); - /* Allow pointer to member conversions here. */ + /* Allow pointer to member conversions here. */ delta = get_delta_difference (TYPE_METHOD_BASETYPE (TREE_TYPE (TREE_TYPE (pfn))), TYPE_METHOD_BASETYPE (TREE_TYPE (type)), force); delta2 = build_binary_op (PLUS_EXPR, delta2, delta, 1); +#if 0 + /* We need to check the argument types to see if they are compatible + (any const or volatile violations. */ + something like this: + comptype (TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (type))), + TREE_VALUE (TYPE_ARG_TYPES (TREE_TYPE (TREE_TYPE (pfn)))), ?); +#endif + if (TREE_CODE (TREE_OPERAND (pfn, 0)) != FUNCTION_DECL) warning ("assuming pointer to member function is non-virtual"); if (TREE_CODE (TREE_OPERAND (pfn, 0)) == FUNCTION_DECL && DECL_VINDEX (TREE_OPERAND (pfn, 0))) { - /* Find the offset to the vfield pointer in the object. */ + /* Find the offset to the vfield pointer in the object. */ vfield_offset = get_binfo (DECL_CONTEXT (TREE_OPERAND (pfn, 0)), DECL_CLASS_CONTEXT (TREE_OPERAND (pfn, 0)), 0); @@ -6039,25 +6372,26 @@ build_ptrmemfunc (type, pfn, force) delta2 = size_binop (PLUS_EXPR, vfield_offset, delta2); /* Map everything down one to make room for the null pointer to member. */ - index = size_binop (PLUS_EXPR, - DECL_VINDEX (TREE_OPERAND (pfn, 0)), - integer_one_node); - u = build_nt (CONSTRUCTOR, 0, tree_cons (delta2_identifier, delta2, NULL_TREE)); + idx = size_binop (PLUS_EXPR, + DECL_VINDEX (TREE_OPERAND (pfn, 0)), + integer_one_node); } else { - index = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node); - - npfn = build1 (NOP_EXPR, type, pfn); - TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn); + idx = size_binop (MINUS_EXPR, integer_zero_node, integer_one_node); - u = build_nt (CONSTRUCTOR, 0, tree_cons (pfn_identifier, npfn, NULL_TREE)); + if (type == TREE_TYPE (pfn)) + { + npfn = pfn; + } + else + { + npfn = build1 (NOP_EXPR, type, pfn); + TREE_CONSTANT (npfn) = TREE_CONSTANT (pfn); + } } - u = build_nt (CONSTRUCTOR, 0, tree_cons (NULL_TREE, delta, - tree_cons (NULL_TREE, index, - tree_cons (NULL_TREE, u, NULL_TREE)))); - return digest_init (TYPE_GET_PTRMEMFUNC_TYPE (type), u, (tree*)0); + return build_ptrmemfunc1 (TYPE_GET_PTRMEMFUNC_TYPE (type), delta, idx, npfn, delta2); } /* Convert value RHS to type TYPE as preparation for an assignment @@ -6143,8 +6477,10 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return error_mark_node; } /* Arithmetic types all interconvert. */ - if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE) - && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE)) + if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE + || codel == COMPLEX_TYPE) + && (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE + || coder == COMPLEX_TYPE)) { /* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */ if (coder == REAL_TYPE && codel == INTEGER_TYPE) @@ -6182,7 +6518,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) || (coder == ENUMERAL_TYPE && (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE))) { - return cp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL); + return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL); } /* Conversions among pointers */ else if (codel == POINTER_TYPE @@ -6258,13 +6594,13 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return error_mark_node; } - if (ctt < 0) + if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr)) cp_pedwarn ("converting `%T' to `%T' is a contravariance violation", rhstype, type); if (TYPE_MAIN_VARIANT (ttl) != void_type_node && TYPE_MAIN_VARIANT (ttr) == void_type_node - && rhs != null_pointer_node) + && ! null_ptr_cst_p (rhs)) { if (coder == RECORD_TYPE) cp_pedwarn ("implicit conversion of signature pointer to type `%T'", @@ -6315,31 +6651,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } } } - else if (TREE_CODE (ttr) == OFFSET_TYPE - && TREE_CODE (ttl) != OFFSET_TYPE) - { - /* Normally, pointers to different type codes (other - than void) are not compatible, but we perform - some type instantiation if that resolves the - ambiguity of (X Y::*) and (X *). */ - - if (current_class_decl) - { - if (TREE_CODE (rhs) == INTEGER_CST) - { - rhs = build (PLUS_EXPR, build_pointer_type (TREE_TYPE (ttr)), - current_class_decl, rhs); - return convert_for_assignment (type, rhs, - errtype, fndecl, parmnum); - } - } - if (TREE_CODE (ttl) == METHOD_TYPE) - error ("%s between pointer-to-method and pointer-to-member types", - errtype); - else - error ("%s between pointer and pointer-to-member types", errtype); - return error_mark_node; - } else { int add_quals = 0, const_parity = 0, volatile_parity = 0; @@ -6431,24 +6742,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) cp_warning ("\t`%T' != `%T'", type, rhstype); } } - else if (TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE) - { - /* When does this happen? */ - my_friendly_abort (119); - /* Conversion of a pointer-to-member type to void *. */ - rhs = build_unary_op (ADDR_EXPR, rhs, 0); - TREE_TYPE (rhs) = type; - return rhs; - } - else if (TREE_CODE (TREE_TYPE (rhs)) == OFFSET_TYPE) - { - /* When does this happen? */ - my_friendly_abort (120); - /* Conversion of a pointer-to-member type to void *. */ - rhs = build_unary_op (ADDR_EXPR, rhs, 0); - TREE_TYPE (rhs) = type; - return rhs; - } else { if (fndecl) @@ -6459,7 +6752,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return error_mark_node; } } - return convert (type, rhs); + return cp_convert (type, rhs); } else if (codel == POINTER_TYPE && coder == INTEGER_TYPE) { @@ -6473,9 +6766,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) else cp_pedwarn ("%s to `%T' from `%T' lacks a cast", errtype, type, rhstype); - return convert (type, rhs); } - return null_pointer_node; + return cp_convert (type, rhs); } else if (codel == INTEGER_TYPE && (coder == POINTER_TYPE @@ -6490,7 +6782,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) else cp_pedwarn ("%s to `%T' from `%T' lacks a cast", errtype, type, rhstype); - return convert (type, rhs); + return cp_convert (type, rhs); } else if (codel == BOOLEAN_TYPE && (coder == POINTER_TYPE @@ -6498,7 +6790,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) && (IS_SIGNATURE_POINTER (rhstype) || TYPE_PTRMEMFUNC_FLAG (rhstype) || IS_SIGNATURE_REFERENCE (rhstype))))) - return convert (type, rhs); + return cp_convert (type, rhs); /* C++ */ else if (((coder == POINTER_TYPE @@ -6518,7 +6810,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) else if (ctt == 0) cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr); - /* compatible pointer to member functions. */ + /* compatible pointer to member functions. */ return build_ptrmemfunc (ttl, rhs, 0); } else if (codel == ERROR_MARK || coder == ERROR_MARK) @@ -6536,7 +6828,14 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) return nrhs; } else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs))) - return convert (type, rhs); + return cp_convert (type, rhs); + /* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */ + else if (TREE_CODE (type) == POINTER_TYPE + && (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE + || TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node) + && TREE_TYPE (rhs) + && TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs))) + return cp_convert (type, rhs); cp_error ("%s to `%T' from `%T'", errtype, type, rhstype); return error_mark_node; @@ -6557,6 +6856,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) exist, an ambiguity exists. If flags doesn't include LOOKUP_COMPLAIN, don't complain about anything. */ + tree convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) tree exp, type, rhs; @@ -6645,6 +6945,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) if (TREE_CODE (rhstype) == REFERENCE_TYPE) rhstype = TREE_TYPE (rhstype); + type = complete_type (type); + if (TYPE_LANG_SPECIFIC (type) && (IS_SIGNATURE_POINTER (type) || IS_SIGNATURE_REFERENCE (type))) return build_signature_pointer_constructor (type, rhs); @@ -6652,6 +6954,9 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) if (IS_AGGR_TYPE (type) && (TYPE_NEEDS_CONSTRUCTING (type) || TREE_HAS_CONSTRUCTOR (rhs))) { + if (flag_ansi_overloading) + return ocp_convert (type, rhs, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); + if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype)) { /* This is sufficient to perform initialization. No need, @@ -6688,7 +6993,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) { if (TYPE_HAS_INIT_REF (type)) { - tree init = build_method_call (exp, constructor_name_full (type), + tree init = build_method_call (exp, ctor_identifier, build_tree_list (NULL_TREE, rhs), TYPE_BINFO (type), LOOKUP_NORMAL); @@ -6721,7 +7026,8 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) return rhs; } - return cp_convert (type, rhs, CONV_OLD_CONVERT, flags); + return ocp_convert (type, rhs, CONV_OLD_CONVERT, + flags | LOOKUP_NO_CONVERSION); } if (type == TREE_TYPE (rhs)) @@ -6810,7 +7116,6 @@ c_expand_return (retval) extern tree dtor_label, ctor_label; tree result = DECL_RESULT (current_function_decl); tree valtype = TREE_TYPE (result); - int returns_value = 1; if (TREE_THIS_VOLATILE (current_function_decl)) warning ("function declared `noreturn' has a `return' statement"); @@ -6821,7 +7126,7 @@ c_expand_return (retval) return; } - if (current_template_parms) + if (processing_template_decl) { add_tree (build_min_nt (RETURN_STMT, retval)); return; @@ -6839,7 +7144,7 @@ c_expand_return (retval) } if (DECL_CONSTRUCTOR_P (current_function_decl)) - retval = current_class_decl; + retval = current_class_ptr; else if (DECL_NAME (result) != NULL_TREE && TREE_CODE (valtype) != VOID_TYPE) retval = result; @@ -6864,22 +7169,29 @@ c_expand_return (retval) } } else if (DECL_CONSTRUCTOR_P (current_function_decl) - && retval != current_class_decl) + && retval != current_class_ptr) { - error ("return from a constructor: use `this = ...' instead"); - retval = current_class_decl; + if (flag_this_is_variable) + error ("return from a constructor: use `this = ...' instead"); + else + error ("return from a constructor"); + retval = current_class_ptr; } + /* Effective C++ rule 15. See also start_function. */ + if (warn_ecpp + && DECL_NAME (current_function_decl) == ansi_opname[(int) MODIFY_EXPR] + && retval != current_class_ref) + cp_warning ("`operator=' should return a reference to `*this'"); + if (valtype == NULL_TREE || TREE_CODE (valtype) == VOID_TYPE) { current_function_returns_null = 1; - /* We do this here so we'll avoid a warning about how the function - "may or may not return a value" in finish_function. */ - returns_value = 0; - - if (retval) + if ((pedantic && ! DECL_ARTIFICIAL (current_function_decl)) + || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE) pedwarn ("`return' with a value, in function returning void"); expand_return (retval); + return; } /* Add some useful error checking for C++. */ else if (TREE_CODE (valtype) == REFERENCE_TYPE) @@ -6896,9 +7208,9 @@ c_expand_return (retval) /* convert to reference now, so we can give error if we return an reference to a non-lvalue. */ - retval = convert_for_initialization (tmp_result, valtype, retval, - LOOKUP_NORMAL, "return", - NULL_TREE, 0); + retval = convert_for_initialization + (tmp_result, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, + "return", NULL_TREE, 0); /* Sort through common things to see what it is we are returning. */ @@ -6909,6 +7221,8 @@ c_expand_return (retval) if (TREE_CODE (whats_returned) == ADDR_EXPR) whats_returned = TREE_OPERAND (whats_returned, 0); } + if (TREE_CODE (whats_returned) == CONVERT_EXPR) + whats_returned = TREE_OPERAND (whats_returned, 0); if (TREE_CODE (whats_returned) == ADDR_EXPR) { whats_returned = TREE_OPERAND (whats_returned, 0); @@ -6942,6 +7256,15 @@ c_expand_return (retval) && !TREE_PUBLIC (whats_returned)) cp_warning_at ("address of local variable `%D' returned", whats_returned); } + else if (TREE_CODE (retval) == VAR_DECL) + { + if (TREE_CODE (TREE_TYPE (retval)) == ARRAY_TYPE + && DECL_NAME (retval) + && IDENTIFIER_LOCAL_VALUE (DECL_NAME (retval)) + && !TREE_STATIC (retval) + && !TREE_PUBLIC (retval)) + cp_warning_at ("address of local array `%D' returned", retval); + } /* Now deal with possible C++ hair: (1) Compute the return value. @@ -6951,141 +7274,56 @@ c_expand_return (retval) (3) If an X(X&) constructor is defined, the return value must be returned via that. */ - /* If we're returning in a register, we can't initialize the - return value from a TARGET_EXPR. */ - if (TREE_CODE (retval) == TARGET_EXPR - && TYPE_MAIN_VARIANT (TREE_TYPE (retval)) == TYPE_MAIN_VARIANT (valtype) - && ! current_function_returns_struct) - retval = expand_target_expr (retval); - if (retval == result - /* Watch out for constructors, which "return" aggregates - via initialization, but which otherwise "return" a pointer. */ || DECL_CONSTRUCTOR_P (current_function_decl)) + /* It's already done for us. */; + else if (TREE_TYPE (retval) == void_type_node) { - /* This is just an error--it's already been reported. */ - if (TYPE_SIZE (valtype) == NULL_TREE) - return; - - if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - retval = get_temp_regvar (valtype, retval); - } - else if (IS_AGGR_TYPE (valtype) && current_function_returns_struct) - { - expand_aggr_init (result, retval, 0, LOOKUP_ONLYCONVERTING); - expand_cleanups_to (NULL_TREE); - DECL_INITIAL (result) = NULL_TREE; + pedwarn ("return of void value in function returning non-void"); + expand_expr_stmt (retval); retval = 0; } else { - if (TYPE_MODE (valtype) == VOIDmode) - { - if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode - && warn_return_type) - warning ("return of void value in function returning non-void"); - expand_expr_stmt (retval); - retval = 0; - result = 0; - } - else if (TYPE_MODE (valtype) != BLKmode - && any_pending_cleanups (1)) - { - retval = get_temp_regvar (valtype, retval); - expand_cleanups_to (NULL_TREE); - result = 0; - } - else + /* We already did this above for refs, don't do it again. */ + if (TREE_CODE (valtype) != REFERENCE_TYPE) + retval = convert_for_initialization + (NULL_TREE, valtype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, + "return", NULL_TREE, 0); + + /* We can't initialize a register from a NEW_EXPR. */ + if (! current_function_returns_struct + && TREE_CODE (retval) == TARGET_EXPR + && TREE_CODE (TREE_OPERAND (retval, 1)) == NEW_EXPR) + retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval, + TREE_OPERAND (retval, 0)); + + if (retval == error_mark_node) { - retval = convert_for_initialization (result, valtype, retval, - LOOKUP_NORMAL, - "return", NULL_TREE, 0); - DECL_INITIAL (result) = NULL_TREE; + /* Avoid warning about control reaching end of function. */ + expand_null_return (); + return; } - if (retval == error_mark_node) - return; } - emit_queue (); - if (retval != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (retval)) == 'd' && cond_stack == 0 && loop_stack == 0 && case_stack == 0) current_function_return_value = retval; - if (result) + if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) { - /* Everything's great--RETVAL is in RESULT. */ - if (original_result_rtx) - { - store_expr (result, original_result_rtx, 0); - expand_cleanups_to (NULL_TREE); - use_variable (DECL_RTL (result)); - if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - expand_goto (ctor_label); - else - expand_null_return (); - } - else if (retval && retval != result) - { - /* Clear this out so the later call to decl_function_context - won't end up bombing on us. */ - if (DECL_CONTEXT (result) == error_mark_node) - DECL_CONTEXT (result) = NULL_TREE; - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - retval = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (result), - retval)); - /* This part _must_ come second, because expand_return looks for - the INIT_EXPR as the toplevel node only. :-( */ - retval = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (retval) = 1; - expand_return (retval); - } - else - expand_return (result); + /* Here RETVAL is CURRENT_CLASS_PTR, so there's nothing to do. */ + expand_goto (ctor_label); } - else + + if (retval && retval != result) { - /* We may still need to put RETVAL into RESULT. */ - result = DECL_RESULT (current_function_decl); - if (original_result_rtx) - { - /* Here we have a named return value that went - into memory. We can compute RETVAL into that. */ - if (retval) - expand_assignment (result, retval, 0, 0); - else - store_expr (result, original_result_rtx, 0); - result = make_tree (TREE_TYPE (result), original_result_rtx); - } - else if (ctor_label && TREE_CODE (ctor_label) != ERROR_MARK) - { - /* Here RETVAL is CURRENT_CLASS_DECL, so there's nothing to do. */ - expand_goto (ctor_label); - } - else if (retval) - { - /* Here is where we finally get RETVAL into RESULT. - `expand_return' does the magic of protecting - RESULT from cleanups. */ - result = build (INIT_EXPR, TREE_TYPE (result), result, retval); - TREE_SIDE_EFFECTS (result) = 1; - expand_return (result); - } - else if (TYPE_MODE (TREE_TYPE (result)) != VOIDmode) - expand_return (result); + result = build (INIT_EXPR, TREE_TYPE (result), result, retval); + TREE_SIDE_EFFECTS (result) = 1; } - - current_function_returns_value = returns_value; - - /* One way to clear out cleanups that EXPR might - generate. Note that this code will really be - dead code, but that is ok--cleanups that were - needed were handled by the magic of `return'. */ - expand_cleanups_to (NULL_TREE); + expand_return (result); + current_function_returns_value = 1; } /* Start a C switch statement, testing expression EXP. @@ -7121,18 +7359,18 @@ c_expand_start_case (exp) } else { - tree index; + tree idx; exp = default_conversion (exp); type = TREE_TYPE (exp); - index = get_unwidened (exp, 0); + idx = get_unwidened (exp, 0); /* We can't strip a conversion from a signed type to an unsigned, because if we did, int_fits_type_p would do the wrong thing when checking case values for being in range, and it's too hard to do the right thing. */ if (TREE_UNSIGNED (TREE_TYPE (exp)) - == TREE_UNSIGNED (TREE_TYPE (index))) - exp = index; + == TREE_UNSIGNED (TREE_TYPE (idx))) + exp = idx; } expand_start_case @@ -7144,7 +7382,8 @@ c_expand_start_case (exp) /* CONSTP remembers whether or not all the intervening pointers in the `to' type have been const. */ -int + +static int comp_ptr_ttypes_real (to, from, constp) tree to, from; int constp; @@ -7154,6 +7393,11 @@ comp_ptr_ttypes_real (to, from, constp) if (TREE_CODE (to) != TREE_CODE (from)) return 0; + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (from), + TYPE_OFFSET_BASETYPE (to), 1)) + continue; + /* Const and volatile mean something different for function types, so the usual checks are not appropriate. */ if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) @@ -7177,9 +7421,92 @@ comp_ptr_ttypes_real (to, from, constp) /* When comparing, say, char ** to char const **, this function takes the 'char *' and 'char const *'. Do not pass non-pointer types to this function. */ + int comp_ptr_ttypes (to, from) tree to, from; { return comp_ptr_ttypes_real (to, from, 1); } + +/* Returns 1 if to and from are (possibly multi-level) pointers to the same + type or inheritance-related types, regardless of cv-quals. */ + +int +ptr_reasonably_similar (to, from) + tree to, from; +{ + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (to) != TREE_CODE (from)) + return 0; + + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (to), + TYPE_OFFSET_BASETYPE (from), -1)) + continue; + + if (TREE_CODE (to) != POINTER_TYPE) + return comptypes + (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), -1); + } +} + +/* Like comp_ptr_ttypes, for const_cast. */ + +static int +comp_ptr_ttypes_const (to, from) + tree to, from; +{ + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (to) != TREE_CODE (from)) + return 0; + + if (TREE_CODE (from) == OFFSET_TYPE + && comptypes (TYPE_OFFSET_BASETYPE (from), + TYPE_OFFSET_BASETYPE (to), 1)) + continue; + + if (TREE_CODE (to) != POINTER_TYPE) + return comptypes (TYPE_MAIN_VARIANT (to), TYPE_MAIN_VARIANT (from), 1); + } +} + +/* Like comp_ptr_ttypes, for reinterpret_cast. */ + +static int +comp_ptr_ttypes_reinterpret (to, from) + tree to, from; +{ + int constp = 1; + + for (; ; to = TREE_TYPE (to), from = TREE_TYPE (from)) + { + if (TREE_CODE (from) == OFFSET_TYPE) + from = TREE_TYPE (from); + if (TREE_CODE (to) == OFFSET_TYPE) + to = TREE_TYPE (to); + + if (TREE_CODE (to) != TREE_CODE (from)) + return 1; + + /* Const and volatile mean something different for function types, + so the usual checks are not appropriate. */ + if (TREE_CODE (to) != FUNCTION_TYPE && TREE_CODE (to) != METHOD_TYPE) + { + if (TYPE_READONLY (from) > TYPE_READONLY (to) + || TYPE_VOLATILE (from) > TYPE_VOLATILE (to)) + return 0; + + if (! constp + && (TYPE_READONLY (to) > TYPE_READONLY (from) + || TYPE_VOLATILE (to) > TYPE_READONLY (from))) + return 0; + constp &= TYPE_READONLY (to); + } + + if (TREE_CODE (to) != POINTER_TYPE) + return 1; + } +}