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:
parent
84e2e37098
commit
41990f9646
@ -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.
|
||||
|
14
gcc/testsuite/g++.dg/conversion/bitfield5.C
Normal file
14
gcc/testsuite/g++.dg/conversion/bitfield5.C
Normal file
@ -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;
|
||||
}
|
10
gcc/testsuite/g++.dg/conversion/bitfield6.C
Normal file
10
gcc/testsuite/g++.dg/conversion/bitfield6.C
Normal file
@ -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);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user