2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-18 01:20:48 +08:00

re PR c++/27471 (ICE within build_c_cast cp/typeck.c:5434)

PR c++/27471
	PR c++/27506
	* typeck.c (decay_conversion): Convert bitfields to their declared
	types here.  Improve documentation.  Avoid use of cp_convert.
	(default_conversion): Make it static.  Perform integral promotions
	before lvalue-to-rvalue, function-to-pointer, and array-to-pointer
	conversions.
	* init.c (build_init): Remove.
	(expand_default_init): Do not call rvalue.
	* call.c (null_ptr_cst_p): Robustify.
	(build_conditional_expr): Tidy.
	* except.c (build_throw): Do not perform lvalue-to-rvalue
	conversion on operand before initializing temporary.
	* tree.c (convert.h): Include it.
	(convert_bitfield_to_declared_type): Use convert_to_integer, not
	cp_convert.
	(rvalue): Don't convert bitfields to their declared type here.
	* cp-tree.h (build_init): Remove.
	(default_conversion): Likewise.
	* typeck2.c (build_m_component_ref): Do not perform
	lvalue-to-rvalue, function-to-pointer, or array-to-pointer
	conversions here.  Correct error message.
	PR c++/27471
	PR c++/27506
	* g++.dg/conversion/bitfield5.C: New test.
	* g++.dg/conversion/bitfield6.C: New test.

From-SVN: r113902
This commit is contained in:
Mark Mitchell 2006-05-19 03:01:14 +00:00 committed by Mark Mitchell
parent 84e2e37098
commit 41990f9646
11 changed files with 172 additions and 72 deletions

@ -1,3 +1,28 @@
2006-05-18 Mark Mitchell <mark@codesourcery.com>
PR c++/27471
PR c++/27506
* typeck.c (decay_conversion): Convert bitfields to their declared
types here. Improve documentation. Avoid use of cp_convert.
(default_conversion): Make it static. Perform integral promotions
before lvalue-to-rvalue, function-to-pointer, and array-to-pointer
conversions.
* init.c (build_init): Remove.
(expand_default_init): Do not call rvalue.
* call.c (null_ptr_cst_p): Robustify.
(build_conditional_expr): Tidy.
* except.c (build_throw): Do not perform lvalue-to-rvalue
conversion on operand before initializing temporary.
* tree.c (convert.h): Include it.
(convert_bitfield_to_declared_type): Use convert_to_integer, not
cp_convert.
(rvalue): Don't convert bitfields to their declared type here.
* cp-tree.h (build_init): Remove.
(default_conversion): Likewise.
* typeck2.c (build_m_component_ref): Do not perform
lvalue-to-rvalue, function-to-pointer, or array-to-pointer
conversions here. Correct error message.
2006-05-17 Mark Mitchell <mark@codesourcery.com>
PR c++/26122

@ -426,11 +426,14 @@ null_ptr_cst_p (tree t)
A null pointer constant is an integral constant expression
(_expr.const_) rvalue of integer type that evaluates to zero. */
t = integral_constant_value (t);
if (t == null_node
|| (CP_INTEGRAL_TYPE_P (TREE_TYPE (t))
&& integer_zerop (t)
&& !TREE_CONSTANT_OVERFLOW (t)))
if (t == null_node)
return true;
if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t))
{
STRIP_NOPS (t);
if (!TREE_CONSTANT_OVERFLOW (t))
return true;
}
return false;
}
@ -3518,16 +3521,18 @@ build_conditional_expr (tree arg1, tree arg2, tree arg3)
/* We can't use result_type below, as fold might have returned a
throw_expr. */
/* Expand both sides into the same slot, hopefully the target of the
?: expression. We used to check for TARGET_EXPRs here, but now we
sometimes wrap them in NOP_EXPRs so the test would fail. */
if (!lvalue_p && CLASS_TYPE_P (TREE_TYPE (result)))
result = get_target_expr (result);
/* If this expression is an rvalue, but might be mistaken for an
lvalue, we must add a NON_LVALUE_EXPR. */
if (!lvalue_p && real_lvalue_p (result))
result = rvalue (result);
if (!lvalue_p)
{
/* Expand both sides into the same slot, hopefully the target of
the ?: expression. We used to check for TARGET_EXPRs here,
but now we sometimes wrap them in NOP_EXPRs so the test would
fail. */
if (CLASS_TYPE_P (TREE_TYPE (result)))
result = get_target_expr (result);
/* If this expression is an rvalue, but might be mistaken for an
lvalue, we must add a NON_LVALUE_EXPR. */
result = rvalue (result);
}
return result;
}

@ -3973,7 +3973,6 @@ extern tree do_friend (tree, tree, tree, tree, enum overload_flags, bool);
extern tree expand_member_init (tree);
extern void emit_mem_initializers (tree);
extern tree build_aggr_init (tree, tree, int);
extern tree build_init (tree, tree, int);
extern int is_aggr_type (tree, int);
extern tree get_type_value (tree);
extern tree build_zero_init (tree, tree, bool);
@ -4357,7 +4356,6 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, bool);
extern tree inline_conversion (tree);
extern tree is_bitfield_expr_with_lowered_type (tree);
extern tree decay_conversion (tree);
extern tree default_conversion (tree);
extern tree build_class_member_access_expr (tree, tree, tree, bool);
extern tree finish_class_member_access_expr (tree, tree, bool);
extern tree build_x_indirect_ref (tree, const char *);

@ -638,6 +638,7 @@ build_throw (tree exp)
else if (exp)
{
tree throw_type;
tree temp_type;
tree cleanup;
tree object, ptr;
tree tmp;
@ -666,9 +667,17 @@ build_throw (tree exp)
fn = push_throw_library_fn (fn, tmp);
}
/* throw expression */
/* First, decay it. */
exp = decay_conversion (exp);
/* [except.throw]
A throw-expression initializes a temporary object, the type
of which is determined by removing any top-level
cv-qualifiers from the static type of the operand of throw
and adjusting the type from "array of T" or "function return
T" to "pointer to T" or "pointer to function returning T"
respectively. */
temp_type = is_bitfield_expr_with_lowered_type (exp);
if (!temp_type)
temp_type = type_decays_to (TYPE_MAIN_VARIANT (TREE_TYPE (exp)));
/* OK, this is kind of wacky. The standard says that we call
terminate when the exception handling mechanism, after
@ -684,21 +693,32 @@ build_throw (tree exp)
matter, since it can't throw). */
/* Allocate the space for the exception. */
allocate_expr = do_allocate_exception (TREE_TYPE (exp));
allocate_expr = do_allocate_exception (temp_type);
allocate_expr = get_target_expr (allocate_expr);
ptr = TARGET_EXPR_SLOT (allocate_expr);
object = build1 (NOP_EXPR, build_pointer_type (TREE_TYPE (exp)), ptr);
object = build_nop (build_pointer_type (temp_type), ptr);
object = build_indirect_ref (object, NULL);
elided = (TREE_CODE (exp) == TARGET_EXPR);
/* And initialize the exception object. */
exp = build_init (object, exp, LOOKUP_ONLYCONVERTING);
if (exp == error_mark_node)
if (CLASS_TYPE_P (temp_type))
{
error (" in thrown expression");
return error_mark_node;
/* Call the copy constructor. */
exp = (build_special_member_call
(object, complete_ctor_identifier,
build_tree_list (NULL_TREE, exp),
TREE_TYPE (object),
LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING));
if (exp == error_mark_node)
{
error (" in thrown expression");
return error_mark_node;
}
}
else
exp = build2 (INIT_EXPR, temp_type, object,
decay_conversion (exp));
/* Pre-evaluate the thrown expression first, since if we allocated
the space first we would have to deal with cleaning it up if

@ -1142,26 +1142,6 @@ build_aggr_init (tree exp, tree init, int flags)
return stmt_expr;
}
/* Like build_aggr_init, but not just for aggregates. */
tree
build_init (tree decl, tree init, int flags)
{
tree expr;
if (TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
expr = build_aggr_init (decl, init, flags);
else if (CLASS_TYPE_P (TREE_TYPE (decl)))
expr = build_special_member_call (decl, complete_ctor_identifier,
build_tree_list (NULL_TREE, init),
TREE_TYPE (decl),
LOOKUP_NORMAL|flags);
else
expr = build2 (INIT_EXPR, TREE_TYPE (decl), decl, init);
return expr;
}
static void
expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags)
{
@ -2057,7 +2037,7 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
rval = build_nop (pointer_type, rval);
/* A new-expression is never an lvalue. */
rval = rvalue (rval);
gcc_assert (!lvalue_p (rval));
return rval;
}

@ -35,6 +35,7 @@ Boston, MA 02110-1301, USA. */
#include "tree-inline.h"
#include "debug.h"
#include "target.h"
#include "convert.h"
static tree bot_manip (tree *, int *, void *);
static tree bot_replace (tree *, int *, void *);
@ -373,7 +374,8 @@ convert_bitfield_to_declared_type (tree expr)
bitfield_type = is_bitfield_expr_with_lowered_type (expr);
if (bitfield_type)
expr = cp_convert (TYPE_MAIN_VARIANT (bitfield_type), expr);
expr = convert_to_integer (TYPE_MAIN_VARIANT (bitfield_type),
expr);
return expr;
}
@ -383,18 +385,23 @@ convert_bitfield_to_declared_type (tree expr)
tree
rvalue (tree expr)
{
expr = convert_bitfield_to_declared_type (expr);
if (real_lvalue_p (expr))
{
tree type;
/* [basic.lval]
Non-class rvalues always have cv-unqualified types. */
type = TREE_TYPE (expr);
if (!CLASS_TYPE_P (type))
type = TYPE_MAIN_VARIANT (type);
expr = build1 (NON_LVALUE_EXPR, type, expr);
}
tree type;
if (error_operand_p (expr))
return expr;
/* [basic.lval]
Non-class rvalues always have cv-unqualified types. */
type = TREE_TYPE (expr);
if (!CLASS_TYPE_P (type) && cp_type_quals (type))
type = TYPE_MAIN_VARIANT (type);
if (!processing_template_decl && real_lvalue_p (expr))
expr = build1 (NON_LVALUE_EXPR, type, expr);
else if (type != TREE_TYPE (expr))
expr = build_nop (type, expr);
return expr;
}

@ -1426,10 +1426,14 @@ is_bitfield_expr_with_lowered_type (tree exp)
/* 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.
function-to-pointer conversions. In addition, manifest constants
are replaced by their values, and bitfield references are converted
to their declared types.
In addition, manifest constants are replaced by their values, and
bitfield references are converted to their declared types. */
Although the returned value is being used as an rvalue, this
function does not wrap the returned expression in a
NON_LVALUE_EXPR; the caller is expected to be mindful of the fact
that the return value is no longer an lvalue. */
tree
decay_conversion (tree exp)
@ -1448,6 +1452,8 @@ decay_conversion (tree exp)
}
exp = decl_constant_value (exp);
if (error_operand_p (exp))
return error_mark_node;
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
Leave such NOP_EXPRs, since RHS is being used in non-lvalue context. */
@ -1498,22 +1504,52 @@ decay_conversion (tree exp)
adr = build_unary_op (ADDR_EXPR, exp, 1);
return cp_convert (ptrtype, adr);
}
/* If a bitfield is used in a context where integral promotion
applies, then the caller is expected to have used
default_conversion. That function promotes bitfields correctly
before calling this function. At this point, if we have a
bitfield referenced, we may assume that is not subject to
promotion, and that, therefore, the type of the resulting rvalue
is the declared type of the bitfield. */
exp = convert_bitfield_to_declared_type (exp);
/* [basic.lval]: Class rvalues can have cv-qualified types; non-class
rvalues always have cv-unqualified types. */
if (! CLASS_TYPE_P (type))
exp = cp_convert (TYPE_MAIN_VARIANT (type), exp);
/* We do not call rvalue() here because we do not want to wrap EXP
in a NON_LVALUE_EXPR. */
/* [basic.lval]
Non-class rvalues always have cv-unqualified types. */
type = TREE_TYPE (exp);
if (!CLASS_TYPE_P (type) && cp_type_quals (type))
exp = build_nop (TYPE_MAIN_VARIANT (type), exp);
return exp;
}
tree
/* Perform prepatory conversions, as part of the "usual arithmetic
conversions". In particular, as per [expr]:
Whenever an lvalue expression appears as an operand of an
operator that expects the rvalue for that operand, the
lvalue-to-rvalue, array-to-pointer, or function-to-pointer
standard conversions are applied to convert the expression to an
rvalue.
In addition, we perform integral promotions here, as those are
applied to both operands to a binary operator before determining
what additional conversions should apply. */
static tree
default_conversion (tree exp)
{
exp = decay_conversion (exp);
/* Perform the integral promotions first so that bitfield
expressions (which may promote to "int", even if the bitfield is
declared "unsigned") are promoted correctly. */
if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
exp = perform_integral_promotions (exp);
/* Perform the other conversions. */
exp = decay_conversion (exp);
return exp;
}

@ -1200,8 +1200,6 @@ build_m_component_ref (tree datum, tree component)
tree binfo;
tree ctype;
datum = decay_conversion (datum);
if (datum == error_mark_node || component == error_mark_node)
return error_mark_node;
@ -1218,7 +1216,7 @@ build_m_component_ref (tree datum, tree component)
if (! IS_AGGR_TYPE (objtype))
{
error ("cannot apply member pointer %qE to %qE, which is of "
"non-aggregate type %qT",
"non-class type %qT",
component, datum, objtype);
return error_mark_node;
}

@ -1,3 +1,10 @@
2006-05-18 Mark Mitchell <mark@codesourcery.com>
PR c++/27471
PR c++/27506
* g++.dg/conversion/bitfield5.C: New test.
* g++.dg/conversion/bitfield6.C: New test.
2006-05-18 Mike Stump <mrs@apple.com>
* gcc.dg/c90-arraydecl-1.c: Update for vla, vm [*] fixups.

@ -0,0 +1,14 @@
// PR c++/27506
enum EBorderStyle
{
BNATIVE, BHIDDEN
};
struct BorderValue
{
enum EBorderStyle style:8;
};
enum EBorderStyle f(const struct BorderValue *border)
{
return border ? border->style : BNATIVE;
}

@ -0,0 +1,10 @@
// PR c++/27471
struct A { unsigned a:8; };
extern void b(unsigned char);
void breakme (A f)
{
b((unsigned char) f.a);
}