https://gcc.gnu.org/bugzilla/show_bug.cgi?id=87380
--- Comment #12 from mrs at gcc dot gnu.org <mrs at gcc dot gnu.org> --- I changed the test case around, and the linker seems to be able to resolve from a .a now: $ ar -q liblib.a lib.o $ nm -m liblib.a liblib.a(lib.o): 0000000000000020 (__TEXT,__eh_frame) non-external EH_frame1 0000000000000000 (__TEXT,__text) external __Z5matchPi 0000000000000018 (__DATA,__data) weak external __ZN1AIiE6memberE $ nm main.o 0000000000000018 s EH_frame1 U __ZN1AIiE6memberE 0000000000000000 T _main $ ../gcc/xgcc -B../gcc main.cc -L. -llib -o t -lstdc++ so, I think this is now safe to flip with later linkers. Some type of code like: if (darwin_target_linker && (strverscmp (darwin_target_linker, "409.12") >= 0)) I think will do it. We just need to figure out when the bug was fixed. I tested 409.12. This is the linker included with Xcode 10.0, which is the now current Xcode. Jack or Iain might have access to older systems. up:t mrs$ cat lib.cc #define LIB #include "lib.h" template class A<int>; bool match(int* p) { return p == &A<int>::member; } up:t mrs$ cat lib.h template<typename T> struct A { static T member; }; template<typename T> T A<T>::member; bool match(int*); #ifndef LIB extern template class A<int>; #endif up:t mrs$ cat main.cc #include "lib.h" extern char _ZN1AIiE6memberE[3]; int main() { void *vp = _ZN1AIiE6memberE; // if (!match(&A<int>::member)) // throw 1; } is the type of test case I tried. This is _with_ the change TARGET_WEAK_NOT_IN_ARCHIVE_TOC to make it 0. This is required to get the symbol weak.