aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2003-07-04 05:05:19 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2003-07-04 05:05:19 +0000
commitd6b4ea8592e338addbd24be14708f66eaa4ac63e (patch)
tree613039e905b0fbc1fe50e07889b99fdc172e8d14 /gcc
parent5f1989e65d23624efdbf26bde56f375e3caa6a22 (diff)
downloadgcc-d6b4ea8592e338addbd24be14708f66eaa4ac63e.zip
gcc-d6b4ea8592e338addbd24be14708f66eaa4ac63e.tar.gz
gcc-d6b4ea8592e338addbd24be14708f66eaa4ac63e.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog46
-rw-r--r--gcc/cp/call.c40
-rw-r--r--gcc/cp/cp-tree.def14
-rw-r--r--gcc/cp/cvt.c54
-rw-r--r--gcc/cp/decl2.c2
-rw-r--r--gcc/cp/init.c131
-rw-r--r--gcc/cp/parser.c72
-rw-r--r--gcc/cp/rtti.c6
-rw-r--r--gcc/cp/semantics.c10
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/cp/typeck.c73
-rw-r--r--gcc/cp/typeck2.c92
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/typeid1.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/net36.C2
15 files changed, 192 insertions, 361 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index ba6abbe..076dcbd 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index bc1179b..e8a54dc 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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));
diff --git a/gcc/cp/cp-tree.def b/gcc/cp/cp-tree.def
index 7d65731..e988a4e 100644
--- a/gcc/cp/cp-tree.def
+++ b/gcc/cp/cp-tree.def
@@ -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
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index 29f0222..24a3416 100644
--- a/gcc/cp/cvt.c
+++ b/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);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index f701037..78e84ca 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b88f1f2..e1a19b1 100644
--- a/gcc/cp/init.c
+++ b/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;
- }
-
- 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
- && TREE_CODE (TREE_TYPE (TREE_TYPE (member))) == METHOD_TYPE)
- return member;
+ my_friendly_assert (TREE_CODE (exp) == OFFSET_REF, 20030703);
- /* 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)
- {
- 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;
- }
+ member = TREE_OPERAND (exp, 1);
- /* 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;
+ /* If MEMBER is non-static, then the program has fallen afoul of
+ [expr.prim]:
- /* Try to get to basetype from 'this'; if that doesn't work,
- nothing will. */
- base = current_class_ref;
+ An id-expression that denotes a nonstatic data member or
+ nonstatic member function of a class can only be used:
- /* 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);
+ -- 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
- return build_class_member_access_expr (base, member,
- /*access_path=*/NULL_TREE,
- /*preserve_reference=*/false);
- }
+ -- to form a pointer to member (_expr.unary.op_), or
- /* 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);
+ -- in the body of a nonstatic member function of that class or
+ of a class derived from that class (_class.mfct.nonstatic_), or
- 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)
- {
- 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);
+ /* 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 (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 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)
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6155af4..d19e4038 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -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;
-
- /* 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);
- }
+ static const cp_parser_token_tree_map map = {
+ { CPP_DEREF_STAR, MEMBER_REF },
+ { CPP_DOT_STAR, DOTSTAR_EXPR },
+ { CPP_EOF, ERROR_MARK }
+ };
- 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. */
diff --git a/gcc/cp/rtti.c b/gcc/cp/rtti.c
index 74b7c90..af494e3 100644
--- a/gcc/cp/rtti.c
+++ b/gcc/cp/rtti.c
@@ -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)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 382bee5..3664590 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 6c6d9b9..9f8a119 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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),
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4900cbf..96b74fa 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 0587816..9d9ade1 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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 ')'. */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b2db902..344cb39 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C b/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C
index 83a0b09..678ab5fc 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/typeid1.C
@@ -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 "" } */
}
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/net36.C b/gcc/testsuite/g++.old-deja/g++.mike/net36.C
index 7d21d56..3ffa60e 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/net36.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/net36.C
@@ -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) {