From c70e087c7ee9db7497da293f8a85891abe895d9a Mon Sep 17 00:00:00 2001 From: Zhao Wei Liew 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 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 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 % 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(this)), // { dg-warning "invalid 'static_cast'" } + y((Derived *)this) // { dg-warning "invalid 'static_cast'" } +{ + static_cast(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +Base::~Base() { + static_cast(this); // { dg-warning "invalid 'static_cast'" } + (Derived *)this; // { dg-warning "invalid 'static_cast'" } +} + +struct Other { + Other() { + Base b; + static_cast(&b); + (Derived *)(&b); + } +}; -- 2.25.1