+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
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
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,
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);
{
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);
/*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.
--- /dev/null
+// 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" }