libcxx and weak attribute

Hi Everyone (particularly Howard and Reid (rnk) and any windows experts out there)

I’m trying to hack some more support for libcxx on Windows (for any compilers) but cl.exe/visual studio in this case:

One task is I’m trying to find out what the Windows equivalent is to the gcc/clang weak attribute.
(would address sanitizer or other llvm related code bases benefit from any solution that can be found here?).

Take code like this, from libcxx:

attribute((weak, visibility(“default”))) void * operator new(std::size_t size) { … }

With cl.exe/Visual Studio, this fails to compile.

One idea, I’m wondering, is if the above line could be changed to this:

_LIBCPP_WEAK _LIBCPP_FUNC_VIS void * operator new(std::size_t size) {…}

  • Where _LIBCPP_WEAK could/would be added to libcxx’s __config like so (i.e. new code):
    #if defined(_WIN32)

define _LIBCPP_WEAK __declspec(noinline) __inline

#else

define _LIBCPP_WEAK attribute((weak))

#endif

  • And _LIBCPP_FUNC_VIS would be used instead of the existing default visibility attribute.
    __config already defines this as so:

// snipped from existing __config:
#ifdef _WIN32
// only really useful for a DLL
#ifdef _LIBCPP_DLL // this should be a compiler builtin define ideally…

ifdef cxx_EXPORTS

define _LIBCPP_HIDDEN

define _LIBCPP_FUNC_VIS __declspec(dllexport)

define _LIBCPP_TYPE_VIS __declspec(dllexport)

else

define _LIBCPP_HIDDEN

define _LIBCPP_FUNC_VIS __declspec(dllimport)

define _LIBCPP_TYPE_VIS __declspec(dllimport)

endif

#else

define _LIBCPP_HIDDEN

define _LIBCPP_FUNC_VIS

define _LIBCPP_TYPE_VIS

#endif
//… snip
#ifndef _LIBCPP_FUNC_VIS
#define _LIBCPP_FUNC_VIS attribute ((visibility(“default”)))
#endif

The thinking is that:

_LIBCPP_WEAK _LIBCPP_FUNC_VIS void * operator new(std::size_t size) {…}

would expand out from the above to this for apple/linux/etc (i.e. remain what it already is on those platforms):
attribute((weak)) attribute ((visibility(“default”))) void * operator new(std::size_t size) {…}

But on Windows, it would expand to this:
__declspec(dllexport) /* or nothing */ __declspec(noinline) void * operator new(std::size_t size) {…}

I got the idea from here (see workarounds):
http://connect.microsoft.com/VisualStudio/feedback/details/505028/add-weak-function-references-for-visual-c-c

Alternatively, would this suggestion I found on SO both be correct and legitimate to use?:
http://stackoverflow.com/questions/2290587/gcc-style-weak-linking-in-visual-studio
and if so what would the reformulated macros look like using it? (_Pragma?)

Generally the whole inline/visibility situation for libcxx on Windows needs some examination and is subtle to get right it seems.

It might be in this example macros aren’t the right implementation choice, a straight #if _MSC_VER #else might be better?

But hopefully I’ve explained the problem I’m trying to solve however it’s done. So what to do here for cl.exe?

While on the topic, it’d be nice to find the correct solution to this problem too:

2>c:/libcxx/include\utility(597): warning C4141: ‘inline’ : used more than once

It’s a warning but it would be nice to find the correct formulation of macro’s that will solve that warning too.
When libcxx is compiled with cl.exe this warning appears 1300 times for various offending lines

The attached patch demonstrates the first proposal, using libcxx’s new.cpp as an example. It at least removes some of the compile errors coming from cl.exe, but it may still not be right even if it compiles.

Suggestions please. Thanks for your help.

ENOPATCH?

Hi Everyone (particularly Howard and Reid (rnk) and any windows experts
out there)

I'm trying to hack some more support for libcxx on Windows (for any
compilers) but cl.exe/visual studio in this case:

One task is I'm trying to find out what the Windows equivalent is to the
gcc/clang weak attribute.
(would address sanitizer or other llvm related code bases benefit from any
solution that can be found here?).

Take code like this, from libcxx:

__attribute__((__weak__, __visibility__("default"))) void * operator
new(std::size_t size) { ... }

Maybe Rui knows more about how Microsoft does this. He had to implement
some weak symbol fallback stuff in lld to link the Visual C++ runtime. I
wonder if operator new was the feature that required this functionality.

While on the topic, it'd be nice to find the correct solution to this
problem too:

2>c:/libcxx/include\utility(597): warning C4141: 'inline' : used more than
once
It's a warning but it would be nice to find the correct formulation of
macro's that will solve that warning too.
When libcxx is compiled with cl.exe this warning appears 1300 times for
various offending lines

The attached patch demonstrates the first proposal, using libcxx's new.cpp
as an example. It at least removes some of the compile errors coming from
cl.exe, but it may still not be right even if it compiles.

Timur had to solve this for asan, and he did this in
compiler-rt/lib/sanitizer_common/sanitizer_internal_defs.h:

#if defined(_MSC_VER)
# define ALWAYS_INLINE __forceinline
...
#else // _MSC_VER
# define ALWAYS_INLINE inline __attribute__((always_inline))
...
#endif

libc++ should do the same. gcc requires you to use inline in combination
with always_inline, while MSVC thinks that inline is redundant with
__forceinline.

They don't do anything special because the linker can resolve functions even if they aren't decorated with dllimport. So if a local definition is not present the linker picks up the exported one from the runtime DLL. The last patch wrt visibility already takes care of not decorating them with dllimport (but dllexport when building). It should be sufficient here to just drop the weak attribute for MSVC.

With COFF's weak externals it's possible to provide weak variants but this requires linking in the object files directly, usually by merging them into the import library. MSVC doesn't provide any means to produce such symbols so it's irrelevant there. Clang with D1309 can and this is what I've done locally in libc++abi (though I'm not sure if it's worth the ugly CMake contortions...).

-Nico

I don't know how this is supposed to work on Windows. But on OS X / iOS, the "new/delete" prototypes should not be decorated with weak attributes. Only their definitions should. That ensures that client supplied replacements dominate at link time.

Howard