I am working on a C++17-project which I am compiling under Linux with GCC 9. However, I EDIT the project under Windows 11 in QT Creator 10 using clangd/clangTidy(16.0.0). Now, when it comes to code that uses thread_local, I get errors in clang-tidy, as this is apparently not supported in the clang-world (?!).
I help myself then as in the following example:
auto gmtimeTS( const time_t *timeval ) -> struct tm*
{
#if ( defined(__GNUC__) && !defined(__clang__) )
thread_local struct tm result;
#else
static std::mutex mtx;
std::unique_lock< std::mutex > lock( mtx );
static struct tm result;
#endif
return gmtime_r( timeval, &result );
}
So I don't get any errors in the IDE and it compiles beautifully under Linux with GCC
But now I have a similar problem with RapidJSON which I can't get solved. Here RapidJSON
seems to take thread_local, even if __clang__
is set.
#define RAPIDJSON_HAS_STDSTRING 1
#define RAPIDJSON_HAS_CXX11_RVALUE_REFS 1
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"
Error-Message:
rapidjson/document.h:1237:35: error: thread-local storage is not supported for the current target [clang-diagnostic-error]
alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
I think this are the relevant parts in document.h, where the usage of thread_local is forced, when RAPIDJSON_HAS_CXX11 is active.
...
...
#ifndef RAPIDJSON_HAS_CXX11
#define RAPIDJSON_HAS_CXX11 (RAPIDJSON_CPLUSPLUS >= 201103L)
#endif
...
...
#if RAPIDJSON_HAS_CXX11
// Use thread-local storage to prevent races between threads.
// Use static buffer and placement-new to prevent destruction, with
// alignas() to ensure proper alignment.
alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(_MSC_VER) && _MSC_VER < 1900
// There's no way to solve both thread locality and proper alignment
// simultaneously.
__declspec(thread) static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(__GNUC__) || defined(__clang__)
// This will generate -Wexit-time-destructors in clang, but that's
// better than having under-alignment.
__thread static GenericValue buffer;
return buffer;
#else
// Don't know what compiler this is, so don't know how to ensure
// thread-locality.
static GenericValue buffer;
return buffer;
#endif
Clang-Tidy-Call is:
C:\Qt\Tools\QtCreator\bin\clang\bin\clang-tidy.exe "-config={Checks: '-,clang-,concurrency-,cppcoreguidelines-virtual-class-destructor,misc-misplaced-const,modernize-use-override,-clang-diagnostic-*', CheckOptions: []}" "-export-fixes=C:\Users\XXX\AppData\Local\Temp\QtCreator-RxIOUr\clangtools-RhHPvy\report-test.h-USFhkc" C:\XXX\libs\include\test.h -- -Wno-unknown-pragmas -Wno-unknown-warning-option -Wno-documentation-unknown-command -w -nostdinc -nostdinc++ -g --param "max-vartrack-size=1024000000" -pipe "-fmessage-length=0" "-std=c++17" -fsyntax-only -m64 "--target=x86_64-pc-cygwin" -x c++ "-D_FILE_OFFSET_BITS=64" -D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_REENTRANT -IC:A -IC:B ...
How do I get the error messages regarding clang-tidy eliminated so that I can still compile under Linux with GCC? A //NOLINT
after the #include
does not work either. Is it possible to create a special .clang-tidy file for this?
EDIT
Finally I fixed it now directly in the source code, even if it is not pretty:
#if RAPIDJSON_HAS_CXX11 && !defined(RAPIDJSON_NO_THREAD_LOCAL)
// Use thread-local storage to prevent races between threads.
// Use static buffer and placement-new to prevent destruction, with
// alignas() to ensure proper alignment.
alignas(GenericValue) thread_local static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif defined(_MSC_VER) && _MSC_VER < 1900 && !defined(RAPIDJSON_NO_THREAD_LOCAL)
// There's no way to solve both thread locality and proper alignment
// simultaneously.
__declspec(thread) static char buffer[sizeof(GenericValue)];
return *new (buffer) GenericValue();
#elif (defined(__GNUC__) || defined(__clang__)) && !defined(RAPIDJSON_NO_THREAD_LOCAL)
// This will generate -Wexit-time-destructors in clang, but that's
// better than having under-alignment.
__thread static GenericValue buffer;
return buffer;
#else
// Don't know what compiler this is, so don't know how to ensure
// thread-locality.
static GenericValue buffer;
return buffer;
#endif
Usage:
#if __clang__
#define RAPIDJSON_NO_THREAD_LOCAL
#endif
#include "rapidjson/document.h"
#include "rapidjson/writer.h"
#include "rapidjson/stringbuffer.h"