# Annoyance in the Windows SDK headers

Today I ran into the following error:

```Error	1	error C2733: second C linkage of overloaded function '_interlockedbittestandset' not allowed	\$VCDIR\include\intrin.h	944
Error	2	error C2733: second C linkage of overloaded function '_interlockedbittestandreset' not allowed	\$VCDIR\include\intrin.h	945```

Eeek, what’s going on there? Well, my first instinct was to redefine the name to something else to see what breaks. Turns out that doesn’t help a lot depending on where you do that. The problem appears to be that the two intrinsic functions `_interlockedbittestandset` and `_interlockedbittestandreset` are declared both in `WinNT.h` and in `intrin.h`. Actually it’s also “defined” (in quotes because it’s using `#pragma intrinsic`) as an intrinsic in `WinNT.h`, and we won’t get around this easily, because if we change the name of those intrinsics before including `WinNT.h`, the compiler is going to complain that it has no clue what intrinsic it is we want to use:

```Warning	1	warning C4163: '_local_interlockedbittestandset' : not available as an intrinsic function	\$SDKDIR\Include\winnt.h	3124
Warning	2	warning C4163: '_local_interlockedbittestandreset' : not available as an intrinsic function	\$SDKDIR\Include\winnt.h	3125```

Now that is annoying. However, I didn’t want to go for the invasive method of editing one of the SDK headers. Instead I decided to use the powers of the preprocessor to my advantage. The first issue here was to make sure `WinNT.h` gets included first. For most Windows code this is a given with `Windows.h` providing this prerequisite.

Next I had to include `intrin.h` (which contains a convenient `#pragma once`) in the main source file which created the mess in the first place. However, in order to mask out the second declaration of the function I had to rename it. That’s where the preprocessor comes in:

```#if _MSC_VER >= 1400
//  Following 8 lines: workaround for a bug in some older SDKs
#   pragma push_macro("_interlockedbittestandset")
#   pragma push_macro("_interlockedbittestandreset")
#   pragma push_macro("_interlockedbittestandset64")
#   pragma push_macro("_interlockedbittestandreset64")
#   define _interlockedbittestandset _local_interlockedbittestandset
#   define _interlockedbittestandreset _local_interlockedbittestandreset
#   define _interlockedbittestandset64 _local_interlockedbittestandset64
#   define _interlockedbittestandreset64 _local_interlockedbittestandreset64
#   include <intrin.h> // to force the header not to be included elsewhere
#   pragma pop_macro("_interlockedbittestandreset64")
#   pragma pop_macro("_interlockedbittestandset64")
#   pragma pop_macro("_interlockedbittestandreset")
#   pragma pop_macro("_interlockedbittestandset")
#endif```

Since `intrin.h` got introduced with VS 2005, we check for this precondition. Then we save (`push_macro`) the values of the `_interlockedbittestandset` and `_interlockedbittestandreset` defines, if any. Then we rename them and include `intrin.h`, thus creating a definition for functions `_local_interlockedbittestandset` and `_local_interlockedbittestandreset` and then we restore (`pop_macro`) the old values of the macros using those function names, just in case.

This could of course be put into a local header, so as to not repeat this every time we need to use `WinNT.h` and `intrin.h` together in a source file.

Attention: make sure that none of your headers ends up including `intrin.h` on its own before the above fix. This will break the fix as Roan found out and remarked in a comment. Sorry for not being more explicit about this requirement before.

Problem solved

Update: Mozilla came up with a subset of my solution here. It won’t work if you make use of those functions, though. Because in this case later references will get renamed according to the macro expansion rules.

// Oliver

PS: the problem also exists for `_interlockedbittestandset64` and `_interlockedbittestandreset64` (now included in the fix above)
PPS: it should also be possible to throw this last block above the inclusion of `WinNT.h` – haven’t tested that, though.

This entry was posted in C/C++, EN, Programming and tagged , , , , , , , . Bookmark the permalink.

### 3 Responses to Annoyance in the Windows SDK headers

1. Bonial says:

Thanks! It helped me to downgrade one project from vc11 to vc10

2. Roan says:

Extremely after the fact here, but I had trouble with this solution until I realized that i was including before this code. That was importing intrin.h first, and preventing the fix. I think it’s worth an extra note to put this code before any other dependents of intrin.h; Perhaps first thing is best. But nonetheless, many thanks for the fix, worked like a charm!

3. Oliver says: