Commit 477f6664 by Jason Merrill Committed by Jason Merrill

pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not DECL_TEMPLATE_RESULT.

        * pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not
        DECL_TEMPLATE_RESULT.

        * search.c (lookup_field_r): Call lookup_fnfields_1, not
        lookup_fnfields_here.

        * parse.y (typename_sub2): Return the TYPE_DECL, not the type.

        * call.c (build_object_call): Also allow conversions that return
        reference to pointer to function.
        (add_conv_candidate): Handle totype being ref to ptr to fn.
        (build_field_call): Also allow members of type reference to function.
        Lose support for calling pointer to METHOD_TYPE fields.

        * error.c (dump_expr): Handle *_CAST_EXPR.

        * typeck2.c (build_scoped_ref): Always convert to the naming class.

        * tree.c (break_out_cleanups): Lose.
        * cp-tree.h: Remove prototype.
        * typeck.c (build_component_ref): Don't break_out_cleanups.
        (build_compound_expr): Likewise.
        * semantics.c (finish_expr_stmt): Likewise.

From-SVN: r38417
parent e98df22a
2000-12-20 Jason Merrill <jason@redhat.com>
* pt.c (tsubst_decl): A FUNCTION_DECL has DECL_RESULT, not
DECL_TEMPLATE_RESULT.
* search.c (lookup_field_r): Call lookup_fnfields_1, not
lookup_fnfields_here.
* parse.y (typename_sub2): Return the TYPE_DECL, not the type.
* call.c (build_object_call): Also allow conversions that return
reference to pointer to function.
(add_conv_candidate): Handle totype being ref to ptr to fn.
(build_field_call): Also allow members of type reference to function.
Lose support for calling pointer to METHOD_TYPE fields.
* error.c (dump_expr): Handle *_CAST_EXPR.
* typeck2.c (build_scoped_ref): Always convert to the naming class.
* tree.c (break_out_cleanups): Lose.
* cp-tree.h: Remove prototype.
* typeck.c (build_component_ref): Don't break_out_cleanups.
(build_compound_expr): Likewise.
* semantics.c (finish_expr_stmt): Likewise.
2000-12-20 Richard Henderson <rth@redhat.com> 2000-12-20 Richard Henderson <rth@redhat.com>
* cp-tree.h: Update declarations. * cp-tree.h: Update declarations.
......
...@@ -156,15 +156,11 @@ build_field_call (basetype_path, instance_ptr, name, parms) ...@@ -156,15 +156,11 @@ build_field_call (basetype_path, instance_ptr, name, parms)
if (IS_AGGR_TYPE (TREE_TYPE (instance))) if (IS_AGGR_TYPE (TREE_TYPE (instance)))
return build_opfncall (CALL_EXPR, LOOKUP_NORMAL, return build_opfncall (CALL_EXPR, LOOKUP_NORMAL,
instance, parms, NULL_TREE); instance, parms, NULL_TREE);
else if (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE) else if (TREE_CODE (TREE_TYPE (instance)) == FUNCTION_TYPE
{ || (TREE_CODE (TREE_TYPE (instance)) == POINTER_TYPE
if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) == FUNCTION_TYPE) && (TREE_CODE (TREE_TYPE (TREE_TYPE (instance)))
return build_function_call (instance, parms); == FUNCTION_TYPE)))
else if (TREE_CODE (TREE_TYPE (TREE_TYPE (instance))) return build_function_call (instance, parms);
== METHOD_TYPE)
return build_function_call
(instance, tree_cons (NULL_TREE, instance_ptr, parms));
}
} }
return NULL_TREE; return NULL_TREE;
...@@ -1422,13 +1418,19 @@ add_conv_candidate (candidates, fn, obj, arglist) ...@@ -1422,13 +1418,19 @@ add_conv_candidate (candidates, fn, obj, arglist)
tree fn, obj, arglist; tree fn, obj, arglist;
{ {
tree totype = TREE_TYPE (TREE_TYPE (fn)); tree totype = TREE_TYPE (TREE_TYPE (fn));
tree parmlist = TYPE_ARG_TYPES (TREE_TYPE (totype)); int i, len, viable, flags;
int i, len = list_length (arglist) + 1; tree parmlist, convs, parmnode, argnode;
tree convs = make_tree_vec (len);
tree parmnode = parmlist; for (parmlist = totype; TREE_CODE (parmlist) != FUNCTION_TYPE; )
tree argnode = arglist; parmlist = TREE_TYPE (parmlist);
int viable = 1; parmlist = TYPE_ARG_TYPES (parmlist);
int flags = LOOKUP_NORMAL;
len = list_length (arglist) + 1;
convs = make_tree_vec (len);
parmnode = parmlist;
argnode = arglist;
viable = 1;
flags = LOOKUP_NORMAL;
/* Don't bother looking up the same type twice. */ /* Don't bother looking up the same type twice. */
if (candidates && candidates->fn == totype) if (candidates && candidates->fn == totype)
...@@ -2659,8 +2661,12 @@ build_object_call (obj, args) ...@@ -2659,8 +2661,12 @@ build_object_call (obj, args)
tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns))); tree totype = TREE_TYPE (TREE_TYPE (OVL_CURRENT (fns)));
if ((TREE_CODE (totype) == POINTER_TYPE if ((TREE_CODE (totype) == POINTER_TYPE
|| TREE_CODE (totype) == REFERENCE_TYPE) && TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE) || (TREE_CODE (totype) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == FUNCTION_TYPE)
|| (TREE_CODE (totype) == REFERENCE_TYPE
&& TREE_CODE (TREE_TYPE (totype)) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (TREE_TYPE (totype))) == FUNCTION_TYPE))
for (; fns; fns = OVL_NEXT (fns)) for (; fns; fns = OVL_NEXT (fns))
{ {
tree fn = OVL_CURRENT (fns); tree fn = OVL_CURRENT (fns);
......
...@@ -4401,7 +4401,6 @@ extern int lvalue_p PARAMS ((tree)); ...@@ -4401,7 +4401,6 @@ extern int lvalue_p PARAMS ((tree));
extern int lvalue_or_else PARAMS ((tree, const char *)); extern int lvalue_or_else PARAMS ((tree, const char *));
extern tree build_cplus_new PARAMS ((tree, tree)); extern tree build_cplus_new PARAMS ((tree, tree));
extern tree get_target_expr PARAMS ((tree)); extern tree get_target_expr PARAMS ((tree));
extern tree break_out_cleanups PARAMS ((tree));
extern tree break_out_calls PARAMS ((tree)); extern tree break_out_calls PARAMS ((tree));
extern tree build_cplus_method_type PARAMS ((tree, tree, tree)); extern tree build_cplus_method_type PARAMS ((tree, tree, tree));
extern tree build_cplus_staticfn_type PARAMS ((tree, tree, tree)); extern tree build_cplus_staticfn_type PARAMS ((tree, tree, tree));
......
...@@ -2051,6 +2051,24 @@ dump_expr (t, flags) ...@@ -2051,6 +2051,24 @@ dump_expr (t, flags)
} }
break; break;
case STATIC_CAST_EXPR:
output_add_string (scratch_buffer, "static_cast<");
goto cast;
case REINTERPRET_CAST_EXPR:
output_add_string (scratch_buffer, "reinterpret_cast<");
goto cast;
case CONST_CAST_EXPR:
output_add_string (scratch_buffer, "const_cast<");
goto cast;
case DYNAMIC_CAST_EXPR:
output_add_string (scratch_buffer, "dynamic_cast<");
cast:
dump_type (TREE_TYPE (t), flags);
output_add_string (scratch_buffer, ">(");
dump_expr (TREE_OPERAND (t, 0), flags);
print_right_paren (scratch_buffer);
break;
case LOOKUP_EXPR: case LOOKUP_EXPR:
print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0)); print_tree_identifier (scratch_buffer, TREE_OPERAND (t, 0));
break; break;
......
...@@ -3056,6 +3056,8 @@ typename_sub1: ...@@ -3056,6 +3056,8 @@ typename_sub1:
{ {
if (TREE_CODE ($1) == IDENTIFIER_NODE) if (TREE_CODE ($1) == IDENTIFIER_NODE)
cp_error ("`%T' is not a class or namespace", $1); cp_error ("`%T' is not a class or namespace", $1);
else if (TREE_CODE ($1) == TYPE_DECL)
$$ = TREE_TYPE ($1);
} }
| typename_sub1 typename_sub2 | typename_sub1 typename_sub2
{ {
...@@ -3078,24 +3080,26 @@ typename_sub1: ...@@ -3078,24 +3080,26 @@ typename_sub1:
= make_typename_type ($1, $3, /*complain=*/1); } = make_typename_type ($1, $3, /*complain=*/1); }
; ;
/* This needs to return a TYPE_DECL for simple names so that we don't
forget what name was used. */
typename_sub2: typename_sub2:
TYPENAME SCOPE TYPENAME SCOPE
{ {
if (TREE_CODE ($1) != IDENTIFIER_NODE) if (TREE_CODE ($1) != TYPE_DECL)
$1 = lastiddecl; $$ = lastiddecl;
/* Retrieve the type for the identifier, which might involve /* Retrieve the type for the identifier, which might involve
some computation. */ some computation. */
got_scope = $$ = complete_type (IDENTIFIER_TYPE_VALUE ($1)); got_scope = complete_type (TREE_TYPE ($$));
if ($$ == error_mark_node) if ($$ == error_mark_node)
cp_error ("`%T' is not a class or namespace", $1); cp_error ("`%T' is not a class or namespace", $1);
} }
| SELFNAME SCOPE | SELFNAME SCOPE
{ {
if (TREE_CODE ($1) != IDENTIFIER_NODE) if (TREE_CODE ($1) != TYPE_DECL)
$$ = lastiddecl; $$ = lastiddecl;
got_scope = $$ = complete_type (TREE_TYPE ($$)); got_scope = complete_type (TREE_TYPE ($$));
} }
| template_type SCOPE | template_type SCOPE
{ got_scope = $$ = complete_type (TREE_TYPE ($$)); } { got_scope = $$ = complete_type (TREE_TYPE ($$)); }
......
...@@ -5715,7 +5715,7 @@ tsubst_decl (t, args, type, in_decl) ...@@ -5715,7 +5715,7 @@ tsubst_decl (t, args, type, in_decl)
DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args,
/*complain=*/1, t); /*complain=*/1, t);
DECL_TEMPLATE_RESULT (r) = NULL_TREE; DECL_RESULT (r) = NULL_TREE;
TREE_STATIC (r) = 0; TREE_STATIC (r) = 0;
TREE_PUBLIC (r) = TREE_PUBLIC (t); TREE_PUBLIC (r) = TREE_PUBLIC (t);
......
...@@ -1251,7 +1251,9 @@ is_subobject_of_p (parent, binfo, most_derived) ...@@ -1251,7 +1251,9 @@ is_subobject_of_p (parent, binfo, most_derived)
/* Very similar to lookup_fnfields_1 but it ensures that at least one /* Very similar to lookup_fnfields_1 but it ensures that at least one
function was declared inside the class given by TYPE. It really should function was declared inside the class given by TYPE. It really should
only return functions that match the given TYPE. */ only return functions that match the given TYPE. Therefore, it should
only be called for situations that ignore using-declarations, such as
determining overrides. */
static int static int
lookup_fnfields_here (type, name) lookup_fnfields_here (type, name)
...@@ -1359,7 +1361,7 @@ lookup_field_r (binfo, data) ...@@ -1359,7 +1361,7 @@ lookup_field_r (binfo, data)
with the same name, the type is hidden by the function. */ with the same name, the type is hidden by the function. */
if (!lfi->want_type) if (!lfi->want_type)
{ {
int idx = lookup_fnfields_here (type, lfi->name); int idx = lookup_fnfields_1 (type, lfi->name);
if (idx >= 0) if (idx >= 0)
nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx); nval = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (type), idx);
} }
......
...@@ -214,9 +214,6 @@ finish_expr_stmt (expr) ...@@ -214,9 +214,6 @@ finish_expr_stmt (expr)
if (stmts_are_full_exprs_p ()) if (stmts_are_full_exprs_p ())
expr = convert_to_void (expr, "statement"); expr = convert_to_void (expr, "statement");
if (!processing_template_decl)
expr = break_out_cleanups (expr);
r = add_stmt (build_stmt (EXPR_STMT, expr)); r = add_stmt (build_stmt (EXPR_STMT, expr));
} }
......
...@@ -317,37 +317,6 @@ get_target_expr (init) ...@@ -317,37 +317,6 @@ get_target_expr (init)
return build_target_expr_with_type (init, TREE_TYPE (init)); return build_target_expr_with_type (init, TREE_TYPE (init));
} }
/* Recursively search EXP for CALL_EXPRs that need cleanups and replace
these CALL_EXPRs with tree nodes that will perform the cleanups. */
tree
break_out_cleanups (exp)
tree exp;
{
tree tmp = exp;
if (TREE_CODE (tmp) == CALL_EXPR
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (tmp)))
return build_cplus_new (TREE_TYPE (tmp), tmp);
while (TREE_CODE (tmp) == NOP_EXPR
|| TREE_CODE (tmp) == CONVERT_EXPR
|| TREE_CODE (tmp) == NON_LVALUE_EXPR)
{
if (TREE_CODE (TREE_OPERAND (tmp, 0)) == CALL_EXPR
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (TREE_TYPE (TREE_OPERAND (tmp, 0))))
{
TREE_OPERAND (tmp, 0)
= build_cplus_new (TREE_TYPE (TREE_OPERAND (tmp, 0)),
TREE_OPERAND (tmp, 0));
break;
}
else
tmp = TREE_OPERAND (tmp, 0);
}
return exp;
}
/* Recursively perform a preorder search EXP for CALL_EXPRs, making /* Recursively perform a preorder search EXP for CALL_EXPRs, making
copies where they are found. Returns a deep copy all nodes transitively copies where they are found. Returns a deep copy all nodes transitively
containing CALL_EXPRs. */ containing CALL_EXPRs. */
......
...@@ -2278,8 +2278,7 @@ build_component_ref (datum, component, basetype_path, protect) ...@@ -2278,8 +2278,7 @@ build_component_ref (datum, component, basetype_path, protect)
field_type = cp_build_qualified_type (field_type, type_quals); field_type = cp_build_qualified_type (field_type, type_quals);
} }
ref = fold (build (COMPONENT_REF, field_type, ref = fold (build (COMPONENT_REF, field_type, datum, field));
break_out_cleanups (datum), field));
/* Mark the expression const or volatile, as appropriate. Even /* Mark the expression const or volatile, as appropriate. Even
though we've dealt with the type above, we still have to mark the though we've dealt with the type above, we still have to mark the
...@@ -5039,8 +5038,7 @@ build_compound_expr (list) ...@@ -5039,8 +5038,7 @@ build_compound_expr (list)
if (! TREE_SIDE_EFFECTS (first) && ! pedantic) if (! TREE_SIDE_EFFECTS (first) && ! pedantic)
return rest; return rest;
return build (COMPOUND_EXPR, TREE_TYPE (rest), return build (COMPOUND_EXPR, TREE_TYPE (rest), first, rest);
break_out_cleanups (first), rest);
} }
tree tree
......
...@@ -957,9 +957,10 @@ process_init_constructor (type, init, elts) ...@@ -957,9 +957,10 @@ process_init_constructor (type, init, elts)
the A part of the C object named by X. In this case, the A part of the C object named by X. In this case,
DATUM would be x, and BASETYPE would be A. DATUM would be x, and BASETYPE would be A.
Note that this is nonconformant; the standard specifies that first I used to think that this was nonconformant, that the standard specified
we look up ii in A, then convert x to an L& and pull out the ii part. that first we look up ii in A, then convert x to an L& and pull out the
But narrowing seems to be standard practice, so let's do it anyway. */ ii part. But in fact, it does say that we convert x to an A&; A here
is known as the "naming class". (jason 2000-12-19) */
tree tree
build_scoped_ref (datum, basetype) build_scoped_ref (datum, basetype)
...@@ -967,16 +968,10 @@ build_scoped_ref (datum, basetype) ...@@ -967,16 +968,10 @@ build_scoped_ref (datum, basetype)
tree basetype; tree basetype;
{ {
tree ref; tree ref;
tree type = TREE_TYPE (datum);
if (datum == error_mark_node) if (datum == error_mark_node)
return error_mark_node; return error_mark_node;
/* Don't do this if it would cause an error or if we're being pedantic. */
if (! ACCESSIBLY_UNIQUELY_DERIVED_P (basetype, type)
|| pedantic)
return datum;
ref = build_unary_op (ADDR_EXPR, datum, 0); ref = build_unary_op (ADDR_EXPR, datum, 0);
ref = convert_pointer_to (basetype, ref); ref = convert_pointer_to (basetype, ref);
......
...@@ -19,8 +19,8 @@ class C : public A, public B {}; ...@@ -19,8 +19,8 @@ class C : public A, public B {};
void foo() { void foo() {
// straight call // straight call
C x; C x;
x.A::ii = 5; // ERROR - L is ambiguous base x.A::ii = 5;
x.A::foo(x.A::ii); // ERROR - L is ambiguous base x.A::foo(x.A::ii);
// 5.1 Primary expressions // 5.1 Primary expressions
// p 8 // p 8
......
...@@ -9,5 +9,5 @@ struct B : public A { ...@@ -9,5 +9,5 @@ struct B : public A {
struct C : public A { struct C : public A {
}; };
struct D : public C, public B { struct D : public C, public B {
void fun() { C::aa = 10; } // ERROR - conversion to A is ambiguous void fun() { C::aa = 10; }
}; };
// Test that various calls to non-functions work.
void f () { }
typedef void (*fptr)();
typedef void (&fref)();
fptr p = f;
fref r = f;
const fptr &pr = p;
struct A {
fptr p;
A (fptr n): p(n) { }
operator fptr () { return p; }
};
struct B {
fref r;
B (fptr n): r(*n) { }
operator const fref () { return r; }
};
struct C {
const fptr &pr;
C (fptr n): pr(n) { }
operator const fptr& () { return pr; }
};
int main ()
{
f();
p();
r();
pr();
A a (f);
a();
a.p();
B b (f);
b();
b.r();
C c (f);
c();
c.pr();
}
// Test that referring to an ambiguous base in name lookup does not // Test that referring to an ambiguous base in name lookup prevents
// interfere with accessing the field, which is not ambiguous. // access to the field, even though the field is not ambiguous.
// Build don't link: // Build don't link:
...@@ -14,10 +14,10 @@ struct E: public C, public D { ...@@ -14,10 +14,10 @@ struct E: public C, public D {
}; };
void E::f() { void E::f() {
B::i = 0; B::i = 0; // ERROR - B is ambiguous
} }
void f () { void f () {
E e; E e;
e.B::i = 0; e.B::i = 0; // ERROR - B is ambiguous
} }
// Bug: typename_sub2 returned the type, so we tried to look up "A" in B.
// Build don't link:
struct A { struct A1 { }; };
struct B {
typedef A Q;
};
struct C: public B::Q::A1 { };
// Test that we can represent static_casts in template arg lists.
// Build don't link:
template <int I> struct A { };
template <class T> struct B {
A<static_cast<T>(3.14)> a;
};
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