dllexport is not actually a global-level attribute. At the object file
level, it is in fact a module-level attribute and is represented with an
/export flag in the directive section. Trying to shoehorn it into being a
global-level attribute creates unnecessary complexity and a burden on the
rest of the compiler and invites bugs.
Independent of whether it is a global- or module-level attribute, it makes
sense to split dllimport from dllexport, as they are somewhat orthogonal. The
meaning of dllexport is similar to ELF symbol visibility, while the meaning
of dllimport is closer to preemptability (see also D20217). With this,
dllimport can potentially receive a meaning in other object formats without
being in the confusing situation where dllexport only has meaning for COFF
and dllimport also has meaning elsewhere.
This patch does three things:
- Moves the linker options from a module flag to top-level module metadata. Storing it as a module flag only makes it harder to manipulate the linker options.
- Causes clang to add an /export flag to the linker options metadata if it is emitting a definition that will be dllexported.
- Removes the dllexport storage class and stores dllimport as a boolean.
Test cases to be updated.
Fixes PR32334.