/* 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, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
+ 2011, 2012
Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com)
index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
- /* If T1 and T2 belong to template parm lists of different size,
- let's assume they are different. */
- if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
- != TEMPLATE_PARM_NUM_SIBLINGS (index2))
- return false;
-
/* Then compare their relative position. */
if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
|| TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
if (error_operand_p (exp))
return error_mark_node;
- if (NULLPTR_TYPE_P (type))
+ if (NULLPTR_TYPE_P (type) && !TREE_SIDE_EFFECTS (exp))
return nullptr_node;
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
return error_mark_node;
}
+ /* Don't let an array compound literal decay to a pointer. It can
+ still be used to initialize an array or bind to a reference. */
+ if (TREE_CODE (exp) == TARGET_EXPR)
+ {
+ error ("taking address of temporary array");
+ return error_mark_node;
+ }
+
ptrtype = build_pointer_type (TREE_TYPE (type));
if (TREE_CODE (exp) == VAR_DECL)
tf_warning_or_error);
expr = (adjust_result_of_qualified_name_lookup
(expr, dtor_type, object_type));
+ if (scope == NULL_TREE)
+ /* We need to call adjust_result_of_qualified_name_lookup in case the
+ destructor names a base class, but we unset BASELINK_QUALIFIED_P so
+ that we still get virtual function binding. */
+ BASELINK_QUALIFIED_P (expr) = false;
return expr;
}
return error_mark_node;
}
/* ...and then the delta in the PMF. */
- instance_ptr = fold_build_pointer_plus (instance_ptr, delta);
+ instance_ptr = build2 (POINTER_PLUS_EXPR, TREE_TYPE (instance_ptr),
+ instance_ptr, fold_convert (sizetype, delta));
/* Hand back the adjusted 'this' argument to our caller. */
*instance_ptrptr = instance_ptr;
return expr;
}
+/* Return whether OP is an expression of enum type cast to integer
+ type. In C++ even unsigned enum types are cast to signed integer
+ types. We do not want to issue warnings about comparisons between
+ signed and unsigned types when one of the types is an enum type.
+ Those warnings are always false positives in practice. */
+
+static bool
+enum_cast_to_int (tree op)
+{
+ if (TREE_CODE (op) == NOP_EXPR
+ && TREE_TYPE (op) == integer_type_node
+ && TREE_CODE (TREE_TYPE (TREE_OPERAND (op, 0))) == ENUMERAL_TYPE
+ && TYPE_UNSIGNED (TREE_TYPE (TREE_OPERAND (op, 0))))
+ return true;
+
+ /* The cast may have been pushed into a COND_EXPR. */
+ if (TREE_CODE (op) == COND_EXPR)
+ return (enum_cast_to_int (TREE_OPERAND (op, 1))
+ || enum_cast_to_int (TREE_OPERAND (op, 2)));
+
+ return false;
+}
+
/* For the c-common bits. */
tree
build_binary_op (location_t location, enum tree_code code, tree op0, tree op1,
if ((short_compare || code == MIN_EXPR || code == MAX_EXPR)
&& warn_sign_compare
- && !TREE_NO_WARNING (orig_op0)
- && !TREE_NO_WARNING (orig_op1)
/* Do not warn until the template is instantiated; we cannot
bound the ranges of the arguments until that point. */
&& !processing_template_decl
&& (complain & tf_warning)
- && c_inhibit_evaluation_warnings == 0)
+ && c_inhibit_evaluation_warnings == 0
+ /* Even unsigned enum types promote to signed int. We don't
+ want to issue -Wsign-compare warnings for this case. */
+ && !enum_cast_to_int (orig_op0)
+ && !enum_cast_to_int (orig_op1))
{
warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1,
result_type, resultcode);
{
tree intype;
tree result;
+ cp_lvalue_kind clk;
/* Assume the cast is valid. */
*valid_p = true;
- intype = TREE_TYPE (expr);
+ intype = unlowered_expr_type (expr);
/* Save casted types in the function's used types hash table. */
used_types_insert (type);
cv2 T2 if cv2 T2 is reference-compatible with cv1 T1 (8.5.3)." */
if (TREE_CODE (type) == REFERENCE_TYPE
&& TYPE_REF_IS_RVALUE (type)
- && real_lvalue_p (expr)
+ && (clk = real_lvalue_p (expr))
&& reference_related_p (TREE_TYPE (type), intype)
&& (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
{
- /* Handle the lvalue case here by casting to lvalue reference and
- then changing it to an rvalue reference. Casting an xvalue to
- rvalue reference will be handled by the main code path. */
- tree lref = cp_build_reference_type (TREE_TYPE (type), false);
- result = (perform_direct_initialization_if_possible
- (lref, expr, c_cast_p, complain));
- result = cp_fold_convert (type, result);
- /* Make sure we don't fold back down to a named rvalue reference,
- because that would be an lvalue. */
- if (DECL_P (result))
- result = build1 (NON_LVALUE_EXPR, type, result);
- return convert_from_reference (result);
+ if (clk == clk_ordinary)
+ {
+ /* Handle the (non-bit-field) lvalue case here by casting to
+ lvalue reference and then changing it to an rvalue reference.
+ Casting an xvalue to rvalue reference will be handled by the
+ main code path. */
+ tree lref = cp_build_reference_type (TREE_TYPE (type), false);
+ result = (perform_direct_initialization_if_possible
+ (lref, expr, c_cast_p, complain));
+ result = cp_fold_convert (type, result);
+ /* Make sure we don't fold back down to a named rvalue reference,
+ because that would be an lvalue. */
+ if (DECL_P (result))
+ result = build1 (NON_LVALUE_EXPR, type, result);
+ return convert_from_reference (result);
+ }
+ else
+ /* For a bit-field or packed field, bind to a temporary. */
+ expr = rvalue (expr);
}
/* Resolve overloaded address here rather than once in
else if (TYPE_PTR_P (type) && INTEGRAL_OR_ENUMERATION_TYPE_P (intype))
/* OK */
;
+ else if ((INTEGRAL_OR_ENUMERATION_TYPE_P (type)
+ || TYPE_PTR_P (type) || TYPE_PTR_TO_MEMBER_P (type))
+ && same_type_p (type, intype))
+ /* DR 799 */
+ return fold_if_not_in_template (build_nop (type, expr));
else if ((TYPE_PTRFN_P (type) && TYPE_PTRFN_P (intype))
|| (TYPE_PTRMEMFUNC_P (type) && TYPE_PTRMEMFUNC_P (intype)))
return fold_if_not_in_template (build_nop (type, expr));
/* Handle null pointer to member function conversions. */
if (null_ptr_cst_p (pfn))
{
- pfn = build_c_cast (input_location, type, nullptr_node);
+ pfn = build_c_cast (input_location, type, pfn);
return build_ptrmemfunc1 (to_type,
integer_zero_node,
pfn);
&& TREE_CODE (retval) == VAR_DECL
&& DECL_CONTEXT (retval) == current_function_decl
&& ! TREE_STATIC (retval)
- && ! DECL_ANON_UNION_VAR_P (retval)
+ /* And not a lambda or anonymous union proxy. */
+ && !DECL_HAS_VALUE_EXPR_P (retval)
&& (DECL_ALIGN (retval)
>= DECL_ALIGN (DECL_RESULT (current_function_decl)))
/* The cv-unqualified type of the returned value must be the
Note that these conditions are similar to, but not as strict as,
the conditions for the named return value optimization. */
if ((cxx_dialect != cxx98)
- && (TREE_CODE (retval) == VAR_DECL
+ && ((TREE_CODE (retval) == VAR_DECL
+ && !DECL_HAS_VALUE_EXPR_P (retval))
|| TREE_CODE (retval) == PARM_DECL)
&& DECL_CONTEXT (retval) == current_function_decl
&& !TREE_STATIC (retval)
constructor can produce constant init, so rely on cp_finish_decl to
clear TREE_READONLY if the variable has non-constant init. */
- /* If the type has a mutable component, that component might be
- modified. */
- if (TYPE_HAS_MUTABLE_P (type))
+ /* If the type has (or might have) a mutable component, that component
+ might be modified. */
+ if (TYPE_HAS_MUTABLE_P (type) || !COMPLETE_TYPE_P (type))
type_quals &= ~TYPE_QUAL_CONST;
c_apply_type_quals_to_decl (type_quals, decl);
bool *long_long_unsigned_p, bool *long_double_p)
{
tree argtypes = TYPE_ARG_TYPES (TREE_TYPE (decl));
+
+ *long_long_unsigned_p = false;
+ *long_double_p = false;
if (processing_template_decl || processing_specialization)
return argtypes == void_list_node;
else
int arity;
int max_arity = 2;
- *long_long_unsigned_p = false;
- *long_double_p = false;
-
/* Count the number and type of arguments and check for ellipsis. */
for (argtype = argtypes, arity = 0;
argtype && argtype != void_list_node;
return true;
}
}
-