Commit d6b4ea85 by Mark Mitchell Committed by Mark Mitchell

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
parent 5f1989e6
...@@ -6,6 +6,52 @@ ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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. */ ...@@ -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
......
...@@ -109,24 +109,26 @@ cp_convert_to_pointer (tree type, tree expr, bool force) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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);
......
...@@ -1689,121 +1689,45 @@ build_offset_ref (tree type, tree name) ...@@ -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)
{
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)
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 my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
&& TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
return member;
/* Syntax error can cause a member which should member = TREE_OPERAND (exp, 1);
have been seen as static to be grok'd as non-static. */
if (TREE_CODE (member) == FIELD_DECL && current_class_ref == NULL_TREE)
{
cp_error_at ("member `%D' is non-static but referenced as a static member",
member);
error ("at this point in file");
return error_mark_node;
}
/* The first case is really just a reference to a member of `this'. */ /* If MEMBER is non-static, then the program has fallen afoul of
if (TREE_CODE (member) == FIELD_DECL [expr.prim]:
&& (base == current_class_ref || is_dummy_object (base)))
{
tree binfo = NULL_TREE;
/* Try to get to basetype from 'this'; if that doesn't work, An id-expression that denotes a nonstatic data member or
nothing will. */ nonstatic member function of a class can only be used:
base = current_class_ref;
/* First convert to the intermediate base specified, if appropriate. */ -- as part of a class member access (_expr.ref_) in which the
if (TREE_CODE (exp) == OFFSET_REF && TREE_CODE (type) == OFFSET_TYPE) object-expression refers to the member's class or a class
base = build_scoped_ref (base, TYPE_OFFSET_BASETYPE (type), &binfo); derived from that class, or
return build_class_member_access_expr (base, member, -- to form a pointer to member (_expr.unary.op_), or
/*access_path=*/NULL_TREE,
/*preserve_reference=*/false);
}
/* Ensure that we have an object. */ -- in the body of a nonstatic member function of that class or
if (is_dummy_object (base)) of a class derived from that class (_class.mfct.nonstatic_), or
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))) -- 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))
{ {
if (addr == error_mark_node) /* In Microsoft mode, treat a non-static member function as if
{ it were a pointer-to-member. */
error ("object missing in `%E'", exp); if (flag_ms_extensions)
return error_mark_node; return build_unary_op (ADDR_EXPR, exp, 0);
} error ("invalid use of non-static member function `%D'", member);
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))) else if (TREE_CODE (member) == FIELD_DECL)
{ {
return get_member_function_from_ptrfunc (&addr, member); error ("invalid use of non-static data member `%D'", member);
return error_mark_node;
} }
abort ();
/* NOTREACHED */ return member;
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, ...@@ -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 ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 },
/* Parse the cast-expresion. */ { CPP_EOF, ERROR_MARK }
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. /* Parse a multiplicative-expression.
...@@ -14025,6 +14005,14 @@ cp_parser_single_declaration (cp_parser* parser, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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 ')'. */
......
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() { ...@@ -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*); ...@@ -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) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment