/* This file is part of the C++ front end.
It contains routines to build C++ expressions given their operands,
including computing the types of the result, C and C++ specific error
- checks, and some optimization.
-
- There are also routines to build RETURN_STMT nodes and CASE_STMT nodes,
- and to process initializations in declarations (since they work
- like a strange sort of assignment). */
+ checks, and some optimization. */
#include "config.h"
#include "system.h"
static bool comp_except_types (tree, tree, bool);
static bool comp_array_types (tree, tree, bool);
static tree common_base_type (tree, tree);
-static tree lookup_anon_field (tree, tree);
static tree pointer_diff (tree, tree, tree);
static tree get_delta_difference (tree, tree, int);
static void casts_away_constness_r (tree *, tree *);
else
type = TREE_TYPE (value);
+ if (type == error_mark_node)
+ return error_mark_node;
+
/* First, detect a valid value with a complete type. */
if (COMPLETE_TYPE_P (type))
return value;
else if (TREE_CODE (type) == ARRAY_TYPE && TYPE_DOMAIN (type))
{
tree t = complete_type (TREE_TYPE (type));
- if (COMPLETE_TYPE_P (t) && ! processing_template_decl)
+ if (COMPLETE_TYPE_P (t) && !dependent_type_p (type))
layout_type (type);
TYPE_NEEDS_CONSTRUCTING (type)
= TYPE_NEEDS_CONSTRUCTING (TYPE_MAIN_VARIANT (t));
int
type_unknown_p (tree exp)
{
- return (TREE_CODE (exp) == OVERLOAD
- || TREE_CODE (exp) == TREE_LIST
+ return (TREE_CODE (exp) == TREE_LIST
|| TREE_TYPE (exp) == unknown_type_node);
}
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_integer_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_long_integer_type_node))
{
- tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
+ tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
? long_long_unsigned_type_node
: long_long_integer_type_node);
return build_type_attribute_variant (t, attributes);
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_integer_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_integer_type_node))
{
- tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
+ tree t = ((TYPE_UNSIGNED (t1) || TYPE_UNSIGNED (t2))
? long_unsigned_type_node : long_integer_type_node);
return build_type_attribute_variant (t, attributes);
}
/* Otherwise prefer the unsigned one. */
- if (TREE_UNSIGNED (t1))
+ if (TYPE_UNSIGNED (t1))
return build_type_attribute_variant (t1, attributes);
else
return build_type_attribute_variant (t2, attributes);
result_type = cp_build_qualified_type (result_type,
(cp_type_quals (pointee1)
| cp_type_quals (pointee2)));
- result_type = build_pointer_type (result_type);
/* If the original types were pointers to members, so is the
result. */
if (TYPE_PTR_TO_MEMBER_P (t1))
result_type = build_ptrmem_type (TYPE_PTRMEM_CLASS_TYPE (t1),
result_type);
}
+ else
+ result_type = build_pointer_type (result_type);
/* Merge the attributes. */
attributes = (*targetm.merge_type_attributes) (t1, t2);
if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
strict & ~COMPARE_REDECLARATION))
return false;
- /* Fall through. */
+ /* Fall through. */
case POINTER_TYPE:
case REFERENCE_TYPE:
case COMPLEX_TYPE:
return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
+ case VECTOR_TYPE:
+ return TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+ && same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
+ break;
+
default:
break;
}
}
\f
+/* EXPR is being used in a context that is not a function call.
+ Enforce:
+
+ [expr.ref]
+
+ The expression can be used only as the left-hand operand of a
+ member function call.
+
+ [expr.mptr.operator]
+
+ If the result of .* or ->* is a function, then that result can be
+ used only as the operand for the function call operator ().
+
+ by issuing an error message if appropriate. Returns true iff EXPR
+ violates these rules. */
+
+bool
+invalid_nonstatic_memfn_p (tree expr)
+{
+ if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
+ {
+ error ("invalid use of non-static member function");
+ return true;
+ }
+ return false;
+}
+
/* Perform the conversions in [expr] that apply when an lvalue appears
in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions.
error ("void value not ignored as it ought to be");
return error_mark_node;
}
- if (code == METHOD_TYPE)
- {
- error ("invalid use of non-static member function");
- return error_mark_node;
- }
+ if (invalid_nonstatic_memfn_p (exp))
+ return error_mark_node;
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
return build_unary_op (ADDR_EXPR, exp, 0);
if (code == ARRAY_TYPE)
if (!cxx_mark_addressable (exp))
return error_mark_node;
adr = build_nop (ptrtype, build_address (exp));
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
return adr;
}
/* This way is better for a COMPONENT_REF since it can
anonymous unions can nest, we must also search all anonymous unions
that are directly reachable. */
-static tree
+tree
lookup_anon_field (tree t, tree type)
{
tree field;
member_type = cp_build_qualified_type (member_type, type_quals);
}
- result = fold (build (COMPONENT_REF, member_type, object, member));
+ result = fold (build (COMPONENT_REF, member_type, object, member,
+ NULL_TREE));
/* Mark the expression const or volatile, as appropriate. Even
though we've dealt with the type above, we still have to mark the
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);
+ result = build (COMPONENT_REF, type, object, member, NULL_TREE);
}
else if (TREE_CODE (member) == CONST_DECL)
{
{
tree object_type = TREE_TYPE (object);
tree dtor_type = TREE_OPERAND (dtor_name, 0);
+ tree expr;
if (scope && !check_dtor_name (scope, dtor_name))
{
scope, dtor_type);
return error_mark_node;
}
- if (!same_type_p (dtor_type, TYPE_MAIN_VARIANT (object_type)))
+ if (!DERIVED_FROM_P (dtor_type, TYPE_MAIN_VARIANT (object_type)))
{
error ("the type being destroyed is `%T', but the destructor refers to `%T'",
TYPE_MAIN_VARIANT (object_type), dtor_type);
return error_mark_node;
}
- if (!TYPE_HAS_DESTRUCTOR (object_type))
+ if (!TYPE_HAS_DESTRUCTOR (dtor_type))
return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
dtor_type);
- return lookup_member (object_type, complete_dtor_identifier,
+ expr = lookup_member (dtor_type, complete_dtor_identifier,
/*protect=*/1, /*want_type=*/false);
+ expr = (adjust_result_of_qualified_name_lookup
+ (expr, dtor_type, object_type));
+ return expr;
}
/* This function is called by the parser to process a class member
|| (TREE_CODE (name) == SCOPE_REF
&& TYPE_P (TREE_OPERAND (name, 0))
&& dependent_type_p (TREE_OPERAND (name, 0))))
- return build_min_nt (COMPONENT_REF, object, name);
+ return build_min_nt (COMPONENT_REF, object, name, NULL_TREE);
object = build_non_dependent_expr (object);
}
/*preserve_reference=*/false);
if (processing_template_decl && expr != error_mark_node)
return build_min_non_dep (COMPONENT_REF, expr,
- orig_object, orig_name);
+ orig_object, orig_name, NULL_TREE);
return expr;
}
/*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));
+ return fold (build (COMPONENT_REF, member_type, ptrmem, member, NULL_TREE));
}
/* Given an expression PTR for a pointer, return an expression
break;
}
- if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE
- && TREE_CODE (array) != INDIRECT_REF)
+ if (TREE_CODE (TREE_TYPE (array)) == ARRAY_TYPE)
{
tree rval, type;
}
type = TREE_TYPE (TREE_TYPE (array));
- rval = build (ARRAY_REF, type, array, idx);
+ rval = build (ARRAY_REF, type, array, idx, NULL_TREE, NULL_TREE);
/* Array ref is const/volatile if the array elements are
or if the array is.. */
TREE_READONLY (rval)
e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
e2 = build_indirect_ref (e2, NULL);
TREE_CONSTANT (e2) = 1;
+ TREE_INVARIANT (e2) = 1;
/* When using function descriptors, the address of the
vtable entry is treated as a function pointer. */
{
tree fntype, fndecl;
tree coerced_params;
- tree result;
tree name = NULL_TREE;
int is_method;
tree original = function;
/* Check for errors in format strings. */
if (warn_format)
- check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
-
- /* Recognize certain built-in functions so we can make tree-codes
- other than CALL_EXPR. We do this when it enables fold-const.c
- to do something useful. */
+ check_function_format (TYPE_ATTRIBUTES (fntype), coerced_params);
- if (TREE_CODE (function) == ADDR_EXPR
- && TREE_CODE (TREE_OPERAND (function, 0)) == FUNCTION_DECL
- && DECL_BUILT_IN (TREE_OPERAND (function, 0)))
- {
- result = expand_tree_builtin (TREE_OPERAND (function, 0),
- params, coerced_params);
- if (result)
- return result;
- }
-
- return build_cxx_call (function, params, coerced_params);
+ return build_cxx_call (function, coerced_params);
}
\f
/* Convert the actual parameter expressions in the list VALUES
point, so we have to dig out the original type to find out if
it was unsigned. */
shorten = ((TREE_CODE (op0) == NOP_EXPR
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
+ && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
|| (TREE_CODE (op1) == INTEGER_CST
&& ! integer_all_onesp (op1)));
quotient can't be represented in the computation mode. We shorten
only if unsigned or if dividing by something we know != -1. */
shorten = ((TREE_CODE (op0) == NOP_EXPR
- && TREE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
+ && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op0, 0))))
|| (TREE_CODE (op1) == INTEGER_CST
&& ! integer_all_onesp (op1)));
common = 1;
tree arg0 = get_narrower (op0, &unsigned0);
tree arg1 = get_narrower (op1, &unsigned1);
/* UNS is 1 if the operation to be done is an unsigned one. */
- int uns = TREE_UNSIGNED (result_type);
+ int uns = TYPE_UNSIGNED (result_type);
tree type;
final_type = result_type;
but it *requires* conversion to FINAL_TYPE. */
if (op0 == arg0 && TREE_TYPE (op0) != final_type)
- unsigned0 = TREE_UNSIGNED (TREE_TYPE (op0));
+ unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
if (op1 == arg1 && TREE_TYPE (op1) != final_type)
- unsigned1 = TREE_UNSIGNED (TREE_TYPE (op1));
+ unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
/* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
final_type = result_type;
if (arg0 == op0 && final_type == TREE_TYPE (op0))
- unsigned_arg = TREE_UNSIGNED (TREE_TYPE (op0));
+ unsigned_arg = TYPE_UNSIGNED (TREE_TYPE (op0));
if (TYPE_PRECISION (TREE_TYPE (arg0)) < TYPE_PRECISION (result_type)
/* We can shorten only if the shift count is less than the
ones made by sign-extension and bring in zeros.
We can't optimize that case at all, but in most machines
it never happens because available widths are 2**N. */
- && (!TREE_UNSIGNED (final_type)
+ && (!TYPE_UNSIGNED (final_type)
|| unsigned_arg
|| (((unsigned) 2 * TYPE_PRECISION (TREE_TYPE (arg0)))
<= TYPE_PRECISION (result_type))))
bound the ranges of the arguments until that point. */
&& !processing_template_decl)
{
- int op0_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op0));
- int op1_signed = ! TREE_UNSIGNED (TREE_TYPE (orig_op1));
+ int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+ int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
int unsignedp0, unsignedp1;
tree primop0 = get_narrower (op0, &unsignedp0);
/* Do not warn if the comparison is being done in a signed type,
since the signed type will only be chosen if it can represent
all the values of the unsigned type. */
- if (! TREE_UNSIGNED (result_type))
+ if (!TYPE_UNSIGNED (result_type))
/* OK */;
/* Do not warn if both operands are unsigned. */
else if (op0_signed == op1_signed)
build_type = result_type;
{
- tree result = build (resultcode, build_type, op0, op1);
- tree folded;
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+ tree result = fold (build (resultcode, build_type, op0, op1));
if (final_type != 0)
- return cp_convert (final_type, folded);
- return folded;
+ result = cp_convert (final_type, result);
+ return result;
}
}
\f
static tree
pointer_diff (tree op0, tree op1, tree ptrtype)
{
- tree result, folded;
+ tree result;
tree restype = ptrdiff_type_node;
tree target_type = TREE_TYPE (ptrtype);
/* Do the division. */
result = build (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
- return folded;
+ return fold (result);
}
\f
/* Construct and perhaps optimize a tree representation
exp = NULL_TREE;
- /* & rec, on incomplete RECORD_TYPEs is the simple opr &, not an
- error message. */
+ /* [expr.unary.op] says:
+
+ The address of an object of incomplete type can be taken.
+
+ (And is just the ordinary address operator, not an overloaded
+ "operator &".) However, if the type is a template
+ specialization, we must complete the type at this point so that
+ an overloaded "operator &" will be available if required. */
if (code == ADDR_EXPR
&& TREE_CODE (xarg) != TEMPLATE_ID_EXPR
- && ((IS_AGGR_TYPE_CODE (TREE_CODE (TREE_TYPE (xarg)))
- && !COMPLETE_TYPE_P (TREE_TYPE (xarg)))
+ && ((CLASS_TYPE_P (TREE_TYPE (xarg))
+ && !COMPLETE_TYPE_P (complete_type (TREE_TYPE (xarg))))
|| (TREE_CODE (xarg) == OFFSET_REF)))
/* Don't look for a function. */;
else
return error_mark_node;
addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
- if (staticp (t))
- TREE_CONSTANT (addr) = 1;
return addr;
}
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;
+ return build1 (NOP_EXPR, type, expr);
}
/* C++: Must handle pointers to members.
else
{
if (!noconvert)
- arg = default_conversion (arg);
+ arg = default_conversion (arg);
arg = build1 (NON_LVALUE_EXPR, TREE_TYPE (arg), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
}
break;
compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
/* Eliminate warning about unused result of + or -. */
- TREE_NO_UNUSED_WARNING (compound) = 1;
+ TREE_NO_WARNING (compound) = 1;
return compound;
}
if (TREE_CODE (argtype) == REFERENCE_TYPE)
{
- arg = build1
- (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (argtype)), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+ tree type = build_pointer_type (TREE_TYPE (argtype));
+ arg = build1 (CONVERT_EXPR, type, arg);
return arg;
}
else if (pedantic && DECL_MAIN_P (arg))
arg = TREE_OPERAND (arg, 0);
if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE)
{
- arg = build1
- (CONVERT_EXPR,
- build_pointer_type (TREE_TYPE (TREE_TYPE (arg))), arg);
- TREE_CONSTANT (arg) = TREE_CONSTANT (TREE_OPERAND (arg, 0));
+ tree type = build_pointer_type (TREE_TYPE (TREE_TYPE (arg)));
+ arg = build1 (CONVERT_EXPR, type, arg);
}
else if (lvalue_p (arg))
/* Don't let this be an lvalue. */
return arg;
}
- /* For &x[y], return x+y. */
- if (TREE_CODE (arg) == ARRAY_REF)
+ /* For &x[y], return x+y. But, in a template, ARG may be an
+ ARRAY_REF representing a non-dependent expression. In that
+ case, there may be an overloaded "operator []" that will be
+ chosen at instantiation time; we must not try to optimize
+ here. */
+ if (TREE_CODE (arg) == ARRAY_REF && !processing_template_decl)
{
if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
return error_mark_node;
if (! lvalue_p (arg) && pedantic)
pedwarn ("ISO C++ forbids taking the address of a cast to a non-lvalue expression");
break;
-
+
+ case OVERLOAD:
+ arg = OVL_CURRENT (arg);
+ break;
+
default:
break;
}
{
tree addr;
- if (TREE_CODE (arg) != COMPONENT_REF)
+ if (TREE_CODE (arg) != COMPONENT_REF
+ /* Inside a template, we are processing a non-dependent
+ expression so we can just form an ADDR_EXPR with the
+ correct type. */
+ || processing_template_decl)
addr = build_address (arg);
else if (TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
{
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 0), 0);
arg = build (COMPOUND_EXPR, TREE_TYPE (real_result), arg, real_result);
- TREE_NO_UNUSED_WARNING (arg) = 1;
+ TREE_NO_WARNING (arg) = 1;
return arg;
}
return error_mark_node;
}
- type = build_ptrmem_type (DECL_FIELD_CONTEXT (t), TREE_TYPE (t));
+ type = build_ptrmem_type (context_for_name_lookup (t),
+ TREE_TYPE (t));
t = make_ptrmem_cst (type, TREE_OPERAND (arg, 1));
return t;
}
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
return true;
case CONSTRUCTOR:
t. */
result = perform_direct_initialization_if_possible (type, expr);
if (result)
- return convert_from_reference (result);
+ {
+ result = convert_from_reference (result);
+ /* [expr.static.cast]
+
+ If T is a reference type, the result is an lvalue; otherwise,
+ the result is an rvalue. */
+ if (TREE_CODE (type) != REFERENCE_TYPE
+ && real_lvalue_p (result))
+ result = build1 (NON_LVALUE_EXPR, TREE_TYPE (result), result);
+ return result;
+ }
/* [expr.static.cast]
return t;
}
- if (!POINTER_TYPE_P (type))
+ if (!POINTER_TYPE_P (type) && !TYPE_PTRMEM_P (type))
error ("invalid use of const_cast with type `%T', which is not a pointer, reference, nor a pointer-to-data-member type", type);
else if (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
{
if (TREE_CODE (value) == INTEGER_CST)
{
TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
- TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+
+ if (TREE_CODE_CLASS (TREE_CODE (ovalue)) == 'c')
+ TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
}
}
return cond;
/* Make sure the code to compute the rhs comes out
before the split. */
- return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+ if (preeval)
+ cond = build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+ return cond;
}
default:
if (olhs)
{
result = build (COMPOUND_EXPR, olhstype, result, olhs);
- TREE_NO_UNUSED_WARNING (result) = 1;
+ TREE_NO_WARNING (result) = 1;
return result;
}
return convert_for_assignment (olhstype, result, "assignment",
tree binfo;
tree virt_binfo;
base_kind kind;
-
+ tree result;
+
+ /* Assume no conversion is required. */
+ result = integer_zero_node;
binfo = lookup_base (to, from, ba_check, &kind);
if (kind == bk_inaccessible || kind == bk_ambig)
- {
- error (" in pointer to member function conversion");
- goto error;
- }
- if (!binfo)
+ error (" in pointer to member function conversion");
+ else if (!binfo)
{
if (!force)
{
error_not_base_type (from, to);
error (" in pointer to member conversion");
- goto error;
}
- binfo = lookup_base (from, to, ba_check, &kind);
- if (!binfo)
- goto error;
+ else
+ {
+ binfo = lookup_base (from, to, ba_check, &kind);
+ if (binfo)
+ {
+ virt_binfo = binfo_from_vbase (binfo);
+ if (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));
+ else
+ result = size_diffop (size_zero_node, BINFO_OFFSET (binfo));
+ }
+ }
+ }
+ else
+ {
virt_binfo = binfo_from_vbase (binfo);
- if (virt_binfo)
- {
- /* This is a reinterpret cast, we choose to do nothing. */
- warning ("pointer to member cast via virtual base `%T'",
+ if (!virt_binfo)
+ result = BINFO_OFFSET (binfo);
+ else
+ {
+ /* This is a reinterpret cast, we choose to do nothing. */
+ if (force)
+ warning ("pointer to member cast via virtual base `%T'",
+ BINFO_TYPE (virt_binfo));
+ else
+ error ("pointer to member conversion via virtual base `%T'",
BINFO_TYPE (virt_binfo));
- goto error;
- }
- return convert_to_integer (ptrdiff_type_node,
- size_diffop (size_zero_node,
- BINFO_OFFSET (binfo)));
+ }
}
- virt_binfo = binfo_from_vbase (binfo);
- if (!virt_binfo)
- return convert_to_integer (ptrdiff_type_node, BINFO_OFFSET (binfo));
-
- /* This is a reinterpret cast, we choose to do nothing. */
- if (force)
- warning ("pointer to member cast via virtual base `%T'",
- BINFO_TYPE (virt_binfo));
- else
- error ("pointer to member conversion via virtual base `%T'",
- BINFO_TYPE (virt_binfo));
-
- error:
- return convert_to_integer(ptrdiff_type_node, integer_zero_node);
+ return fold (convert_to_integer (ptrdiff_type_node, result));
}
/* Return a constructor for the pointer-to-member-function TYPE using
u = tree_cons (pfn_field, pfn,
build_tree_list (delta_field, delta));
u = build_constructor (type, u);
- TREE_CONSTANT (u) = TREE_CONSTANT (pfn) && TREE_CONSTANT (delta);
+ TREE_CONSTANT (u) = TREE_CONSTANT (pfn) & TREE_CONSTANT (delta);
+ TREE_INVARIANT (u) = TREE_INVARIANT (pfn) & TREE_INVARIANT (delta);
TREE_STATIC (u) = (TREE_CONSTANT (u)
&& (initializer_constant_valid_p (pfn, TREE_TYPE (pfn))
!= NULL_TREE)
}
/* And warn about assigning a negative value to an unsigned
variable. */
- else if (TREE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
+ else if (TYPE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
{
- if (TREE_CODE (expr) == INTEGER_CST
- && TREE_NEGATED_INT (expr))
+ if (TREE_CODE (expr) == INTEGER_CST && TREE_NEGATED_INT (expr))
{
if (fndecl)
warning ("passing negative value `%E' for %s %P of `%D'",
coder = TREE_CODE (rhstype);
if (TREE_CODE (type) == VECTOR_TYPE && coder == VECTOR_TYPE
- && ((*targetm.vector_opaque_p) (type)
- || (*targetm.vector_opaque_p) (rhstype)))
+ && vector_types_convertible_p (type, rhstype))
return convert (type, rhs);
if (rhs == error_mark_node || rhstype == error_mark_node)
returned expression uses the chosen variable somehow. And people expect
this restriction, anyway. (jason 2000-11-19)
- See finish_function, cxx_expand_function_start, and
- cp_copy_res_decl_for_inlining for other pieces of this
- optimization. */
+ See finish_function and finalize_nrv for the rest of this optimization. */
if (fn_returns_value_p && flag_elide_constructors)
{