Commit 7e361ae6 by Jason Merrill Committed by Jason Merrill

re PR c++/40139 (ICE on invalid use of destructor)

	PR c++/40139
	* pt.c (tsubst_qualified_id): Retain the type if we aren't dealing
	with a dependent type.  Actually look up the destructor.
	* semantics.c (finish_id_expression): Fix logic.
	(finish_qualified_id_expr): Don't try to use 'this' if we aren't in
	a function.
	* typeck.c (build_x_unary_op): Diagnose taking the address of a
	constructor or destructor.
	* tree.c (get_first_fn): Handle OFFSET_REF.

From-SVN: r147638
parent 8fa6fa79
2009-05-16 Jason Merrill <jason@redhat.com>
PR c++/40139
* pt.c (tsubst_qualified_id): Retain the type if we aren't dealing
with a dependent type. Actually look up the destructor.
* semantics.c (finish_id_expression): Fix logic.
(finish_qualified_id_expr): Don't try to use 'this' if we aren't in
a function.
* typeck.c (build_x_unary_op): Diagnose taking the address of a
constructor or destructor.
* tree.c (get_first_fn): Handle OFFSET_REF.
2009-05-17 Joseph Myers <joseph@codesourcery.com>
* tree.c (cxx_printable_name_internal): Allow consecutive
......
......@@ -9930,16 +9930,29 @@ tsubst_qualified_id (tree qualified_id, tree args,
expr = name;
if (dependent_type_p (scope))
return build_qualified_name (/*type=*/NULL_TREE,
scope, expr,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
{
tree type = NULL_TREE;
if (DECL_P (expr) && !dependent_scope_p (scope))
type = TREE_TYPE (expr);
return build_qualified_name (type, scope, expr,
QUALIFIED_NAME_IS_TEMPLATE (qualified_id));
}
if (!BASELINK_P (name) && !DECL_P (expr))
{
if (TREE_CODE (expr) == BIT_NOT_EXPR)
/* If this were actually a destructor call, it would have been
parsed as such by the parser. */
expr = error_mark_node;
{
/* A BIT_NOT_EXPR is used to represent a destructor. */
if (!check_dtor_name (scope, TREE_OPERAND (expr, 0)))
{
error ("qualifying type %qT does not match destructor name ~%qT",
scope, TREE_OPERAND (expr, 0));
expr = error_mark_node;
}
else
expr = lookup_qualified_name (scope, complete_dtor_identifier,
/*is_type_p=*/0, false);
}
else
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
......
......@@ -1664,11 +1664,10 @@ finish_qualified_id_expr (tree qualifying_class,
fns = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
fns = TREE_OPERAND (fns, 0);
/* If so, the expression may be relative to the current
class. */
/* If so, the expression may be relative to 'this'. */
if (!shared_member_p (fns)
&& current_class_type
&& DERIVED_FROM_P (qualifying_class, current_class_type))
&& current_class_ref
&& DERIVED_FROM_P (qualifying_class, TREE_TYPE (current_class_ref)))
expr = (build_class_member_access_expr
(maybe_dummy_object (qualifying_class, NULL),
expr,
......@@ -2871,16 +2870,16 @@ finish_id_expression (tree id_expression,
done, address_p,
template_p,
template_arg_p);
else if (dependent_scope_p (scope))
decl = build_qualified_name (/*type=*/NULL_TREE,
scope,
id_expression,
template_p);
else if (DECL_P (decl))
decl = build_qualified_name (TREE_TYPE (decl),
scope,
id_expression,
template_p);
else
{
tree type = NULL_TREE;
if (DECL_P (decl) && !dependent_scope_p (scope))
type = TREE_TYPE (decl);
decl = build_qualified_name (type,
scope,
id_expression,
template_p);
}
}
if (TREE_TYPE (decl))
decl = convert_from_reference (decl);
......
......@@ -1200,7 +1200,8 @@ get_first_fn (tree from)
{
gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */
if (TREE_CODE (from) == COMPONENT_REF)
if (TREE_CODE (from) == OFFSET_REF
|| TREE_CODE (from) == COMPONENT_REF)
from = TREE_OPERAND (from, 1);
if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from);
......
......@@ -4141,8 +4141,20 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
/*overloaded_p=*/NULL, complain);
if (!exp && code == ADDR_EXPR)
{
/* A pointer to member-function can be formed only by saying
&X::mf. */
if (is_overloaded_fn (xarg))
{
tree fn = get_first_fn (xarg);
if (DECL_CONSTRUCTOR_P (fn) || DECL_DESTRUCTOR_P (fn))
{
const char *type =
(DECL_CONSTRUCTOR_P (fn) ? "constructor" : "destructor");
error ("taking address of %s %qE", type, xarg);
return error_mark_node;
}
}
/* A pointer to member-function can be formed only by saying
&X::mf. */
if (!flag_ms_extensions && TREE_CODE (TREE_TYPE (xarg)) == METHOD_TYPE
&& (TREE_CODE (xarg) != OFFSET_REF || !PTRMEM_OK_P (xarg)))
{
......
2009-05-17 Jason Merrill <jason@redhat.com>
PR c++/40139
* g++.dg/template/dtor6.C: New.
2009-05-17 Joseph Myers <joseph@codesourcery.com>
* g++.dg/warn/translate-ice-1.C: New test.
......
// PR c++/40139
template<int> struct A
{
static int i;
};
template<int N> int A<N>::i = { A::~A }; // { dg-error "non-static member function" }
template class A<0>;
struct X { };
int i1 = X::~X; // { dg-error "non-static member function" }
int i2 = &X::~X; // { dg-error "address of destructor" }
int i3 = &A<0>::~A; // { dg-error "address of destructor" }
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