2

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"
SoulfreezerXP
  • 459
  • 1
  • 5
  • 19

0 Answers0