https://github.com/vtjnash created https://github.com/llvm/llvm-project/pull/122330
The C++ standard prohibits this implicit destructor call, leading to incorrect reports from clang-analyzer. This causes projects that use std::option (including llvm) to fail the cplusplus.NewDelete test incorrectly when run through the analyzer. Fixes #119415 >From 533e475ffa57da335a2cce387f08c83f442fd16b Mon Sep 17 00:00:00 2001 From: Jameson Nash <vtjn...@gmail.com> Date: Thu, 9 Jan 2025 17:10:08 +0000 Subject: [PATCH] [Sema] do not destruct fields of unions The C++ standard prohibits this implicit destructor call, leading to incorrect reports from clang-analyzer. This causes projects that use std::option (including llvm) to fail the cplusplus.NewDelete test incorrectly when run through the analyzer. Fixes #119415 --- clang/lib/Analysis/CFG.cpp | 2 ++ .../test/Analysis/NewDelete-checker-test.cpp | 28 +++++++++++++++++++ clang/test/Analysis/dtor-array.cpp | 24 ++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/clang/lib/Analysis/CFG.cpp b/clang/lib/Analysis/CFG.cpp index 304bbb2b422c61..3e144395cffc6f 100644 --- a/clang/lib/Analysis/CFG.cpp +++ b/clang/lib/Analysis/CFG.cpp @@ -2041,6 +2041,8 @@ void CFGBuilder::addImplicitDtorsForDestructor(const CXXDestructorDecl *DD) { } // First destroy member objects. + if (RD->isUnion()) + return; for (auto *FI : RD->fields()) { // Check for constant size array. Set type to array element type. QualType QT = FI->getType(); diff --git a/clang/test/Analysis/NewDelete-checker-test.cpp b/clang/test/Analysis/NewDelete-checker-test.cpp index 21b4cf817b5df6..806edd47840fc1 100644 --- a/clang/test/Analysis/NewDelete-checker-test.cpp +++ b/clang/test/Analysis/NewDelete-checker-test.cpp @@ -441,3 +441,31 @@ void testLeakBecauseNTTPIsNotDeallocation() { void* p = ::operator new(10); deallocate_via_nttp<not_free>(p); } // leak-warning{{Potential leak of memory pointed to by 'p'}} + +namespace optional_union { + template <typename T> + class unique_ptr { + T *q; + public: + unique_ptr() : q(new T) {} + ~unique_ptr() { + delete q; + } + }; + + union custom_union_t { + unique_ptr<int> present; + char notpresent; + custom_union_t() : present(unique_ptr<int>()) {} + ~custom_union_t() {}; + }; + + void testUnionCorrect() { + custom_union_t a; + a.present.~unique_ptr<int>(); + } + + void testUnionLeak() { + custom_union_t a; + } // leak-warning{{Potential leak of memory pointed to by 'a.present.q'}} +} diff --git a/clang/test/Analysis/dtor-array.cpp b/clang/test/Analysis/dtor-array.cpp index 84a34af9225169..1bbe55c09ee7e2 100644 --- a/clang/test/Analysis/dtor-array.cpp +++ b/clang/test/Analysis/dtor-array.cpp @@ -377,3 +377,27 @@ void directUnknownSymbol() { } } + +void testUnionDtor() { + static int unionDtorCalled; + InlineDtor::cnt = 0; + InlineDtor::dtorCalled = 0; + unionDtorCalled = 0; + { + union UnionDtor { + InlineDtor kind1; + char kind2; + ~UnionDtor() { unionDtorCalled++; } + }; + UnionDtor u1{.kind1{}}; + UnionDtor u2{.kind2{}}; + auto u3 = new UnionDtor{.kind1{}}; + auto u4 = new UnionDtor{.kind2{}}; + delete u3; + delete u4; + } + + clang_analyzer_eval(unionDtorCalled == 4); // expected-warning {{TRUE}} + clang_analyzer_eval(InlineDtor::dtorCalled != 4); // expected-warning {{TRUE}} + clang_analyzer_eval(InlineDtor::dtorCalled == 0); // expected-warning {{TRUE}} +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits