Message ID | CALHvHFV=tTQxwOR=8Ew2DJ4gPmJ+3p8Lr=eU0soPvZPW4gW89A@mail.gmail.com |
---|---|
State | New |
Headers |
Return-Path: <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 287283857810 for <patchwork@sourceware.org>; Mon, 14 Mar 2022 06:37:16 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 287283857810 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1647239836; bh=L+4raAKO2QDJ4vTY8vuLCvDjgxW0jgSoQPFz2X+h4l0=; h=Date:Subject:To:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=wNQbGaQXcy1AgHBoi72IPFYYAsbE0wrKki2nmqaZg8esz22QbcWF/TE7yTNgRM1d0 nNDPutUVQxh5me5MSEEW3hoNg5Zq86ztMFKH/Jwpl5Aqym7/QaMkNFeHrfjzxcm8q3 ZwuMV9fxYOmfvR/Xuvmk+MzlaJX32td768e2Nyr0= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-io1-xd2f.google.com (mail-io1-xd2f.google.com [IPv6:2607:f8b0:4864:20::d2f]) by sourceware.org (Postfix) with ESMTPS id 320703858D20 for <gcc-patches@gcc.gnu.org>; Mon, 14 Mar 2022 06:36:47 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 320703858D20 Received: by mail-io1-xd2f.google.com with SMTP id 195so17082823iou.0 for <gcc-patches@gcc.gnu.org>; Sun, 13 Mar 2022 23:36:47 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=L+4raAKO2QDJ4vTY8vuLCvDjgxW0jgSoQPFz2X+h4l0=; b=097znu8ALMOhd7IjsUr/k0bFSHZuyfAZBtI45PEgTnz8SXP/iNfhNokNctpD+hmzCW PWzP+wc7tjRCsmC3gRPaAMnk0jhgdSyQGdAaxXQwy4pw37ywzw8bhH9yksGRKTlFS05O IFZF/lzXNY8nSAefWZ1xIJ2xWQQfqiTTpghIuk4Ne9WiIvPhBVmDqYmSlFtBqQ1iPvVl ukqYOubirk/GZTwg6smHFlD5mqL6rkE6PrgEe9XtXh25WSZgQsKl1lNifofNbNWTp98k Wh14G61kICYkqEce0Q02k0ua5GkazTJuaUTnux0jvyVCrM1Ah8eKBvhaZHkGSVQvo2te hD1Q== X-Gm-Message-State: AOAM531ZC+AT+PXW8Dg85KGEu30cSJhlXXJ6Vngqmz/EFiAbxZnsXDUT wz38diGFOoflrob5B9SFgS9NSyTXR40s81nHx4X/cEHkbtE= X-Google-Smtp-Source: ABdhPJxHHHcsebcz0QQQc+4+kiN70nevBA0y+tI/jCUsbEWhRKv9Z4HfKcIO2+uTVhMEVrdGBNM0vWccCFLpkxfACPI= X-Received: by 2002:a5d:8d03:0:b0:612:608:9a67 with SMTP id p3-20020a5d8d03000000b0061206089a67mr18356842ioj.19.1647239806213; Sun, 13 Mar 2022 23:36:46 -0700 (PDT) MIME-Version: 1.0 Date: Mon, 14 Mar 2022 14:36:09 +0800 Message-ID: <CALHvHFV=tTQxwOR=8Ew2DJ4gPmJ+3p8Lr=eU0soPvZPW4gW89A@mail.gmail.com> Subject: [PATCH] c++/96765: warn when casting "this" to Derived* in Base ctor/dtor To: GCC Patches <gcc-patches@gcc.gnu.org> Content-Type: multipart/mixed; boundary="0000000000008282a405da27e77f" X-Spam-Status: No, score=-9.2 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list <gcc-patches.gcc.gnu.org> List-Unsubscribe: <https://gcc.gnu.org/mailman/options/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe> List-Archive: <https://gcc.gnu.org/pipermail/gcc-patches/> List-Post: <mailto:gcc-patches@gcc.gnu.org> List-Help: <mailto:gcc-patches-request@gcc.gnu.org?subject=help> List-Subscribe: <https://gcc.gnu.org/mailman/listinfo/gcc-patches>, <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe> From: Zhao Wei Liew via Gcc-patches <gcc-patches@gcc.gnu.org> Reply-To: Zhao Wei Liew <zhaoweiliew@gmail.com> Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" <gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org> |
Series |
c++/96765: warn when casting "this" to Derived* in Base ctor/dtor
|
|
Commit Message
Zhao Wei Liew
March 14, 2022, 6:36 a.m. UTC
Hi! This patch adds a warning when casting "this" to Derived* in the Base class constructor and destructor. I've added the warning under the -Wextra flag as I can't find a more appropriate flag for it. The patch has been bootstrapped and regression tested on x86_64-pc-linux-gnu. Appreciate reviews and feedback. Thanks! From c70e087c7ee9db7497da293f8a85891abe895d9a Mon Sep 17 00:00:00 2001 From: Zhao Wei Liew <zhaoweiliew@gmail.com> Date: Tue, 22 Feb 2022 16:03:17 +0800 Subject: [PATCH] c++: warn when casting "this" to Derived* in Base ctor/dtor [PR96765] Casting "this" in a base class constructor to a derived class type is undefined behaviour, but there is no warning when doing so. Add a warning for this. Signed-off-by: Zhao Wei Liew <zhaoweiliew@gmail.com> PR c++/96765 gcc/cp/ChangeLog: * typeck.cc (build_static_cast_1): Add a warning when casting "this" to Derived * in Base constructor and destructor. gcc/testsuite/ChangeLog: * g++.dg/warn/Wextra-5.C: New test. --- gcc/cp/typeck.cc | 9 ++++++++ gcc/testsuite/g++.dg/warn/Wextra-5.C | 33 ++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/Wextra-5.C
Comments
On 3/14/22 02:36, Zhao Wei Liew via Gcc-patches wrote: > This patch adds a warning when casting "this" to Derived* in the Base > class constructor and destructor. I've added the warning under the > -Wextra flag as I can't find a more appropriate flag for it. It's generally best to add a new warning flag if an existing one isn't a good match. Maybe -Wderived-cast-undefined? It seems like it could be part of -Wall. > + if (current_function_decl > + && (DECL_CONSTRUCTOR_P (current_function_decl) > + || DECL_DESTRUCTOR_P (current_function_decl)) > + && TREE_CODE (expr) == NOP_EXPR > + && is_this_parameter (TREE_OPERAND (expr, 0))) I think the resolves_to_fixed_type_p function would be useful here; you're testing for a subset of the cases it handles. > + warning_at(loc, OPT_Wextra, Missing space before '('. Jason
Thanks for the review. I've tested and uploaded a new patch v2 with the requested changes. On Thu, 17 Mar 2022 at 09:20, Jason Merrill <jason@redhat.com> wrote: > > On 3/14/22 02:36, Zhao Wei Liew via Gcc-patches wrote: > > > This patch adds a warning when casting "this" to Derived* in the Base > > class constructor and destructor. I've added the warning under the > > -Wextra flag as I can't find a more appropriate flag for it. > > It's generally best to add a new warning flag if an existing one isn't a > good match. Maybe -Wderived-cast-undefined? It seems like it could be > part of -Wall. Hmm, I agree. I've added a new -Wderived-cast-undefined flag for this. > > + if (current_function_decl > > + && (DECL_CONSTRUCTOR_P (current_function_decl) > > + || DECL_DESTRUCTOR_P (current_function_decl)) > > + && TREE_CODE (expr) == NOP_EXPR > > + && is_this_parameter (TREE_OPERAND (expr, 0))) > > I think the resolves_to_fixed_type_p function would be useful here; > you're testing for a subset of the cases it handles. Does the new patch look like how you intended it to? The new patch passes all regression tests and newly added tests. However, I don't fully understand the code for resolves_to_fixed_type_p() and fixed_type_or_null(), except that I see that they contain logic to return -1 when within a ctor/dtor. Thanks! From a8bbd4158f3311372b67d32816ce40d5613ae0d8 Mon Sep 17 00:00:00 2001 From: Zhao Wei Liew <zhaoweiliew@gmail.com> Date: Tue, 22 Feb 2022 16:03:17 +0800 Subject: [PATCH] c++: warn when casting Base* to Derived* in Base ctor/dtor [PR96765] Casting "this" in a base class constructor to a derived class type is undefined behaviour, but there is no warning when doing so. Add a warning for this. Signed-off-by: Zhao Wei Liew <zhaoweiliew@gmail.com> PR c++/96765 gcc/c-family/ChangeLog: * c.opt (-Wderived-cast-undefined): New option. gcc/cp/ChangeLog: * typeck.cc (build_static_cast_1): Add a warning when casting Base* to Derived* in Base constructor and destructor. gcc/testsuite/ChangeLog: * g++.dg/warn/Wderived-cast-undefined.C: New test. --- gcc/c-family/c.opt | 4 +++ gcc/cp/typeck.cc | 6 ++++ .../g++.dg/warn/Wderived-cast-undefined.C | 33 +++++++++++++++++++ 3 files changed, 43 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9cfd2a6bc4e..1681395c529 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -598,6 +598,10 @@ C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning Warn about deprecated arithmetic conversions on operands where one is of enumeration type and the other is of a floating-point type. +Wderived-cast-undefined +C++ Var(warn_derived_cast_undefined) Warning LangEnabledBy(C++, Wall) +Warn about undefined casts from Base* to Derived* in the Base constructor or destructor. + Wdesignated-init C ObjC Var(warn_designated_init) Init(1) Warning Warn about positional initialization of structs requiring designated initializers. diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 516fa574ef6..0bbbc378806 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -8079,6 +8079,12 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p, { tree base; + if (TREE_CODE (expr) == NOP_EXPR + && resolves_to_fixed_type_p (TREE_OPERAND (expr, 0)) == -1) + warning_at (loc, OPT_Wderived_cast_undefined, + "invalid %<static_cast%> from type %qT to type %qT before the latter is constructed", + intype, type); + if (processing_template_decl) return expr; diff --git a/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C b/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C new file mode 100644 index 00000000000..ea7388514dc --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C @@ -0,0 +1,33 @@ +// PR c++/96765 +// { dg-options "-Wderived-cast-undefined" } + +struct Derived; +struct Base { + Derived *x; + Derived *y; + Base(); + ~Base(); +}; + +struct Derived : Base {}; + +Base::Base() + : x(static_cast<Derived *>(this)), // { dg-warning "invalid 'static_cast'" } + y((Derived *)this) // { dg-warning "invalid 'static_cast'" } +{ + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +Base::~Base() { + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +struct Other { + Other() { + Base b; + static_cast<Derived *>(&b); + (Derived *)(&b); + } +};
On 3/17/22 01:51, Zhao Wei Liew wrote: > Thanks for the review. I've tested and uploaded a new patch v2 with > the requested changes. > > On Thu, 17 Mar 2022 at 09:20, Jason Merrill <jason@redhat.com> wrote: >> >> On 3/14/22 02:36, Zhao Wei Liew via Gcc-patches wrote: >> >>> This patch adds a warning when casting "this" to Derived* in the Base >>> class constructor and destructor. I've added the warning under the >>> -Wextra flag as I can't find a more appropriate flag for it. >> >> It's generally best to add a new warning flag if an existing one isn't a >> good match. Maybe -Wderived-cast-undefined? It seems like it could be >> part of -Wall. > > Hmm, I agree. I've added a new -Wderived-cast-undefined flag for this. > >>> + if (current_function_decl >>> + && (DECL_CONSTRUCTOR_P (current_function_decl) >>> + || DECL_DESTRUCTOR_P (current_function_decl)) >>> + && TREE_CODE (expr) == NOP_EXPR >>> + && is_this_parameter (TREE_OPERAND (expr, 0))) >> >> I think the resolves_to_fixed_type_p function would be useful here; >> you're testing for a subset of the cases it handles. > > Does the new patch look like how you intended it to? The new patch > passes all regression tests and newly added tests. However, I don't > fully understand the code for resolves_to_fixed_type_p() and > fixed_type_or_null(), except that I see that they contain logic to > return -1 when within a ctor/dtor. > + if (TREE_CODE (expr) == NOP_EXPR > + && resolves_to_fixed_type_p (TREE_OPERAND (expr, 0)) == -1) Why not just pass expr itself to resolves_to_fixed_type_p? We might as well also warn if it returns >0, e.g. struct A { } a; struct B: A { }; auto p = static_cast<B*>(&a); // undefined You should also handle reference casts. Jason
On Fri, 25 Mar 2022 at 05:58, Jason Merrill <jason@redhat.com> wrote: > > > >>> + if (current_function_decl > >>> + && (DECL_CONSTRUCTOR_P (current_function_decl) > >>> + || DECL_DESTRUCTOR_P (current_function_decl)) > >>> + && TREE_CODE (expr) == NOP_EXPR > >>> + && is_this_parameter (TREE_OPERAND (expr, 0))) > >> > >> I think the resolves_to_fixed_type_p function would be useful here; > >> you're testing for a subset of the cases it handles. > > > > Does the new patch look like how you intended it to? The new patch > > passes all regression tests and newly added tests. However, I don't > > fully understand the code for resolves_to_fixed_type_p() and > > fixed_type_or_null(), except that I see that they contain logic to > > return -1 when within a ctor/dtor. > > > + if (TREE_CODE (expr) == NOP_EXPR > > + && resolves_to_fixed_type_p (TREE_OPERAND (expr, 0)) == -1) > > Why not just pass expr itself to resolves_to_fixed_type_p? You're right. I didn't realise that fixed_type_or_null handles the NOP_EXPR case as part of CASE_CONVERT. > We might as well also warn if it returns >0, e.g. > > struct A { } a; > struct B: A { }; > auto p = static_cast<B*>(&a); // undefined > > You should also handle reference casts. I've made some changes in v3 to handle reference casts and the case where resolves_to_fixed_type_p > 0. I've also slightly modified the patch title to reflect the new changes. Thanks as always! v2: https://gcc.gnu.org/pipermail/gcc-patches/2022-March/591894.html Changes since v2: - Handle reference casts and add new tests. - Warn if resolves_to_fixed_type_p > 0 to handle more general cases. v1: https://gcc.gnu.org/pipermail/gcc-patches/2022-March/591683.html - Add new warning flag. - Use resolves_to_fixed_type_p. From 261fcff504d2a4971a501747979b1b424d6b09e4 Mon Sep 17 00:00:00 2001 From: Zhao Wei Liew <zhaoweiliew@gmail.com> Date: Tue, 22 Feb 2022 16:03:17 +0800 Subject: [PATCH] c++: warn on undefined casts from Base to Derived ref/ptr [PR96765] In some cases, converting a Base class reference/pointer to Derived is undefined behavior. This patch adds a new warning for them (-Wderived-cast-undefined). Signed-off-by: Zhao Wei Liew <zhaoweiliew@gmail.com> PR c++/96765 gcc/c-family/ChangeLog: * c.opt (-Wderived-cast-undefined): New option. gcc/cp/ChangeLog: * typeck.cc (build_static_cast_1): Add warnings. gcc/testsuite/ChangeLog: * g++.dg/warn/Wderived-cast-undefined.C: New test. --- gcc/c-family/c.opt | 4 ++ gcc/cp/typeck.cc | 13 +++++ .../g++.dg/warn/Wderived-cast-undefined.C | 49 +++++++++++++++++++ 3 files changed, 66 insertions(+) create mode 100644 gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C diff --git a/gcc/c-family/c.opt b/gcc/c-family/c.opt index 9a4828ebe37..1928aee62e6 100644 --- a/gcc/c-family/c.opt +++ b/gcc/c-family/c.opt @@ -598,6 +598,10 @@ C++ ObjC++ Var(warn_deprecated_enum_float_conv) Warning Warn about deprecated arithmetic conversions on operands where one is of enumeration type and the other is of a floating-point type. +Wderived-cast-undefined +C++ Var(warn_derived_cast_undefined) Warning LangEnabledBy(C++, Wall) +Warn about undefined casts from Base* to Derived* in the Base constructor or destructor. + Wdesignated-init C ObjC Var(warn_designated_init) Init(1) Warning Warn about positional initialization of structs requiring designated initializers. diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 516fa574ef6..6e19ba5af7f 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -7894,6 +7894,13 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p, { tree base; + if (TYPE_MAIN_VARIANT (intype) != TYPE_MAIN_VARIANT (TREE_TYPE (type)) + && resolves_to_fixed_type_p (expr)) + warning_at (loc, OPT_Wderived_cast_undefined, + "invalid %<static_cast%> from type %qT to type %qT " + "before the latter is constructed", + intype, type); + if (processing_template_decl) return expr; @@ -8079,6 +8086,12 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p, { tree base; + if (resolves_to_fixed_type_p (expr)) + warning_at (loc, OPT_Wderived_cast_undefined, + "invalid %<static_cast%> from type %qT to type %qT " + "before the latter is constructed", + intype, type); + if (processing_template_decl) return expr; diff --git a/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C b/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C new file mode 100644 index 00000000000..3459deadd3f --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wderived-cast-undefined.C @@ -0,0 +1,49 @@ +// PR c++/96765 +// { dg-options "-Wderived-cast-undefined" } + +struct Derived; +struct Base { + Derived *x; + Derived &y; + Base(); + ~Base(); +}; + +struct Derived : Base {}; + +Base::Base() + : x(static_cast<Derived *>(this)), // { dg-warning "invalid 'static_cast'" } + y(static_cast<Derived &>(*this)) // { dg-warning "invalid 'static_cast'" } +{ + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + static_cast<Derived &>(*this); // { dg-warning "invalid 'static_cast'" } +} + +Base::~Base() { + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + static_cast<Derived &>(*this); // { dg-warning "invalid 'static_cast'" } +} + +void f1() { + Base b; + static_cast<Derived *>(&b); // { dg-warning "invalid 'static_cast'" } + static_cast<Derived &>(b); // { dg-warning "invalid 'static_cast'" } +} + +void f2(Base *b1, Base &b2) { + static_cast<Derived *>(b1); + static_cast<Derived &>(*b1); + static_cast<Derived *>(&b2); + static_cast<Derived &>(b2); +} + +void f3(Derived *d1, Derived &d2) { + Base *b = d1; + static_cast<Derived *>(b); + static_cast<Derived &>(*b); + + b = &d2; + static_cast<Derived *>(b); + static_cast<Derived &>(*b); +} +
On 3/27/22 08:37, Zhao Wei Liew wrote: > On Fri, 25 Mar 2022 at 05:58, Jason Merrill <jason@redhat.com> wrote: >>> >>>>> + if (current_function_decl >>>>> + && (DECL_CONSTRUCTOR_P (current_function_decl) >>>>> + || DECL_DESTRUCTOR_P (current_function_decl)) >>>>> + && TREE_CODE (expr) == NOP_EXPR >>>>> + && is_this_parameter (TREE_OPERAND (expr, 0))) >>>> >>>> I think the resolves_to_fixed_type_p function would be useful here; >>>> you're testing for a subset of the cases it handles. >>> >>> Does the new patch look like how you intended it to? The new patch >>> passes all regression tests and newly added tests. However, I don't >>> fully understand the code for resolves_to_fixed_type_p() and >>> fixed_type_or_null(), except that I see that they contain logic to >>> return -1 when within a ctor/dtor. >> >>> + if (TREE_CODE (expr) == NOP_EXPR >>> + && resolves_to_fixed_type_p (TREE_OPERAND (expr, 0)) == -1) >> >> Why not just pass expr itself to resolves_to_fixed_type_p? > > You're right. I didn't realise that fixed_type_or_null handles the > NOP_EXPR case as part of CASE_CONVERT. > >> We might as well also warn if it returns >0, e.g. >> >> struct A { } a; >> struct B: A { }; >> auto p = static_cast<B*>(&a); // undefined >> >> You should also handle reference casts. > > I've made some changes in v3 to handle reference casts and the case > where resolves_to_fixed_type_p > 0. I've also slightly modified the > patch title to reflect the new changes. Looks good, I've queued this for when GCC 13 development opens. Thanks, Jason
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 516fa574ef6..782f70b27e6 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -8079,6 +8079,15 @@ build_static_cast_1 (location_t loc, tree type, tree expr, bool c_cast_p, { tree base; + if (current_function_decl + && (DECL_CONSTRUCTOR_P (current_function_decl) + || DECL_DESTRUCTOR_P (current_function_decl)) + && TREE_CODE (expr) == NOP_EXPR + && is_this_parameter (TREE_OPERAND (expr, 0))) + warning_at(loc, OPT_Wextra, + "invalid %<static_cast%> from type %qT to type %qT before the latter is constructed", + intype, type); + if (processing_template_decl) return expr; diff --git a/gcc/testsuite/g++.dg/warn/Wextra-5.C b/gcc/testsuite/g++.dg/warn/Wextra-5.C new file mode 100644 index 00000000000..7e82c4c6121 --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/Wextra-5.C @@ -0,0 +1,33 @@ +// PR c++/96765 +// { dg-options "-Wextra" } + +struct Derived; +struct Base { + Derived *x; + Derived *y; + Base(); + ~Base(); +}; + +struct Derived : Base {}; + +Base::Base() + : x(static_cast<Derived *>(this)), // { dg-warning "invalid 'static_cast'" } + y((Derived *)this) // { dg-warning "invalid 'static_cast'" } +{ + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +Base::~Base() { + static_cast<Derived *>(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +struct Other { + Other() { + Base b; + static_cast<Derived *>(&b); + (Derived *)(&b); + } +};