From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 72595 invoked by alias); 21 Nov 2018 12:19:42 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 72573 invoked by uid 89); 21 Nov 2018 12:19:42 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-23.8 required=5.0 tests=AWL,BAYES_00,GIT_PATCH_0,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_LAZY_DOMAIN_SECURITY autolearn=ham version=3.3.2 spammy=H*r:4.89 X-HELO: outpost19.zedat.fu-berlin.de Received: from outpost19.zedat.fu-berlin.de (HELO outpost19.zedat.fu-berlin.de) (130.133.4.112) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 21 Nov 2018 12:19:40 +0000 Received: from relay1.zedat.fu-berlin.de ([130.133.4.67]) by outpost.zedat.fu-berlin.de (Exim 4.85) with esmtps (TLSv1.2:DHE-RSA-AES256-GCM-SHA384:256) (envelope-from ) id <1gPRTl-001Voj-SZ>; Wed, 21 Nov 2018 13:19:37 +0100 Received: from mx.physik.fu-berlin.de ([160.45.64.218]) by relay1.zedat.fu-berlin.de (Exim 4.85) with esmtps (TLSv1.2:DHE-RSA-AES128-SHA:128) (envelope-from ) id <1gPRTl-0015qN-OS>; Wed, 21 Nov 2018 13:19:37 +0100 Received: from login1.physik.fu-berlin.de ([160.45.66.207]) by mx.physik.fu-berlin.de with esmtps (TLS1.2:RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1gPRTj-0002Be-GL; Wed, 21 Nov 2018 13:19:35 +0100 Received: from tburnus by login1.physik.fu-berlin.de with local (Exim 4.89 #2 (Debian)) id 1gPRTj-0003bM-F3; Wed, 21 Nov 2018 13:19:35 +0100 Date: Wed, 21 Nov 2018 12:19:00 -0000 From: Tobias Burnus To: gcc-patches@gcc.gnu.org Subject: PR C++/88114 - patch for destructor not generated for "virtual ~destructor() = default" Message-ID: <20181121121935.tm4y2wyie6bc72sn@physik.fu-berlin.de> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="5txfezfsp3xsufrs" Content-Disposition: inline User-Agent: NeoMutt/20170113 (1.7.2) Sender: Tobias Burnus X-SW-Source: 2018-11/txt/msg01824.txt.bz2 --5txfezfsp3xsufrs Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1946 Hello all, if a class contains any 'virtual ... = 0', it's an abstract class and for an abstract class, the destructor not added to the vtable. For a normal virtual ~class() { } that's not a problem as the class::~class() destructor will be generated during the parsing of the function. But for virtual ~class() = default; the destructor will be generated via mark_used via the vtable. If one now declares a derived class and uses it, the class::~class() is generated in that translation unit. Unless, #pragma interface/implementation is used. In that case, the 'default' destructor will never be generated. The following code seems to work both for the big code and for the example; without '#pragma implementation', the destructor is not generated for the example, only with. The patch survived boostrapping GCC with default languages on x86-64-gnu-linux and "make check-g++".* [One probably could get rid of some of the conditions for generating the code, e.g. TREE_USED and DECL_DEFAULTED_FN are probably not both needed; one might want to set some additional DECL to the fn decl.] Does the patch and the test case make sense? Or is something else/in addition needed? Tobias *I do get the following failures on this CentOS6 system: FAIL: g++.dg/pr83239.C -std=gnu++98 (test for excess errors) Excess errors: cc1plus: warning: 'void* __builtin_memset(void*, int, long unsigned int)' specified size 18446744073709551608 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=] cc1plus: warning: 'void* __builtin_memset(void*, int, long unsigned int)' specified size 18446744073709551600 exceeds maximum object size 9223372036854775807 [-Wstringop-overflow=] FAIL: g++.dg/tls/thread_local-order2.C -std=c++14 execution test FAIL: g++.dg/tls/thread_local-order2.C -std=c++17 execution test plus each 32 times: FAIL: guality/guality.h: 0 PASS, 1 FAIL, 0 UNRESOLVED FAIL: guality/guality.h: varl is -1, not 6 --5txfezfsp3xsufrs Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="pr88114-destructor-default.diff" Content-length: 2363 PR C++/88114 * decl2.c (c_parse_final_cleanups): If needed, generate code for the destructor of an abstract class. (mark_used): Update comment for older function-name change. PR C++/88114 * g++.dg/cpp0x/defaulted61.C: New. diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index ffc0d0d6ec4..056e49ad88a 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4782,6 +4782,18 @@ c_parse_final_cleanups (void) { reconsider = true; keyed_classes->unordered_remove (i); + + /* For abstract classes, the destructor has been removed from the + vtable (in class.c's build_vtbl_initializer). For a compiler- + generated destructor, it hence might not have been generated in + this translation unit - and with '#pragma interface' it might + never get generated. */ + if (CLASSTYPE_PURE_VIRTUALS (t) + && TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) + for (tree x = TYPE_FIELDS (t); x; x = DECL_CHAIN (x)) + if (DECL_DECLARES_FUNCTION_P (x) && DECL_DESTRUCTOR_P (x) + && !TREE_USED (x) && DECL_DEFAULTED_FN (x)) + note_vague_linkage_fn (x); } /* The input_location may have been changed during marking of vtable entries. */ @@ -5465,7 +5477,7 @@ mark_used (tree decl, tsubst_flags_t complain) within the body of a function so as to avoid collecting live data on the stack (such as overload resolution candidates). - We could just let cp_write_global_declarations handle synthesizing + We could just let c_parse_final_cleanups handle synthesizing this function by adding it to deferred_fns, but doing it at the use site produces better error messages. */ ++function_depth; diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted61.C b/gcc/testsuite/g++.dg/cpp0x/defaulted61.C new file mode 100644 index 00000000000..e7e0a486292 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/defaulted61.C @@ -0,0 +1,22 @@ +// { dg-do compile { target c++11 } } +// { dg-final { scan-assembler "_ZN3OneD0Ev" } } + +// PR C++/88114 +// Destructor of an abstract class was never generated +// when compiling the class - nor later due to the +// '#pragma interface' + +#pragma implementation +#pragma interface + +class One +{ + public: + virtual ~One() = default; + void some_fn(); + virtual void later() = 0; + private: + int m_int; +}; + +void One::some_fn() { } --5txfezfsp3xsufrs--