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




Reply via email to