Commit 0a72704b by Mark Mitchell Committed by Mark Mitchell

re PR c++/11431 (static_cast behavior with subclasses when default constructor available)

	PR c++/11431
	* typeck.c (build_static_cast): Check for reference conversions
	earlier.

	* cp-tree.h (perform_integral_promotions): Declare.
	* call.c (build_addr_func): Use decay_conversion.
	(convert_arg_to_ellipsis): Likewise.  Remove misleading comment.
	(convert_for_arg_passing): Use perform_integral_promotions.
	* cvt.c (build_expr_type_conversion): Use decay_conversion.
	(type_promotes_to): Do not return a cv-qualified type.
	* decl.c (grok_reference_init): Fix formatting.
	(get_atexit_node): Use decay_conversion.
	(build_enumerator): Use perform_integral_promotions.
	* init.c (build_vec_init): Use decay_conversion.
	* semantics.c (finish_expr_stmt): Likewise.
	(finish_switch_cond): Use perform_integral_promotions.
	* typeck.c (default_conversion): Likewise.
	(perform_integral_promotions): New function.
	(build_indirect_ref): Use decay_conversion.
	(build_array_ref): Use perform_integral_promotions.
	(convert_arguments): Use decay_conversion.
	(build_unary_op): Use perform_integral_promotions.
	(build_c_cast): Use decay_conversion.
	(build_modify_expr): Likewise.
	(convert_for_initialization): Likewise.
	* typeck2.c (build_x_arrow): Likewise.

	* g++.old-deja/g++.jason/typeid1.C: Make it a compile test, not a
	run test.

	PR c++/11431
	* g++.dg/expr/static_cast3.C: New test.

From-SVN: r68989
parent ac3d7b44
2003-07-05 Mark Mitchell <mark@codesourcery.com>
PR c++/11431
* typeck.c (build_static_cast): Check for reference conversions
earlier.
2003-07-04 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (perform_integral_promotions): Declare.
* call.c (build_addr_func): Use decay_conversion.
(convert_arg_to_ellipsis): Likewise. Remove misleading comment.
(convert_for_arg_passing): Use perform_integral_promotions.
* cvt.c (build_expr_type_conversion): Use decay_conversion.
(type_promotes_to): Do not return a cv-qualified type.
* decl.c (grok_reference_init): Fix formatting.
(get_atexit_node): Use decay_conversion.
(build_enumerator): Use perform_integral_promotions.
* init.c (build_vec_init): Use decay_conversion.
* semantics.c (finish_expr_stmt): Likewise.
(finish_switch_cond): Use perform_integral_promotions.
* typeck.c (default_conversion): Likewise.
(perform_integral_promotions): New function.
(build_indirect_ref): Use decay_conversion.
(build_array_ref): Use perform_integral_promotions.
(convert_arguments): Use decay_conversion.
(build_unary_op): Use perform_integral_promotions.
(build_c_cast): Use decay_conversion.
(build_modify_expr): Likewise.
(convert_for_initialization): Likewise.
* typeck2.c (build_x_arrow): Likewise.
2003-07-04 Kazu Hirata <kazu@cs.umass.edu> 2003-07-04 Kazu Hirata <kazu@cs.umass.edu>
* call.c: Fix comment typos. * call.c: Fix comment typos.
......
...@@ -326,7 +326,7 @@ build_addr_func (tree function) ...@@ -326,7 +326,7 @@ build_addr_func (tree function)
function = build_address (function); function = build_address (function);
} }
else else
function = default_conversion (function); function = decay_conversion (function);
return function; return function;
} }
...@@ -4339,20 +4339,29 @@ call_builtin_trap (void) ...@@ -4339,20 +4339,29 @@ call_builtin_trap (void)
} }
/* ARG is being passed to a varargs function. Perform any conversions /* ARG is being passed to a varargs function. Perform any conversions
required. Array/function to pointer decay must have already happened. required. Return the converted value. */
Return the converted value. */
tree tree
convert_arg_to_ellipsis (tree arg) convert_arg_to_ellipsis (tree arg)
{ {
/* [expr.call]
The lvalue-to-rvalue, array-to-pointer, and function-to-pointer
standard conversions are performed. */
arg = decay_conversion (arg);
/* [expr.call]
If the argument has integral or enumeration type that is subject
to the integral promotions (_conv.prom_), or a floating point
type that is subject to the floating point promotion
(_conv.fpprom_), the value of the argument is converted to the
promoted type before the call. */
if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE if (TREE_CODE (TREE_TYPE (arg)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (arg)) && (TYPE_PRECISION (TREE_TYPE (arg))
< TYPE_PRECISION (double_type_node))) < TYPE_PRECISION (double_type_node)))
/* Convert `float' to `double'. */
arg = cp_convert (double_type_node, arg); arg = cp_convert (double_type_node, arg);
else else if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (arg)))
/* Convert `short' and `char' to full-size `int'. */ arg = perform_integral_promotions (arg);
arg = default_conversion (arg);
arg = require_complete_type (arg); arg = require_complete_type (arg);
...@@ -4487,7 +4496,7 @@ convert_for_arg_passing (tree type, tree val) ...@@ -4487,7 +4496,7 @@ convert_for_arg_passing (tree type, tree val)
else if (PROMOTE_PROTOTYPES else if (PROMOTE_PROTOTYPES
&& INTEGRAL_TYPE_P (type) && INTEGRAL_TYPE_P (type)
&& TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)) && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
val = default_conversion (val); val = perform_integral_promotions (val);
return val; return val;
} }
......
...@@ -4255,6 +4255,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, int); ...@@ -4255,6 +4255,7 @@ extern tree cxx_sizeof_or_alignof_type (tree, enum tree_code, int);
#define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false) #define cxx_sizeof_nowarn(T) cxx_sizeof_or_alignof_type (T, SIZEOF_EXPR, false)
extern tree inline_conversion (tree); extern tree inline_conversion (tree);
extern tree decay_conversion (tree); extern tree decay_conversion (tree);
extern tree perform_integral_promotions (tree);
extern tree build_class_member_access_expr (tree, tree, tree, bool); extern tree build_class_member_access_expr (tree, tree, tree, bool);
extern tree finish_class_member_access_expr (tree, tree); extern tree finish_class_member_access_expr (tree, tree);
extern tree build_x_indirect_ref (tree, const char *); extern tree build_x_indirect_ref (tree, const char *);
......
...@@ -1056,7 +1056,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain) ...@@ -1056,7 +1056,7 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
case FUNCTION_TYPE: case FUNCTION_TYPE:
case ARRAY_TYPE: case ARRAY_TYPE:
return (desires & WANT_POINTER) ? default_conversion (expr) return (desires & WANT_POINTER) ? decay_conversion (expr)
: NULL_TREE; : NULL_TREE;
default: default:
return NULL_TREE; return NULL_TREE;
...@@ -1131,12 +1131,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain) ...@@ -1131,12 +1131,9 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
tree tree
type_promotes_to (tree type) type_promotes_to (tree type)
{ {
int type_quals;
if (type == error_mark_node) if (type == error_mark_node)
return error_mark_node; return error_mark_node;
type_quals = cp_type_quals (type);
type = TYPE_MAIN_VARIANT (type); type = TYPE_MAIN_VARIANT (type);
/* bool always promotes to int (not unsigned), even if it's the same /* bool always promotes to int (not unsigned), even if it's the same
...@@ -1169,8 +1166,8 @@ type_promotes_to (tree type) ...@@ -1169,8 +1166,8 @@ type_promotes_to (tree type)
} }
else if (type == float_type_node) else if (type == float_type_node)
type = double_type_node; type = double_type_node;
return cp_build_qualified_type (type, type_quals); return type;
} }
/* The routines below this point are carefully written to conform to /* The routines below this point are carefully written to conform to
......
...@@ -7213,10 +7213,8 @@ grok_reference_init (tree decl, tree type, tree init) ...@@ -7213,10 +7213,8 @@ grok_reference_init (tree decl, tree type, tree init)
if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE if (TREE_CODE (TREE_TYPE (type)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE) && TREE_CODE (TREE_TYPE (init)) == ARRAY_TYPE)
{ /* Note: default conversion is only called in very special cases. */
/* Note: default conversion is only called in very special cases. */ init = decay_conversion (init);
init = default_conversion (init);
}
/* Convert INIT to the reference type TYPE. This may involve the /* Convert INIT to the reference type TYPE. This may involve the
creation of a temporary, whose lifetime must be the same as that creation of a temporary, whose lifetime must be the same as that
...@@ -8356,7 +8354,7 @@ get_atexit_node (void) ...@@ -8356,7 +8354,7 @@ get_atexit_node (void)
atexit_fndecl = build_library_fn_ptr (name, fn_type); atexit_fndecl = build_library_fn_ptr (name, fn_type);
mark_used (atexit_fndecl); mark_used (atexit_fndecl);
pop_lang_context (); pop_lang_context ();
atexit_node = default_conversion (atexit_fndecl); atexit_node = decay_conversion (atexit_fndecl);
return atexit_node; return atexit_node;
} }
...@@ -13180,7 +13178,7 @@ build_enumerator (tree name, tree value, tree enumtype) ...@@ -13180,7 +13178,7 @@ build_enumerator (tree name, tree value, tree enumtype)
if (TREE_CODE (value) == INTEGER_CST) if (TREE_CODE (value) == INTEGER_CST)
{ {
value = default_conversion (value); value = perform_integral_promotions (value);
constant_expression_warning (value); constant_expression_warning (value);
} }
else else
......
...@@ -2656,7 +2656,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) ...@@ -2656,7 +2656,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
ptype = build_pointer_type (type); ptype = build_pointer_type (type);
size = size_in_bytes (type); size = size_in_bytes (type);
if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE) if (TREE_CODE (TREE_TYPE (base)) == ARRAY_TYPE)
base = cp_convert (ptype, default_conversion (base)); base = cp_convert (ptype, decay_conversion (base));
/* The code we are generating looks like: /* The code we are generating looks like:
...@@ -2739,7 +2739,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array) ...@@ -2739,7 +2739,7 @@ build_vec_init (tree base, tree maxindex, tree init, int from_array)
checking. */ checking. */
if (init) if (init)
{ {
base2 = default_conversion (init); base2 = decay_conversion (init);
itype = TREE_TYPE (base2); itype = TREE_TYPE (base2);
base2 = get_temp_regvar (itype, base2); base2 = get_temp_regvar (itype, base2);
itype = TREE_TYPE (itype); itype = TREE_TYPE (itype);
......
...@@ -425,7 +425,7 @@ finish_expr_stmt (tree expr) ...@@ -425,7 +425,7 @@ finish_expr_stmt (tree expr)
&& ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE && ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
&& lvalue_p (expr)) && lvalue_p (expr))
|| TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE))
expr = default_conversion (expr); expr = decay_conversion (expr);
/* Remember the type of the expression. */ /* Remember the type of the expression. */
expr_type = TREE_TYPE (expr); expr_type = TREE_TYPE (expr);
...@@ -748,7 +748,10 @@ finish_switch_cond (tree cond, tree switch_stmt) ...@@ -748,7 +748,10 @@ finish_switch_cond (tree cond, tree switch_stmt)
orig_type = TREE_TYPE (cond); orig_type = TREE_TYPE (cond);
if (cond != error_mark_node) if (cond != error_mark_node)
{ {
cond = default_conversion (cond); /* [stmt.switch]
Integral promotions are performed. */
cond = perform_integral_promotions (cond);
cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond)); cond = fold (build1 (CLEANUP_POINT_EXPR, TREE_TYPE (cond), cond));
} }
......
...@@ -1483,11 +1483,11 @@ expr_sizeof (tree e) ...@@ -1483,11 +1483,11 @@ expr_sizeof (tree e)
} }
/* Perform the array-to-pointer and function-to-pointer conversions /* Perform the conversions in [expr] that apply when an lvalue appears
for EXP. in an rvalue context: the lvalue-to-rvalue, array-to-pointer, and
function-to-pointer conversions.
In addition, references are converted to lvalues and manifest In addition manifest constants are replaced by their values. */
constants are replaced by their values. */
tree tree
decay_conversion (tree exp) decay_conversion (tree exp)
...@@ -1609,24 +1609,32 @@ decay_conversion (tree exp) ...@@ -1609,24 +1609,32 @@ decay_conversion (tree exp)
tree tree
default_conversion (tree exp) default_conversion (tree exp)
{ {
tree type;
enum tree_code code;
exp = decay_conversion (exp); exp = decay_conversion (exp);
type = TREE_TYPE (exp); if (INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (exp)))
code = TREE_CODE (type); exp = perform_integral_promotions (exp);
if (INTEGRAL_CODE_P (code))
{
tree t = type_promotes_to (type);
if (t != type)
return cp_convert (t, exp);
}
return exp; return exp;
} }
/* EXPR is an expression with an integral or enumeration type.
Perform the integral promotions in [conv.prom], and return the
converted value. */
tree
perform_integral_promotions (tree expr)
{
tree type;
tree promoted_type;
type = TREE_TYPE (expr);
my_friendly_assert (INTEGRAL_OR_ENUMERATION_TYPE_P (type), 20030703);
promoted_type = type_promotes_to (type);
if (type != promoted_type)
expr = cp_convert (promoted_type, expr);
return expr;
}
/* Take the address of an inline function without setting TREE_ADDRESSABLE /* Take the address of an inline function without setting TREE_ADDRESSABLE
or TREE_USED. */ or TREE_USED. */
...@@ -2232,7 +2240,7 @@ build_indirect_ref (ptr, errorstring) ...@@ -2232,7 +2240,7 @@ build_indirect_ref (ptr, errorstring)
return current_class_ref; return current_class_ref;
pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE pointer = (TREE_CODE (TREE_TYPE (ptr)) == REFERENCE_TYPE
? ptr : default_conversion (ptr)); ? ptr : decay_conversion (ptr));
type = TREE_TYPE (pointer); type = TREE_TYPE (pointer);
if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE) if (TYPE_PTR_P (type) || TREE_CODE (type) == REFERENCE_TYPE)
...@@ -2350,15 +2358,19 @@ build_array_ref (array, idx) ...@@ -2350,15 +2358,19 @@ build_array_ref (array, idx)
&& TYPE_MAIN_VARIANT (TREE_TYPE (idx)) == char_type_node) && TYPE_MAIN_VARIANT (TREE_TYPE (idx)) == char_type_node)
warning ("array subscript has type `char'"); warning ("array subscript has type `char'");
/* Apply default promotions *after* noticing character types. */ if (!INTEGRAL_OR_ENUMERATION_TYPE_P (TREE_TYPE (idx)))
idx = default_conversion (idx);
if (TREE_CODE (TREE_TYPE (idx)) != INTEGER_TYPE)
{ {
error ("array subscript is not an integer"); error ("array subscript is not an integer");
return error_mark_node; return error_mark_node;
} }
/* Apply integral promotions *after* noticing character types.
(It is unclear why we do these promotions -- the standard
does not say that we should. In fact, the natual thing would
seem to be to convert IDX to ptrdiff_t; we're performing
pointer arithmetic.) */
idx = perform_integral_promotions (idx);
/* An array that is indexed by a non-constant /* An array that is indexed by a non-constant
cannot be stored in a register; we must be able to do cannot be stored in a register; we must be able to do
address arithmetic on its address. address arithmetic on its address.
...@@ -2742,7 +2754,7 @@ convert_arguments (typelist, values, fndecl, flags) ...@@ -2742,7 +2754,7 @@ convert_arguments (typelist, values, fndecl, flags)
if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE if (TREE_CODE (TREE_TYPE (val)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (val)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE) || TREE_CODE (TREE_TYPE (val)) == METHOD_TYPE)
val = default_conversion (val); val = decay_conversion (val);
} }
if (val == error_mark_node) if (val == error_mark_node)
...@@ -4039,8 +4051,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) ...@@ -4039,8 +4051,8 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
case NEGATE_EXPR: case NEGATE_EXPR:
if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true))) if (!(arg = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, arg, true)))
errstring = "wrong type argument to unary minus"; errstring = "wrong type argument to unary minus";
else if (!noconvert) else if (!noconvert && CP_INTEGRAL_TYPE_P (TREE_TYPE (arg)))
arg = default_conversion (arg); arg = perform_integral_promotions (arg);
break; break;
case BIT_NOT_EXPR: case BIT_NOT_EXPR:
...@@ -4054,7 +4066,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert) ...@@ -4054,7 +4066,7 @@ build_unary_op (enum tree_code code, tree xarg, int noconvert)
arg, true))) arg, true)))
errstring = "wrong type argument to bit-complement"; errstring = "wrong type argument to bit-complement";
else if (!noconvert) else if (!noconvert)
arg = default_conversion (arg); arg = perform_integral_promotions (arg);
break; break;
case ABS_EXPR: case ABS_EXPR:
...@@ -4780,28 +4792,23 @@ build_static_cast (tree type, tree expr) ...@@ -4780,28 +4792,23 @@ build_static_cast (tree type, tree expr)
/* [expr.static.cast] /* [expr.static.cast]
An expression e can be explicitly converted to a type T using a
static_cast of the form static_cast<T>(e) if the declaration T
t(e);" is well-formed, for some invented temporary variable
t. */
result = perform_direct_initialization_if_possible (type, expr);
if (result)
return convert_from_reference (result);
/* [expr.static.cast]
Any expression can be explicitly converted to type cv void. */
if (TREE_CODE (type) == VOID_TYPE)
return convert_to_void (expr, /*implicit=*/NULL);
/* [expr.static.cast]
An lvalue of type "cv1 B", where B is a class type, can be cast An lvalue of type "cv1 B", where B is a class type, can be cast
to type "reference to cv2 D", where D is a class derived (clause to type "reference to cv2 D", where D is a class derived (clause
_class.derived_) from B, if a valid standard conversion from _class.derived_) from B, if a valid standard conversion from
"pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the "pointer to D" to "pointer to B" exists (_conv.ptr_), cv2 is the
same cv-qualification as, or greater cv-qualification than, cv1, same cv-qualification as, or greater cv-qualification than, cv1,
and B is not a virtual base class of D. */ and B is not a virtual base class of D. */
/* We check this case before checking the validity of "TYPE t =
EXPR;" below because for this case:
struct B {};
struct D : public B { D(const B&); };
extern B& b;
void f() { static_cast<const D&>(b); }
we want to avoid constructing a new D. The standard is not
completely clear about this issue, but our interpretation is
consistent with other compilers. */
if (TREE_CODE (type) == REFERENCE_TYPE if (TREE_CODE (type) == REFERENCE_TYPE
&& CLASS_TYPE_P (TREE_TYPE (type)) && CLASS_TYPE_P (TREE_TYPE (type))
&& CLASS_TYPE_P (intype) && CLASS_TYPE_P (intype)
...@@ -4827,6 +4834,22 @@ build_static_cast (tree type, tree expr) ...@@ -4827,6 +4834,22 @@ build_static_cast (tree type, tree expr)
/* [expr.static.cast] /* [expr.static.cast]
An expression e can be explicitly converted to a type T using a
static_cast of the form static_cast<T>(e) if the declaration T
t(e);" is well-formed, for some invented temporary variable
t. */
result = perform_direct_initialization_if_possible (type, expr);
if (result)
return convert_from_reference (result);
/* [expr.static.cast]
Any expression can be explicitly converted to type cv void. */
if (TREE_CODE (type) == VOID_TYPE)
return convert_to_void (expr, /*implicit=*/NULL);
/* [expr.static.cast]
The inverse of any standard conversion sequence (clause _conv_), The inverse of any standard conversion sequence (clause _conv_),
other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer other than the lvalue-to-rvalue (_conv.lval_), array-to-pointer
(_conv.array_), function-to-pointer (_conv.func_), and boolean (_conv.array_), function-to-pointer (_conv.func_), and boolean
...@@ -5158,7 +5181,7 @@ build_c_cast (tree type, tree expr) ...@@ -5158,7 +5181,7 @@ build_c_cast (tree type, tree expr)
&& bound_pmf_p (value))) && bound_pmf_p (value)))
|| TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE || TREE_CODE (TREE_TYPE (value)) == ARRAY_TYPE
|| TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) || TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
value = default_conversion (value); value = decay_conversion (value);
} }
else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE) else if (TREE_CODE (TREE_TYPE (value)) == REFERENCE_TYPE)
/* However, even for class types, we still need to strip away /* However, even for class types, we still need to strip away
...@@ -5422,7 +5445,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs) ...@@ -5422,7 +5445,7 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
|| TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE || TREE_CODE (TREE_TYPE (newrhs)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE || TREE_CODE (TREE_TYPE (newrhs)) == METHOD_TYPE
|| TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE) || TREE_CODE (TREE_TYPE (newrhs)) == OFFSET_TYPE)
newrhs = default_conversion (newrhs); newrhs = decay_conversion (newrhs);
/* ISO C++ 5.4/1: The result is an lvalue if T is a reference /* ISO C++ 5.4/1: The result is an lvalue if T is a reference
type, otherwise the result is an rvalue. */ type, otherwise the result is an rvalue. */
...@@ -6078,7 +6101,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags, ...@@ -6078,7 +6101,7 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
&& (TREE_CODE (type) != REFERENCE_TYPE && (TREE_CODE (type) != REFERENCE_TYPE
|| TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)) || TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE))
|| TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE) || TREE_CODE (TREE_TYPE (rhs)) == METHOD_TYPE)
rhs = default_conversion (rhs); rhs = decay_conversion (rhs);
rhstype = TREE_TYPE (rhs); rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype); coder = TREE_CODE (rhstype);
......
...@@ -1030,7 +1030,7 @@ build_x_arrow (tree datum) ...@@ -1030,7 +1030,7 @@ build_x_arrow (tree datum)
last_rval = convert_from_reference (last_rval); last_rval = convert_from_reference (last_rval);
} }
else else
last_rval = default_conversion (rval); last_rval = decay_conversion (rval);
if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE) if (TREE_CODE (TREE_TYPE (last_rval)) == POINTER_TYPE)
return build_indirect_ref (last_rval, NULL); return build_indirect_ref (last_rval, NULL);
......
2003-07-05 Mark Mitchell <mark@codesourcery.com>
* g++.old-deja/g++.jason/typeid1.C: Make it a compile test, not a
run test.
PR c++/11431
* g++.dg/expr/static_cast3.C: New test.
2003-07-04 Zack Weinberg <zack@codesourcery.com> 2003-07-04 Zack Weinberg <zack@codesourcery.com>
* gcc.c-torture/execute/wchar_t-1.x: New file; XFAIL wchar_t-1.c * gcc.c-torture/execute/wchar_t-1.x: New file; XFAIL wchar_t-1.c
......
template <class T> struct static_abort {};
template <class E>
struct any
{
const E& self() const { return static_cast<const E&>(*this); }
};
struct range : public any<range>
{
range() {}
template <class U>
range(const U&)
{
typedef typename static_abort<U>::ret t;
}
};
int main()
{
const any<range>& r = *new range();
r.self();
}
// { dg-do run } // { dg-do compile }
#include <typeinfo> #include <typeinfo>
#include <iostream> #include <iostream>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment