XXH_STATIC_ASSERT() doesn't work with VC++2019 as a C compiler #567

Closed
opened 2021-08-19 06:44:08 -05:00 by t-mat · 3 comments
t-mat commented 2021-08-19 06:44:08 -05:00 (Migrated from github.com)

When we compile a code with Visual C++ 2019 as a C compiler, it doesn't interpret XXH_STATIC_ASSERT(0) properly.

If we use Visual C++ 2019 as a C++ compiler, XXH_STATIC_ASSERT(0) works correctly though.

/* C code */
#define XXH_STATIC_ASSERT(c)  do { enum { XXH_sa = 1/(int)(!!(c)) }; } while (0)

int main(int argc, char** argv) {
    XXH_STATIC_ASSERT(0); /* VC++2019 as a C compiler reports no error */
}
When we compile a code with Visual C++ 2019 as a *C compiler*, it doesn't interpret `XXH_STATIC_ASSERT(0)` properly. If we use Visual C++ 2019 as a *C++ compiler*, `XXH_STATIC_ASSERT(0)` works correctly though. ```C /* C code */ #define XXH_STATIC_ASSERT(c) do { enum { XXH_sa = 1/(int)(!!(c)) }; } while (0) int main(int argc, char** argv) { XXH_STATIC_ASSERT(0); /* VC++2019 as a C compiler reports no error */ } ``` - [Test at Compiler Explorer](https://godbolt.org/z/Tqc18YPza)
t-mat commented 2021-08-19 06:49:53 -05:00 (Migrated from github.com)
/* test.c or test.cpp */
int f() {
    enum { x = 123 / 0 };
    return x;
}

When we compile above code as test.cpp, VC++2019 reports the following error.

test.cpp(2,17): error C2131: expression did not evaluate to a constant
test.cpp(2,17): message : failure was caused by an undefined arithmetic operation

But compile as test.c, it reports nothing.

At Compiler Explorer, it seems VC++ as a C compiler is only compiler which accepts above f() without error / warning.

I don't know there's a compiler switch to disable this behavior.


(edit)

```C /* test.c or test.cpp */ int f() { enum { x = 123 / 0 }; return x; } ``` When we compile above code as `test.cpp`, VC++2019 reports the following error. ``` test.cpp(2,17): error C2131: expression did not evaluate to a constant test.cpp(2,17): message : failure was caused by an undefined arithmetic operation ``` But compile as `test.c`, it reports nothing. At Compiler Explorer, it seems VC++ as a C compiler is only compiler which accepts above `f()` without error / warning. I don't know there's a compiler switch to disable this behavior. ---- (edit) - `/std:c11`, `/std:c17` don't change the behavior. - [`_Static_assert()`](https://docs.microsoft.com/en-us/cpp/c-language/static-assert-c) works. But [it requires recent version of MSVC and Windows SDK](https://docs.microsoft.com/en-us/cpp/c-language/static-assert-c?view=msvc-160#requirements). MSVC2019 isn't shipped with `<stdalign.h>` etc.
t-mat commented 2021-08-19 11:50:56 -05:00 (Migrated from github.com)

I think it's a good chance to introduce standard static_assert().

Both of them have same form: static_assert( <cond> , "<message>" ).

Still we need discussion how we can implement static_assert() for pre-C11 and MSVC (as a C) compilers. But it might look like this:

#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)    /* C11 */
#  include <assert.h>
#  define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) static_assert(c,m)
#elif defined(__cplusplus) && (__cplusplus >= 201103L)            /* C++11 */
#  define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) static_assert(c,m)
#else
/*#define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { enum { XXH_sa = 1/(int)(!!(c)) }; } while (0)*/
#  define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct XXH_sa { char xxh_static_assert[0-(int)(!(c))]; }; } while (0)
#endif

#define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE(c,"XXH_STATIC_ASSERT")
I think it's a good chance to introduce standard `static_assert()`. - C11 : `<assert.h>`, `static_assert()` and [_Static_assert](https://en.cppreference.com/w/c/language/_Static_assert) - C++11 : [`static_assert()`](https://en.cppreference.com/w/cpp/language/static_assert) Both of them have same form: `static_assert( <cond> , "<message>" )`. Still we need discussion how we can implement `static_assert()` for pre-C11 and MSVC (as a C) compilers. But it might look like this: ```C #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) /* C11 */ # include <assert.h> # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) static_assert(c,m) #elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) static_assert(c,m) #else /*#define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { enum { XXH_sa = 1/(int)(!!(c)) }; } while (0)*/ # define XXH_STATIC_ASSERT_WITH_MESSAGE(c,m) do { struct XXH_sa { char xxh_static_assert[0-(int)(!(c))]; }; } while (0) #endif #define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE(c,"XXH_STATIC_ASSERT") ```
Cyan4973 commented 2021-08-19 12:29:25 -05:00 (Migrated from github.com)

I'm fine with the idea of an improved version of XXH_STATIC_ASSERT() that remains compatible with C90.

I'm fine with the idea of an improved version of `XXH_STATIC_ASSERT()` that remains compatible with `C90`.
Sign in to join this conversation.
No milestone
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
gh-Cyan4973/xxHash#567
No description provided.