aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2009-05-17 14:01:33 -0400
committerJason Merrill <jason@gcc.gnu.org>2009-05-17 14:01:33 -0400
commit7e361ae60a7b275571bba267b2354b72df40c99a (patch)
tree097a2b317a3f015b864632a6294fe207c4fd91d4 /gcc/cp
parent8fa6fa79177806a38422c7c13a29a8fc12e38bf3 (diff)
downloadgcc-7e361ae60a7b275571bba267b2354b72df40c99a.zip
gcc-7e361ae60a7b275571bba267b2354b72df40c99a.tar.gz
gcc-7e361ae60a7b275571bba267b2354b72df40c99a.tar.bz2
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
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog12
-rw-r--r--gcc/cp/pt.c25
-rw-r--r--gcc/cp/semantics.c27
-rw-r--r--gcc/cp/tree.c3
-rw-r--r--gcc/cp/typeck.c16
5 files changed, 60 insertions, 23 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index bffec90..af4b69c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e100d6b..2ca28d6 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 8c0a1e5..18aa051 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -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);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 219cb39..f1868f5 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -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);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 4486b90..069a057 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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)))
{