X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fcp%2Ftypeck.c;h=21068b321eb20930bf5cc8385ace55fbd754ebd9;hb=d19bc3a3c77d3458c5ac967d3a6fe47125762b98;hp=09ecd66b4ad1ca2044ec5bea0f1ffbf4a02b82d2;hpb=6c0cc2cd712aa7e0b91176c5aa3dd74abd200407;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 09ecd66b4ad..21068b321eb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1,22 +1,22 @@ /* Build expressions with type checking for C++ compiler. Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc. Hacked by Michael Tiemann (tiemann@cygnus.com) -This file is part of GNU CC. +This file is part of GCC. -GNU CC is free software; you can redistribute it and/or modify +GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. -GNU CC is distributed in the hope that it will be useful, +GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GNU CC; see the file COPYING. If not, write to +along with GCC; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ @@ -32,6 +32,8 @@ Boston, MA 02111-1307, USA. */ #include "config.h" #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "tree.h" #include "rtl.h" #include "expr.h" @@ -64,6 +66,7 @@ static void casts_away_constness_r PARAMS ((tree *, tree *)); static int casts_away_constness PARAMS ((tree, tree)); static void maybe_warn_about_returning_address_of_local PARAMS ((tree)); static tree strip_all_pointer_quals PARAMS ((tree)); +static tree lookup_destructor (tree, tree, tree); /* Return the target type of TYPE, which means return T for: T*, T&, T[], T (...), and otherwise, just T. */ @@ -155,16 +158,16 @@ complete_type (type) return type; } -/* Like complete_type, but issue an error if the TYPE cannot be - completed. VALUE is used for informative diagnostics. WARN_ONLY - will cause a warning message to be printed, instead of an error. +/* Like complete_type, but issue an error if the TYPE cannot be completed. + VALUE is used for informative diagnostics. DIAG_TYPE indicates the type + of diagnostic: 0 for an error, 1 for a warning, 2 for a pedwarn. Returns NULL_TREE if the type cannot be made complete. */ tree -complete_type_or_diagnostic (type, value, warn_only) +complete_type_or_diagnostic (type, value, diag_type) tree type; tree value; - int warn_only; + int diag_type; { type = complete_type (type); if (type == error_mark_node) @@ -172,7 +175,7 @@ complete_type_or_diagnostic (type, value, warn_only) return NULL_TREE; else if (!COMPLETE_TYPE_P (type)) { - cxx_incomplete_type_diagnostic (value, type, warn_only); + cxx_incomplete_type_diagnostic (value, type, diag_type); return NULL_TREE; } else @@ -203,28 +206,33 @@ qualify_type_recursive (t1, t2) if ((TYPE_PTR_P (t1) && TYPE_PTR_P (t2)) || (TYPE_PTRMEM_P (t1) && TYPE_PTRMEM_P (t2))) { - tree tt1 = TREE_TYPE (t1); - tree tt2 = TREE_TYPE (t2); + tree tt1; + tree tt2; tree b1; int type_quals; tree tgt; tree attributes = (*targetm.merge_type_attributes) (t1, t2); - if (TREE_CODE (tt1) == OFFSET_TYPE) + if (TYPE_PTRMEM_P (t1)) { - b1 = TYPE_OFFSET_BASETYPE (tt1); - tt1 = TREE_TYPE (tt1); - tt2 = TREE_TYPE (tt2); + b1 = TYPE_PTRMEM_CLASS_TYPE (t1); + tt1 = TYPE_PTRMEM_POINTED_TO_TYPE (t1); + tt2 = TYPE_PTRMEM_POINTED_TO_TYPE (t2); } else - b1 = NULL_TREE; + { + b1 = NULL_TREE; + tt1 = TREE_TYPE (t1); + tt2 = TREE_TYPE (t2); + } type_quals = (cp_type_quals (tt1) | cp_type_quals (tt2)); tgt = qualify_type_recursive (tt1, tt2); tgt = cp_build_qualified_type (tgt, type_quals); if (b1) - tgt = build_offset_type (b1, tgt); - t1 = build_pointer_type (tgt); + t1 = build_ptrmem_type (b1, tgt); + else + t1 = build_pointer_type (tgt); t1 = build_type_attribute_variant (t1, attributes); } return t1; @@ -486,7 +494,7 @@ composite_pointer_type (t1, t2, arg1, arg2, location) return t1; /* Deal with pointer-to-member functions in the same way as we deal - with pointers to functions. */ + with pointers to functions. */ if (TYPE_PTRMEMFUNC_P (t1)) t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1); if (TYPE_PTRMEMFUNC_P (t2)) @@ -795,11 +803,11 @@ comp_except_specs (t1, t2, exact) if (t1 == t2) return 1; - if (t1 == NULL_TREE) /* T1 is ... */ + if (t1 == NULL_TREE) /* T1 is ... */ return t2 == NULL_TREE || !exact; if (!TREE_VALUE (t1)) /* t1 is EMPTY */ return t2 != NULL_TREE && !TREE_VALUE (t2); - if (t2 == NULL_TREE) /* T2 is ... */ + if (t2 == NULL_TREE) /* T2 is ... */ return 0; if (TREE_VALUE (t1) && !TREE_VALUE (t2)) /* T2 is EMPTY, T1 is not */ return !exact; @@ -938,6 +946,13 @@ comptypes (t1, t2, strict) if (TYPE_PTRMEMFUNC_P (t2)) t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2); + /* TYPENAME_TYPEs should be resolved if the qualifying scope is the + current instantiation. */ + if (TREE_CODE (t1) == TYPENAME_TYPE) + t1 = resolve_typename_type_in_current_instantiation (t1); + if (TREE_CODE (t2) == TYPENAME_TYPE) + t2 = resolve_typename_type_in_current_instantiation (t2); + /* Different classes of types can't be compatible. */ if (TREE_CODE (t1) != TREE_CODE (t2)) return 0; @@ -956,11 +971,9 @@ comptypes (t1, t2, strict) if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2)) return 1; - if (strict & COMPARE_NO_ATTRIBUTES) - attrval = 1; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ - else if (! (attrval = (*targetm.comp_type_attributes) (t1, t2))) - return 0; + if (! (attrval = (*targetm.comp_type_attributes) (t1, t2))) + return 0; /* 1 if no need for warning yet, 2 if warning cause has been seen. */ val = 0; @@ -1806,7 +1819,7 @@ lookup_anon_field (t, type) { if (TREE_STATIC (field)) continue; - if (TREE_CODE (field) != FIELD_DECL) + if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) continue; /* If we find it directly, return the field. */ @@ -1851,6 +1864,9 @@ build_class_member_access_expr (tree object, tree member, if (object == error_mark_node || member == error_mark_node) return error_mark_node; + if (TREE_CODE (member) == PSEUDO_DTOR_EXPR) + return member; + my_friendly_assert (DECL_P (member) || BASELINK_P (member), 20020801); @@ -1893,6 +1909,15 @@ build_class_member_access_expr (tree object, tree member, return error_mark_node; } + /* Transform `(a, b).x' into `(*(a, &b)).x', `(a ? b : c).x' into + `(*(a ? &b : &c)).x', and so on. A COND_EXPR is only an lvalue + in the frontend; only _DECLs and _REFs are lvalues in the backend. */ + { + tree temp = unary_complex_lvalue (ADDR_EXPR, object); + if (temp) + object = build_indirect_ref (temp, NULL); + } + /* In [expr.ref], there is an explicit list of the valid choices for MEMBER. We check for each of those cases here. */ if (TREE_CODE (member) == VAR_DECL) @@ -1914,7 +1939,8 @@ build_class_member_access_expr (tree object, tree member, && integer_zerop (TREE_OPERAND (object, 0))); /* Convert OBJECT to the type of MEMBER. */ - if (!same_type_p (object_type, member_scope)) + if (!same_type_p (TYPE_MAIN_VARIANT (object_type), + TYPE_MAIN_VARIANT (member_scope))) { tree binfo; base_kind kind; @@ -1924,7 +1950,7 @@ build_class_member_access_expr (tree object, tree member, if (binfo == error_mark_node) return error_mark_node; - /* It is invalid to use to try to get to a virtual base of a + /* It is invalid to try to get to a virtual base of a NULL object. The most common cause is invalid use of offsetof macro. */ if (null_object_p && kind == bk_via_virtual) @@ -1943,9 +1969,13 @@ build_class_member_access_expr (tree object, tree member, my_friendly_assert (object != error_mark_node, 20020801); } - - /* Issue a warning about access a member of a NULL object. */ - if (null_object_p && CLASSTYPE_NON_POD_P (object_type)) + + /* Complain about other invalid uses of offsetof, even though they will + give the right answer. Note that we complain whether or not they + actually used the offsetof macro, since there's no way to know at this + point. So we just give a warning, instead of a pedwarn. */ + if (null_object_p && warn_invalid_offsetof + && CLASSTYPE_NON_POD_P (object_type)) { warning ("invalid access to non-static data member `%D' of NULL object", member); @@ -1956,7 +1986,15 @@ build_class_member_access_expr (tree object, tree member, OBJECT so that it refers to the class containing the anonymous union. Generate a reference to the anonymous union itself, and recur to find MEMBER. */ - if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member))) + if (ANON_AGGR_TYPE_P (DECL_CONTEXT (member)) + /* When this code is called from build_field_call, the + object already has the type of the anonymous union. + That is because the COMPONENT_REF was already + constructed, and was then disassembled before calling + build_field_call. After the function-call code is + cleaned up, this waste can be eliminated. */ + && (!same_type_ignoring_top_level_qualifiers_p + (TREE_TYPE (object), DECL_CONTEXT (member)))) { tree anonymous_union; @@ -1998,6 +2036,7 @@ build_class_member_access_expr (tree object, tree member, { /* The member is a (possibly overloaded) member function. */ tree functions; + tree type; /* If the MEMBER is exactly one static member function, then we know the type of the expression. Otherwise, we must wait @@ -2005,19 +2044,12 @@ build_class_member_access_expr (tree object, tree member, functions = BASELINK_FUNCTIONS (member); if (TREE_CODE (functions) == FUNCTION_DECL && DECL_STATIC_FUNCTION_P (functions)) - { - /* A static member function. */ - result = functions; - mark_used (result); - /* If OBJECT has side-effects, they are supposed to occur. */ - if (TREE_SIDE_EFFECTS (object)) - result = build (COMPOUND_EXPR, TREE_TYPE (result), - object, result); - } + type = TREE_TYPE (functions); else - /* Note that we do not convert OBJECT to the BASELINK_BINFO - base. That will happen when the function is called. */ - result = build (COMPONENT_REF, unknown_type_node, object, member); + type = unknown_type_node; + /* Note that we do not convert OBJECT to the BASELINK_BINFO + base. That will happen when the function is called. */ + result = build (COMPONENT_REF, type, object, member); } else if (TREE_CODE (member) == CONST_DECL) { @@ -2044,6 +2076,34 @@ build_class_member_access_expr (tree object, tree member, return result; } +/* Return the destructor denoted by OBJECT.SCOPE::~DTOR_NAME, or, if + SCOPE is NULL, by OBJECT.~DTOR_NAME. */ + +static tree +lookup_destructor (tree object, tree scope, tree dtor_name) +{ + tree object_type = TREE_TYPE (object); + tree dtor_type = TREE_OPERAND (dtor_name, 0); + + if (scope && !check_dtor_name (scope, dtor_name)) + { + error ("qualified type `%T' does not match destructor name `~%T'", + scope, dtor_type); + return error_mark_node; + } + if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type))) + { + error ("destructor name `%T' does not match type `%T' of expression", + dtor_type, object_type); + return error_mark_node; + } + if (!TYPE_HAS_DESTRUCTOR (object_type)) + return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope, + dtor_type); + return lookup_member (object_type, complete_dtor_identifier, + /*protect=*/1, /*want_type=*/false); +} + /* This function is called by the parser to process a class member access expression of the form OBJECT.NAME. NAME is a node used by the parser to represent a name; it is not yet a DECL. It may, @@ -2130,7 +2190,7 @@ finish_class_member_access_expr (tree object, tree name) if (TREE_CODE (scope) == NAMESPACE_DECL) { error ("`%D::%D' is not a member of `%T'", - scope, member, object_type); + scope, name, object_type); return error_mark_node; } @@ -2139,34 +2199,35 @@ finish_class_member_access_expr (tree object, tree name) if (!access_path || access_path == error_mark_node) return error_mark_node; - /* Look up the member. */ - member = lookup_member (access_path, name, /*protect=*/1, - /*want_type=*/0); - if (member == error_mark_node) - return error_mark_node; - } - else if (TREE_CODE (name) == BIT_NOT_EXPR) - { - /* A destructor. */ - if (TYPE_IDENTIFIER (object_type) != TREE_OPERAND (name, 0)) - { - error ("destructor specifier `%T::~%T' must have matching names", - object_type, TREE_OPERAND (name, 0)); - return error_mark_node; - } - if (! TYPE_HAS_DESTRUCTOR (object_type)) + if (TREE_CODE (name) == BIT_NOT_EXPR) + member = lookup_destructor (object, scope, name); + else { - error ("type `%T' has no destructor", object_type); - return error_mark_node; + /* Look up the member. */ + member = lookup_member (access_path, name, /*protect=*/1, + /*want_type=*/false); + if (member == NULL_TREE) + { + error ("'%D' has no member named '%E'", object_type, name); + return error_mark_node; + } + if (member == error_mark_node) + return error_mark_node; } - member = CLASSTYPE_DESTRUCTORS (object_type); } + else if (TREE_CODE (name) == BIT_NOT_EXPR) + member = lookup_destructor (object, /*scope=*/NULL_TREE, name); else if (TREE_CODE (name) == IDENTIFIER_NODE) { /* An unqualified name. */ member = lookup_member (object_type, name, /*protect=*/1, - /*want_type=*/0); - if (member == error_mark_node) + /*want_type=*/false); + if (member == NULL_TREE) + { + error ("'%D' has no member named '%E'", object_type, name); + return error_mark_node; + } + else if (member == error_mark_node) return error_mark_node; } else @@ -2196,6 +2257,9 @@ finish_class_member_access_expr (tree object, tree name) } } + if (TREE_DEPRECATED (member)) + warn_deprecated_use (member); + return build_class_member_access_expr (object, member, access_path, /*preserve_reference=*/false); } @@ -2221,7 +2285,7 @@ build_ptrmemfunc_access_expr (tree ptrmem, tree member_name) ptrmem_type = TREE_TYPE (ptrmem); my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804); member = lookup_member (ptrmem_type, member_name, /*protect=*/0, - /*want_type=*/0); + /*want_type=*/false); member_type = cp_build_qualified_type (TREE_TYPE (member), cp_type_quals (ptrmem_type)); return fold (build (COMPONENT_REF, member_type, ptrmem, member)); @@ -2244,8 +2308,8 @@ build_x_indirect_ref (ptr, errorstring) if (processing_template_decl) return build_min_nt (INDIRECT_REF, ptr); - rval = build_opfncall (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, - NULL_TREE); + rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, ptr, NULL_TREE, + NULL_TREE); if (rval) return rval; return build_indirect_ref (ptr, errorstring); @@ -2288,8 +2352,7 @@ build_indirect_ref (ptr, errorstring) return error_mark_node; } else if (TREE_CODE (pointer) == ADDR_EXPR - && !flag_volatile - && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0)))) + && same_type_p (t, TREE_TYPE (TREE_OPERAND (pointer, 0)))) /* The POINTER was something like `&x'. We simplify `*&x' to `x'. */ return TREE_OPERAND (pointer, 0); @@ -2303,8 +2366,7 @@ build_indirect_ref (ptr, errorstring) TREE_READONLY (ref) = CP_TYPE_CONST_P (t); TREE_THIS_VOLATILE (ref) = CP_TYPE_VOLATILE_P (t); TREE_SIDE_EFFECTS (ref) - = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer) - || flag_volatile); + = (TREE_THIS_VOLATILE (ref) || TREE_SIDE_EFFECTS (pointer)); return ref; } } @@ -2486,7 +2548,7 @@ build_array_ref (array, idx) With the final ISO C++ rules, such an optimization is incorrect: A pointer to a derived member can be static_cast to pointer-to-base-member, as long as the dynamic object - later has the right member. */ + later has the right member. */ tree get_member_function_from_ptrfunc (instance_ptrptr, function) @@ -2502,13 +2564,14 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) tree fntype = TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (function)); tree instance_ptr = *instance_ptrptr; + tree instance_save_expr = 0; if (instance_ptr == error_mark_node) { if (TREE_CODE (function) == PTRMEM_CST) { /* Extracting the function address from a pmf is only allowed with -Wno-pmf-conversions. It only works for - pmf constants. */ + pmf constants. */ e1 = build_addr_func (PTRMEM_CST_MEMBER (function)); e1 = convert (fntype, e1); return e1; @@ -2521,7 +2584,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) } if (TREE_SIDE_EFFECTS (instance_ptr)) - instance_ptr = save_expr (instance_ptr); + instance_ptr = instance_save_expr = save_expr (instance_ptr); if (TREE_SIDE_EFFECTS (function)) function = save_expr (function); @@ -2547,7 +2610,7 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) } /* Convert down to the right base before using the instance. First - use the type... */ + use the type... */ basetype = TYPE_METHOD_BASETYPE (TREE_TYPE (fntype)); basetype = lookup_base (TREE_TYPE (TREE_TYPE (instance_ptr)), basetype, ba_check, NULL); @@ -2582,9 +2645,9 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) /* Make sure this doesn't get evaluated first inside one of the branches of the COND_EXPR. */ - if (TREE_CODE (instance_ptr) == SAVE_EXPR) + if (instance_save_expr) e1 = build (COMPOUND_EXPR, TREE_TYPE (e1), - instance_ptr, e1); + instance_save_expr, e1); function = e1; } @@ -2592,12 +2655,10 @@ get_member_function_from_ptrfunc (instance_ptrptr, function) } tree -build_function_call_real (function, params, require_complete, flags) +build_function_call (function, params) tree function, params; - int require_complete, flags; { register tree fntype, fndecl; - register tree value_type; register tree coerced_params; tree result; tree name = NULL_TREE, assembler_name = NULL_TREE; @@ -2668,20 +2729,10 @@ build_function_call_real (function, params, require_complete, flags) /* Convert the parameters to the types declared in the function prototype, or apply default promotions. */ - if (flags & LOOKUP_COMPLAIN) - coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), - params, fndecl, LOOKUP_NORMAL); - else - coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), - params, fndecl, 0); - + coerced_params = convert_arguments (TYPE_ARG_TYPES (fntype), + params, fndecl, LOOKUP_NORMAL); if (coerced_params == error_mark_node) - { - if (flags & LOOKUP_SPECULATIVELY) - return NULL_TREE; - else - return error_mark_node; - } + return error_mark_node; /* Check for errors in format strings. */ @@ -2702,27 +2753,7 @@ build_function_call_real (function, params, require_complete, flags) return result; } - /* Some built-in function calls will be evaluated at - compile-time in fold (). */ - result = fold (build_call (function, coerced_params)); - value_type = TREE_TYPE (result); - - if (require_complete) - { - if (TREE_CODE (value_type) == VOID_TYPE) - 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); -} - -tree -build_function_call (function, params) - tree function, params; -{ - return build_function_call_real (function, params, 1, LOOKUP_NORMAL); + return build_cxx_call (function, params, coerced_params); } /* Convert the actual parameter expressions in the list VALUES @@ -2864,7 +2895,8 @@ convert_arguments (typelist, values, fndecl, flags) if (typetail != 0 && typetail != void_list_node) { /* See if there are default arguments that can be used */ - if (TREE_PURPOSE (typetail)) + if (TREE_PURPOSE (typetail) + && TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG) { for (; typetail != void_list_node; ++i) { @@ -2914,6 +2946,183 @@ build_x_binary_op (code, arg1, arg2) return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE); } +#if 0 + +tree +build_template_expr (enum tree_code code, tree op0, tree op1, tree op2) +{ + tree type; + + /* If any of the operands is erroneous the result is erroneous too. */ + if (error_operand_p (op0) + || (op1 && error_operand_p (op1)) + || (op2 && error_operand_p (op2))) + return error_mark_node; + + if (dependent_type_p (TREE_TYPE (op0)) + || (op1 && dependent_type_p (TREE_TYPE (op1))) + || (op2 && dependent_type_p (TREE_TYPE (op2)))) + /* If at least one operand has a dependent type, we cannot + determine the type of the expression until instantiation time. */ + type = NULL_TREE; + else + { + struct z_candidate *cand; + tree op0_type; + tree op1_type; + tree op2_type; + + /* None of the operands is dependent, so we can compute the type + of the expression at this point. We must compute the type so + that in things like: + + template + void f() { S s; ... } + + we can tell that the type of "s" is non-dependent. + + If we're processing a template argument, we do not want to + actually change the operands in any way. Adding conversions, + performing constant folding, etc., would all change mangled + names. For example, in: + + template + void f(S); + + we need to determine that "3 + 4 + I" has type "int", without + actually turning the expression into "7 + I". */ + cand = find_overloaded_op (code, op0, op1, op2); + if (cand) + /* If an overloaded operator was found, the expression will + have the type returned by the function. */ + type = non_reference (TREE_TYPE (cand->fn)); + else + { + /* There is no overloaded operator so we can just use the + default rules for determining the type of the operand. */ + op0_type = TREE_TYPE (op0); + op1_type = op1 ? TREE_TYPE (op1) : NULL_TREE; + op2_type = op2 ? TREE_TYPE (op2) : NULL_TREE; + type = NULL_TREE; + + switch (code) + { + case MODIFY_EXPR: + /* [expr.ass] + + The result of the assignment operation is the value + stored in the left operand. */ + type = op0_type; + break; + case COMPONENT_REF: + /* Implement this case. */ + break; + case POSTINCREMENT_EXPR: + case POSTDECREMENT_EXPR: + /* [expr.post.incr] + + The type of the result is the cv-unqualified version + of the type of the operand. */ + type = TYPE_MAIN_VARIANT (op0_type); + break; + case PREINCREMENT_EXPR: + case PREDECREMENT_EXPR: + /* [expr.pre.incr] + + The value is the new value of the operand. */ + type = op0_type; + break; + case INDIRECT_REF: + /* [expr.unary.op] + + If the type of the expression is "pointer to T", the + type of the result is "T". */ + type = TREE_TYPE (op0_type); + break; + case ADDR_EXPR: + /* [expr.unary.op] + + If the type of the expression is "T", the type of the + result is "pointer to T". */ + /* FIXME: Handle the pointer-to-member case. */ + break; + case MEMBER_REF: + /* FIXME: Implement this case. */ + break; + case LSHIFT_EXPR: + case RSHIFT_EXPR: + /* [expr.shift] + + The type of the result is that of the promoted left + operand. */ + break; + case PLUS_EXPR: + case MINUS_EXPR: + /* FIXME: Be careful of special pointer-arithmetic + cases. */ + /* Fall through. */ + case MAX_EXPR: + case MIN_EXPR: + /* These are GNU extensions; the result type is computed + as it would be for other arithmetic operators. */ + /* Fall through. */ + case BIT_AND_EXPR: + case BIT_XOR_EXPR: + case BIT_IOR_EXPR: + case MULT_EXPR: + case TRUNC_DIV_EXPR: + case TRUNC_MOD_EXPR: + /* [expr.bit.and], [expr.xor], [expr.or], [expr.mul] + + The usual arithmetic conversions are performed on the + operands and determine the type of the result. */ + /* FIXME: Check that this is possible. */ + type = type_after_usual_arithmetic_conversions (t1, t2); + break; + case GT_EXPR: + case LT_EXPR: + case GE_EXPR: + case LE_EXPR: + case EQ_EXPR: + case NE_EXPR: + /* [expr.rel] + + The type of the result is bool. */ + type = boolean_type_node; + break; + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + /* [expr.log.and], [expr.log.org] + + The result is a bool. */ + type = boolean_type_node; + break; + case COND_EXPR: + /* FIXME: Handle special rules for conditioanl + expressions. */ + break; + case COMPOUND_EXPR: + type = op1_type; + break; + default: + abort (); + } + /* If the type of the expression could not be determined, + something is wrong. */ + if (!type) + abort (); + /* If the type is erroneous, the expression is erroneous + too. */ + if (type == error_mark_node) + return error_mark_node; + } + } + + return build_min (code, type, op0, op1, op2, NULL_TREE); +} + +#endif + /* Build a binary-operation expression without default conversions. CODE is the kind of expression to build. This function differs from `build' in several ways: @@ -3848,7 +4057,45 @@ condition_conversion (expr) t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t)); return t; } - + +/* Return an ADDR_EXPR giving the address of T. This function + attempts no optimizations or simplifications; it is a low-level + primitive. */ + +tree +build_address (tree t) +{ + tree addr; + + if (error_operand_p (t) || !cxx_mark_addressable (t)) + return error_mark_node; + + addr = build1 (ADDR_EXPR, + build_pointer_type (TREE_TYPE (t)), + t); + if (staticp (t)) + TREE_CONSTANT (addr) = 1; + + return addr; +} + +/* Return a NOP_EXPR converting EXPR to TYPE. */ + +tree +build_nop (tree type, tree expr) +{ + tree nop; + + if (type == error_mark_node || error_operand_p (expr)) + return expr; + + nop = build1 (NOP_EXPR, type, expr); + if (TREE_CONSTANT (expr)) + TREE_CONSTANT (nop) = 1; + + return nop; +} + /* C++: Must handle pointers to members. Perhaps type instantiation should be extended to handle conversion @@ -3880,7 +4127,7 @@ build_unary_op (code, xarg, noconvert) is enough to prevent anybody from looking inside for associativity, but won't generate any code. */ if (!(arg = build_expr_type_conversion - (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, 1))) + (WANT_ARITH | WANT_ENUM | WANT_POINTER, arg, true))) errstring = "wrong type argument to unary plus"; else { @@ -3892,7 +4139,7 @@ build_unary_op (code, xarg, noconvert) break; case NEGATE_EXPR: - if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1))) + if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true))) errstring = "wrong type argument to unary minus"; else if (!noconvert) arg = default_conversion (arg); @@ -3906,14 +4153,14 @@ build_unary_op (code, xarg, noconvert) arg = default_conversion (arg); } else if (!(arg = build_expr_type_conversion (WANT_INT | WANT_ENUM, - arg, 1))) + arg, true))) errstring = "wrong type argument to bit-complement"; else if (!noconvert) arg = default_conversion (arg); break; case ABS_EXPR: - if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, 1))) + if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true))) errstring = "wrong type argument to abs"; else if (!noconvert) arg = default_conversion (arg); @@ -3921,7 +4168,7 @@ build_unary_op (code, xarg, noconvert) 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))) + if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true))) errstring = "wrong type argument to conjugation"; else if (!noconvert) arg = default_conversion (arg); @@ -3981,7 +4228,7 @@ build_unary_op (code, xarg, noconvert) /* Report invalid types. */ if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_POINTER, - arg, 1))) + arg, true))) { if (code == PREINCREMENT_EXPR) errstring ="no pre-increment operator for type"; @@ -4182,7 +4429,11 @@ build_unary_op (code, xarg, noconvert) We could defer this in non-MS mode, but it's easier to give a useful error here. */ - tree base = TREE_TYPE (TREE_OPERAND (arg, 0)); + /* Inside constant member functions, the `this' pointer + contains an extra const qualifier. TYPE_MAIN_VARIANT + is used here to remove this const from the diagnostics + and the created OFFSET_REF. */ + tree base = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_OPERAND (arg, 0))); tree name = DECL_NAME (get_first_fn (TREE_OPERAND (arg, 1))); if (! flag_ms_extensions) @@ -4190,9 +4441,15 @@ build_unary_op (code, xarg, noconvert) if (current_class_type && TREE_OPERAND (arg, 0) == current_class_ref) /* An expression like &memfn. */ - pedwarn ("ISO C++ forbids taking the address of an unqualified non-static member function to form a pointer to member function. Say `&%T::%D'", base, name); + pedwarn ("ISO C++ forbids taking the address of an unqualified" + " or parenthesized non-static member function to form" + " a pointer to member function. Say `&%T::%D'", + base, name); else - pedwarn ("ISO C++ forbids taking the address of a bound member function to form a pointer to member function. Say `&%T::%D'", base, name); + pedwarn ("ISO C++ forbids taking the address of a bound member" + " function to form a pointer to member function." + " Say `&%T::%D'", + base, name); } arg = build_offset_ref (base, name); } @@ -4232,32 +4489,44 @@ build_unary_op (code, xarg, noconvert) is an error. */ else if (TREE_CODE (argtype) != FUNCTION_TYPE && TREE_CODE (argtype) != METHOD_TYPE - && !lvalue_or_else (arg, "unary `&'")) + && !non_cast_lvalue_or_else (arg, "unary `&'")) return error_mark_node; if (argtype != error_mark_node) argtype = build_pointer_type (argtype); - if (!cxx_mark_addressable (arg)) - return error_mark_node; - { tree addr; if (TREE_CODE (arg) == COMPONENT_REF - && DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) + && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK) + arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1)); + + if (TREE_CODE (arg) != COMPONENT_REF) + addr = build_address (arg); + else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) { error ("attempt to take address of bit-field structure member `%D'", TREE_OPERAND (arg, 1)); return error_mark_node; } else - addr = build1 (ADDR_EXPR, argtype, arg); - - /* Address of a static or external variable or - function counts as a constant */ - if (staticp (arg)) - TREE_CONSTANT (addr) = 1; + { + /* Unfortunately we cannot just build an address + expression here, because we would not handle + address-constant-expressions or offsetof correctly. */ + tree field = TREE_OPERAND (arg, 1); + tree rval = build_unary_op (ADDR_EXPR, TREE_OPERAND (arg, 0), 0); + tree binfo = lookup_base (TREE_TYPE (TREE_TYPE (rval)), + decl_type_context (field), + ba_check, NULL); + + rval = build_base_path (PLUS_EXPR, rval, binfo, 1); + rval = build1 (NOP_EXPR, argtype, rval); + TREE_CONSTANT (rval) = TREE_CONSTANT (TREE_OPERAND (rval, 0)); + addr = fold (build (PLUS_EXPR, argtype, rval, + cp_convert (argtype, byte_position (field)))); + } if (TREE_CODE (argtype) == POINTER_TYPE && TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE) @@ -4390,9 +4659,7 @@ unary_complex_lvalue (code, arg) return error_mark_node; } - type = build_offset_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t)); - type = build_pointer_type (type); - + type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t)); t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1)); return t; } @@ -4473,7 +4740,7 @@ cxx_mark_addressable (exp) warning ("address requested for `%D', which is declared `register'", x); TREE_ADDRESSABLE (x) = 1; - put_var_into_stack (x); + put_var_into_stack (x, /*rescan=*/true); return true; case FUNCTION_DECL: @@ -4523,19 +4790,19 @@ build_x_compound_expr (list) if (rest == NULL_TREE) return build_compound_expr (list); - result = build_opfncall (COMPOUND_EXPR, LOOKUP_NORMAL, - TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE); + result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, + TREE_VALUE (list), TREE_VALUE (rest), NULL_TREE); if (result) return build_x_compound_expr (tree_cons (NULL_TREE, result, TREE_CHAIN (rest))); if (! TREE_SIDE_EFFECTS (TREE_VALUE (list))) { - /* FIXME: This test should be in the implicit cast to void of the LHS. */ + /* FIXME: This test should be in the implicit cast to void of the LHS. */ /* the left-hand operand of a comma expression is like an expression statement: we should warn if it doesn't have any side-effects, unless it was explicitly cast to (void). */ - if ((extra_warnings || warn_unused_value) + if (warn_unused_value && !(TREE_CODE (TREE_VALUE(list)) == CONVERT_EXPR && VOID_TYPE_P (TREE_TYPE (TREE_VALUE(list))))) warning("left-hand operand of comma expression has no effect"); @@ -4642,12 +4909,12 @@ build_static_cast (type, expr) ? can_convert_arg (type, intype, expr) : can_convert_arg (strip_all_pointer_quals (type), strip_all_pointer_quals (intype), expr)) - /* This is a standard conversion. */ + /* This is a standard conversion. */ ok = 1; else if (TYPE_PTROB_P (type) && TYPE_PTROB_P (intype)) { /* They're pointers to objects. They must be aggregates that - are related non-virtually. */ + are related non-virtually. */ base_kind kind; if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype)) @@ -4660,7 +4927,7 @@ build_static_cast (type, expr) { /* They're pointers to members. The pointed to objects must be the same (ignoring CV qualifiers), and the containing classes - must be related non-virtually. */ + must be related non-virtually. */ base_kind kind; if (same_type_p @@ -5068,6 +5335,10 @@ build_modify_expr (lhs, modifycode, rhs) TREE_OPERAND (lhs, 0), newrhs); case MODIFY_EXPR: + if (TREE_SIDE_EFFECTS (TREE_OPERAND (lhs, 0))) + lhs = build (TREE_CODE (lhs), TREE_TYPE (lhs), + stabilize_reference (TREE_OPERAND (lhs, 0)), + TREE_OPERAND (lhs, 1)); newrhs = build_modify_expr (TREE_OPERAND (lhs, 0), modifycode, rhs); if (newrhs == error_mark_node) return error_mark_node; @@ -5156,8 +5427,8 @@ build_modify_expr (lhs, modifycode, rhs) /* Do the default thing */; else { - result = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, - lhs, rhs, make_node (NOP_EXPR)); + result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, + lhs, rhs, make_node (NOP_EXPR)); if (result == NULL_TREE) return error_mark_node; return result; @@ -5248,7 +5519,7 @@ build_modify_expr (lhs, modifycode, rhs) || TREE_CODE (TREE_TYPE (lhs)) == METHOD_TYPE /* If it's an aggregate and any field is const, then it is effectively const. */ - || (IS_AGGR_TYPE_CODE (TREE_CODE (lhstype)) + || (CLASS_TYPE_P (lhstype) && C_TYPE_FIELDS_READONLY (lhstype)))) readonly_error (lhs, "assignment", 0); @@ -5273,14 +5544,6 @@ build_modify_expr (lhs, modifycode, rhs) } } - if (TREE_CODE (lhstype) != REFERENCE_TYPE) - { - if (TREE_SIDE_EFFECTS (lhs)) - lhs = stabilize_reference (lhs); - if (TREE_SIDE_EFFECTS (newrhs)) - newrhs = stabilize_reference (newrhs); - } - /* Convert new value to destination type. */ if (TREE_CODE (lhstype) == ARRAY_TYPE) @@ -5301,7 +5564,7 @@ build_modify_expr (lhs, modifycode, rhs) from_array = TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE ? 1 + (modifycode != INIT_EXPR): 0; - return build_vec_init (lhs, newrhs, from_array); + return build_vec_init (lhs, NULL_TREE, newrhs, from_array); } if (modifycode == INIT_EXPR) @@ -5409,8 +5672,8 @@ build_x_modify_expr (lhs, modifycode, rhs) if (modifycode != NOP_EXPR) { - tree rval = build_opfncall (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, - make_node (modifycode)); + tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs, + make_node (modifycode)); if (rval) return rval; } @@ -5458,10 +5721,9 @@ get_delta_difference (from, to, force) if (virt_binfo) { - /* This is a reinterpret cast, we choose to do nothing. */ - warning ("pointer to member cast via virtual base `%T' of `%T'", - BINFO_TYPE (virt_binfo), - BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo))); + /* This is a reinterpret cast, we choose to do nothing. */ + warning ("pointer to member cast via virtual base `%T'", + BINFO_TYPE (virt_binfo)); return delta; } delta = BINFO_OFFSET (binfo); @@ -5476,15 +5738,13 @@ get_delta_difference (from, to, force) virt_binfo = binfo_from_vbase (binfo); if (virt_binfo) { - /* This is a reinterpret cast, we choose to do nothing. */ + /* This is a reinterpret cast, we choose to do nothing. */ if (force) - warning ("pointer to member cast via virtual base `%T' of `%T'", - BINFO_TYPE (virt_binfo), - BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo))); + warning ("pointer to member cast via virtual base `%T'", + BINFO_TYPE (virt_binfo)); else - error ("pointer to member conversion via virtual base `%T' of `%T'", - BINFO_TYPE (virt_binfo), - BINFO_TYPE (BINFO_INHERITANCE_CHAIN (virt_binfo))); + error ("pointer to member conversion via virtual base `%T'", + BINFO_TYPE (virt_binfo)); return delta; } delta = BINFO_OFFSET (binfo); @@ -5513,7 +5773,7 @@ build_ptrmemfunc1 (type, delta, pfn) /* Finish creating the initializer. */ u = tree_cons (pfn_field, pfn, build_tree_list (delta_field, delta)); - u = build (CONSTRUCTOR, type, NULL_TREE, u); + u = build_constructor (type, u); TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta); TREE_STATIC (u) = (TREE_CONSTANT (u) && (initializer_constant_valid_p (pfn, TREE_TYPE (pfn)) @@ -5528,7 +5788,7 @@ build_ptrmemfunc1 (type, delta, pfn) as a value in expressions. TYPE is the POINTER to METHOD_TYPE we want to be. - If FORCE is non-zero, then force this conversion, even if + If FORCE is nonzero, then force this conversion, even if we would rather not do it. Usually set when using an explicit cast. @@ -5540,11 +5800,17 @@ build_ptrmemfunc (type, pfn, force) int force; { tree fn; - tree pfn_type = TREE_TYPE (pfn); - tree to_type = build_ptrmemfunc_type (type); + tree pfn_type; + tree to_type; + + if (error_operand_p (pfn)) + return error_mark_node; + + pfn_type = TREE_TYPE (pfn); + to_type = build_ptrmemfunc_type (type); /* Handle multiple conversions of pointer to member functions. */ - if (TYPE_PTRMEMFUNC_P (TREE_TYPE (pfn))) + if (TYPE_PTRMEMFUNC_P (pfn_type)) { tree delta = NULL_TREE; tree npfn = NULL_TREE; @@ -5643,7 +5909,7 @@ expand_ptrmemfunc_cst (cst, delta, pfn) /* If we're dealing with a virtual function, we have to adjust 'this' again, to point to the base which provides the vtable entry for fn; the call will do the opposite adjustment. */ - tree orig_class = DECL_VIRTUAL_CONTEXT (fn); + tree orig_class = DECL_CONTEXT (fn); tree binfo = binfo_or_else (orig_class, fn_class); *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta), *delta, BINFO_OFFSET (binfo))); @@ -5803,8 +6069,16 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) /* Simplify the RHS if possible. */ if (TREE_CODE (rhs) == CONST_DECL) rhs = DECL_INITIAL (rhs); - else if (coder != ARRAY_TYPE) - rhs = decl_constant_value (rhs); + + /* We do not use decl_constant_value here because of this case: + + const char* const s = "s"; + + The conversion rules for a string literal are more lax than for a + variable; in particular, a string literal can be converted to a + "char *" but the variable "s" cannot be converted in the same + way. If the conversion is allowed, the optimization should be + performed while creating the converted expression. */ /* [expr.ass] @@ -5843,7 +6117,7 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum) } /* Convert RHS to be of type TYPE. - If EXP is non-zero, it is the target of the initialization. + If EXP is nonzero, it is the target of the initialization. ERRTYPE is a string to use in error messages. Two major differences between the behavior of @@ -5917,7 +6191,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) if (fndecl) savew = warningcount, savee = errorcount; - rhs = initialize_reference (type, rhs); + rhs = initialize_reference (type, rhs, /*decl=*/NULL_TREE); if (fndecl) { if (warningcount > savew) @@ -5993,9 +6267,9 @@ c_expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line) else { tree type = TREE_TYPE (o[i]); - if (CP_TYPE_CONST_P (type) - || (IS_AGGR_TYPE_CODE (TREE_CODE (type)) - && C_TYPE_FIELDS_READONLY (type))) + if (type != error_mark_node + && (CP_TYPE_CONST_P (type) + || (CLASS_TYPE_P (type) && C_TYPE_FIELDS_READONLY (type)))) readonly_error (o[i], "modification by `asm'", 1); } } @@ -6097,7 +6371,7 @@ check_return_expr (retval) { if (in_function_try_handler) /* If a return statement appears in a handler of the - function-try-block of a constructor, the program is ill-formed. */ + function-try-block of a constructor, the program is ill-formed. */ error ("cannot return from a handler of a function-try-block of a constructor"); else if (retval) /* You can't return a value from a constructor. */ @@ -6105,6 +6379,12 @@ check_return_expr (retval) return NULL_TREE; } + if (processing_template_decl) + { + current_function_returns_value = 1; + return retval; + } + /* When no explicit return-value is given in a function with a named return value, the named return value is used. */ result = DECL_RESULT (current_function_decl); @@ -6218,7 +6498,7 @@ check_return_expr (retval) /* First convert the value to the function's return type, then to the type of return value's location to handle the - case that functype is smaller than the valtype. */ + case that functype is smaller than the valtype. */ retval = convert_for_initialization (NULL_TREE, functype, retval, LOOKUP_NORMAL|LOOKUP_ONLYCONVERTING, "return", NULL_TREE, 0); @@ -6245,9 +6525,9 @@ check_return_expr (retval) } -/* Returns non-zero if the pointer-type FROM can be converted to the +/* Returns nonzero if the pointer-type FROM can be converted to the pointer-type TO via a qualification conversion. If CONSTP is -1, - then we return non-zero if the pointers are similar, and the + then we return nonzero if the pointers are similar, and the cv-qualification signature of FROM is a proper subset of that of TO. If CONSTP is positive, then all outer pointers have been @@ -6290,15 +6570,14 @@ comp_ptr_ttypes_real (to, from, constp) } if (TREE_CODE (to) != POINTER_TYPE) - return - same_type_ignoring_top_level_qualifiers_p (to, from) - && (constp >= 0 || to_more_cv_qualified); + return ((constp >= 0 || to_more_cv_qualified) + && same_type_ignoring_top_level_qualifiers_p (to, from)); } } -/* When comparing, say, char ** to char const **, this function takes the - 'char *' and 'char const *'. Do not pass non-pointer types to this - function. */ +/* When comparing, say, char ** to char const **, this function takes + the 'char *' and 'char const *'. Do not pass non-pointer/reference + types to this function. */ int comp_ptr_ttypes (to, from) @@ -6408,10 +6687,12 @@ cp_type_quals (type) tree type; { type = strip_array_types (type); + if (type == error_mark_node) + return TYPE_UNQUALIFIED; return TYPE_QUALS (type); } -/* Returns non-zero if the TYPE contains a mutable member */ +/* Returns nonzero if the TYPE contains a mutable member */ int cp_has_mutable_p (type) @@ -6484,7 +6765,7 @@ casts_away_constness_r (t1, t2) *t2 = cp_build_qualified_type (*t2, quals2); } -/* Returns non-zero if casting from TYPE1 to TYPE2 casts away +/* Returns nonzero if casting from TYPE1 to TYPE2 casts away constness. */ static int