<table border="1" cellspacing="0" cellpadding="8">
<tr>
<th>Issue</th>
<td>
<a href=https://github.com/llvm/llvm-project/issues/58820>58820</a>
</td>
</tr>
<tr>
<th>Summary</th>
<td>
[clang-tidy] False positive when using `QPointer<>` with LLVM-15
</td>
</tr>
<tr>
<th>Labels</th>
<td>
new issue
</td>
</tr>
<tr>
<th>Assignees</th>
<td>
</td>
</tr>
<tr>
<th>Reporter</th>
<td>
kieselnb
</td>
</tr>
</table>
<pre>
Linting a codebase that uses Qt 6 with clang-tidy 15 (have tested 15.0.0 and 15.0.3) results in a false positive within `QWeakPointer` (triggered by usage of `QPointer`):
```
(py3) [nkiesel@host repro]$ clang-tidy -checks='-*,clang-analyzer-*' -p build/ main.cpp
1 warning generated.
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:162:50: error: Use of memory after it is freed [clang-analyzer-cplusplus.NewDelete,-warnings-as-errors]
inline void operator delete(void *ptr) { ::operator delete(ptr); }
^
/tmp/nkiesel/repro/main.cpp:21:21: note: Calling implicit destructor for 'MainWindow'
return app.exec();
^
/tmp/nkiesel/repro/main.cpp:21:21: note: Calling implicit destructor for 'QPointer<QWidget>'
/tmp/nkiesel/repro/main.cpp:21:21: note: Calling '~QWeakPointer'
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:34: note: Assuming field 'd' is non-null
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
^
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:34: note: Left side of '&&' is true
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:39: note: Assuming the condition is true
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
^~~~~~~~~~~~~~~~~~~
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:30: note: Taking true branch
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
^
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:60: note: Memory is released
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
^~~~~~~~
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:579:60: note: Calling 'ExternalRefCountData::operator delete'
inline ~QWeakPointer() { if (d && !d->weakref.deref()) delete d; }
^~~~~~~~
/mnt/vol02/nkiesel/opt/qt/Qt-6.2.4/include/QtCore/qsharedpointer_impl.h:162:50: note: Use of memory after it is freed
inline void operator delete(void *ptr) { ::operator delete(ptr); }
^ ~~~
1 warning treated as error
```
`ExternalRefCountData::operator delete(void*)` is incorrectly treated as a proper `::operator delete(void*)`, and the memory is marked as freed. Parsing then continues down the stack and sees the true call of `::operator delete(void*)`, triggering the error since clang-tidy thinks the memory has already been freed.
LLVM 12.0.1 and 14.0.6 did not exhibit this behavior.
CMakeLists.txt:
```cmake
cmake_minimum_required(VERSION 3.11...3.22)
project(repro CXX)
find_package(Qt6 COMPONENTS Gui Widgets)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
add_executable(repro main.cpp)
target_link_libraries(repro PRIVATE Qt6::Gui Qt6::Widgets)
```
main.cpp:
```cpp
#include <QApplication>
#include <QMainWindow>
#include <QWidget>
#include <QPointer>
class MainWindow : public QMainWindow {
public:
MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {}
private:
QPointer<QWidget> m_widget;
};
int main(int argc, char *argv[]) {
QApplication app(argc, argv);
MainWindow main_window;
main_window.show();
return app.exec();
}
```
</pre>
<img width="1px" height="1px" alt="" src="http://email.email.llvm.org/o/eJztWEtz4zYM_jXyhWONHrZlH3zw2nIn07ycZHdz81ASZbGWKS1JJZv--gLUw0ritLvtNM2hGYeiSBAEPoAgoKhInubnXGgudoSSuEhYRBUjOqOaVIopstFkQh65zkicU7Ebap48EXdMLG-a0QegZEqzBEZsx3YIFU3Xt7wZkUxVuVaEC-Cd0hwYl4XimsM6ZAnj1sTZfGV0f12AEEzCK3LWku92TALf6AnEoDtGitTQHulgA8tfWM7Kchb4Wv_qV29aPhkJrPEnsedMsdwaOVmhNMhUysIaryxv1NdoGGcs3ivLh4lgaHnAY1lPU0Hzp9-ZrAcDMixJVPE8sbw1OVAu7Lgs621d8kilQCR3TDBJARe7FWh9EBrahyJ3PHi2QnnrosTxb9hs9HBie_YIulzEeZUwM7gsJHa-qYwCImUNwJYfytzOAAF34kE7dqAhTMpCYuezMogd2KGQT4SmsIJwTbgiqWQAK-DyQru4zCuF__Yle1yxnGnYdDlsNFJDqoaGu0LsjFKk-eMi54KRh4InpChR70KSpOEwNcMAXamlMUjwiaDZ_MVr0prE8oEieLHHD_9Z47CDXB_KZ1DXpgdTtFbzF57bNkQUIAQ8lzTP0YYIMI8BtAQ8XFYxiprCP_jABTD4ykVSPMLLUVDJdCXB1cvSZt9ZDBrV6rytyrtI250Zf7n5ypMd05YfdoL_452RUxA-O8Q93v-a248DPP7-qC_SQqnqgDKlnOXodUGCJxa8XhRiKKo8P5qi8dpXok9bL-UpRiLkMoEfPNxkCMA9ArFkqZ1AeEobE8OK2olJ8nPe27f_uyJ1zlJNFE_quAr2Mko2YIH_sHcTa3bSgDpjcBmJBO6KQjyX6cMYr7Ng8Ld-7wWw0wf4ju4NvIAmiSQVcfaBQH3H0zB5hspFfU2Cm0kQGvKf5AOh8jf97z8BsncnhN-BGpKLG5Yui0roFdX0jYs_-B_tn8ryWrT_Isn72Fna67HnYB6TaS0ZptKEqia_PZnyt4M_4XdGa5PVz7Du4FioxIWULNb5U39bSiAhgtVYgfwQL8icTSmE19ihCy4HKvc1Q2Mfm1xTqZrbTuB1B1VYBSUX5JXCLFWaxnvDSDEYxyETuWM4Zk1B9MPiNCVVe7kaJCEDEDHrl0FYk-1VX-4M9c8BC5iNGMhZy95H_fz8ywVxPaj63LoAHEF3QhJwKXBVwr5nPAK_BN4KWEDVyAv5jMHygu7ZOVda2fq7fl3VxQeYr8dMdws5Aj9Uh61k3yoOxwUU_hLe3J5dXRLfdl3btn3b81D5vnOYFiz5GxgYVpg0lyzv70_SpZDfb0vAH4pPIN7oCVleXVxfXYaXd7fkl4qTOpdWJ1crhjssLxa_htvw_vrq5m6Lq8_OQ3xeLC5Xt-Tq8sXS_iIQa3t7B3SLmxVxg47yLZrtTbj5fHYTrvpsXxKH93fhJaIEm6_XJwWnSbLF4qXSNMpZh1JXCrRrNJWg_BZiyh4aSCUkhLqO_Prm7MviLiSAWu2giFf38gq4U0e5V3y89Ia23rY8v4mgBGubRYklEMWMEQucUyS9wu0NimOBdGq2q6TCvqhwfpQiR94YOklZRSAN2fSHg6YUrOc6zTD69UvKaSOFCchwGwjo-SuC9Usbn2GDzbMlNV0Tu7vA3Lo8f6Dmyjjud7IoJIftY9NvJEVOXd-0sMp4A-yJXXCDGMNLDNcWygvvD9b4k_nAMjtqbLbsGQiLZODQrjarerXyKVzMriBfbb0e3964rTKDxmlef16fH0FrHW3A5u5kEoxnM3fmDJK5n8z8GR1ornM2776gYNwEdcn6xfctjOmVCe_971b-Ep0HbhvzSQ0j59AdDyqZzzOtS4U28uBkrncwXUV2XBzgJc8f2sewi19rDsUSnrn1eDr1nEE2D4J06gdBEjDHj2OPUXfEPBqn08B1aDCZDXIasVyh6JbnCfZIDAvog_wDPvccz3NdZ-S549loZkepmybeiKbpJPJHs7E1chhgndsoh13I3UDOjUhRtVMwmZsA3k3CmeA7wQxSyJ9WOivkvE6JRDQwe8-N7H8Ab8f6KQ">