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>
|
||||
|
||||
* 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.
|
||||
(build_method_call): Likewise.
|
||||
* class.c (check_field_decls): Remove dead code.
|
||||
|
|
|
@ -317,21 +317,13 @@ build_addr_func (tree function)
|
|||
functions. */
|
||||
if (TREE_CODE (type) == METHOD_TYPE)
|
||||
{
|
||||
tree addr;
|
||||
|
||||
type = build_pointer_type (type);
|
||||
|
||||
if (!cxx_mark_addressable (function))
|
||||
return error_mark_node;
|
||||
|
||||
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;
|
||||
if (TREE_CODE (function) == OFFSET_REF)
|
||||
{
|
||||
tree object = build_address (TREE_OPERAND (function, 0));
|
||||
return get_member_function_from_ptrfunc (&object,
|
||||
TREE_OPERAND (function, 1));
|
||||
}
|
||||
function = build_address (function);
|
||||
}
|
||||
else
|
||||
function = default_conversion (function);
|
||||
|
@ -477,8 +469,6 @@ build_method_call (tree instance, tree name, tree parms,
|
|||
if (processing_template_decl)
|
||||
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)
|
||||
instance = convert_from_reference (instance);
|
||||
object_type = TREE_TYPE (instance);
|
||||
|
@ -1295,14 +1285,6 @@ implicit_conversion (tree to, tree from, tree expr, int flags)
|
|||
{
|
||||
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
|
||||
|| expr == error_mark_node)
|
||||
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. */
|
||||
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)
|
||||
|
@ -2831,8 +2813,6 @@ resolve_args (tree args)
|
|||
error ("invalid use of void expression");
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (TREE_CODE (arg) == OFFSET_REF)
|
||||
arg = resolve_offset_ref (arg);
|
||||
arg = convert_from_reference (arg);
|
||||
TREE_VALUE (t) = arg;
|
||||
}
|
||||
|
@ -3565,8 +3545,6 @@ prep_operand (tree operand)
|
|||
{
|
||||
if (operand)
|
||||
{
|
||||
if (TREE_CODE (operand) == OFFSET_REF)
|
||||
operand = resolve_offset_ref (operand);
|
||||
operand = convert_from_reference (operand);
|
||||
if (CLASS_TYPE_P (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)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (instance) == OFFSET_REF)
|
||||
instance = resolve_offset_ref (instance);
|
||||
if (TREE_CODE (TREE_TYPE (instance)) == REFERENCE_TYPE)
|
||||
instance = convert_from_reference (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:
|
||||
|
||||
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
|
||||
TYPE (corresponding to `A') and operand 1 will be a FIELD_DECL
|
||||
(corresponding to `m'.
|
||||
a non-static member. In this case, operand 0 will be a TYPE
|
||||
(corresponding to `A') and operand 1 will be a FIELD_DECL,
|
||||
BASELINK, or TEMPLATE_ID_EXPR (corresponding to `m').
|
||||
|
||||
The expression is a pointer-to-member if its address is taken,
|
||||
but simply denotes a member of the object if its address isnot
|
||||
taken. In the latter case, resolve_offset_ref is used to
|
||||
convert it to a representation of the member referred to by the
|
||||
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
|
||||
be an expression corresponding to `x' and operand 1 will be an
|
||||
expression with pointer-to-member type.
|
||||
|
||||
OFFSET_REFs are only used during the parsing phase; once semantic
|
||||
analysis has taken place they are eliminated. */
|
||||
expression with pointer-to-member type. */
|
||||
DEFTREECODE (OFFSET_REF, "offset_ref", 'r', 2)
|
||||
|
||||
/* 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. */
|
||||
if (TYPE_PTRMEMFUNC_P (intype))
|
||||
{
|
||||
tree fntype = TREE_TYPE (TYPE_PTRMEMFUNC_FN_TYPE (intype));
|
||||
tree decl = maybe_dummy_object (TYPE_METHOD_BASETYPE (fntype), 0);
|
||||
expr = build (OFFSET_REF, fntype, decl, expr);
|
||||
if (pedantic || warn_pmf2ptr)
|
||||
pedwarn ("converting from `%T' to `%T'", intype, type);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
else if (TREE_CODE (TREE_TYPE (expr)) == METHOD_TYPE)
|
||||
{
|
||||
if (TREE_CODE (TREE_TYPE (TREE_TYPE (expr))) == METHOD_TYPE)
|
||||
if (pedantic || warn_pmf2ptr)
|
||||
pedwarn ("converting from `%T' to `%T'", TREE_TYPE (expr),
|
||||
type);
|
||||
return build1 (NOP_EXPR, type, expr);
|
||||
if (pedantic || warn_pmf2ptr)
|
||||
pedwarn ("converting from `%T' to `%T'", intype, type);
|
||||
expr = build_addr_func (expr);
|
||||
}
|
||||
if (TREE_CODE (TREE_TYPE (expr)) == POINTER_TYPE)
|
||||
return build_nop (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);
|
||||
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'",
|
||||
expr, intype, type);
|
||||
return error_mark_node;
|
||||
|
@ -663,9 +678,6 @@ ocp_convert (tree type, tree expr, int convtype, int flags)
|
|||
code = TREE_CODE (type);
|
||||
}
|
||||
|
||||
if (TREE_CODE (e) == OFFSET_REF)
|
||||
e = resolve_offset_ref (e);
|
||||
|
||||
if (INTEGRAL_CODE_P (code))
|
||||
{
|
||||
tree intype = TREE_TYPE (e);
|
||||
|
@ -879,10 +891,6 @@ convert_to_void (tree expr, const char *implicit)
|
|||
break;
|
||||
}
|
||||
|
||||
case OFFSET_REF:
|
||||
expr = resolve_offset_ref (expr);
|
||||
break;
|
||||
|
||||
default:;
|
||||
}
|
||||
{
|
||||
|
@ -1023,8 +1031,6 @@ build_expr_type_conversion (int desires, tree expr, bool complain)
|
|||
&& !(desires & WANT_NULL))
|
||||
warning ("converting NULL to non-pointer type");
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
expr = convert_from_reference (expr);
|
||||
basetype = TREE_TYPE (expr);
|
||||
|
||||
|
|
|
@ -481,8 +481,6 @@ delete_sanity (tree exp, tree size, int doing_vec, int use_global_delete)
|
|||
return t;
|
||||
}
|
||||
|
||||
if (TREE_CODE (exp) == OFFSET_REF)
|
||||
exp = resolve_offset_ref (exp);
|
||||
exp = convert_from_reference (exp);
|
||||
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
|
||||
resolve_offset_ref (tree exp)
|
||||
{
|
||||
tree type = TREE_TYPE (exp);
|
||||
tree base = NULL_TREE;
|
||||
tree member;
|
||||
tree basetype, addr;
|
||||
|
||||
if (TREE_CODE (exp) == OFFSET_REF)
|
||||
{
|
||||
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;
|
||||
}
|
||||
my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
|
||||
|
||||
if (BASELINK_P (member) || TREE_CODE (member) == TEMPLATE_ID_EXPR)
|
||||
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;
|
||||
}
|
||||
member = TREE_OPERAND (exp, 1);
|
||||
|
||||
if (TREE_CODE (TREE_TYPE (member)) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
|
||||
return member;
|
||||
/* If MEMBER is non-static, then the program has fallen afoul of
|
||||
[expr.prim]:
|
||||
|
||||
/* Syntax error can cause a member which should
|
||||
have been seen as static to be grok'd as non-static. */
|
||||
if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
|
||||
An id-expression that denotes a nonstatic data member or
|
||||
nonstatic member function of a class can only be used:
|
||||
|
||||
-- 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",
|
||||
member);
|
||||
error ("at this point in file");
|
||||
/* In Microsoft mode, treat a non-static member function as if
|
||||
it were a pointer-to-member. */
|
||||
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;
|
||||
}
|
||||
|
||||
/* The first case is really just a reference to a member of `this'. */
|
||||
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;
|
||||
return member;
|
||||
}
|
||||
|
||||
/* 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 base_init = NULL_TREE;
|
||||
|
||||
if (TREE_CODE (base) == OFFSET_REF)
|
||||
base = resolve_offset_ref (base);
|
||||
|
||||
type = TREE_TYPE (base);
|
||||
|
||||
if (TREE_CODE (type) == POINTER_TYPE)
|
||||
|
|
|
@ -1667,6 +1667,8 @@ static bool cp_parser_check_declarator_template_parameters
|
|||
(cp_parser *, tree);
|
||||
static bool cp_parser_check_template_parameters
|
||||
(cp_parser *, unsigned);
|
||||
static tree cp_parser_simple_cast_expression
|
||||
(cp_parser *);
|
||||
static tree cp_parser_binary_expression
|
||||
(cp_parser *, const cp_parser_token_tree_map, cp_parser_expression_fn);
|
||||
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),
|
||||
/*preserve_reference=*/false));
|
||||
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. */
|
||||
cp_parser_extension_opt (parser, &saved_pedantic);
|
||||
/* Parse the cast-expression. */
|
||||
expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
||||
expr = cp_parser_simple_cast_expression (parser);
|
||||
/* Restore the PEDANTIC flag. */
|
||||
pedantic = saved_pedantic;
|
||||
|
||||
|
@ -4394,8 +4403,7 @@ cp_parser_unary_expression (cp_parser *parser, bool address_p)
|
|||
/* Consume the `__real__' or `__imag__' token. */
|
||||
cp_lexer_consume_token (parser->lexer);
|
||||
/* Parse the cast-expression. */
|
||||
expression = cp_parser_cast_expression (parser,
|
||||
/*address_p=*/false);
|
||||
expression = cp_parser_simple_cast_expression (parser);
|
||||
/* Create the complete representation. */
|
||||
return build_x_unary_op ((keyword == RID_REALPART
|
||||
? REALPART_EXPR : IMAGPART_EXPR),
|
||||
|
@ -4817,7 +4825,7 @@ cp_parser_delete_expression (cp_parser* parser)
|
|||
array_p = false;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
@ -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
|
||||
without a dependent expression. */
|
||||
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))
|
||||
{
|
||||
|
@ -4943,42 +4951,14 @@ cp_parser_cast_expression (cp_parser *parser, bool address_p)
|
|||
static tree
|
||||
cp_parser_pm_expression (cp_parser* parser)
|
||||
{
|
||||
tree cast_expr;
|
||||
tree pm_expr;
|
||||
static const cp_parser_token_tree_map map = {
|
||||
{ CPP_DEREF_STAR, MEMBER_REF },
|
||||
{ CPP_DOT_STAR, DOTSTAR_EXPR },
|
||||
{ CPP_EOF, ERROR_MARK }
|
||||
};
|
||||
|
||||
/* Parse the cast-expresion. */
|
||||
cast_expr = cp_parser_cast_expression (parser, /*address_p=*/false);
|
||||
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;
|
||||
return cp_parser_binary_expression (parser, map,
|
||||
cp_parser_simple_cast_expression);
|
||||
}
|
||||
|
||||
/* Parse a multiplicative-expression.
|
||||
|
@ -14025,6 +14005,14 @@ cp_parser_single_declaration (cp_parser* parser,
|
|||
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
|
||||
representing the cast. */
|
||||
|
||||
|
|
|
@ -473,12 +473,6 @@ build_dynamic_cast_1 (tree type, tree expr)
|
|||
goto fail;
|
||||
}
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
{
|
||||
expr = resolve_offset_ref (expr);
|
||||
exprtype = TREE_TYPE (expr);
|
||||
}
|
||||
|
||||
if (tc == POINTER_TYPE)
|
||||
expr = convert_from_reference (expr);
|
||||
else if (TREE_CODE (exprtype) != REFERENCE_TYPE)
|
||||
|
|
|
@ -1476,13 +1476,6 @@ finish_call_expr (tree fn, tree args, bool disallow_virtual)
|
|||
tree
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -2083,9 +2076,6 @@ finish_typeof (tree expr)
|
|||
return type;
|
||||
}
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
|
||||
type = TREE_TYPE (expr);
|
||||
|
||||
if (!type || type == unknown_type_node)
|
||||
|
|
|
@ -133,10 +133,6 @@ lvalue_p_1 (tree ref,
|
|||
/* A currently unresolved scope ref. */
|
||||
case SCOPE_REF:
|
||||
abort ();
|
||||
case OFFSET_REF:
|
||||
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
|
||||
return clk_ordinary;
|
||||
/* Fall through. */
|
||||
case MAX_EXPR:
|
||||
case MIN_EXPR:
|
||||
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
|
||||
|
|
|
@ -105,17 +105,6 @@ require_complete_type (tree value)
|
|||
if (COMPLETE_TYPE_P (type))
|
||||
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))
|
||||
return value;
|
||||
else
|
||||
|
@ -1486,11 +1475,6 @@ expr_sizeof (tree e)
|
|||
cxx_incomplete_type_error (e, TREE_TYPE (e));
|
||||
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)
|
||||
return e;
|
||||
|
@ -1511,9 +1495,6 @@ decay_conversion (tree exp)
|
|||
register tree type;
|
||||
register enum tree_code code;
|
||||
|
||||
if (TREE_CODE (exp) == OFFSET_REF)
|
||||
exp = resolve_offset_ref (exp);
|
||||
|
||||
type = TREE_TYPE (exp);
|
||||
code = TREE_CODE (type);
|
||||
|
||||
|
@ -1555,7 +1536,10 @@ decay_conversion (tree exp)
|
|||
return error_mark_node;
|
||||
}
|
||||
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))
|
||||
return build_unary_op (ADDR_EXPR, exp, 0);
|
||||
if (code == ARRAY_TYPE)
|
||||
|
@ -2047,9 +2031,6 @@ finish_class_member_access_expr (tree object, tree name)
|
|||
if (processing_template_decl)
|
||||
return build_min_nt (COMPONENT_REF, object, name);
|
||||
|
||||
if (TREE_CODE (object) == OFFSET_REF)
|
||||
object = resolve_offset_ref (object);
|
||||
|
||||
object_type = TREE_TYPE (object);
|
||||
if (TREE_CODE (object_type) == REFERENCE_TYPE)
|
||||
{
|
||||
|
@ -2749,9 +2730,6 @@ convert_arguments (typelist, values, fndecl, flags)
|
|||
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.
|
||||
Strip such NOP_EXPRs, since VAL is used in non-lvalue context. */
|
||||
if (TREE_CODE (val) == NOP_EXPR
|
||||
|
@ -2865,6 +2843,9 @@ build_x_binary_op (code, arg1, arg2)
|
|||
if (processing_template_decl)
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -3973,8 +3954,6 @@ condition_conversion (expr)
|
|||
tree t;
|
||||
if (processing_template_decl)
|
||||
return expr;
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
t = perform_implicit_conversion (boolean_type_node, expr);
|
||||
t = fold (build1 (CLEANUP_POINT_EXPR, boolean_type_node, t));
|
||||
return t;
|
||||
|
@ -4560,15 +4539,7 @@ unary_complex_lvalue (enum tree_code code, tree arg)
|
|||
return error_mark_node;
|
||||
}
|
||||
if (!PTRMEM_OK_P (arg))
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
return build_unary_op (code, arg, 0);
|
||||
|
||||
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)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
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)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
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)
|
||||
return error_mark_node;
|
||||
|
||||
if (TREE_CODE (expr) == OFFSET_REF)
|
||||
expr = resolve_offset_ref (expr);
|
||||
|
||||
if (processing_template_decl)
|
||||
{
|
||||
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)))
|
||||
value = TREE_OPERAND (value, 0);
|
||||
|
||||
if (TREE_CODE (value) == OFFSET_REF)
|
||||
value = resolve_offset_ref (value);
|
||||
|
||||
if (TREE_CODE (type) == ARRAY_TYPE)
|
||||
{
|
||||
/* 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);
|
||||
}
|
||||
|
||||
case OFFSET_REF:
|
||||
lhs = resolve_offset_ref (lhs);
|
||||
if (lhs == error_mark_node)
|
||||
return error_mark_node;
|
||||
olhstype = lhstype = TREE_TYPE (lhs);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -6008,9 +5961,6 @@ convert_for_assignment (tree type, tree rhs,
|
|||
if (codel == OFFSET_TYPE)
|
||||
abort ();
|
||||
|
||||
if (TREE_CODE (rhs) == OFFSET_REF)
|
||||
rhs = resolve_offset_ref (rhs);
|
||||
|
||||
/* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue. */
|
||||
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
|
||||
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))
|
||||
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)
|
||||
rhs = convert_from_reference (rhs);
|
||||
|
||||
|
|
|
@ -993,12 +993,6 @@ build_x_arrow (tree datum)
|
|||
if (processing_template_decl)
|
||||
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)
|
||||
{
|
||||
rval = convert_from_reference (rval);
|
||||
|
@ -1048,72 +1042,32 @@ build_x_arrow (tree datum)
|
|||
return error_mark_node;
|
||||
}
|
||||
|
||||
/* Make an expression to refer to the COMPONENT field of
|
||||
structure or union value DATUM. COMPONENT is an arbitrary
|
||||
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. */
|
||||
/* Return an expression for "DATUM .* COMPONENT". DATUM has not
|
||||
already been checked out to be of aggregate type. */
|
||||
|
||||
tree
|
||||
build_m_component_ref (tree datum, tree component)
|
||||
{
|
||||
tree type;
|
||||
tree ptrmem_type;
|
||||
tree objtype;
|
||||
tree field_type;
|
||||
int type_quals;
|
||||
tree type;
|
||||
tree binfo;
|
||||
|
||||
if (processing_template_decl)
|
||||
return build_min_nt (DOTSTAR_EXPR, datum, component);
|
||||
|
||||
datum = decay_conversion (datum);
|
||||
|
||||
if (datum == error_mark_node || component == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||
|
||||
if (TYPE_PTRMEMFUNC_P (TREE_TYPE (component)))
|
||||
{
|
||||
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
|
||||
ptrmem_type = TREE_TYPE (component);
|
||||
if (!TYPE_PTRMEM_P (ptrmem_type)
|
||||
&& !TYPE_PTRMEMFUNC_P (ptrmem_type))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
objtype = TYPE_MAIN_VARIANT (TREE_TYPE (datum));
|
||||
if (! IS_AGGR_TYPE (objtype))
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
if (!binfo)
|
||||
{
|
||||
error ("member type `%T::' incompatible with object type `%T'",
|
||||
TYPE_METHOD_BASETYPE (type), objtype);
|
||||
type, objtype);
|
||||
return error_mark_node;
|
||||
}
|
||||
else if (binfo == error_mark_node)
|
||||
return error_mark_node;
|
||||
|
||||
component = build (OFFSET_REF, field_type, datum, component);
|
||||
if (TREE_CODE (type) == OFFSET_TYPE)
|
||||
component = resolve_offset_ref (component);
|
||||
return component;
|
||||
if (TYPE_PTRMEM_P (ptrmem_type))
|
||||
{
|
||||
/* Compute the type of the field, as described in [expr.ref].
|
||||
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 ')'. */
|
||||
|
|
|
@ -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>
|
||||
|
||||
* gcc.dg/builtins-25.c: New testcase.
|
||||
|
|
|
@ -8,5 +8,5 @@ int main() {
|
|||
double f (int);
|
||||
const std::type_info &r = typeid (f);
|
||||
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 {
|
||||
public:
|
||||
void setHandler(handler); // { dg-error "" } candidate
|
||||
void setHandler(handler);
|
||||
};
|
||||
|
||||
void f(B* b) {
|
||||
|
|
Loading…
Reference in New Issue