In a testdir on MSVC 14, I see these compilation errors: /home/bruno/msvc/compile cl -nologo -DHAVE_CONFIG_H -I. -I../../gltests -I.. -DGNULIB_STRICT_CHECKING=1 -DIN_GNULIB_TESTS=1 -I. -I../../gltests -I.. -I../../gltests/.. -I../gllib -I../../gltests/../gllib -D_WIN32_WINNT=_WIN32_WINNT_WIN7 -I/usr/local/msvc64/include -MD -c -o test-stdbit-h-c++.obj `cygpath -w '../../gltests/test-stdbit-h-c++.cc'` test-stdbit-h-c++.cc ../gllib\stdbit.h(153): warning C4164: '_BitScanReverse': intrinsic function not declared ../gllib\stdbit.h(155): warning C4164: '_BitScanReverse64': intrinsic function not declared ../gllib\stdbit.h(161): error C3861: '_BitScanReverse': identifier not found ../gllib\stdbit.h(173): error C3861: '_BitScanReverse64': identifier not found ../gllib\stdbit.h(226): warning C4164: '_BitScanForward': intrinsic function not declared ../gllib\stdbit.h(228): warning C4164: '_BitScanForward64': intrinsic function not declared ../gllib\stdbit.h(234): error C3861: '_BitScanForward': identifier not found ../gllib\stdbit.h(246): error C3861: '_BitScanForward64': identifier not found ../gllib\stdbit.h(328): warning C4164: '__cpuid': intrinsic function not declared ../gllib\stdbit.h(329): warning C4164: '__popcnt': intrinsic function not declared ../gllib\stdbit.h(331): warning C4164: '__popcnt64': intrinsic function not declared ../gllib\stdbit.h(354): error C3861: '__cpuid': identifier not found ../gllib\stdbit.h(363): error C3861: '__popcnt': identifier not found ../gllib\stdbit.h(370): error C3861: '__popcnt': identifier not found ../gllib\stdbit.h(377): error C3861: '__popcnt64': identifier not found make[4]: *** [Makefile:2245: test-stdbit-h-c++.obj] Error 2
The cause: Declaring these intrinsics with a prototype is mandatory in C++ mode and optional in C mode. This patch fixes the errors and warnings. 2024-05-17 Bruno Haible <br...@clisp.org> stdbit-h: Fix compilation error with MSVC in C++ mode. * lib/stdbit.in.h (_BitScanReverse, _BitScanReverse64, _BitScanForward, _BitScanForward64, __cpuid, __popcnt, __popcnt64): Declare with a prototype. * lib/count-leading-zeros.h (_BitScanReverse, _BitScanReverse64): Likewise. * lib/count-trailing-zeros.h (_BitScanForward, _BitScanForward64): Likewise. * lib/count-one-bits.h (__cpuid, __popcnt, __popcnt64): Likewise. diff --git a/lib/count-leading-zeros.h b/lib/count-leading-zeros.h index 545749d6d2..a4b68c2106 100644 --- a/lib/count-leading-zeros.h +++ b/lib/count-leading-zeros.h @@ -45,8 +45,10 @@ extern "C" { # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ return x ? BUILTIN (x) : CHAR_BIT * sizeof x; #elif _MSC_VER +extern unsigned char _BitScanReverse (unsigned long *, unsigned long); # pragma intrinsic (_BitScanReverse) # if defined _M_X64 +extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long); # pragma intrinsic (_BitScanReverse64) # endif # define COUNT_LEADING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ diff --git a/lib/count-one-bits.h b/lib/count-one-bits.h index 8d67f8718a..24bf8cc232 100644 --- a/lib/count-one-bits.h +++ b/lib/count-one-bits.h @@ -85,9 +85,12 @@ count_one_bits_32 (unsigned int x) # include <intrin.h> # else /* Don't pollute the namespace with too many MSVC intrinsics. */ +extern void __cpuid (int[4], int); # pragma intrinsic (__cpuid) +extern unsigned int __popcnt (unsigned int); # pragma intrinsic (__popcnt) # if defined _M_X64 +extern unsigned long long __popcnt64 (unsigned long long); # pragma intrinsic (__popcnt64) # endif # endif diff --git a/lib/count-trailing-zeros.h b/lib/count-trailing-zeros.h index ed1e013114..82de8731ec 100644 --- a/lib/count-trailing-zeros.h +++ b/lib/count-trailing-zeros.h @@ -45,8 +45,10 @@ extern "C" { # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ return x ? BUILTIN (x) : CHAR_BIT * sizeof x; #elif _MSC_VER +extern unsigned char _BitScanForward (unsigned long *, unsigned long); # pragma intrinsic (_BitScanForward) # if defined _M_X64 +extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); # pragma intrinsic (_BitScanForward64) # endif # define COUNT_TRAILING_ZEROS(BUILTIN, MSC_BUILTIN, TYPE) \ diff --git a/lib/stdbit.in.h b/lib/stdbit.in.h index a466a45d77..9f9e60a5d3 100644 --- a/lib/stdbit.in.h +++ b/lib/stdbit.in.h @@ -149,10 +149,16 @@ __gl_stdbit_clzll (unsigned long long int n) return n ? __builtin_clzll (n) : 8 * sizeof n; } #elif defined _MSC_VER + +/* Declare the few MSVC intrinsics that we need. We prefer not to include + <intrin.h> because it would pollute the namespace. */ +extern unsigned char _BitScanReverse (unsigned long *, unsigned long); # pragma intrinsic (_BitScanReverse) # ifdef _M_X64 +extern unsigned char _BitScanReverse64 (unsigned long *, unsigned long long); # pragma intrinsic (_BitScanReverse64) # endif + _GL_STDBIT_INLINE int __gl_stdbit_clzl (unsigned long int n) { @@ -222,10 +228,16 @@ __gl_stdbit_ctzll (unsigned long long int n) return n ? __builtin_ctzll (n) : 8 * sizeof n; } #elif defined _MSC_VER + +/* Declare the few MSVC intrinsics that we need. We prefer not to include + <intrin.h> because it would pollute the namespace. */ +extern unsigned char _BitScanForward (unsigned long *, unsigned long); # pragma intrinsic (_BitScanForward) # ifdef _M_X64 +extern unsigned char _BitScanForward64 (unsigned long *, unsigned long long); # pragma intrinsic (_BitScanForward64) # endif + _GL_STDBIT_INLINE int __gl_stdbit_ctzl (unsigned long int n) { @@ -324,9 +336,14 @@ __gl_stdbit_popcount_wide (unsigned long long int n) # ifdef _MSC_VER # if 1500 <= _MSC_VER && (defined _M_IX86 || defined _M_X64) +/* Declare the few MSVC intrinsics that we need. We prefer not to include + <intrin.h> because it would pollute the namespace. */ +extern void __cpuid (int[4], int); # pragma intrinsic (__cpuid) +extern unsigned int __popcnt (unsigned int); # pragma intrinsic (__popcnt) # ifdef _M_X64 +extern unsigned long long __popcnt64 (unsigned long long); # pragma intrinsic (__popcnt64) # else _GL_STDC_COUNT_ONES_INLINE int