aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/typeck.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/typeck.c')
-rw-r--r--gcc/cp/typeck.c445
1 files changed, 267 insertions, 178 deletions
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 85eef41c2e0..98da207a922 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -909,10 +909,8 @@ comptypes (t1, t2, strict)
if (t1 == t2)
return 1;
- /* This should never happen. */
- my_friendly_assert (t1 != error_mark_node, 307);
-
- if (t2 == error_mark_node)
+ /* Suppress errors caused by previously reported errors */
+ if (t1 == error_mark_node || t2 == error_mark_node)
return 0;
/* If either type is the internal version of sizetype, return the
@@ -1405,7 +1403,7 @@ compparms (parms1, parms2)
they fail to match. */
if (t1 == 0 || t2 == 0)
return 0;
- if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1)))
+ if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
return 0;
t1 = TREE_CHAIN (t1);
@@ -1940,7 +1938,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;
@@ -1950,7 +1949,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)
@@ -1985,7 +1984,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;
@@ -2165,8 +2172,13 @@ finish_class_member_access_expr (tree object, tree name)
/* Find the base of OBJECT_TYPE corresponding to SCOPE. */
access_path = lookup_base (object_type, scope, ba_check, NULL);
- if (!access_path || access_path == error_mark_node)
+ if (access_path == error_mark_node)
return error_mark_node;
+ if (!access_path)
+ {
+ error ("`%T' is not a base of `%T'", scope, object_type);
+ return error_mark_node;
+ }
/* Look up the member. */
member = lookup_member (access_path, name, /*protect=*/1,
@@ -2632,12 +2644,11 @@ get_member_function_from_ptrfunc (instance_ptrptr, function)
}
tree
-build_function_call_real (function, params, require_complete, flags)
+build_function_call_real (function, params, flags)
tree function, params;
- int require_complete, flags;
+ int flags;
{
register tree fntype, fndecl;
- register tree value_type;
register tree coerced_params;
tree result;
tree name = NULL_TREE, assembler_name = NULL_TREE;
@@ -2742,27 +2753,14 @@ 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);
+ return build_cxx_call (function, params, coerced_params);
}
tree
build_function_call (function, params)
tree function, params;
{
- return build_function_call_real (function, params, 1, LOOKUP_NORMAL);
+ return build_function_call_real (function, params, LOOKUP_NORMAL);
}
/* Convert the actual parameter expressions in the list VALUES
@@ -3888,7 +3886,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
@@ -4278,25 +4314,22 @@ build_unary_op (code, xarg, noconvert)
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)))
+ 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 if (TREE_CODE (arg) == COMPONENT_REF
- && TREE_CODE (TREE_OPERAND (arg, 0)) == INDIRECT_REF
- && (TREE_CODE (TREE_OPERAND (TREE_OPERAND (arg, 0), 0))
- == INTEGER_CST))
+ else
{
- /* offsetof idiom, fold it. */
+ /* 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)),
@@ -4309,13 +4342,6 @@ build_unary_op (code, xarg, noconvert)
addr = fold (build (PLUS_EXPR, argtype, rval,
cp_convert (argtype, byte_position (field))));
}
- 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;
if (TREE_CODE (argtype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (argtype)) == METHOD_TYPE)
@@ -4529,7 +4555,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:
@@ -4646,12 +4672,25 @@ build_compound_expr (list)
return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
}
+/* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
+ away constness. */
+
+static void
+check_for_casting_away_constness (tree src_type, tree dest_type)
+{
+ if (casts_away_constness (src_type, dest_type))
+ error ("static_cast from type `%T' to type `%T' casts away constness",
+ src_type, dest_type);
+}
+
+/* Return an expression representing static_cast<TYPE>(EXPR). */
+
tree
build_static_cast (type, expr)
tree type, expr;
{
tree intype;
- int ok;
+ tree result;
if (type == error_mark_node || expr == error_mark_node)
return error_mark_node;
@@ -4672,89 +4711,163 @@ build_static_cast (type, expr)
&& TREE_TYPE (expr) == TREE_TYPE (TREE_OPERAND (expr, 0)))
expr = TREE_OPERAND (expr, 0);
- if (TREE_CODE (type) == VOID_TYPE)
- {
- expr = convert_to_void (expr, /*implicit=*/NULL);
- return expr;
+ intype = TREE_TYPE (expr);
+
+ /* [expr.static.cast]
+
+ An lvalue of type "cv1 B", where B is a class type, can be cast
+ to type "reference to cv2 D", where D is a class derived (clause
+ _class.derived_) from B, if a valid standard conversion from
+ "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the
+ same cv-qualification as, or greater cv-qualification than, cv1,
+ and B is not a virtual base class of D. */
+ /* We check this case before checking the validity of "TYPE t =
+ EXPR;" below because for this case:
+
+ struct B {};
+ struct D : public B { D(const B&); };
+ extern B& b;
+ void f() { static_cast<const D&>(b); }
+
+ we want to avoid constructing a new D. The standard is not
+ completely clear about this issue, but our interpretation is
+ consistent with other compilers. */
+ if (TREE_CODE (type) == REFERENCE_TYPE
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (intype)
+ && real_non_cast_lvalue_p (expr)
+ && DERIVED_FROM_P (intype, TREE_TYPE (type))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT (intype)),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type))))
+ && at_least_as_qualified_p (TREE_TYPE (type), intype))
+ {
+ /* There is a standard conversion from "D*" to "B*" even if "B"
+ is ambiguous or inaccessible. Therefore, we ask lookup_base
+ to check these conditions. */
+ tree base = lookup_base (TREE_TYPE (type), intype, ba_check, NULL);
+
+ /* Convert from "B*" to "D*". This function will check that "B"
+ is not a virtual base of "D". */
+ expr = build_base_path (MINUS_EXPR, build_address (expr),
+ base, /*nonnull=*/false);
+ /* Convert the pointer to a reference -- but then remember that
+ there are no expressions with reference type in C++. */
+ return convert_from_reference (build_nop (type, expr));
}
- if (TREE_CODE (type) == REFERENCE_TYPE)
- return (convert_from_reference
- (convert_to_reference (type, expr, CONV_STATIC|CONV_IMPLICIT,
- LOOKUP_COMPLAIN, NULL_TREE)));
+ /* [expr.static.cast]
- if (IS_AGGR_TYPE (type))
- return build_cplus_new (type, (build_special_member_call
- (NULL_TREE, complete_ctor_identifier,
- build_tree_list (NULL_TREE, expr),
- TYPE_BINFO (type), LOOKUP_NORMAL)));
+ An expression e can be explicitly converted to a type T using a
+ static_cast of the form static_cast<T>(e) if the declaration T
+ t(e);" is well-formed, for some invented temporary variable
+ t. */
+ result = perform_direct_initialization_if_possible (type, expr);
+ if (result)
+ return convert_from_reference (result);
- intype = TREE_TYPE (expr);
+ /* [expr.static.cast]
- /* FIXME handle casting to array type. */
+ Any expression can be explicitly converted to type cv void. */
+ if (TREE_CODE (type) == VOID_TYPE)
+ return convert_to_void (expr, /*implicit=*/NULL);
- ok = 0;
- if (IS_AGGR_TYPE (intype)
- ? 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. */
- 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. */
- base_kind kind;
-
- if (IS_AGGR_TYPE (TREE_TYPE (type)) && IS_AGGR_TYPE (TREE_TYPE (intype))
- && lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_ignore | ba_quiet, &kind)
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
- {
- /* 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. */
- base_kind kind;
-
- if (same_type_p
- (strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (type))),
- strip_all_pointer_quals (TREE_TYPE (TREE_TYPE (intype))))
- && (lookup_base (TYPE_OFFSET_BASETYPE (TREE_TYPE (intype)),
- TYPE_OFFSET_BASETYPE (TREE_TYPE (type)),
- ba_ignore | ba_quiet, &kind))
- && kind != bk_via_virtual)
- ok = 1;
- }
- else if (TREE_CODE (intype) != BOOLEAN_TYPE
- && TREE_CODE (type) != ARRAY_TYPE
- && TREE_CODE (type) != FUNCTION_TYPE
- && can_convert (intype, strip_all_pointer_quals (type)))
- ok = 1;
- else if (TREE_CODE (intype) == ENUMERAL_TYPE
- && TREE_CODE (type) == ENUMERAL_TYPE)
- /* DR 128: "A value of integral _or enumeration_ type can be explicitly
- converted to an enumeration type."
- The integral to enumeration will be accepted by the previous clause.
- We need to explicitly check for enumeration to enumeration. */
- ok = 1;
+ /* [expr.static.cast]
+ The inverse of any standard conversion sequence (clause _conv_),
+ other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
+ (_conv.array_), function-to-pointer (_conv.func_), and boolean
+ (_conv.bool_) conversions, can be performed explicitly using
+ static_cast subject to the restriction that the explicit
+ conversion does not cast away constness (_expr.const.cast_), and
+ the following additional rules for specific cases: */
+ /* For reference, the conversions not excluded are: integral
+ promotions, floating point promotion, integral conversions,
+ floating point conversions, floating-integral conversions,
+ pointer conversions, and pointer to member conversions. */
+ if ((ARITHMETIC_TYPE_P (type) && ARITHMETIC_TYPE_P (intype))
+ /* DR 128
+
+ A value of integral _or enumeration_ type can be explicitly
+ converted to an enumeration type. */
+ || (INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ && INTEGRAL_OR_ENUMERATION_TYPE_P (intype)))
+ /* Really, build_c_cast should defer to this function rather
+ than the other way around. */
+ return build_c_cast (type, expr);
+ if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
+ && CLASS_TYPE_P (TREE_TYPE (type))
+ && CLASS_TYPE_P (TREE_TYPE (intype))
+ && can_convert (build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (intype))),
+ build_pointer_type (TYPE_MAIN_VARIANT
+ (TREE_TYPE (type)))))
+ {
+ tree base;
+
+ check_for_casting_away_constness (intype, type);
+ base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
+ ba_check, NULL);
+ return build_base_path (MINUS_EXPR, expr, base, /*nonnull=*/false);
+ }
+ if ((TYPE_PTRMEM_P (type) && TYPE_PTRMEM_P (intype))
+ || (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
+ {
+ tree c1;
+ tree c2;
+ tree t1;
+ tree t2;
+
+ c1 = TYPE_PTRMEM_CLASS_TYPE (intype);
+ c2 = TYPE_PTRMEM_CLASS_TYPE (type);
+
+ if (TYPE_PTRMEM_P (type))
+ {
+ t1 = (build_ptrmem_type
+ (c1,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (intype))));
+ t2 = (build_ptrmem_type
+ (c2,
+ TYPE_MAIN_VARIANT (TYPE_PTRMEM_POINTED_TO_TYPE (type))));
+ }
+ else
+ {
+ t1 = intype;
+ t2 = type;
+ }
+ if (can_convert (t1, t2))
+ {
+ check_for_casting_away_constness (intype, type);
+ if (TYPE_PTRMEM_P (type))
+ {
+ if (TREE_CODE (expr) == PTRMEM_CST)
+ expr = cplus_expand_constant (expr);
+ expr = cp_build_binary_op (PLUS_EXPR,
+ cp_convert (ptrdiff_type_node, expr),
+ get_delta_difference (c1, c2,
+ /*force=*/1));
+ return build_nop (type, expr);
+ }
+ else
+ return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr,
+ /*force=*/1);
+ }
+ }
+
/* [expr.static.cast]
- The static_cast operator shall not be used to cast away
- constness. */
- if (ok && casts_away_constness (intype, type))
+ An rvalue of type "pointer to cv void" can be explicitly
+ converted to a pointer to object type. A value of type pointer
+ to object converted to "pointer to cv void" and back to the
+ original pointer type will have its original value. */
+ if (TREE_CODE (intype) == POINTER_TYPE
+ && VOID_TYPE_P (TREE_TYPE (intype))
+ && TYPE_PTROB_P (type))
{
- error ("static_cast from type `%T' to type `%T' casts away constness",
- intype, type);
- return error_mark_node;
+ check_for_casting_away_constness (intype, type);
+ return build_nop (type, expr);
}
- if (ok)
- return build_c_cast (type, expr);
-
error ("invalid static_cast from type `%T' to type `%T'", intype, type);
return error_mark_node;
}
@@ -4978,6 +5091,10 @@ build_c_cast (type, expr)
value = convert_to_void (value, /*implicit=*/NULL);
return value;
}
+
+ if (!complete_type_or_else (type, NULL_TREE))
+ return error_mark_node;
+
/* Convert functions and arrays to pointers and
convert references to their expanded types,
but don't convert any other types. If, however, we are
@@ -5093,7 +5210,7 @@ build_modify_expr (lhs, modifycode, rhs)
tree newrhs = rhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
- tree olhs = lhs;
+ tree olhs = NULL_TREE;
/* Avoid duplicate error messages from operands that had errors. */
if (lhs == error_mark_node || rhs == error_mark_node)
@@ -5124,6 +5241,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;
@@ -5175,8 +5296,9 @@ build_modify_expr (lhs, modifycode, rhs)
{
if (TREE_CODE (rhs) == CONSTRUCTOR)
{
- my_friendly_assert (same_type_p (TREE_TYPE (rhs), lhstype),
- 20011220);
+ if (! same_type_p (TREE_TYPE (rhs), lhstype))
+ /* Call convert to generate an error; see PR 11063. */
+ rhs = convert (lhstype, rhs);
result = build (INIT_EXPR, lhstype, lhs, rhs);
TREE_SIDE_EFFECTS (result) = 1;
return result;
@@ -5324,19 +5446,20 @@ build_modify_expr (lhs, modifycode, rhs)
if (lhstype != TREE_TYPE (lhs))
{
+ /* Avoid warnings converting integral types back into enums for
+ enum bit fields. */
+ if (TREE_CODE (lhstype) == INTEGER_TYPE
+ && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+ {
+ if (TREE_SIDE_EFFECTS (lhs))
+ lhs = stabilize_reference (lhs);
+ olhs = lhs;
+ }
lhs = copy_node (lhs);
TREE_TYPE (lhs) = lhstype;
}
}
- 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)
@@ -5357,7 +5480,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)
@@ -5392,44 +5515,8 @@ build_modify_expr (lhs, modifycode, rhs)
if (newrhs == error_mark_node)
return error_mark_node;
- if (TREE_CODE (newrhs) == COND_EXPR)
- {
- tree lhs1;
- tree cond = TREE_OPERAND (newrhs, 0);
-
- if (TREE_SIDE_EFFECTS (lhs))
- cond = build_compound_expr (tree_cons
- (NULL_TREE, lhs,
- build_tree_list (NULL_TREE, cond)));
-
- /* Cannot have two identical lhs on this one tree (result) as preexpand
- calls will rip them out and fill in RTL for them, but when the
- rtl is generated, the calls will only be in the first side of the
- condition, not on both, or before the conditional jump! (mrs) */
- lhs1 = break_out_calls (lhs);
-
- if (lhs == lhs1)
- /* If there's no change, the COND_EXPR behaves like any other rhs. */
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- lhstype, lhs, newrhs);
- else
- {
- tree result_type = TREE_TYPE (newrhs);
- /* We have to convert each arm to the proper type because the
- types may have been munged by constant folding. */
- result
- = build (COND_EXPR, result_type, cond,
- build_modify_expr (lhs, modifycode,
- cp_convert (result_type,
- TREE_OPERAND (newrhs, 1))),
- build_modify_expr (lhs1, modifycode,
- cp_convert (result_type,
- TREE_OPERAND (newrhs, 2))));
- }
- }
- else
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- lhstype, lhs, newrhs);
+ result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
+ lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
@@ -5440,10 +5527,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. */
- if (TREE_CODE (TREE_TYPE (result)) == INTEGER_TYPE
- && TREE_CODE (olhstype) == ENUMERAL_TYPE)
+ if (olhs)
{
result = build (COMPOUND_EXPR, olhstype, result, olhs);
TREE_NO_UNUSED_WARNING (result) = 1;
@@ -5596,11 +5680,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;
@@ -5847,8 +5937,6 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
return error_mark_node;
- rhs = dubious_conversion_warnings (type, rhs, errtype, fndecl, parmnum);
-
/* The RHS of an assignment cannot have void type. */
if (coder == VOID_TYPE)
{
@@ -5981,7 +6069,8 @@ 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,
+ /*cleanup=*/NULL);
if (fndecl)
{
if (warningcount > savew)