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> 2009-05-17 Joseph Myers <joseph@codesourcery.com>
* tree.c (cxx_printable_name_internal): Allow consecutive * tree.c (cxx_printable_name_internal): Allow consecutive
......
...@@ -9930,16 +9930,29 @@ tsubst_qualified_id (tree qualified_id, tree args, ...@@ -9930,16 +9930,29 @@ tsubst_qualified_id (tree qualified_id, tree args,
expr = name; expr = name;
if (dependent_type_p (scope)) if (dependent_type_p (scope))
return build_qualified_name (/*type=*/NULL_TREE, {
scope, expr, tree type = NULL_TREE;
QUALIFIED_NAME_IS_TEMPLATE (qualified_id)); 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 (!BASELINK_P (name) && !DECL_P (expr))
{ {
if (TREE_CODE (expr) == BIT_NOT_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. */ /* A BIT_NOT_EXPR is used to represent a destructor. */
expr = error_mark_node; 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 else
expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false); expr = lookup_qualified_name (scope, expr, /*is_type_p=*/0, false);
if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL if (TREE_CODE (TREE_CODE (expr) == TEMPLATE_DECL
......
...@@ -1664,11 +1664,10 @@ finish_qualified_id_expr (tree qualifying_class, ...@@ -1664,11 +1664,10 @@ finish_qualified_id_expr (tree qualifying_class,
fns = BASELINK_FUNCTIONS (expr); fns = BASELINK_FUNCTIONS (expr);
if (TREE_CODE (fns) == TEMPLATE_ID_EXPR) if (TREE_CODE (fns) == TEMPLATE_ID_EXPR)
fns = TREE_OPERAND (fns, 0); fns = TREE_OPERAND (fns, 0);
/* If so, the expression may be relative to the current /* If so, the expression may be relative to 'this'. */
class. */
if (!shared_member_p (fns) if (!shared_member_p (fns)
&& current_class_type && current_class_ref
&& DERIVED_FROM_P (qualifying_class, current_class_type)) && DERIVED_FROM_P (qualifying_class, TREE_TYPE (current_class_ref)))
expr = (build_class_member_access_expr expr = (build_class_member_access_expr
(maybe_dummy_object (qualifying_class, NULL), (maybe_dummy_object (qualifying_class, NULL),
expr, expr,
...@@ -2871,16 +2870,16 @@ finish_id_expression (tree id_expression, ...@@ -2871,16 +2870,16 @@ finish_id_expression (tree id_expression,
done, address_p, done, address_p,
template_p, template_p,
template_arg_p); template_arg_p);
else if (dependent_scope_p (scope)) else
decl = build_qualified_name (/*type=*/NULL_TREE, {
scope, tree type = NULL_TREE;
id_expression, if (DECL_P (decl) && !dependent_scope_p (scope))
template_p); type = TREE_TYPE (decl);
else if (DECL_P (decl)) decl = build_qualified_name (type,
decl = build_qualified_name (TREE_TYPE (decl), scope,
scope, id_expression,
id_expression, template_p);
template_p); }
} }
if (TREE_TYPE (decl)) if (TREE_TYPE (decl))
decl = convert_from_reference (decl); decl = convert_from_reference (decl);
......
...@@ -1200,7 +1200,8 @@ get_first_fn (tree from) ...@@ -1200,7 +1200,8 @@ get_first_fn (tree from)
{ {
gcc_assert (is_overloaded_fn (from)); gcc_assert (is_overloaded_fn (from));
/* A baselink is also considered an overloaded function. */ /* 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); from = TREE_OPERAND (from, 1);
if (BASELINK_P (from)) if (BASELINK_P (from))
from = BASELINK_FUNCTIONS (from); from = BASELINK_FUNCTIONS (from);
......
...@@ -4141,8 +4141,20 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain) ...@@ -4141,8 +4141,20 @@ build_x_unary_op (enum tree_code code, tree xarg, tsubst_flags_t complain)
/*overloaded_p=*/NULL, complain); /*overloaded_p=*/NULL, complain);
if (!exp && code == ADDR_EXPR) if (!exp && code == ADDR_EXPR)
{ {
/* A pointer to member-function can be formed only by saying if (is_overloaded_fn (xarg))
&X::mf. */ {
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 if (!flag_ms_extensions && TREE_CODE (TREE_TYPE (xarg)) == METHOD_TYPE
&& (TREE_CODE (xarg) != OFFSET_REF || !PTRMEM_OK_P (xarg))) && (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> 2009-05-17 Joseph Myers <joseph@codesourcery.com>
* g++.dg/warn/translate-ice-1.C: New test. * 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