mirror of git://gcc.gnu.org/git/gcc.git
call.c (build_addr_func): Handle bound pointers-to-members.
* call.c (build_addr_func): Handle bound pointers-to-members. (build_method_call): Do not call resolve_offset_ref. (implicit_conversion): Likewise. (resolve_scoped_fn_name): Use finish_non_static_data_member, not resolve_offset_ref. (resolve_args): Do not call resolve_offset_ref. (build_conditional_expr): Likewise. (build_new_method_call): Likewise. * cp-tree.def (OFFSET_REF): Update documentation. (cp_convert_to_pointer): Update handling of conversions from pointers to members to pointers. (ocp_convert): Do not call resolve_offset_ref. (convert_to_void): Likewise. (build_expr_type_conversion): Likewise. (delete_sanity): Likewise. (resolve_offset_ref): Simplify greatly. (build_vec_delete): Do not call resolve_offset_ref. * parser.c (cp_parser_postfix_expression): Call resolve_offset_ref if appropriate. (cp_parser_unary_expression): Use cp_parser_simple_cast_expression. (cp_parser_delete_expression): Likewise. (cp_parser_cast_expression): Likewise. (cp_parser_pm_expression): Use cp_parser_binary_op. (cp_parser_simple_cast_expression): New function. * rtti.c (build_dynamic_cast_1): Do not call resolve_offset_ref. * semantics.c (finish_increment_expr): Likewise. (finish_typeof): Likewise. * tree.c (lvalue_p_1): Do not handle OFFSET_REF. * typeck.c (require_complete_type): Do not handle OFFSET_REFs. (decay_conversion): Do not call resolve_offset_ref. (finish_class_member_access_expr): Likewise. (convert_arguments): Likewise. (build_x_binary_op): Handle DOTSTAR_EXPR. (condition_conversion): Do not call resolve_offset_ref. (unary_complex_lvalue): Likewise. (build_static_cast): Likewise. (build_reinterpret_cast): Likewise. (build_const_cast): Likewise. (build_c_cast): Likewise. (build_modify_expr): Likewise. (convert_for_assignment): Likewise. (convert_for_initialization): Likewise. * typeck2.c (build_x_arrow): Likewise. (build_m_component_ref): Simplify. * g++.old-deja/g++.jason/typeid1.C: Add dg-error marker. * g++.old-deja/g++.mike/net36.C: Tweak error messages. From-SVN: r68911
This commit is contained in:
parent
5f1989e65d
commit
d6b4ea8592
|
@ -6,6 +6,52 @@
|
||||||
|
|
||||||
2003-07-03 Mark Mitchell <mark@codesourcery.com>
|
2003-07-03 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* call.c (build_addr_func): Handle bound pointers-to-members.
|
||||||
|
(build_method_call): Do not call resolve_offset_ref.
|
||||||
|
(implicit_conversion): Likewise.
|
||||||
|
(resolve_scoped_fn_name): Use finish_non_static_data_member, not
|
||||||
|
resolve_offset_ref.
|
||||||
|
(resolve_args): Do not call resolve_offset_ref.
|
||||||
|
(build_conditional_expr): Likewise.
|
||||||
|
(build_new_method_call): Likewise.
|
||||||
|
* cp-tree.def (OFFSET_REF): Update documentation.
|
||||||
|
(cp_convert_to_pointer): Update handling of conversions from
|
||||||
|
pointers to members to pointers.
|
||||||
|
(ocp_convert): Do not call resolve_offset_ref.
|
||||||
|
(convert_to_void): Likewise.
|
||||||
|
(build_expr_type_conversion): Likewise.
|
||||||
|
(delete_sanity): Likewise.
|
||||||
|
(resolve_offset_ref): Simplify greatly.
|
||||||
|
(build_vec_delete): Do not call resolve_offset_ref.
|
||||||
|
* parser.c (cp_parser_postfix_expression): Call resolve_offset_ref
|
||||||
|
if appropriate.
|
||||||
|
(cp_parser_unary_expression): Use
|
||||||
|
cp_parser_simple_cast_expression.
|
||||||
|
(cp_parser_delete_expression): Likewise.
|
||||||
|
(cp_parser_cast_expression): Likewise.
|
||||||
|
(cp_parser_pm_expression): Use cp_parser_binary_op.
|
||||||
|
(cp_parser_simple_cast_expression): New function.
|
||||||
|
* rtti.c (build_dynamic_cast_1): Do not call resolve_offset_ref.
|
||||||
|
* semantics.c (finish_increment_expr): Likewise.
|
||||||
|
(finish_typeof): Likewise.
|
||||||
|
* tree.c (lvalue_p_1): Do not handle OFFSET_REF.
|
||||||
|
* typeck.c (require_complete_type): Do not handle OFFSET_REFs.
|
||||||
|
(decay_conversion): Do not call resolve_offset_ref.
|
||||||
|
(finish_class_member_access_expr): Likewise.
|
||||||
|
(convert_arguments): Likewise.
|
||||||
|
(build_x_binary_op): Handle DOTSTAR_EXPR.
|
||||||
|
(condition_conversion): Do not call resolve_offset_ref.
|
||||||
|
(unary_complex_lvalue): Likewise.
|
||||||
|
(build_static_cast): Likewise.
|
||||||
|
(build_reinterpret_cast): Likewise.
|
||||||
|
(build_const_cast): Likewise.
|
||||||
|
(build_c_cast): Likewise.
|
||||||
|
(build_modify_expr): Likewise.
|
||||||
|
(convert_for_assignment): Likewise.
|
||||||
|
(convert_for_initialization): Likewise.
|
||||||
|
* typeck2.c (build_x_arrow): Likewise.
|
||||||
|
(build_m_component_ref): Simplify.
|
||||||
|
|
||||||
* call.c (build_scoped_method_call): Use convert_to_void.
|
* call.c (build_scoped_method_call): Use convert_to_void.
|
||||||
(build_method_call): Likewise.
|
(build_method_call): Likewise.
|
||||||
* class.c (check_field_decls): Remove dead code.
|
* class.c (check_field_decls): Remove dead code.
|
||||||
|
|
|
@ -317,21 +317,13 @@ build_addr_func (tree function)
|
||||||
functions. */
|
functions. */
|
||||||
if (TREE_CODE (type) == METHOD_TYPE)
|
if (TREE_CODE (type) == METHOD_TYPE)
|
||||||
{
|
{
|
||||||
tree addr;
|
if (TREE_CODE (function) == OFFSET_REF)
|
||||||
|
{
|
||||||
type = build_pointer_type (type);
|
tree object = build_address (TREE_OPERAND (function, 0));
|
||||||
|
return get_member_function_from_ptrfunc (&object,
|
||||||
if (!cxx_mark_addressable (function))
|
TREE_OPERAND (function, 1));
|
||||||
return error_mark_node;
|
}
|
||||||
|
function = build_address (function);
|
||||||
addr = build1 (ADDR_EXPR, type, function);
|
|
||||||
|
|
||||||
/* Address of a static or external variable or function counts
|
|
||||||
as a constant */
|
|
||||||
if (staticp (function))
|
|
||||||
TREE_CONSTANT (addr) = 1;
|
|
||||||
|
|
||||||
function = addr;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
function = default_conversion (function);
|
function = default_conversion (function);
|
||||||
|
@ -477,8 +469,6 @@ build_method_call (tree instance, tree name, tree parms,
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
|
return build_min_nt (METHOD_CALL_EXPR, name, instance, parms, NULL_TREE);
|
||||||
|
|
||||||
if (TREE_CODE (instance) == OFFSET_REF)
|
|
||||||
instance = resolve_offset_ref (instance);
|
|
||||||
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
|
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
|
||||||
instance = convert_from_reference (instance);
|
instance = convert_from_reference (instance);
|
||||||
object_type = TREE_TYPE (instance);
|
object_type = TREE_TYPE (instance);
|
||||||
|
@ -1295,14 +1285,6 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
|
||||||
{
|
{
|
||||||
tree conv;
|
tree conv;
|
||||||
|
|
||||||
/* Resolve expressions like `A::p' that we thought might become
|
|
||||||
pointers-to-members. */
|
|
||||||
if (expr && TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
{
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
from = TREE_TYPE (expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (from == error_mark_node || to == error_mark_node
|
if (from == error_mark_node || to == error_mark_node
|
||||||
|| expr == error_mark_node)
|
|| expr == error_mark_node)
|
||||||
return NULL_TREE;
|
return NULL_TREE;
|
||||||
|
@ -2790,7 +2772,7 @@ resolve_scoped_fn_name (tree scope, tree name)
|
||||||
|
|
||||||
/* It might be the name of a function pointer member. */
|
/* It might be the name of a function pointer member. */
|
||||||
if (fn && TREE_CODE (fn) == FIELD_DECL)
|
if (fn && TREE_CODE (fn) == FIELD_DECL)
|
||||||
fn = resolve_offset_ref (build_offset_ref (scope, fn));
|
fn = finish_non_static_data_member (fn, scope);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!fn)
|
if (!fn)
|
||||||
|
@ -2831,8 +2813,6 @@ resolve_args (tree args)
|
||||||
error ("invalid use of void expression");
|
error ("invalid use of void expression");
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (TREE_CODE (arg) == OFFSET_REF)
|
|
||||||
arg = resolve_offset_ref (arg);
|
|
||||||
arg = convert_from_reference (arg);
|
arg = convert_from_reference (arg);
|
||||||
TREE_VALUE (t) = arg;
|
TREE_VALUE (t) = arg;
|
||||||
}
|
}
|
||||||
|
@ -3565,8 +3545,6 @@ prep_operand (tree operand)
|
||||||
{
|
{
|
||||||
if (operand)
|
if (operand)
|
||||||
{
|
{
|
||||||
if (TREE_CODE (operand) == OFFSET_REF)
|
|
||||||
operand = resolve_offset_ref (operand);
|
|
||||||
operand = convert_from_reference (operand);
|
operand = convert_from_reference (operand);
|
||||||
if (CLASS_TYPE_P (TREE_TYPE (operand))
|
if (CLASS_TYPE_P (TREE_TYPE (operand))
|
||||||
&& CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
|
&& CLASSTYPE_TEMPLATE_INSTANTIATION (TREE_TYPE (operand)))
|
||||||
|
@ -5025,8 +5003,6 @@ build_new_method_call (tree instance, tree fns, tree args,
|
||||||
if (args == error_mark_node)
|
if (args == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (instance) == OFFSET_REF)
|
|
||||||
instance = resolve_offset_ref (instance);
|
|
||||||
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
|
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
|
||||||
instance = convert_from_reference (instance);
|
instance = convert_from_reference (instance);
|
||||||
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
|
basetype = TYPE_MAIN_VARIANT (TREE_TYPE (instance));
|
||||||
|
|
|
@ -26,22 +26,22 @@ Boston, MA 02111-1307, USA. */
|
||||||
/* An OFFSET_REF is used in two situations:
|
/* An OFFSET_REF is used in two situations:
|
||||||
|
|
||||||
1. An expression of the form `A::m' where `A' is a class and `m' is
|
1. An expression of the form `A::m' where `A' is a class and `m' is
|
||||||
a non-static data member. In this case, operand 0 will be a
|
a non-static member. In this case, operand 0 will be a TYPE
|
||||||
TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL
|
(corresponding to `A') and operand 1 will be a FIELD_DECL,
|
||||||
(corresponding to `m'.
|
BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m').
|
||||||
|
|
||||||
The expression is a pointer-to-member if its address is taken,
|
The expression is a pointer-to-member if its address is taken,
|
||||||
but simply denotes a member of the object if its address isnot
|
but simply denotes a member of the object if its address isnot
|
||||||
taken. In the latter case, resolve_offset_ref is used to
|
taken. In the latter case, resolve_offset_ref is used to
|
||||||
convert it to a representation of the member referred to by the
|
convert it to a representation of the member referred to by the
|
||||||
OFFSET_REF.
|
OFFSET_REF.
|
||||||
|
|
||||||
|
This form is only used during the parsing phase; once semantic
|
||||||
|
analysis has taken place they are eliminated.
|
||||||
|
|
||||||
2. An expression of the form `x.*p'. In this case, operand 0 will
|
2. An expression of the form `x.*p'. In this case, operand 0 will
|
||||||
be an expression corresponding to `x' and operand 1 will be an
|
be an expression corresponding to `x' and operand 1 will be an
|
||||||
expression with pointer-to-member type.
|
expression with pointer-to-member type. */
|
||||||
|
|
||||||
OFFSET_REFs are only used during the parsing phase; once semantic
|
|
||||||
analysis has taken place they are eliminated. */
|
|
||||||
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
|
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
|
||||||
|
|
||||||
/* A pointer-to-member constant. For a pointer-to-member constant
|
/* A pointer-to-member constant. For a pointer-to-member constant
|
||||||
|
|
54
gcc/cp/cvt.c
54
gcc/cp/cvt.c
|
@ -109,24 +109,26 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
|
||||||
functions. */
|
functions. */
|
||||||
if (TYPE_PTRMEMFUNC_P (intype))
|
if (TYPE_PTRMEMFUNC_P (intype))
|
||||||
{
|
{
|
||||||
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
|
if (pedantic || warn_pmf2ptr)
|
||||||
tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
|
pedwarn ("converting from `%T' to `%T'", intype, type);
|
||||||
expr = build (OFFSET_REF, fntype, decl, expr);
|
if (TREE_CODE (expr) == PTRMEM_CST)
|
||||||
|
expr = build_address (PTRMEM_CST_MEMBER (expr));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
tree decl = maybe_dummy_object (TYPE_PTRMEM_CLASS_TYPE (intype),
|
||||||
|
0);
|
||||||
|
decl = build_address (decl);
|
||||||
|
expr = get_member_function_from_ptrfunc (&decl, expr);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
|
||||||
if (TREE_CODE (expr) == OFFSET_REF
|
|
||||||
&& TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
|
|
||||||
expr = build_addr_func (expr);
|
|
||||||
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
|
|
||||||
{
|
{
|
||||||
if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
|
if (pedantic || warn_pmf2ptr)
|
||||||
if (pedantic || warn_pmf2ptr)
|
pedwarn ("converting from `%T' to `%T'", intype, type);
|
||||||
pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr),
|
expr = build_addr_func (expr);
|
||||||
type);
|
|
||||||
return build1 (NOP_EXPR, type, expr);
|
|
||||||
}
|
}
|
||||||
|
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
|
||||||
|
return build_nop (type, expr);
|
||||||
intype = TREE_TYPE (expr);
|
intype = TREE_TYPE (expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,6 +235,19 @@ cp_convert_to_pointer (tree type, tree expr, bool force)
|
||||||
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
|
return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0);
|
||||||
else if (TYPE_PTRMEMFUNC_P (intype))
|
else if (TYPE_PTRMEMFUNC_P (intype))
|
||||||
{
|
{
|
||||||
|
if (!warn_pmf2ptr)
|
||||||
|
{
|
||||||
|
if (TREE_CODE (expr) == PTRMEM_CST)
|
||||||
|
return cp_convert_to_pointer (type,
|
||||||
|
PTRMEM_CST_MEMBER (expr),
|
||||||
|
force);
|
||||||
|
else if (TREE_CODE (expr) == OFFSET_REF)
|
||||||
|
{
|
||||||
|
tree object = TREE_OPERAND (expr, 0);
|
||||||
|
return get_member_function_from_ptrfunc (&object,
|
||||||
|
TREE_OPERAND (expr, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
error ("cannot convert `%E' from type `%T' to type `%T'",
|
error ("cannot convert `%E' from type `%T' to type `%T'",
|
||||||
expr, intype, type);
|
expr, intype, type);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
@ -663,9 +678,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
|
||||||
code = TREE_CODE (type);
|
code = TREE_CODE (type);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (e) == OFFSET_REF)
|
|
||||||
e = resolve_offset_ref (e);
|
|
||||||
|
|
||||||
if (INTEGRAL_CODE_P (code))
|
if (INTEGRAL_CODE_P (code))
|
||||||
{
|
{
|
||||||
tree intype = TREE_TYPE (e);
|
tree intype = TREE_TYPE (e);
|
||||||
|
@ -879,10 +891,6 @@ convert_to_void (tree expr, const char *implicit)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OFFSET_REF:
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:;
|
default:;
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
|
@ -1023,8 +1031,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
|
||||||
&& !(desires & WANT_NULL))
|
&& !(desires & WANT_NULL))
|
||||||
warning ("converting NULL to non-pointer type");
|
warning ("converting NULL to non-pointer type");
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
expr = convert_from_reference (expr);
|
expr = convert_from_reference (expr);
|
||||||
basetype = TREE_TYPE (expr);
|
basetype = TREE_TYPE (expr);
|
||||||
|
|
||||||
|
|
|
@ -481,8 +481,6 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (exp) == OFFSET_REF)
|
|
||||||
exp = resolve_offset_ref (exp);
|
|
||||||
exp = convert_from_reference (exp);
|
exp = convert_from_reference (exp);
|
||||||
t = build_expr_type_conversion (WANT_POINTER, exp, true);
|
t = build_expr_type_conversion (WANT_POINTER, exp, true);
|
||||||
|
|
||||||
|
|
139
gcc/cp/init.c
139
gcc/cp/init.c
|
@ -1689,121 +1689,45 @@ build_offset_ref (tree type, tree name)
|
||||||
tree
|
tree
|
||||||
resolve_offset_ref (tree exp)
|
resolve_offset_ref (tree exp)
|
||||||
{
|
{
|
||||||
tree type = TREE_TYPE (exp);
|
|
||||||
tree base = NULL_TREE;
|
|
||||||
tree member;
|
tree member;
|
||||||
tree basetype, addr;
|
|
||||||
|
|
||||||
if (TREE_CODE (exp) == OFFSET_REF)
|
my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
|
||||||
{
|
|
||||||
member = TREE_OPERAND (exp, 1);
|
|
||||||
base = TREE_OPERAND (exp, 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
my_friendly_assert (TREE_CODE (type) == OFFSET_TYPE, 214);
|
|
||||||
if (TYPE_OFFSET_BASETYPE (type) != current_class_type)
|
|
||||||
{
|
|
||||||
error ("object missing in use of pointer-to-member construct");
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
member = exp;
|
|
||||||
type = TREE_TYPE (type);
|
|
||||||
base = current_class_ref;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (BASELINK_P (member) || TREE_CODE (member) == TEMPLATE_ID_EXPR)
|
member = TREE_OPERAND (exp, 1);
|
||||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (member)) == METHOD_TYPE)
|
|
||||||
{
|
|
||||||
if (!flag_ms_extensions)
|
|
||||||
/* A single non-static member, make sure we don't allow a
|
|
||||||
pointer-to-member. */
|
|
||||||
exp = ovl_cons (member, NULL_TREE);
|
|
||||||
|
|
||||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((TREE_CODE (member) == VAR_DECL
|
|
||||||
&& ! TYPE_PTRMEMFUNC_P (TREE_TYPE (member))
|
|
||||||
&& ! TYPE_PTRMEM_P (TREE_TYPE (member)))
|
|
||||||
|| TREE_CODE (TREE_TYPE (member)) == FUNCTION_TYPE)
|
|
||||||
{
|
|
||||||
/* These were static members. */
|
|
||||||
if (!cxx_mark_addressable (member))
|
|
||||||
return error_mark_node;
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE
|
/* If MEMBER is non-static, then the program has fallen afoul of
|
||||||
&& TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
|
[expr.prim]:
|
||||||
return member;
|
|
||||||
|
|
||||||
/* Syntax error can cause a member which should
|
An id-expression that denotes a nonstatic data member or
|
||||||
have been seen as static to be grok'd as non-static. */
|
nonstatic member function of a class can only be used:
|
||||||
if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
|
|
||||||
|
-- as part of a class member access (_expr.ref_) in which the
|
||||||
|
object-expression refers to the member's class or a class
|
||||||
|
derived from that class, or
|
||||||
|
|
||||||
|
-- to form a pointer to member (_expr.unary.op_), or
|
||||||
|
|
||||||
|
-- in the body of a nonstatic member function of that class or
|
||||||
|
of a class derived from that class (_class.mfct.nonstatic_), or
|
||||||
|
|
||||||
|
-- in a mem-initializer for a constructor for that class or for
|
||||||
|
a class derived from that class (_class.base.init_). */
|
||||||
|
if (DECL_NONSTATIC_MEMBER_FUNCTION_P (member))
|
||||||
{
|
{
|
||||||
cp_error_at ("member `%D' is non-static but referenced as a static member",
|
/* In Microsoft mode, treat a non-static member function as if
|
||||||
member);
|
it were a pointer-to-member. */
|
||||||
error ("at this point in file");
|
if (flag_ms_extensions)
|
||||||
|
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||||
|
error ("invalid use of non-static member function `%D'", member);
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
|
else if (TREE_CODE (member) == FIELD_DECL)
|
||||||
|
{
|
||||||
|
error ("invalid use of non-static data member `%D'", member);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* The first case is really just a reference to a member of `this'. */
|
return member;
|
||||||
if (TREE_CODE (member) == FIELD_DECL
|
|
||||||
&& (base == current_class_ref || is_dummy_object (base)))
|
|
||||||
{
|
|
||||||
tree binfo = NULL_TREE;
|
|
||||||
|
|
||||||
/* Try to get to basetype from 'this'; if that doesn't work,
|
|
||||||
nothing will. */
|
|
||||||
base = current_class_ref;
|
|
||||||
|
|
||||||
/* First convert to the intermediate base specified, if appropriate. */
|
|
||||||
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE)
|
|
||||||
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo);
|
|
||||||
|
|
||||||
return build_class_member_access_expr (base, member,
|
|
||||||
/*access_path=*/NULL_TREE,
|
|
||||||
/*preserve_reference=*/false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure that we have an object. */
|
|
||||||
if (is_dummy_object (base))
|
|
||||||
addr = error_mark_node;
|
|
||||||
else
|
|
||||||
/* If this is a reference to a member function, then return the
|
|
||||||
address of the member function (which may involve going
|
|
||||||
through the object's vtable), otherwise, return an expression
|
|
||||||
for the dereferenced pointer-to-member construct. */
|
|
||||||
addr = build_unary_op (ADDR_EXPR, base, 0);
|
|
||||||
|
|
||||||
if (TYPE_PTRMEM_P (TREE_TYPE (member)))
|
|
||||||
{
|
|
||||||
if (addr == error_mark_node)
|
|
||||||
{
|
|
||||||
error ("object missing in `%E'", exp);
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
basetype = TYPE_OFFSET_BASETYPE (TREE_TYPE (TREE_TYPE (member)));
|
|
||||||
basetype = lookup_base (TREE_TYPE (TREE_TYPE (addr)),
|
|
||||||
basetype, ba_check, NULL);
|
|
||||||
addr = build_base_path (PLUS_EXPR, addr, basetype, 1);
|
|
||||||
|
|
||||||
member = cp_convert (ptrdiff_type_node, member);
|
|
||||||
|
|
||||||
addr = build (PLUS_EXPR, build_pointer_type (type), addr, member);
|
|
||||||
return build_indirect_ref (addr, 0);
|
|
||||||
}
|
|
||||||
else if (TYPE_PTRMEMFUNC_P (TREE_TYPE (member)))
|
|
||||||
{
|
|
||||||
return get_member_function_from_ptrfunc (&addr, member);
|
|
||||||
}
|
|
||||||
abort ();
|
|
||||||
/* NOTREACHED */
|
|
||||||
return NULL_TREE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If DECL is a `const' declaration, and its value is a known
|
/* If DECL is a `const' declaration, and its value is a known
|
||||||
|
@ -3300,9 +3224,6 @@ build_vec_delete (tree base, tree maxindex,
|
||||||
tree rval;
|
tree rval;
|
||||||
tree base_init = NULL_TREE;
|
tree base_init = NULL_TREE;
|
||||||
|
|
||||||
if (TREE_CODE (base) == OFFSET_REF)
|
|
||||||
base = resolve_offset_ref (base);
|
|
||||||
|
|
||||||
type = TREE_TYPE (base);
|
type = TREE_TYPE (base);
|
||||||
|
|
||||||
if (TREE_CODE (type) == POINTER_TYPE)
|
if (TREE_CODE (type) == POINTER_TYPE)
|
||||||
|
|
|
@ -1667,6 +1667,8 @@ static bool cp_parser_check_declarator_template_parameters
|
||||||
(cp_parser *, tree);
|
(cp_parser *, tree);
|
||||||
static bool cp_parser_check_template_parameters
|
static bool cp_parser_check_template_parameters
|
||||||
(cp_parser *, unsigned);
|
(cp_parser *, unsigned);
|
||||||
|
static tree cp_parser_simple_cast_expression
|
||||||
|
(cp_parser *);
|
||||||
static tree cp_parser_binary_expression
|
static tree cp_parser_binary_expression
|
||||||
(cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
|
(cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
|
||||||
static tree cp_parser_global_scope_opt
|
static tree cp_parser_global_scope_opt
|
||||||
|
@ -3846,8 +3848,15 @@ cp_parser_postfix_expression (cp_parser *parser, bool address_p)
|
||||||
BASELINK_ACCESS_BINFO (postfix_expression),
|
BASELINK_ACCESS_BINFO (postfix_expression),
|
||||||
/*preserve_reference=*/false));
|
/*preserve_reference=*/false));
|
||||||
else if (done)
|
else if (done)
|
||||||
return build_offset_ref (qualifying_class,
|
{
|
||||||
postfix_expression);
|
/* The expression is a qualified name whose address is not
|
||||||
|
being taken. */
|
||||||
|
postfix_expression = build_offset_ref (qualifying_class,
|
||||||
|
postfix_expression);
|
||||||
|
if (TREE_CODE (postfix_expression) == OFFSET_REF)
|
||||||
|
postfix_expression = resolve_offset_ref (postfix_expression);
|
||||||
|
return postfix_expression;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4379,7 +4388,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
|
||||||
/* Save away the PEDANTIC flag. */
|
/* Save away the PEDANTIC flag. */
|
||||||
cp_parser_extension_opt (parser, &saved_pedantic);
|
cp_parser_extension_opt (parser, &saved_pedantic);
|
||||||
/* Parse the cast-expression. */
|
/* Parse the cast-expression. */
|
||||||
expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
expr = cp_parser_simple_cast_expression (parser);
|
||||||
/* Restore the PEDANTIC flag. */
|
/* Restore the PEDANTIC flag. */
|
||||||
pedantic = saved_pedantic;
|
pedantic = saved_pedantic;
|
||||||
|
|
||||||
|
@ -4394,8 +4403,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
|
||||||
/* Consume the `__real__' or `__imag__' token. */
|
/* Consume the `__real__' or `__imag__' token. */
|
||||||
cp_lexer_consume_token (parser->lexer);
|
cp_lexer_consume_token (parser->lexer);
|
||||||
/* Parse the cast-expression. */
|
/* Parse the cast-expression. */
|
||||||
expression = cp_parser_cast_expression (parser,
|
expression = cp_parser_simple_cast_expression (parser);
|
||||||
/*address_p=*/false);
|
|
||||||
/* Create the complete representation. */
|
/* Create the complete representation. */
|
||||||
return build_x_unary_op ((keyword == RID_REALPART
|
return build_x_unary_op ((keyword == RID_REALPART
|
||||||
? REALPART_EXPR : IMAGPART_EXPR),
|
? REALPART_EXPR : IMAGPART_EXPR),
|
||||||
|
@ -4817,7 +4825,7 @@ cp_parser_delete_expression (cp_parser* parser)
|
||||||
array_p = false;
|
array_p = false;
|
||||||
|
|
||||||
/* Parse the cast-expression. */
|
/* Parse the cast-expression. */
|
||||||
expression = cp_parser_cast_expression (parser, /*address_p=*/false);
|
expression = cp_parser_simple_cast_expression (parser);
|
||||||
|
|
||||||
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
|
return delete_sanity (expression, NULL_TREE, array_p, global_scope_p);
|
||||||
}
|
}
|
||||||
|
@ -4897,7 +4905,7 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
|
||||||
ctor of T, but looks like a cast to function returning T
|
ctor of T, but looks like a cast to function returning T
|
||||||
without a dependent expression. */
|
without a dependent expression. */
|
||||||
if (!cp_parser_error_occurred (parser))
|
if (!cp_parser_error_occurred (parser))
|
||||||
expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
expr = cp_parser_simple_cast_expression (parser);
|
||||||
|
|
||||||
if (cp_parser_parse_definitely (parser))
|
if (cp_parser_parse_definitely (parser))
|
||||||
{
|
{
|
||||||
|
@ -4943,42 +4951,14 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
|
||||||
static tree
|
static tree
|
||||||
cp_parser_pm_expression (cp_parser* parser)
|
cp_parser_pm_expression (cp_parser* parser)
|
||||||
{
|
{
|
||||||
tree cast_expr;
|
static const cp_parser_token_tree_map map = {
|
||||||
tree pm_expr;
|
{ CPP_DEREF_STAR, MEMBER_REF },
|
||||||
|
{ CPP_DOT_STAR, DOTSTAR_EXPR },
|
||||||
|
{ CPP_EOF, ERROR_MARK }
|
||||||
|
};
|
||||||
|
|
||||||
/* Parse the cast-expresion. */
|
return cp_parser_binary_expression (parser, map,
|
||||||
cast_expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
cp_parser_simple_cast_expression);
|
||||||
pm_expr = cast_expr;
|
|
||||||
/* Now look for pointer-to-member operators. */
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
cp_token *token;
|
|
||||||
enum cpp_ttype token_type;
|
|
||||||
|
|
||||||
/* Peek at the next token. */
|
|
||||||
token = cp_lexer_peek_token (parser->lexer);
|
|
||||||
token_type = token->type;
|
|
||||||
/* If it's not `.*' or `->*' there's no pointer-to-member
|
|
||||||
operation. */
|
|
||||||
if (token_type != CPP_DOT_STAR
|
|
||||||
&& token_type != CPP_DEREF_STAR)
|
|
||||||
break;
|
|
||||||
|
|
||||||
/* Consume the token. */
|
|
||||||
cp_lexer_consume_token (parser->lexer);
|
|
||||||
|
|
||||||
/* Parse another cast-expression. */
|
|
||||||
cast_expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
|
||||||
|
|
||||||
/* Build the representation of the pointer-to-member
|
|
||||||
operation. */
|
|
||||||
if (token_type == CPP_DEREF_STAR)
|
|
||||||
pm_expr = build_x_binary_op (MEMBER_REF, pm_expr, cast_expr);
|
|
||||||
else
|
|
||||||
pm_expr = build_m_component_ref (pm_expr, cast_expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
return pm_expr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse a multiplicative-expression.
|
/* Parse a multiplicative-expression.
|
||||||
|
@ -14025,6 +14005,14 @@ cp_parser_single_declaration (cp_parser* parser,
|
||||||
return decl;
|
return decl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parse a cast-expression that is not the operand of a unary "&". */
|
||||||
|
|
||||||
|
static tree
|
||||||
|
cp_parser_simple_cast_expression (cp_parser *parser)
|
||||||
|
{
|
||||||
|
return cp_parser_cast_expression (parser, /*address_p=*/false);
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse a functional cast to TYPE. Returns an expression
|
/* Parse a functional cast to TYPE. Returns an expression
|
||||||
representing the cast. */
|
representing the cast. */
|
||||||
|
|
||||||
|
|
|
@ -473,12 +473,6 @@ build_dynamic_cast_1 (tree type, tree expr)
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
{
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
exprtype = TREE_TYPE (expr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (tc == POINTER_TYPE)
|
if (tc == POINTER_TYPE)
|
||||||
expr = convert_from_reference (expr);
|
expr = convert_from_reference (expr);
|
||||||
else if (TREE_CODE (exprtype) != REFERENCE_TYPE)
|
else if (TREE_CODE (exprtype) != REFERENCE_TYPE)
|
||||||
|
|
|
@ -1476,13 +1476,6 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
||||||
tree
|
tree
|
||||||
finish_increment_expr (tree expr, enum tree_code code)
|
finish_increment_expr (tree expr, enum tree_code code)
|
||||||
{
|
{
|
||||||
/* If we get an OFFSET_REF, turn it into what it really means (e.g.,
|
|
||||||
a COMPONENT_REF). This way if we've got, say, a reference to a
|
|
||||||
static member that's being operated on, we don't end up trying to
|
|
||||||
find a member operator for the class it's in. */
|
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
return build_x_unary_op (code, expr);
|
return build_x_unary_op (code, expr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2083,9 +2076,6 @@ finish_typeof (tree expr)
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
|
|
||||||
type = TREE_TYPE (expr);
|
type = TREE_TYPE (expr);
|
||||||
|
|
||||||
if (!type || type == unknown_type_node)
|
if (!type || type == unknown_type_node)
|
||||||
|
|
|
@ -133,10 +133,6 @@ lvalue_p_1 (tree ref,
|
||||||
/* A currently unresolved scope ref. */
|
/* A currently unresolved scope ref. */
|
||||||
case SCOPE_REF:
|
case SCOPE_REF:
|
||||||
abort ();
|
abort ();
|
||||||
case OFFSET_REF:
|
|
||||||
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
|
|
||||||
return clk_ordinary;
|
|
||||||
/* Fall through. */
|
|
||||||
case MAX_EXPR:
|
case MAX_EXPR:
|
||||||
case MIN_EXPR:
|
case MIN_EXPR:
|
||||||
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
|
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
|
||||||
|
|
|
@ -105,17 +105,6 @@ require_complete_type (tree value)
|
||||||
if (COMPLETE_TYPE_P (type))
|
if (COMPLETE_TYPE_P (type))
|
||||||
return value;
|
return value;
|
||||||
|
|
||||||
/* If we see X::Y, we build an OFFSET_TYPE which has
|
|
||||||
not been laid out. Try to avoid an error by interpreting
|
|
||||||
it as this->X::Y, if reasonable. */
|
|
||||||
if (TREE_CODE (value) == OFFSET_REF
|
|
||||||
&& current_class_ref != 0
|
|
||||||
&& TREE_OPERAND (value, 0) == current_class_ref)
|
|
||||||
{
|
|
||||||
value = resolve_offset_ref (value);
|
|
||||||
return require_complete_type (value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (complete_type_or_else (type, value))
|
if (complete_type_or_else (type, value))
|
||||||
return value;
|
return value;
|
||||||
else
|
else
|
||||||
|
@ -1486,11 +1475,6 @@ expr_sizeof (tree e)
|
||||||
cxx_incomplete_type_error (e, TREE_TYPE (e));
|
cxx_incomplete_type_error (e, TREE_TYPE (e));
|
||||||
return c_sizeof (char_type_node);
|
return c_sizeof (char_type_node);
|
||||||
}
|
}
|
||||||
/* It's invalid to say `sizeof (X::i)' for `i' a non-static data
|
|
||||||
member unless you're in a non-static member of X. So hand off to
|
|
||||||
resolve_offset_ref. [expr.prim] */
|
|
||||||
else if (TREE_CODE (e) == OFFSET_REF)
|
|
||||||
e = resolve_offset_ref (e);
|
|
||||||
|
|
||||||
if (e == error_mark_node)
|
if (e == error_mark_node)
|
||||||
return e;
|
return e;
|
||||||
|
@ -1511,9 +1495,6 @@ decay_conversion (tree exp)
|
||||||
register tree type;
|
register tree type;
|
||||||
register enum tree_code code;
|
register enum tree_code code;
|
||||||
|
|
||||||
if (TREE_CODE (exp) == OFFSET_REF)
|
|
||||||
exp = resolve_offset_ref (exp);
|
|
||||||
|
|
||||||
type = TREE_TYPE (exp);
|
type = TREE_TYPE (exp);
|
||||||
code = TREE_CODE (type);
|
code = TREE_CODE (type);
|
||||||
|
|
||||||
|
@ -1555,7 +1536,10 @@ decay_conversion (tree exp)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
if (code == METHOD_TYPE)
|
if (code == METHOD_TYPE)
|
||||||
abort ();
|
{
|
||||||
|
error ("invalid use of non-static member function");
|
||||||
|
return error_mark_node;
|
||||||
|
}
|
||||||
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
|
if (code == FUNCTION_TYPE || is_overloaded_fn (exp))
|
||||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||||
if (code == ARRAY_TYPE)
|
if (code == ARRAY_TYPE)
|
||||||
|
@ -2047,9 +2031,6 @@ finish_class_member_access_expr (tree object, tree name)
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (COMPONENT_REF, object, name);
|
return build_min_nt (COMPONENT_REF, object, name);
|
||||||
|
|
||||||
if (TREE_CODE (object) == OFFSET_REF)
|
|
||||||
object = resolve_offset_ref (object);
|
|
||||||
|
|
||||||
object_type = TREE_TYPE (object);
|
object_type = TREE_TYPE (object);
|
||||||
if (TREE_CODE (object_type) == REFERENCE_TYPE)
|
if (TREE_CODE (object_type) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
|
@ -2749,9 +2730,6 @@ convert_arguments (typelist, values, fndecl, flags)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TREE_CODE (val) == OFFSET_REF)
|
|
||||||
val = resolve_offset_ref (val);
|
|
||||||
|
|
||||||
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
|
/* build_c_cast puts on a NOP_EXPR to make the result not an lvalue.
|
||||||
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
|
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
|
||||||
if (TREE_CODE (val) == NOP_EXPR
|
if (TREE_CODE (val) == NOP_EXPR
|
||||||
|
@ -2865,6 +2843,9 @@ build_x_binary_op (code, arg1, arg2)
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (code, arg1, arg2);
|
return build_min_nt (code, arg1, arg2);
|
||||||
|
|
||||||
|
if (code == DOTSTAR_EXPR)
|
||||||
|
return build_m_component_ref (arg1, arg2);
|
||||||
|
|
||||||
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
return build_new_op (code, LOOKUP_NORMAL, arg1, arg2, NULL_TREE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3973,8 +3954,6 @@ condition_conversion (expr)
|
||||||
tree t;
|
tree t;
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return expr;
|
return expr;
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
t = perform_implicit_conversion (boolean_type_node, expr);
|
t = perform_implicit_conversion (boolean_type_node, expr);
|
||||||
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
|
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
|
||||||
return t;
|
return t;
|
||||||
|
@ -4560,15 +4539,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
if (!PTRMEM_OK_P (arg))
|
if (!PTRMEM_OK_P (arg))
|
||||||
{
|
return build_unary_op (code, arg, 0);
|
||||||
/* This cannot form a pointer to method, so we must
|
|
||||||
resolve the offset ref, and take the address of the
|
|
||||||
result. For instance,
|
|
||||||
&(C::m) */
|
|
||||||
arg = resolve_offset_ref (arg);
|
|
||||||
|
|
||||||
return build_unary_op (code, arg, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
|
if (TREE_CODE (TREE_TYPE (t)) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
|
@ -4792,9 +4763,6 @@ build_static_cast (tree type, tree expr)
|
||||||
if (type == error_mark_node || expr == error_mark_node)
|
if (type == error_mark_node || expr == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
{
|
{
|
||||||
tree t = build_min (STATIC_CAST_EXPR, type, expr);
|
tree t = build_min (STATIC_CAST_EXPR, type, expr);
|
||||||
|
@ -4965,9 +4933,6 @@ build_reinterpret_cast (tree type, tree expr)
|
||||||
if (type == error_mark_node || expr == error_mark_node)
|
if (type == error_mark_node || expr == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
{
|
{
|
||||||
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
|
tree t = build_min (REINTERPRET_CAST_EXPR, type, expr);
|
||||||
|
@ -5055,9 +5020,6 @@ build_const_cast (tree type, tree expr)
|
||||||
if (type == error_mark_node || expr == error_mark_node)
|
if (type == error_mark_node || expr == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (expr) == OFFSET_REF)
|
|
||||||
expr = resolve_offset_ref (expr);
|
|
||||||
|
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
{
|
{
|
||||||
tree t = build_min (CONST_CAST_EXPR, type, expr);
|
tree t = build_min (CONST_CAST_EXPR, type, expr);
|
||||||
|
@ -5139,9 +5101,6 @@ build_c_cast (tree type, tree expr)
|
||||||
&& TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
|
&& TREE_TYPE (value) == TREE_TYPE (TREE_OPERAND (value, 0)))
|
||||||
value = TREE_OPERAND (value, 0);
|
value = TREE_OPERAND (value, 0);
|
||||||
|
|
||||||
if (TREE_CODE (value) == OFFSET_REF)
|
|
||||||
value = resolve_offset_ref (value);
|
|
||||||
|
|
||||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||||
{
|
{
|
||||||
/* Allow casting from T1* to T2[] because Cfront allows it.
|
/* Allow casting from T1* to T2[] because Cfront allows it.
|
||||||
|
@ -5361,12 +5320,6 @@ build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
|
||||||
return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
|
return build (COMPOUND_EXPR, TREE_TYPE (lhs), preeval, cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
case OFFSET_REF:
|
|
||||||
lhs = resolve_offset_ref (lhs);
|
|
||||||
if (lhs == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
olhstype = lhstype = TREE_TYPE (lhs);
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -6008,9 +5961,6 @@ convert_for_assignment (tree type, tree rhs,
|
||||||
if (codel == OFFSET_TYPE)
|
if (codel == OFFSET_TYPE)
|
||||||
abort ();
|
abort ();
|
||||||
|
|
||||||
if (TREE_CODE (rhs) == OFFSET_REF)
|
|
||||||
rhs = resolve_offset_ref (rhs);
|
|
||||||
|
|
||||||
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
|
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
|
||||||
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
|
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
|
||||||
rhs = TREE_OPERAND (rhs, 0);
|
rhs = TREE_OPERAND (rhs, 0);
|
||||||
|
@ -6117,13 +6067,6 @@ convert_for_initialization (tree exp, tree type, tree rhs, int flags,
|
||||||
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
|
|| (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node))
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
if (TREE_CODE (rhs) == OFFSET_REF)
|
|
||||||
{
|
|
||||||
rhs = resolve_offset_ref (rhs);
|
|
||||||
if (rhs == error_mark_node)
|
|
||||||
return error_mark_node;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
|
if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
|
||||||
rhs = convert_from_reference (rhs);
|
rhs = convert_from_reference (rhs);
|
||||||
|
|
||||||
|
|
|
@ -993,12 +993,6 @@ build_x_arrow (tree datum)
|
||||||
if (processing_template_decl)
|
if (processing_template_decl)
|
||||||
return build_min_nt (ARROW_EXPR, rval);
|
return build_min_nt (ARROW_EXPR, rval);
|
||||||
|
|
||||||
if (TREE_CODE (rval) == OFFSET_REF)
|
|
||||||
{
|
|
||||||
rval = resolve_offset_ref (datum);
|
|
||||||
type = TREE_TYPE (rval);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (TREE_CODE (type) == REFERENCE_TYPE)
|
if (TREE_CODE (type) == REFERENCE_TYPE)
|
||||||
{
|
{
|
||||||
rval = convert_from_reference (rval);
|
rval = convert_from_reference (rval);
|
||||||
|
@ -1048,72 +1042,32 @@ build_x_arrow (tree datum)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make an expression to refer to the COMPONENT field of
|
/* Return an expression for "DATUM .* COMPONENT". DATUM has not
|
||||||
structure or union value DATUM. COMPONENT is an arbitrary
|
already been checked out to be of aggregate type. */
|
||||||
expression. DATUM has not already been checked out to be of
|
|
||||||
aggregate type.
|
|
||||||
|
|
||||||
For C++, COMPONENT may be a TREE_LIST. This happens when we must
|
|
||||||
return an object of member type to a method of the current class,
|
|
||||||
but there is not yet enough typing information to know which one.
|
|
||||||
As a special case, if there is only one method by that name,
|
|
||||||
it is returned. Otherwise we return an expression which other
|
|
||||||
routines will have to know how to deal with later. */
|
|
||||||
|
|
||||||
tree
|
tree
|
||||||
build_m_component_ref (tree datum, tree component)
|
build_m_component_ref (tree datum, tree component)
|
||||||
{
|
{
|
||||||
tree type;
|
tree ptrmem_type;
|
||||||
tree objtype;
|
tree objtype;
|
||||||
tree field_type;
|
tree type;
|
||||||
int type_quals;
|
|
||||||
tree binfo;
|
tree binfo;
|
||||||
|
|
||||||
if (processing_template_decl)
|
|
||||||
return build_min_nt (DOTSTAR_EXPR, datum, component);
|
|
||||||
|
|
||||||
datum = decay_conversion (datum);
|
datum = decay_conversion (datum);
|
||||||
|
|
||||||
if (datum == error_mark_node || component == error_mark_node)
|
if (datum == error_mark_node || component == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
ptrmem_type = TREE_TYPE (component);
|
||||||
|
if (!TYPE_PTRMEM_P (ptrmem_type)
|
||||||
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
|
&& !TYPE_PTRMEMFUNC_P (ptrmem_type))
|
||||||
{
|
|
||||||
type = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (TREE_TYPE (component)));
|
|
||||||
field_type = type;
|
|
||||||
}
|
|
||||||
else if (TYPE_PTRMEM_P (TREE_TYPE (component)))
|
|
||||||
{
|
|
||||||
type = TREE_TYPE (TREE_TYPE (component));
|
|
||||||
field_type = TREE_TYPE (type);
|
|
||||||
|
|
||||||
/* Compute the type of the field, as described in [expr.ref]. */
|
|
||||||
type_quals = TYPE_UNQUALIFIED;
|
|
||||||
if (TREE_CODE (field_type) == REFERENCE_TYPE)
|
|
||||||
/* The standard says that the type of the result should be the
|
|
||||||
type referred to by the reference. But for now, at least,
|
|
||||||
we do the conversion from reference type later. */
|
|
||||||
;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
type_quals = (cp_type_quals (field_type)
|
|
||||||
| cp_type_quals (TREE_TYPE (datum)));
|
|
||||||
|
|
||||||
/* There's no such thing as a mutable pointer-to-member, so
|
|
||||||
things are not as complex as they are for references to
|
|
||||||
non-static data members. */
|
|
||||||
field_type = cp_build_qualified_type (field_type, type_quals);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
error ("`%E' cannot be used as a member pointer, since it is of type `%T'",
|
error ("`%E' cannot be used as a member pointer, since it is of type `%T'",
|
||||||
component, TREE_TYPE (component));
|
component, ptrmem_type);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||||
if (! IS_AGGR_TYPE (objtype))
|
if (! IS_AGGR_TYPE (objtype))
|
||||||
{
|
{
|
||||||
error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'",
|
error ("cannot apply member pointer `%E' to `%E', which is of non-aggregate type `%T'",
|
||||||
|
@ -1121,21 +1075,35 @@ build_m_component_ref (tree datum, tree component)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
|
|
||||||
binfo = lookup_base (objtype, TYPE_METHOD_BASETYPE (type),
|
type = TYPE_PTRMEM_POINTED_TO_TYPE (ptrmem_type);
|
||||||
|
binfo = lookup_base (objtype, TYPE_PTRMEM_CLASS_TYPE (ptrmem_type),
|
||||||
ba_check, NULL);
|
ba_check, NULL);
|
||||||
if (!binfo)
|
if (!binfo)
|
||||||
{
|
{
|
||||||
error ("member type `%T::' incompatible with object type `%T'",
|
error ("member type `%T::' incompatible with object type `%T'",
|
||||||
TYPE_METHOD_BASETYPE (type), objtype);
|
type, objtype);
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
}
|
}
|
||||||
else if (binfo == error_mark_node)
|
else if (binfo == error_mark_node)
|
||||||
return error_mark_node;
|
return error_mark_node;
|
||||||
|
|
||||||
component = build (OFFSET_REF, field_type, datum, component);
|
if (TYPE_PTRMEM_P (ptrmem_type))
|
||||||
if (TREE_CODE (type) == OFFSET_TYPE)
|
{
|
||||||
component = resolve_offset_ref (component);
|
/* Compute the type of the field, as described in [expr.ref].
|
||||||
return component;
|
There's no such thing as a mutable pointer-to-member, so
|
||||||
|
things are not as complex as they are for references to
|
||||||
|
non-static data members. */
|
||||||
|
type = cp_build_qualified_type (type,
|
||||||
|
(cp_type_quals (type)
|
||||||
|
| cp_type_quals (TREE_TYPE (datum))));
|
||||||
|
|
||||||
|
datum = build_base_path (PLUS_EXPR, build_address (datum), binfo, 1);
|
||||||
|
component = cp_convert (ptrdiff_type_node, component);
|
||||||
|
datum = build (PLUS_EXPR, build_pointer_type (type), datum, component);
|
||||||
|
return build_indirect_ref (datum, 0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return build (OFFSET_REF, type, datum, component);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
|
/* Return a tree node for the expression TYPENAME '(' PARMS ')'. */
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2003-07-03 Mark Mitchell <mark@codesourcery.com>
|
||||||
|
|
||||||
|
* g++.old-deja/g++.jason/typeid1.C: Add dg-error marker.
|
||||||
|
* g++.old-deja/g++.mike/net36.C: Tweak error messages.
|
||||||
|
|
||||||
2003-07-03 Roger Sayle <roger@eyesopen.com>
|
2003-07-03 Roger Sayle <roger@eyesopen.com>
|
||||||
|
|
||||||
* gcc.dg/builtins-25.c: New testcase.
|
* gcc.dg/builtins-25.c: New testcase.
|
||||||
|
|
|
@ -8,5 +8,5 @@ int main() {
|
||||||
double f (int);
|
double f (int);
|
||||||
const std::type_info &r = typeid (f);
|
const std::type_info &r = typeid (f);
|
||||||
std::cout << typeid(f).name() << std::endl;
|
std::cout << typeid(f).name() << std::endl;
|
||||||
std::cout << typeid(foo::f).name() << std::endl;
|
std::cout << typeid(foo::f).name() << std::endl; /* { dg-error "" } */
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ typedef void (A::*handler) (X*);
|
||||||
|
|
||||||
class B {
|
class B {
|
||||||
public:
|
public:
|
||||||
void setHandler(handler); // { dg-error "" } candidate
|
void setHandler(handler);
|
||||||
};
|
};
|
||||||
|
|
||||||
void f(B* b) {
|
void f(B* b) {
|
||||||
|
|
Loading…
Reference in New Issue