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:
Mark Mitchell 2003-07-04 05:05:19 +00:00 committed by Mark Mitchell
parent 5f1989e65d
commit d6b4ea8592
15 changed files with 196 additions and 365 deletions

View File

@ -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.

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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. */

View File

@ -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)

View File

@ -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)

View File

@ -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),

View File

@ -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);

View File

@ -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 ')'. */

View File

@ -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.

View File

@ -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 "" } */
}

View File

@ -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) {