clang-cl: building OpenSSL in 32 bit mode.

Hello,

As part of our efforts to replace MSVC with Clang on Windows we have
started to rebuild our dependencies with clang-cl and lld-link.

Most dependencies just needs very small adjustments to work, but one
of our dependencies are OpenSSL. It required some editing of the build
system to call clang-cl instead of clang. At the start I thought it
worked just fine because it came all the way to the linking phase -
but that then failed because the linker was running in 32 bit mode and
it said that clang-cl had built 64 bit binaries. Turns out that I had
to make more adjustments to forward the -m32 flag to clang-cl to get
it to build. This unfortunately totally broke the build:

clang-cl -m32 /Fotmp32dll\uplink.obj -Iinc32 -Itmp32dll /MD /Ox /O2
/Ob2 -DOPENSSL_THREADS -DDSO_WIN32 -DW
INVER=0x0601 -D_WIN32_WINNT=0x0601 -W3 -Gs0 -GF -Gy -nologo
-DOPENSSL_SYSNAME_WIN32 -DWIN32_LEAN_AND_MEAN -DL_ENDIAN
-D_CRT_SECURE_NO_DEPRECATE -D_WINSOCK_DEPRECATED_NO_WARNINGS
-DOPENSSL_BN_ASM_PART
_WORDS -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_GF2m
-DRC4_ASM -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DRMD160_ASM
-DAES_ASM -DVPAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DOPENSSL
_USE_APPLINK -I. -DOPENSSL_NO_RC5 -DOPENSSL_NO_MD2 -DOPENSSL_NO_SSL2
-DOPENSSL_NO_KRB5 -DOPENSSL_NO_JPAKE -DOPENSSL_NO_WEAK_SSL_CIPHERS
-DOPENSSL_NO_STATIC_ENGINE /Zi /Fdtmp32dll/lib -D_WINDLL -c ms\
uplink.c
ms\uplink.c(106,1): error: asm operand has incomplete type 'void *[]'
LAZY(1) LAZY(2) LAZY(3) LAZY(4) LAZY(5)
^
ms\uplink.c(97,29): note: expanded from macro 'LAZY'
_asm push OFFSET OPENSSL_UplinkTable \
^
ms\uplink.c(106,1): error: asm operand has incomplete type 'void *[]'
ms\uplink.c(100,22): note: expanded from macro 'LAZY'
_asm jmp OPENSSL_UplinkTable+4*i }
^
ms\uplink.c(106,1): error: use of undeclared label 'OPENSSL_UplinkTable'
ms\uplink.c(100,22): note: expanded from macro 'LAZY'
_asm jmp OPENSSL_UplinkTable+4*i }
^

Dropping the -m32 flag makes this build without a problem. I had to
dig around in the source and it seems like the _asm flags are only
evaluated when we are building 32 bit which explains why it worked
with 64bit, relevant code here:

https://github.com/openssl/openssl/blob/OpenSSL_1_0_2-stable/ms/uplink.c#L95

Is this expected? Just a missing feature of Clang?

Thanks,
Tobias

I bet clang doesn’t like that the LAZY() macros are referring to OPENSSL_UplinkTable before it’s been defined. To test this theory: does it work if you move the LAZY()s after the table? (I guess you’d need to forward-declare the lazy##i functions then too.)