Well, this one has been around for a while. this->X::~X() is handled by finish_class_member_access_expr and its lookup_destructor subroutine; let's use it in cp_parser_lookup_name for the case where this-> is implicit.
Tested x86_64-pc-linux-gnu, applying to trunk. * parser.c (cp_parser_lookup_name): Use lookup_destructor. * typeck.c (lookup_destructor): No longer static. --- gcc/cp/cp-tree.h | 1 + gcc/cp/parser.c | 5 +++++ gcc/cp/typeck.c | 3 +-- gcc/testsuite/g++.dg/lookup/dtor1.C | 13 +++++++++++++ gcc/testsuite/g++.dg/parse/dtor3.C | 8 ++++---- 5 files changed, 24 insertions(+), 6 deletions(-) create mode 100644 gcc/testsuite/g++.dg/lookup/dtor1.C diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b47698e1d0c..c35ed9abe08 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -7500,6 +7500,7 @@ extern tree build_class_member_access_expr (cp_expr, tree, tree, bool, tsubst_flags_t); extern tree finish_class_member_access_expr (cp_expr, tree, bool, tsubst_flags_t); +extern tree lookup_destructor (tree, tree, tree, tsubst_flags_t); extern tree build_x_indirect_ref (location_t, tree, ref_operator, tsubst_flags_t); diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 16d1359c47d..a1816e8ace7 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -27918,6 +27918,11 @@ cp_parser_lookup_name (cp_parser *parser, tree name, if (!type || !CLASS_TYPE_P (type)) return error_mark_node; + /* In a non-static member function, check implicit this->. */ + if (current_class_ref) + return lookup_destructor (current_class_ref, parser->scope, name, + tf_warning_or_error); + if (CLASSTYPE_LAZY_DESTRUCTOR (type)) lazily_declare_fn (sfk_destructor, type); diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index d3814585e3f..669ca83cccf 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -59,7 +59,6 @@ static tree get_delta_difference (tree, tree, bool, bool, tsubst_flags_t); static void casts_away_constness_r (tree *, tree *, tsubst_flags_t); static bool casts_away_constness (tree, tree, tsubst_flags_t); static bool maybe_warn_about_returning_address_of_local (tree); -static tree lookup_destructor (tree, tree, tree, tsubst_flags_t); static void error_args_num (location_t, tree, bool); static int convert_arguments (tree, vec<tree, va_gc> **, tree, int, tsubst_flags_t); @@ -2696,7 +2695,7 @@ build_class_member_access_expr (cp_expr object, tree member, /* Return the destructor denoted by OBJECT.SCOPE::DTOR_NAME, or, if SCOPE is NULL, by OBJECT.DTOR_NAME, where DTOR_NAME is ~type. */ -static tree +tree lookup_destructor (tree object, tree scope, tree dtor_name, tsubst_flags_t complain) { diff --git a/gcc/testsuite/g++.dg/lookup/dtor1.C b/gcc/testsuite/g++.dg/lookup/dtor1.C new file mode 100644 index 00000000000..29122876401 --- /dev/null +++ b/gcc/testsuite/g++.dg/lookup/dtor1.C @@ -0,0 +1,13 @@ +// PR c++/12333 + +struct A { }; + +struct X { + void f () { + X::~X (); + this->~X(); + ~X(); // { dg-error "" "unary ~" } + A::~A (); // { dg-error "" } + X::~A (); // { dg-error "" } + } +}; diff --git a/gcc/testsuite/g++.dg/parse/dtor3.C b/gcc/testsuite/g++.dg/parse/dtor3.C index 3041ae4a568..6121bed7e8b 100644 --- a/gcc/testsuite/g++.dg/parse/dtor3.C +++ b/gcc/testsuite/g++.dg/parse/dtor3.C @@ -4,13 +4,13 @@ // destructor call. struct Y { - ~Y() {} // { dg-bogus "note" "implemented DR272" { xfail *-*-* } } + ~Y() {} // { dg-bogus "note" "implemented DR272" } }; struct X : Y { - ~X() {} // { dg-bogus "note" "implemented DR272" { xfail *-*-* } } + ~X() {} // { dg-bogus "note" "implemented DR272" } void f() { - X::~X(); // { dg-bogus "" "implemented DR272" { xfail *-*-* } } - Y::~Y(); // { dg-bogus "" "implemented DR272" { xfail *-*-* } } + X::~X(); // { dg-bogus "" "implemented DR272" } + Y::~Y(); // { dg-bogus "" "implemented DR272" } } }; base-commit: 6e8f413c4dc0dc14eec025c1ab21757d88b7b352 -- 2.18.1