/* Build expressions with type checking for C++ compiler.
Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC.
/* 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);
}
tree attributes;
/* FIXME: Attributes. */
- my_friendly_assert (ARITHMETIC_TYPE_P (t1)
- || TREE_CODE (t1) == COMPLEX_TYPE
- || TREE_CODE (t1) == ENUMERAL_TYPE,
- 19990725);
- my_friendly_assert (ARITHMETIC_TYPE_P (t2)
- || TREE_CODE (t2) == COMPLEX_TYPE
- || TREE_CODE (t2) == ENUMERAL_TYPE,
- 19990725);
+ gcc_assert (ARITHMETIC_TYPE_P (t1)
+ || TREE_CODE (t1) == COMPLEX_TYPE
+ || TREE_CODE (t1) == ENUMERAL_TYPE);
+ gcc_assert (ARITHMETIC_TYPE_P (t2)
+ || TREE_CODE (t2) == COMPLEX_TYPE
+ || TREE_CODE (t2) == ENUMERAL_TYPE);
/* In what follows, we slightly generalize the rules given in [expr] so
as to deal with `long long' and `complex'. First, merge the
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);
tree
merge_types (tree t1, tree t2)
{
- register enum tree_code code1;
- register enum tree_code code2;
+ enum tree_code code1;
+ enum tree_code code2;
tree attributes;
/* Save time if the two types are the same. */
/* Save space: see if the result is identical to one of the args. */
if (valtype == TREE_TYPE (t1) && ! p2)
- return build_type_attribute_variant (t1, attributes);
+ return cp_build_type_attribute_variant (t1, attributes);
if (valtype == TREE_TYPE (t2) && ! p1)
- return build_type_attribute_variant (t2, attributes);
+ return cp_build_type_attribute_variant (t2, attributes);
/* Simple way if one arg fails to specify argument types. */
if (p1 == NULL_TREE || TREE_VALUE (p1) == void_type_node)
rval = build_function_type (valtype, p2);
if ((raises = TYPE_RAISES_EXCEPTIONS (t2)))
rval = build_exception_variant (rval, raises);
- return build_type_attribute_variant (rval, attributes);
+ return cp_build_type_attribute_variant (rval, attributes);
}
raises = TYPE_RAISES_EXCEPTIONS (t1);
if (p2 == NULL_TREE || TREE_VALUE (p2) == void_type_node)
rval = build_function_type (valtype, p1);
if (raises)
rval = build_exception_variant (rval, raises);
- return build_type_attribute_variant (rval, attributes);
+ return cp_build_type_attribute_variant (rval, attributes);
}
rval = build_function_type (valtype, commonparms (p1, p2));
break;
}
+ case TYPENAME_TYPE:
+ /* There is no need to merge attributes into a TYPENAME_TYPE.
+ When the type is instantiated it will have whatever
+ attributes result from the instantiation. */
+ return t1;
+
default:;
}
- return build_type_attribute_variant (t1, attributes);
+ return cp_build_type_attribute_variant (t1, attributes);
}
/* Return the common type of two types.
return composite_pointer_type (t1, t2, error_mark_node, error_mark_node,
"conversion");
else
- abort ();
+ gcc_unreachable ();
}
\f
/* Compare two exception specifier types for exactness or subsetness, if
{
tree d1;
tree d2;
+ tree max1, max2;
if (t1 == t2)
return true;
return allow_redeclaration;
/* Check that the dimensions are the same. */
- return (cp_tree_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2))
- && cp_tree_equal (TYPE_MAX_VALUE (d1), TYPE_MAX_VALUE (d2)));
+
+ if (!cp_tree_equal (TYPE_MIN_VALUE (d1), TYPE_MIN_VALUE (d2)))
+ return false;
+ max1 = TYPE_MAX_VALUE (d1);
+ max2 = TYPE_MAX_VALUE (d2);
+ if (processing_template_decl && !abi_version_at_least (2)
+ && !value_dependent_expression_p (max1)
+ && !value_dependent_expression_p (max2))
+ {
+ /* With abi-1 we do not fold non-dependent array bounds, (and
+ consequently mangle them incorrectly). We must therefore
+ fold them here, to verify the domains have the same
+ value. */
+ max1 = fold (max1);
+ max2 = fold (max2);
+ }
+
+ if (!cp_tree_equal (max1, max2))
+ return false;
+
+ return true;
}
/* Return true if T1 and T2 are related as allowed by STRICT. STRICT
if (t1 == t2)
return true;
- /* This should never happen. */
- my_friendly_assert (t1 != error_mark_node, 307);
-
- /* Suppress errors caused by previously reported errors */
- if (t2 == error_mark_node)
+ /* Suppress errors caused by previously reported errors. */
+ if (t1 == error_mark_node || t2 == error_mark_node)
return false;
- my_friendly_assert (TYPE_P (t1) && TYPE_P (t2), 20030623);
+ gcc_assert (TYPE_P (t1) && TYPE_P (t2));
/* TYPENAME_TYPEs should be resolved if the qualifying scope is the
current instantiation. */
/* If either type is the internal version of sizetype, use the
language version. */
if (TREE_CODE (t1) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t1)
- && TYPE_DOMAIN (t1))
- t1 = TYPE_DOMAIN (t1);
+ && TYPE_ORIG_SIZE_TYPE (t1))
+ t1 = TYPE_ORIG_SIZE_TYPE (t1);
if (TREE_CODE (t2) == INTEGER_TYPE && TYPE_IS_SIZETYPE (t2)
- && TYPE_DOMAIN (t2))
- t2 = TYPE_DOMAIN (t2);
+ && TYPE_ORIG_SIZE_TYPE (t2))
+ t2 = TYPE_ORIG_SIZE_TYPE (t2);
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TREE_CODE (t1) != TREE_CODE (t2))
return false;
- /* Qualifiers must match. */
- if (cp_type_quals (t1) != cp_type_quals (t2))
+ /* Qualifiers must match. For array types, we will check when we
+ recur on the array element types. */
+ if (TREE_CODE (t1) != ARRAY_TYPE
+ && TYPE_QUALS (t1) != TYPE_QUALS (t2))
return false;
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false;
definition. Note that we already checked for equality of the type
qualifiers (just above). */
- if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
+ if (TREE_CODE (t1) != ARRAY_TYPE
+ && TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
if (!(*targetm.comp_type_attributes) (t1, t2))
return true;
/* Don't check inheritance. */
strict = COMPARE_STRICT;
- /* fall through */
+ /* Fall through. */
case RECORD_TYPE:
case UNION_TYPE:
if (!comptypes (TYPE_OFFSET_BASETYPE (t1), TYPE_OFFSET_BASETYPE (t2),
strict & ~COMPARE_REDECLARATION))
return false;
- /* FALLTHROUGH*/
+ /* 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;
}
/* Otherwise, try to find a unique baseclass of TT1
that is shared by TT2, and follow that down. */
- for (i = CLASSTYPE_N_BASECLASSES (tt1)-1; i >= 0; i--)
+ for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt1))-1; i >= 0; i--)
{
- tree basetype = TYPE_BINFO_BASETYPE (tt1, i);
+ tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt1), i));
tree trial = common_base_type (basetype, tt2);
+
if (trial)
{
if (trial == error_mark_node)
}
/* Same for TT2. */
- for (i = CLASSTYPE_N_BASECLASSES (tt2)-1; i >= 0; i--)
+ for (i = BINFO_N_BASE_BINFOS (TYPE_BINFO (tt2))-1; i >= 0; i--)
{
- tree basetype = TYPE_BINFO_BASETYPE (tt2, i);
+ tree basetype = BINFO_TYPE (BINFO_BASE_BINFO (TYPE_BINFO (tt2), i));
tree trial = common_base_type (tt1, basetype);
+
if (trial)
{
if (trial == error_mark_node)
they fail to match. */
if (!t1 || !t2)
return false;
- if (!same_type_p (TREE_VALUE (t2), TREE_VALUE (t1)))
+ if (!same_type_p (TREE_VALUE (t1), TREE_VALUE (t2)))
return false;
}
return true;
tree value;
const char *op_name;
- my_friendly_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR, 20020720);
+ gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
if (type == error_mark_node)
return error_mark_node;
}
if (TREE_CODE (e) == COMPONENT_REF
+ && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL
&& DECL_C_BIT_FIELD (TREE_OPERAND (e, 1)))
{
error ("invalid application of `%s' to a bit-field", op_name);
}
\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.
tree
decay_conversion (tree exp)
{
- register tree type;
- register enum tree_code code;
+ tree type;
+ enum tree_code code;
type = TREE_TYPE (exp);
code = TREE_CODE (type);
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)
{
- register tree adr;
+ tree adr;
tree ptrtype;
if (TREE_CODE (exp) == INDIRECT_REF)
if (TREE_CODE (exp) == COMPOUND_EXPR)
{
tree op1 = decay_conversion (TREE_OPERAND (exp, 1));
- return build (COMPOUND_EXPR, TREE_TYPE (op1),
- TREE_OPERAND (exp, 0), op1);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (op1),
+ TREE_OPERAND (exp, 0), op1);
}
if (!lvalue_p (exp)
if (TREE_CODE (exp) == VAR_DECL)
{
- /* ??? This is not really quite correct
- in that the type of the operand of ADDR_EXPR
- is not the target type of the type of the ADDR_EXPR itself.
- Question is, can this lossage be avoided? */
- adr = build1 (ADDR_EXPR, ptrtype, exp);
if (!cxx_mark_addressable (exp))
return error_mark_node;
- TREE_CONSTANT (adr) = staticp (exp);
- TREE_SIDE_EFFECTS (adr) = 0; /* Default would be, same as EXP. */
+ adr = build_nop (ptrtype, build_address (exp));
return adr;
}
/* This way is better for a COMPONENT_REF since it can
tree promoted_type;
type = TREE_TYPE (expr);
- my_friendly_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type), 20030703);
+ gcc_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type));
promoted_type = type_promotes_to (type);
if (type != promoted_type)
expr = cp_convert (promoted_type, expr);
build_conditional_expr (build_x_binary_op ((TREE_CODE (t) == MIN_EXPR
? LE_EXPR : GE_EXPR),
TREE_OPERAND (t, 0),
- TREE_OPERAND (t, 1)),
+ TREE_OPERAND (t, 1),
+ /*overloaded_p=*/NULL),
build_unary_op (code, TREE_OPERAND (t, 0), 0),
build_unary_op (code, TREE_OPERAND (t, 1), 0));
}
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;
if (TREE_CODE (member) == PSEUDO_DTOR_EXPR)
return member;
- my_friendly_assert (DECL_P (member) || BASELINK_P (member),
- 20020801);
+ gcc_assert (DECL_P (member) || BASELINK_P (member));
/* [expr.ref]
The type of the first expression shall be "class object" (of a
complete type). */
object_type = TREE_TYPE (object);
- if (!complete_type_or_else (object_type, object))
+ if (!currently_open_class (object_type)
+ && !complete_type_or_else (object_type, object))
return error_mark_node;
if (!CLASS_TYPE_P (object_type))
{
result = member;
/* If OBJECT has side-effects, they are supposed to occur. */
if (TREE_SIDE_EFFECTS (object))
- result = build (COMPOUND_EXPR, TREE_TYPE (result), object, result);
+ result = build2 (COMPOUND_EXPR, TREE_TYPE (result), object, result);
}
else if (TREE_CODE (member) == FIELD_DECL)
{
/*nonnull=*/1);
/* If we found the base successfully then we should be able
to convert to it successfully. */
- my_friendly_assert (object != error_mark_node,
- 20020801);
+ gcc_assert (object != error_mark_node);
}
/* Complain about other invalid uses of offsetof, even though they will
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))
+ && CLASSTYPE_NON_POD_P (object_type)
+ && ! skip_evaluation)
{
warning ("invalid access to non-static data member `%D' of NULL object",
member);
member_type = cp_build_qualified_type (member_type, type_quals);
}
- result = fold (build (COMPONENT_REF, member_type, object, member));
+ result = fold (build3 (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 = build3 (COMPONENT_REF, type, object, member, NULL_TREE);
}
else if (TREE_CODE (member) == CONST_DECL)
{
result = member;
/* If OBJECT has side-effects, they are supposed to occur. */
if (TREE_SIDE_EFFECTS (object))
- result = build (COMPOUND_EXPR, TREE_TYPE (result),
- object, result);
+ result = build2 (COMPOUND_EXPR, TREE_TYPE (result),
+ object, result);
}
else
{
{
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 ("destructor name `%T' does not match type `%T' of expression",
- dtor_type, 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))
- return build (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
- dtor_type);
- return lookup_member (object_type, complete_dtor_identifier,
+ if (!TYPE_HAS_DESTRUCTOR (dtor_type))
+ return build3 (PSEUDO_DTOR_EXPR, void_type_node, object, scope,
+ dtor_type);
+ 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
{
if (/* If OBJECT_TYPE is dependent, so is OBJECT.NAME. */
dependent_type_p (object_type)
+ /* If NAME is just an IDENTIFIER_NODE, then the expression
+ is dependent. */
+ || TREE_CODE (object) == IDENTIFIER_NODE
/* If NAME is "f<args>", where either 'f' or 'args' is
dependent, then the expression is dependent. */
|| (TREE_CODE (name) == TEMPLATE_ID_EXPR
|| (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);
}
The type of the first expression shall be "class object" (of a
complete type). */
- if (!complete_type_or_else (object_type, object))
+ if (!currently_open_class (object_type)
+ && !complete_type_or_else (object_type, object))
return error_mark_node;
if (!CLASS_TYPE_P (object_type))
{
if (BASELINK_P (name))
{
/* A member function that has already been looked up. */
- my_friendly_assert ((TREE_CODE (BASELINK_FUNCTIONS (name))
- == TEMPLATE_ID_EXPR),
- 20020805);
+ gcc_assert (TREE_CODE (BASELINK_FUNCTIONS (name)) == TEMPLATE_ID_EXPR);
member = name;
}
else
is_template_id = true;
template_args = TREE_OPERAND (name, 1);
name = TREE_OPERAND (name, 0);
+
+ if (TREE_CODE (name) == OVERLOAD)
+ name = DECL_NAME (get_first_fn (name));
+ else if (DECL_P (name))
+ name = DECL_NAME (name);
}
if (TREE_CODE (name) == SCOPE_REF)
or a BIT_NOT_EXPR. */
scope = TREE_OPERAND (name, 0);
name = TREE_OPERAND (name, 1);
- my_friendly_assert ((CLASS_TYPE_P (scope)
- || TREE_CODE (scope) == NAMESPACE_DECL),
- 20020804);
- my_friendly_assert ((TREE_CODE (name) == IDENTIFIER_NODE
- || TREE_CODE (name) == BIT_NOT_EXPR),
- 20020804);
+ gcc_assert (CLASS_TYPE_P (scope)
+ || TREE_CODE (scope) == NAMESPACE_DECL);
+ gcc_assert (TREE_CODE (name) == IDENTIFIER_NODE
+ || TREE_CODE (name) == BIT_NOT_EXPR);
/* If SCOPE is a namespace, then the qualified name does not
name a member of OBJECT_TYPE. */
/* 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;
+ }
}
else
{
expr = build_class_member_access_expr (object, member, access_path,
/*preserve_reference=*/false);
if (processing_template_decl && expr != error_mark_node)
- return build_min (COMPONENT_REF, TREE_TYPE (expr), orig_object,
- orig_name);
+ return build_min_non_dep (COMPONENT_REF, expr,
+ orig_object, orig_name, NULL_TREE);
return expr;
}
routine directly because it expects the object to be of class
type. */
ptrmem_type = TREE_TYPE (ptrmem);
- my_friendly_assert (TYPE_PTRMEMFUNC_P (ptrmem_type), 20020804);
+ gcc_assert (TYPE_PTRMEMFUNC_P (ptrmem_type));
member = lookup_member (ptrmem_type, member_name, /*protect=*/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));
+ return fold (build3 (COMPONENT_REF, member_type,
+ ptrmem, member, NULL_TREE));
}
/* Given an expression PTR for a pointer, return an expression
}
rval = build_new_op (INDIRECT_REF, LOOKUP_NORMAL, expr, NULL_TREE,
- NULL_TREE);
+ NULL_TREE, /*overloaded_p=*/NULL);
if (!rval)
rval = build_indirect_ref (expr, errorstring);
if (processing_template_decl && rval != error_mark_node)
- return build_min (INDIRECT_REF, TREE_TYPE (rval), orig_expr);
+ return build_min_non_dep (INDIRECT_REF, rval, orig_expr);
else
return rval;
}
tree
build_indirect_ref (tree ptr, const char *errorstring)
{
- register tree pointer, type;
+ tree pointer, type;
if (ptr == error_mark_node)
return error_mark_node;
case COMPOUND_EXPR:
{
tree value = build_array_ref (TREE_OPERAND (array, 1), idx);
- return build (COMPOUND_EXPR, TREE_TYPE (value),
- TREE_OPERAND (array, 0), value);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (value),
+ TREE_OPERAND (array, 0), value);
}
case COND_EXPR:
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;
would get a crash in store_bit_field/extract_bit_field when trying
to access a non-existent part of the register. */
if (TREE_CODE (idx) == INTEGER_CST
- && TYPE_VALUES (TREE_TYPE (array))
- && ! int_fits_type_p (idx, TYPE_VALUES (TREE_TYPE (array))))
+ && TYPE_DOMAIN (TREE_TYPE (array))
+ && ! int_fits_type_p (idx, TYPE_DOMAIN (TREE_TYPE (array))))
{
if (!cxx_mark_addressable (array))
return error_mark_node;
}
type = TREE_TYPE (TREE_TYPE (array));
- rval = build (ARRAY_REF, type, array, idx);
+ rval = build4 (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)
break;
default:
- abort ();
+ gcc_unreachable ();
}
/* Convert down to the right base before using the instance. First
if (instance_ptr == error_mark_node)
return error_mark_node;
/* ...and then the delta in the PMF. */
- instance_ptr = build (PLUS_EXPR, TREE_TYPE (instance_ptr),
- instance_ptr, delta);
+ instance_ptr = build2 (PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, delta);
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
vtbl = build_indirect_ref (vtbl, NULL);
/* Finally, extract the function pointer from the vtable. */
- e2 = fold (build (PLUS_EXPR, TREE_TYPE (vtbl), vtbl, idx));
+ e2 = fold (build2 (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. */
/* Make sure this doesn't get evaluated first inside one of the
branches of the COND_EXPR. */
if (instance_save_expr)
- e1 = build (COMPOUND_EXPR, TREE_TYPE (e1),
- instance_save_expr, e1);
+ e1 = build2 (COMPOUND_EXPR, TREE_TYPE (e1),
+ instance_save_expr, e1);
function = e1;
}
tree
build_function_call (tree function, tree params)
{
- register tree fntype, fndecl;
- register tree coerced_params;
- tree result;
- tree name = NULL_TREE, assembler_name = NULL_TREE;
+ tree fntype, fndecl;
+ tree coerced_params;
+ tree name = NULL_TREE;
int is_method;
tree original = function;
if (TREE_CODE (function) == FUNCTION_DECL)
{
name = DECL_NAME (function);
- assembler_name = DECL_ASSEMBLER_NAME (function);
mark_used (function);
fndecl = function;
if (coerced_params == error_mark_node)
return error_mark_node;
- /* Check for errors in format strings. */
-
- if (warn_format)
- check_function_format (NULL, TYPE_ATTRIBUTES (fntype), coerced_params);
+ /* Check for errors in format strings and inappropriately
+ null parameters. */
- /* 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_arguments (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
tree
convert_arguments (tree typelist, tree values, tree fndecl, int flags)
{
- register tree typetail, valtail;
- register tree result = NULL_TREE;
+ tree typetail, valtail;
+ tree result = NULL_TREE;
const char *called_thing = 0;
int i = 0;
valtail;
valtail = TREE_CHAIN (valtail), i++)
{
- register tree type = typetail ? TREE_VALUE (typetail) : 0;
- register tree val = TREE_VALUE (valtail);
+ tree type = typetail ? TREE_VALUE (typetail) : 0;
+ tree val = TREE_VALUE (valtail);
if (val == error_mark_node)
return error_mark_node;
if (!COMPLETE_TYPE_P (complete_type (type)))
{
- error ("parameter type of called function is incomplete");
- parmval = val;
+ if (fndecl)
+ error ("parameter %P of `%D' has incomplete type `%T'",
+ i, fndecl, type);
+ else
+ error ("parameter %P has incomplete type `%T'", i, type);
+ parmval = error_mark_node;
}
else
{
if (typetail != 0 && typetail != void_list_node)
{
- /* See if there are default arguments that can be used */
+ /* See if there are default arguments that can be used. */
if (TREE_PURPOSE (typetail)
&& TREE_CODE (TREE_PURPOSE (typetail)) != DEFAULT_ARG)
{
conversions on the operands. CODE is the kind of expression to build. */
tree
-build_x_binary_op (enum tree_code code, tree arg1, tree arg2)
+build_x_binary_op (enum tree_code code, tree arg1, tree arg2,
+ bool *overloaded_p)
{
tree orig_arg1;
tree orig_arg2;
if (code == DOTSTAR_EXPR)
expr = build_m_component_ref (arg1, arg2);
else
- expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
+ expr = build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE,
+ overloaded_p);
if (processing_template_decl && expr != error_mark_node)
- return build_min (code, TREE_TYPE (expr), orig_arg1, orig_arg2);
+ return build_min_non_dep (code, expr, orig_arg1, orig_arg2);
return expr;
}
int convert_p ATTRIBUTE_UNUSED)
{
tree op0, op1;
- register enum tree_code code0, code1;
+ enum tree_code code0, code1;
tree type0, type1;
/* Expression code to give to the expression when it is built.
Normally this is CODE, which is what the caller asked for,
but in some special cases we change it. */
- register enum tree_code resultcode = code;
+ enum tree_code resultcode = code;
/* Data type in which the computation is to be performed.
In the simplest cases this is the common type of the arguments. */
- register tree result_type = NULL;
+ tree result_type = NULL;
/* Nonzero means operands have already been type-converted
in whatever way is necessary.
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
- || code0 == COMPLEX_TYPE)
+ || code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
&& (code1 == INTEGER_TYPE || code1 == REAL_TYPE
- || code1 == COMPLEX_TYPE))
+ || code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE))
{
if (TREE_CODE (op1) == INTEGER_CST && integer_zerop (op1))
warning ("division by zero in `%E / 0'", op0);
else if (TREE_CODE (op1) == REAL_CST && real_zerop (op1))
warning ("division by zero in `%E / 0.'", op0);
+ if (code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
+ code0 = TREE_CODE (TREE_TYPE (TREE_TYPE (op0)));
+ if (code1 == COMPLEX_TYPE || code1 == VECTOR_TYPE)
+ code1 = TREE_CODE (TREE_TYPE (TREE_TYPE (op1)));
+
if (!(code0 == INTEGER_TYPE && code1 == INTEGER_TYPE))
resultcode = RDIV_EXPR;
else
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;
cp_convert (TREE_TYPE (pfn0),
integer_zero_node));
e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
- e2 = build (EQ_EXPR, boolean_type_node, pfn0, pfn1);
+ e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1);
e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
if (code == EQ_EXPR)
return e;
return cp_build_binary_op (EQ_EXPR, e, integer_zero_node);
}
- else if ((TYPE_PTRMEMFUNC_P (type0)
- && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0), type1))
- || (TYPE_PTRMEMFUNC_P (type1)
- && same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1), type0)))
- abort ();
+ else
+ {
+ gcc_assert (!TYPE_PTRMEMFUNC_P (type0)
+ || !same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type0),
+ type1));
+ gcc_assert (!TYPE_PTRMEMFUNC_P (type1)
+ || !same_type_p (TYPE_PTRMEMFUNC_FN_TYPE (type1),
+ type0));
+ }
+
break;
case MAX_EXPR:
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;
{
- register tree result = build (resultcode, build_type, op0, op1);
- register tree folded;
-
- folded = fold (result);
- if (folded == result)
- TREE_CONSTANT (folded) = TREE_CONSTANT (op0) & TREE_CONSTANT (op1);
+ tree result = fold (build2 (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
of pointer PTROP and integer INTOP. */
static tree
-cp_pointer_int_sum (enum tree_code resultcode, register tree ptrop,
- register tree intop)
+cp_pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
{
tree res_type = TREE_TYPE (ptrop);
The resulting tree has type int. */
static tree
-pointer_diff (register tree op0, register tree op1, register tree ptrtype)
+pointer_diff (tree op0, tree op1, tree ptrtype)
{
- register 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;
+ result = build2 (EXACT_DIV_EXPR, restype, op0, cp_convert (restype, op1));
+ return fold (result);
}
\f
/* Construct and perhaps optimize a tree representation
{
if (type_dependent_expression_p (xarg))
return build_min_nt (code, xarg, NULL_TREE);
+
+ /* For non-dependent pointer-to-member, the SCOPE_REF will be
+ processed during template substitution. Just compute the
+ right type here and build an ADDR_EXPR around it for
+ diagnostics. */
+ if (code == ADDR_EXPR && TREE_CODE (xarg) == SCOPE_REF)
+ {
+ tree type;
+ if (TREE_TYPE (xarg) == unknown_type_node)
+ type = unknown_type_node;
+ else if (TREE_CODE (TREE_TYPE (xarg)) == FUNCTION_TYPE)
+ type = build_pointer_type (TREE_TYPE (xarg));
+ else
+ type = build_ptrmem_type (TREE_OPERAND (xarg, 0),
+ TREE_TYPE (xarg));
+ return build_min (code, type, xarg, NULL_TREE);
+ }
+
xarg = build_non_dependent_expr (xarg);
}
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 */;
+ /* Don't look for a function. */;
else
- exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE);
+ exp = build_new_op (code, LOOKUP_NORMAL, xarg, NULL_TREE, NULL_TREE,
+ /*overloaded_p=*/NULL);
if (!exp && code == ADDR_EXPR)
{
/* A pointer to member-function can be formed only by saying
{
/* A single non-static member, make sure we don't allow a
pointer-to-member. */
- xarg = build (OFFSET_REF, TREE_TYPE (xarg),
- TREE_OPERAND (xarg, 0),
- ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
+ xarg = build2 (OFFSET_REF, TREE_TYPE (xarg),
+ TREE_OPERAND (xarg, 0),
+ ovl_cons (TREE_OPERAND (xarg, 1), NULL_TREE));
PTRMEM_OK_P (xarg) = ptrmem;
}
}
}
if (processing_template_decl && exp != error_mark_node)
- return build_min (code, TREE_TYPE (exp), orig_expr, NULL_TREE);
+ return build_min_non_dep (code, exp, orig_expr,
+ /*For {PRE,POST}{INC,DEC}REMENT_EXPR*/NULL_TREE);
return exp;
}
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;
+ addr = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (t)), t);
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.
build_unary_op (enum tree_code code, tree xarg, int noconvert)
{
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
- register tree arg = xarg;
- register tree argtype = 0;
+ tree arg = xarg;
+ tree argtype = 0;
const char *errstring = NULL;
tree val;
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;
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);
+ return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+ build_unary_op (code, real, 1), imag);
}
/* Report invalid types. */
0);
{
- register tree inc;
+ tree inc;
tree result_type = TREE_TYPE (arg);
arg = get_unwidened (arg, 0);
value = arg;
else
value = save_expr (arg);
- incremented = build (((code == PREINCREMENT_EXPR
- || code == POSTINCREMENT_EXPR)
- ? PLUS_EXPR : MINUS_EXPR),
- argtype, value, inc);
+ incremented = build2 (((code == PREINCREMENT_EXPR
+ || code == POSTINCREMENT_EXPR)
+ ? PLUS_EXPR : MINUS_EXPR),
+ argtype, value, inc);
modify = build_modify_expr (arg, NOP_EXPR, incremented);
- compound = build (COMPOUND_EXPR, TREE_TYPE (arg), modify, value);
+ compound = build2 (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;
}
val = boolean_increment (code, arg);
}
else
- val = build (code, TREE_TYPE (arg), arg, inc);
+ val = build2 (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
return cp_convert (result_type, val);
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)
- {
- if (!cxx_mark_addressable (TREE_OPERAND (arg, 0)))
- return error_mark_node;
- return cp_build_binary_op (PLUS_EXPR, TREE_OPERAND (arg, 0),
- TREE_OPERAND (arg, 1));
- }
-
/* Uninstantiated types are all functions. Taking the
address of a function is a no-op, so just return the
argument. */
- if (TREE_CODE (arg) == IDENTIFIER_NODE
- && IDENTIFIER_OPNAME_P (arg))
- {
- abort ();
- /* We don't know the type yet, so just work around the problem.
- We know that this will resolve to an lvalue. */
- return build1 (ADDR_EXPR, unknown_type_node, arg);
- }
+ gcc_assert (TREE_CODE (arg) != IDENTIFIER_NODE
+ || !IDENTIFIER_OPNAME_P (arg));
if (TREE_CODE (arg) == COMPONENT_REF && type_unknown_p (arg)
&& !really_overloaded_fn (TREE_OPERAND (arg, 1)))
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
- && TREE_CODE (TREE_OPERAND (arg, 1)) == BASELINK)
- arg = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
-
- 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 fn = BASELINK_FUNCTIONS (TREE_OPERAND (arg, 1));
+
+ /* We can only get here with a single static member
+ function. */
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL
+ && DECL_STATIC_FUNCTION_P (fn));
+ mark_used (fn);
+ addr = build_address (fn);
+ if (TREE_SIDE_EFFECTS (TREE_OPERAND (arg, 0)))
+ /* Do not lose object's side effects. */
+ addr = build2 (COMPOUND_EXPR, TREE_TYPE (addr),
+ TREE_OPERAND (arg, 0), addr);
+ }
else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1)))
{
error ("attempt to take address of bit-field structure member `%D'",
}
else
{
- /* 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)),
ba_check, NULL);
rval = build_base_path (PLUS_EXPR, rval, binfo, 1);
- rval = build_nop (argtype, rval);
- addr = fold (build (PLUS_EXPR, argtype, rval,
- cp_convert (argtype, byte_position (field))));
+
+ TREE_OPERAND (arg, 0) = build_indirect_ref (rval, NULL);
+ addr = build_address (arg);
}
if (TREE_CODE (argtype) == POINTER_TYPE
if (TREE_CODE (arg) == COMPOUND_EXPR)
{
tree real_result = build_unary_op (code, TREE_OPERAND (arg, 1), 0);
- return build (COMPOUND_EXPR, TREE_TYPE (real_result),
- TREE_OPERAND (arg, 0), real_result);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
+ TREE_OPERAND (arg, 0), real_result);
}
/* Handle (a ? b : c) used as an "lvalue". */
if (TREE_SIDE_EFFECTS (lvalue))
{
lvalue = stabilize_reference (lvalue);
- arg = build (TREE_CODE (arg), TREE_TYPE (arg),
- lvalue, TREE_OPERAND (arg, 1));
+ arg = build2 (TREE_CODE (arg), TREE_TYPE (arg),
+ lvalue, TREE_OPERAND (arg, 1));
}
return unary_complex_lvalue
- (code, build (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue));
+ (code, build2 (COMPOUND_EXPR, TREE_TYPE (lvalue), arg, lvalue));
}
if (code != ADDR_EXPR)
|| TREE_CODE (arg) == INIT_EXPR)
{
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;
+ arg = build2 (COMPOUND_EXPR, TREE_TYPE (real_result),
+ arg, real_result);
+ TREE_NO_WARNING (arg) = 1;
return arg;
}
{
tree t;
- my_friendly_assert (TREE_CODE (arg) != SCOPE_REF, 313);
+ gcc_assert (TREE_CODE (arg) != SCOPE_REF);
if (TREE_CODE (arg) != OFFSET_REF)
return 0;
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;
}
}
if (TREE_CODE (arg) == SAVE_EXPR && TREE_CODE (targ) == INDIRECT_REF)
- return build (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
+ return build3 (SAVE_EXPR, build_pointer_type (TREE_TYPE (arg)),
TREE_OPERAND (targ, 0), current_function_decl, NULL);
}
bool
cxx_mark_addressable (tree exp)
{
- register tree x = exp;
+ tree x = exp;
while (1)
switch (TREE_CODE (x))
if (x == current_class_ptr)
{
error ("cannot take the address of `this', which is an rvalue expression");
- TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later */
+ TREE_ADDRESSABLE (x) = 1; /* so compiler doesn't die later. */
return true;
}
- /* FALLTHRU */
+ /* Fall through. */
case VAR_DECL:
/* Caller should not be trying to mark initialized
constant fields addressable. */
- my_friendly_assert (DECL_LANG_SPECIFIC (x) == 0
- || DECL_IN_AGGR_P (x) == 0
- || TREE_STATIC (x)
- || DECL_EXTERNAL (x), 314);
- /* FALLTHRU */
+ gcc_assert (DECL_LANG_SPECIFIC (x) == 0
+ || DECL_IN_AGGR_P (x) == 0
+ || TREE_STATIC (x)
+ || DECL_EXTERNAL (x));
+ /* Fall through. */
case CONST_DECL:
case RESULT_DECL:
warning ("address requested for `%D', which is declared `register'",
x);
TREE_ADDRESSABLE (x) = 1;
- put_var_into_stack (x, /*rescan=*/true);
return true;
case FUNCTION_DECL:
TREE_ADDRESSABLE (x) = 1;
- TREE_ADDRESSABLE (DECL_ASSEMBLER_NAME (x)) = 1;
return true;
case CONSTRUCTOR:
IFEXP is type-dependent, even though the eventual type of the
expression doesn't dependent on IFEXP. */
if (type_dependent_expression_p (ifexp)
- || type_dependent_expression_p (op1)
+ /* As a GNU extension, the middle operand may be omitted. */
+ || (op1 && type_dependent_expression_p (op1))
|| type_dependent_expression_p (op2))
return build_min_nt (COND_EXPR, ifexp, op1, op2);
ifexp = build_non_dependent_expr (ifexp);
- op1 = build_non_dependent_expr (op1);
+ if (op1)
+ op1 = build_non_dependent_expr (op1);
op2 = build_non_dependent_expr (op2);
}
expr = build_conditional_expr (ifexp, op1, op2);
if (processing_template_decl && expr != error_mark_node)
- return build_min (COND_EXPR, TREE_TYPE (expr),
- orig_ifexp, orig_op1, orig_op2);
+ return build_min_non_dep (COND_EXPR, expr,
+ orig_ifexp, orig_op1, orig_op2);
return expr;
}
\f
/* Given a list of expressions, return a compound expression
- that performs them all and returns the value of the last of them. */
+ that performs them all and returns the value of the last of them. */
tree build_x_compound_expr_from_list (tree list, const char *msg)
{
op2 = build_non_dependent_expr (op2);
}
- result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE);
+ result = build_new_op (COMPOUND_EXPR, LOOKUP_NORMAL, op1, op2, NULL_TREE,
+ /*overloaded_p=*/NULL);
if (!result)
result = build_compound_expr (op1, op2);
if (processing_template_decl && result != error_mark_node)
- return build_min (COMPOUND_EXPR, TREE_TYPE (result),
- orig_op1, orig_op2);
+ return build_min_non_dep (COMPOUND_EXPR, result, orig_op1, orig_op2);
+
return result;
}
-/* Build a compound expression. */
+/* Build a compound expression. */
tree
build_compound_expr (tree lhs, tree rhs)
{
/* If the rhs is a TARGET_EXPR, then build the compound
expression inside the target_expr's initializer. This
- helps the compiler to eliminate unncessary temporaries. */
+ helps the compiler to eliminate unnecessary temporaries. */
tree init = TREE_OPERAND (rhs, 1);
- init = build (COMPOUND_EXPR, TREE_TYPE (init), lhs, init);
+ init = build2 (COMPOUND_EXPR, TREE_TYPE (init), lhs, init);
TREE_OPERAND (rhs, 1) = init;
return rhs;
}
- return build (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
+ return build2 (COMPOUND_EXPR, TREE_TYPE (rhs), lhs, rhs);
}
/* Issue an error message if casting from SRC_TYPE to DEST_TYPE casts
if (processing_template_decl)
{
- tree t = build_min (STATIC_CAST_EXPR, type, expr);
- return t;
+ expr = build_min (STATIC_CAST_EXPR, type, expr);
+ /* We don't know if it will or will not have side effects. */
+ TREE_SIDE_EFFECTS (expr) = 1;
+ return expr;
}
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
(TREE_TYPE (type))))
&& at_least_as_qualified_p (TREE_TYPE (type), intype))
{
- /* At this point we have checked all of the conditions except
- that B is not a virtual base class of D. That will be
- checked by build_base_path. */
- tree base = lookup_base (TREE_TYPE (type), intype, ba_any, NULL);
+ /* 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*. */
+ /* 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
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]
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);
+ /* 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))
tree base;
check_for_casting_away_constness (intype, type, "static_cast");
- base = lookup_base (TREE_TYPE (type), TREE_TYPE (intype),
- ba_check | ba_quiet, NULL);
+ 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)))
{
if (processing_template_decl)
{
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
+
+ if (!TREE_SIDE_EFFECTS (t)
+ && type_dependent_expression_p (expr))
+ /* There might turn out to be side effects inside expr. */
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
if (processing_template_decl)
{
tree t = build_min (CONST_CAST_EXPR, type, expr);
+
+ if (!TREE_SIDE_EFFECTS (t)
+ && type_dependent_expression_p (expr))
+ /* There might turn out to be side effects inside expr. */
+ TREE_SIDE_EFFECTS (t) = 1;
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)
{
tree
build_c_cast (tree type, tree expr)
{
- register tree value = expr;
+ tree value = expr;
tree otype;
if (type == error_mark_node || expr == error_mark_node)
{
tree t = build_min (CAST_EXPR, type,
tree_cons (NULL_TREE, value, NULL_TREE));
+ /* We don't know if it will or will not have side effects. */
+ TREE_SIDE_EFFECTS (t) = 1;
return t;
}
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);
}
}
tree
build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
{
- register tree result;
+ tree result;
tree newrhs = rhs;
tree lhstype = TREE_TYPE (lhs);
tree olhstype = lhstype;
- tree olhs = lhs;
+ tree olhs = NULL_TREE;
+ bool plain_assign = (modifycode == NOP_EXPR);
/* Avoid duplicate error messages from operands that had errors. */
if (lhs == error_mark_node || rhs == error_mark_node)
/* Handle control structure constructs used as "lvalues". */
switch (TREE_CODE (lhs))
{
- /* Handle --foo = 5; as these are valid constructs in C++ */
+ /* Handle --foo = 5; as these are valid constructs in C++. */
case PREDECREMENT_EXPR:
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)),
- TREE_OPERAND (lhs, 1));
- return build (COMPOUND_EXPR, lhstype,
- lhs,
- build_modify_expr (TREE_OPERAND (lhs, 0),
- modifycode, rhs));
+ lhs = build2 (TREE_CODE (lhs), TREE_TYPE (lhs),
+ stabilize_reference (TREE_OPERAND (lhs, 0)),
+ TREE_OPERAND (lhs, 1));
+ return build2 (COMPOUND_EXPR, lhstype,
+ lhs,
+ build_modify_expr (TREE_OPERAND (lhs, 0),
+ modifycode, rhs));
/* Handle (a, b) used as an "lvalue". */
case COMPOUND_EXPR:
modifycode, rhs);
if (newrhs == error_mark_node)
return error_mark_node;
- return build (COMPOUND_EXPR, lhstype,
- TREE_OPERAND (lhs, 0), newrhs);
+ return build2 (COMPOUND_EXPR, lhstype,
+ 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));
+ lhs = build2 (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;
- return build (COMPOUND_EXPR, lhstype, lhs, newrhs);
+ return build2 (COMPOUND_EXPR, lhstype, lhs, newrhs);
/* Handle (a ? b : c) used as an "lvalue". */
case COND_EXPR:
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 = build2 (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
+ return cond;
}
default:
{
if (TREE_CODE (rhs) == CONSTRUCTOR)
{
- my_friendly_assert (same_type_p (TREE_TYPE (rhs), lhstype),
- 20011220);
- result = build (INIT_EXPR, lhstype, lhs, rhs);
+ if (! same_type_p (TREE_TYPE (rhs), lhstype))
+ /* Call convert to generate an error; see PR 11063. */
+ rhs = convert (lhstype, rhs);
+ result = build2 (INIT_EXPR, lhstype, lhs, rhs);
TREE_SIDE_EFFECTS (result) = 1;
return result;
}
else if (! IS_AGGR_TYPE (lhstype))
- /* Do the default thing */;
+ /* Do the default thing. */;
else
{
result = build_special_member_call (lhs, complete_ctor_identifier,
build_tree_list (NULL_TREE, rhs),
- TYPE_BINFO (lhstype),
- LOOKUP_NORMAL);
+ lhstype, LOOKUP_NORMAL);
if (result == NULL_TREE)
return error_mark_node;
return result;
{
/* `operator=' is not an inheritable operator. */
if (! IS_AGGR_TYPE (lhstype))
- /* Do the default thing */;
+ /* Do the default thing. */;
else
{
result = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL,
- lhs, rhs, make_node (NOP_EXPR));
+ lhs, rhs, make_node (NOP_EXPR),
+ /*overloaded_p=*/NULL);
if (result == NULL_TREE)
return error_mark_node;
return result;
value with the RHS producing the value we should actually
store into the LHS. */
- my_friendly_assert (!PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE),
- 978652);
+ gcc_assert (!PROMOTES_TO_AGGR_TYPE (lhstype, REFERENCE_TYPE));
lhs = stabilize_reference (lhs);
newrhs = cp_build_binary_op (modifycode, lhs, rhs);
if (newrhs == error_mark_node)
/* Now it looks like a plain assignment. */
modifycode = NOP_EXPR;
}
- my_friendly_assert (TREE_CODE (lhstype) != REFERENCE_TYPE, 20011220);
- my_friendly_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE,
- 20011220);
+ gcc_assert (TREE_CODE (lhstype) != REFERENCE_TYPE);
+ gcc_assert (TREE_CODE (TREE_TYPE (newrhs)) != REFERENCE_TYPE);
}
- /* Handle a cast used as an "lvalue".
- We have already performed any binary operator using the value as cast.
- Now convert the result to the cast type of the lhs,
- and then true type of the lhs and store it there;
- then convert result back to the cast type to be the value
- of the assignment. */
-
- switch (TREE_CODE (lhs))
- {
- case NOP_EXPR:
- case CONVERT_EXPR:
- case FLOAT_EXPR:
- case FIX_TRUNC_EXPR:
- case FIX_FLOOR_EXPR:
- case FIX_ROUND_EXPR:
- case FIX_CEIL_EXPR:
- {
- tree inner_lhs = TREE_OPERAND (lhs, 0);
- tree result;
-
- if (TREE_CODE (TREE_TYPE (newrhs)) == ARRAY_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
- || TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
- newrhs = decay_conversion (newrhs);
-
- /* ISO C++ 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 ("ISO C++ forbids cast to non-reference type used as lvalue");
-
- result = build_modify_expr (inner_lhs, NOP_EXPR,
- cp_convert (TREE_TYPE (inner_lhs),
- cp_convert (lhstype, newrhs)));
- if (result == error_mark_node)
- return result;
- return cp_convert (TREE_TYPE (lhs), result);
- }
-
- default:
- break;
- }
-
- /* Now we have handled acceptable kinds of LHS that are not truly lvalues.
- Reject anything strange now. */
-
+ /* The left-hand side must be an lvalue. */
if (!lvalue_or_else (lhs, "assignment"))
return error_mark_node;
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;
}
accidental self-initialization. So we force the TARGET_EXPR to be
expanded without a target. */
if (TREE_CODE (newrhs) == TARGET_EXPR)
- newrhs = build (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
- TREE_OPERAND (newrhs, 0));
+ newrhs = build2 (COMPOUND_EXPR, TREE_TYPE (newrhs), newrhs,
+ TREE_OPERAND (newrhs, 0));
}
if (newrhs == error_mark_node)
return error_mark_node;
- result = build (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
- lhstype, lhs, newrhs);
+ result = build2 (modifycode == NOP_EXPR ? MODIFY_EXPR : INIT_EXPR,
+ lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
+ if (!plain_assign)
+ TREE_NO_WARNING (result) = 1;
/* If we got the LHS in a different type for storing in,
convert the result back to the nominal type of LHS
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;
+ result = build2 (COMPOUND_EXPR, olhstype, result, olhs);
+ TREE_NO_WARNING (result) = 1;
return result;
}
return convert_for_assignment (olhstype, result, "assignment",
if (modifycode != NOP_EXPR)
{
tree rval = build_new_op (MODIFY_EXPR, LOOKUP_NORMAL, lhs, rhs,
- make_node (modifycode));
+ make_node (modifycode),
+ /*overloaded_p=*/NULL);
if (rval)
- return rval;
+ {
+ TREE_NO_WARNING (rval) = 1;
+ return rval;
+ }
}
return build_modify_expr (lhs, modifycode, rhs);
}
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)
}
/* Just adjust the DELTA field. */
- my_friendly_assert (TREE_TYPE (delta) == ptrdiff_type_node, 20030727);
+ gcc_assert (same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (delta), ptrdiff_type_node));
if (TARGET_PTRMEMFUNC_VBIT_LOCATION == ptrmemfunc_vbit_in_delta)
n = cp_build_binary_op (LSHIFT_EXPR, n, integer_one_node);
delta = cp_build_binary_op (PLUS_EXPR, delta, n);
return instantiate_type (type, pfn, tf_error | tf_warning);
fn = TREE_OPERAND (pfn, 0);
- my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
return make_ptrmem_cst (to_type, fn);
}
given by CST.
??? There is no consistency as to the types returned for the above
- values. Some code acts as if its a sizetype and some as if its
+ values. Some code acts as if it were a sizetype and some as if it were
integer_type_node. */
void
tree fn = PTRMEM_CST_MEMBER (cst);
tree ptr_class, fn_class;
- my_friendly_assert (TREE_CODE (fn) == FUNCTION_DECL, 0);
+ gcc_assert (TREE_CODE (fn) == FUNCTION_DECL);
/* The class that the function belongs to. */
fn_class = DECL_CONTEXT (fn);
fn; the call will do the opposite adjustment. */
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)));
+ *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
+ *delta, BINFO_OFFSET (binfo)));
/* We set PFN to the vtable offset at which the function can be
found, plus one (unless ptrmemfunc_vbit_in_delta, in which
case delta is shifted left, and then incremented). */
*pfn = DECL_VINDEX (fn);
- *pfn = fold (build (MULT_EXPR, integer_type_node, *pfn,
- TYPE_SIZE_UNIT (vtable_entry_type)));
+ *pfn = fold (build2 (MULT_EXPR, integer_type_node, *pfn,
+ TYPE_SIZE_UNIT (vtable_entry_type)));
switch (TARGET_PTRMEMFUNC_VBIT_LOCATION)
{
case ptrmemfunc_vbit_in_pfn:
- *pfn = fold (build (PLUS_EXPR, integer_type_node, *pfn,
- integer_one_node));
+ *pfn = fold (build2 (PLUS_EXPR, integer_type_node, *pfn,
+ integer_one_node));
break;
case ptrmemfunc_vbit_in_delta:
- *delta = fold (build (LSHIFT_EXPR, TREE_TYPE (*delta),
- *delta, integer_one_node));
- *delta = fold (build (PLUS_EXPR, TREE_TYPE (*delta),
- *delta, integer_one_node));
+ *delta = fold (build2 (LSHIFT_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node));
+ *delta = fold (build2 (PLUS_EXPR, TREE_TYPE (*delta),
+ *delta, integer_one_node));
break;
default:
- abort ();
+ gcc_unreachable ();
}
*pfn = fold (build1 (NOP_EXPR, TYPE_PTRMEMFUNC_FN_TYPE (type),
}
/* 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'",
convert_for_assignment (tree type, tree rhs,
const char *errtype, tree fndecl, int parmnum)
{
- register tree rhstype;
- register enum tree_code coder;
+ tree rhstype;
+ enum tree_code coder;
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
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)
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)
{
convert_for_initialization (tree exp, tree type, tree rhs, int flags,
const char *errtype, tree fndecl, int parmnum)
{
- register enum tree_code codel = TREE_CODE (type);
- register tree rhstype;
- register enum tree_code coder;
+ enum tree_code codel = TREE_CODE (type);
+ tree rhstype;
+ enum tree_code coder;
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Strip such NOP_EXPRs, since RHS is used in non-lvalue context. */
return convert_for_assignment (type, rhs, errtype, fndecl, parmnum);
}
\f
-/* Expand an ASM statement with operands, handling output operands
- that are not variables or INDIRECT_REFS by transforming such
- cases into cases that expand_asm_operands can handle.
-
- Arguments are same as for expand_asm_operands.
-
- We don't do default conversions on all inputs, because it can screw
- up operands that are expected to be in memory. */
-
-void
-c_expand_asm_operands (tree string, tree outputs, tree inputs, tree clobbers,
- int vol, const char *filename, int line)
-{
- int noutputs = list_length (outputs);
- register int i;
- /* o[I] is the place that output number I should be written. */
- register tree *o = alloca (noutputs * sizeof (tree));
- register tree tail;
-
- /* Record the contents of OUTPUTS before it is modified. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- o[i] = TREE_VALUE (tail);
-
- /* Generate the ASM_OPERANDS insn;
- store into the TREE_VALUEs of OUTPUTS some trees for
- where the values were actually stored. */
- expand_asm_operands (string, outputs, inputs, clobbers, vol, filename, line);
-
- /* Copy all the intermediate outputs into the specified outputs. */
- for (i = 0, tail = outputs; tail; tail = TREE_CHAIN (tail), i++)
- {
- if (o[i] != TREE_VALUE (tail))
- {
- expand_expr (build_modify_expr (o[i], NOP_EXPR, TREE_VALUE (tail)),
- const0_rtx, VOIDmode, EXPAND_NORMAL);
- free_temp_slots ();
-
- /* Restore the original value so that it's correct the next
- time we expand this function. */
- TREE_VALUE (tail) = o[i];
- }
- /* Detect modification of read-only values.
- (Otherwise done by build_modify_expr.) */
- else
- {
- tree type = TREE_TYPE (o[i]);
- 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);
- }
- }
-
- /* Those MODIFY_EXPRs could do autoincrements. */
- emit_queue ();
-}
-\f
/* If RETVAL is the address of, or a reference to, a local variable or
temporary give an appropriate warning. */
}
}
- if (TREE_CODE (whats_returned) == VAR_DECL
+ if (DECL_P (whats_returned)
&& DECL_NAME (whats_returned)
&& DECL_FUNCTION_SCOPE_P (whats_returned)
&& !(TREE_STATIC (whats_returned)
return value, the named return value is used. */
result = DECL_RESULT (current_function_decl);
valtype = TREE_TYPE (result);
- my_friendly_assert (valtype != NULL_TREE, 19990924);
+ gcc_assert (valtype != NULL_TREE);
fn_returns_value_p = !VOID_TYPE_P (valtype);
if (!retval && DECL_NAME (result) && fn_returns_value_p)
retval = result;
/* Effective C++ rule 15. See also start_function. */
if (warn_ecpp
- && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR)
- && retval != current_class_ref)
- warning ("`operator=' should return a reference to `*this'");
+ && DECL_NAME (current_function_decl) == ansi_assopname(NOP_EXPR))
+ {
+ bool warn = true;
+
+ /* The function return type must be a reference to the current
+ class. */
+ if (TREE_CODE (valtype) == REFERENCE_TYPE
+ && same_type_ignoring_top_level_qualifiers_p
+ (TREE_TYPE (valtype), TREE_TYPE (current_class_ref)))
+ {
+ /* Returning '*this' is obviously OK. */
+ if (retval == current_class_ref)
+ warn = false;
+ /* If we are calling a function whose return type is the same of
+ the current class reference, it is ok. */
+ else if (TREE_CODE (retval) == INDIRECT_REF
+ && TREE_CODE (TREE_OPERAND (retval, 0)) == CALL_EXPR)
+ warn = false;
+ }
+
+ if (warn)
+ warning ("`operator=' should return a reference to `*this'");
+ }
/* The fabled Named Return Value optimization, as per [class.copy]/15:
returned expression uses the chosen variable somehow. And people expect
this restriction, anyway. (jason 2000-11-19)
- See finish_function, genrtl_start_function, and declare_return_variable
- 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)
{
else if (! current_function_returns_struct
&& TREE_CODE (retval) == TARGET_EXPR
&& TREE_CODE (TREE_OPERAND (retval, 1)) == AGGR_INIT_EXPR)
- retval = build (COMPOUND_EXPR, TREE_TYPE (retval), retval,
- TREE_OPERAND (retval, 0));
+ retval = build2 (COMPOUND_EXPR, TREE_TYPE (retval), retval,
+ TREE_OPERAND (retval, 0));
else
maybe_warn_about_returning_address_of_local (retval);
}
/* Actually copy the value returned into the appropriate location. */
if (retval && retval != result)
- retval = build (INIT_EXPR, TREE_TYPE (result), result, retval);
+ retval = build2 (INIT_EXPR, TREE_TYPE (result), result, retval);
return retval;
}
return TYPE_QUALS (type);
}
-/* Returns nonzero if the TYPE contains a mutable member */
+/* Returns nonzero if the TYPE contains a mutable member. */
bool
cp_has_mutable_p (tree type)