forked from OSchip/llvm-project
clang-cl: Add documentation for /Zc:dllexportInlines-
Differential revision: https://reviews.llvm.org/D54319 llvm-svn: 346639
This commit is contained in:
parent
8443f881bf
commit
96a7860f79
|
@ -2947,6 +2947,8 @@ Execute ``clang-cl /?`` to see a list of supported options:
|
|||
/Yc<filename> Generate a pch file for all code up to and including <filename>
|
||||
/Yu<filename> Load a pch file and use it instead of all code up to and including <filename>
|
||||
/Z7 Enable CodeView debug information in object files
|
||||
/Zc:dllexportInlines- Don't dllexport/import inline member functions of dllexport/import classes
|
||||
/Zc:dllexportInlines dllexport/import inline member functions of dllexport/import classes (default)
|
||||
/Zc:sizedDealloc- Disable C++14 sized global deallocation functions
|
||||
/Zc:sizedDealloc Enable C++14 sized global deallocation functions
|
||||
/Zc:strictStrings Treat string literals as const
|
||||
|
@ -3096,6 +3098,80 @@ driver. Regardless of where they appear in the command line, the ``/clang:``
|
|||
arguments are treated as if they were passed at the end of the clang-cl command
|
||||
line.
|
||||
|
||||
The /Zc:dllexportInlines- Option
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
This causes the class-level `dllexport` and `dllimport` attributes not to be
|
||||
applied to inline member functions, as they otherwise would. For example, in
|
||||
the code below `S::foo()` would normally be defined and exported by the DLL,
|
||||
but when using the ``/Zc:dllexportInlines-`` flag it is not:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
struct __declspec(dllexport) S {
|
||||
void foo() {}
|
||||
}
|
||||
|
||||
This has the benefit that the compiler doesn't need to emit a definition of
|
||||
`S::foo()` in every translation unit where the declaration is included, as it
|
||||
would otherwise do to ensure there's a definition in the DLL even if it's not
|
||||
used there. If the declaration occurs in a header file that's widely used, this
|
||||
can save significant compilation time and output size. It also reduces the
|
||||
number of functions exported by the DLL similarly to what
|
||||
``-fvisibility-inlines-hidden`` does for shared objects on ELF and Mach-O.
|
||||
Since the function declaration comes with an inline definition, users of the
|
||||
library can use that definition directly instead of importing it from the DLL.
|
||||
|
||||
Note that the Microsoft Visual C++ compiler does not support this option, and
|
||||
if code in a DLL is compiled with ``/Zc:dllexportInlines-``, the code using the
|
||||
DLL must be compiled in the same way so that it doesn't attempt to dllimport
|
||||
the inline member functions. The reverse scenario should generally work though:
|
||||
a DLL compiled without this flag (such as a system library compiled with Visual
|
||||
C++) can be referenced from code compiled using the flag, meaning that the
|
||||
referencing code will use the inline definitions instead of importing them from
|
||||
the DLL.
|
||||
|
||||
Also note that like when using ``-fvisibility-inlines-hidden``, the address of
|
||||
`S::foo()` will be different inside and outside the DLL, breaking the C/C++
|
||||
standard requirement that functions have a unique address.
|
||||
|
||||
The flag does not apply to explicit class template instantiation definitions or
|
||||
declarations, as those are typically used to explicitly provide a single
|
||||
definition in a DLL, (dllexported instantiation definition) or to signal that
|
||||
the definition is available elsewhere (dllimport instantiation declaration). It
|
||||
also doesn't apply to inline members with static local variables, to ensure
|
||||
that the same instance of the variable is used inside and outside the DLL.
|
||||
|
||||
Using this flag can cause problems when inline functions that would otherwise
|
||||
be dllexported refer to internal symbols of a DLL. For example:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
void internal();
|
||||
|
||||
struct __declspec(dllimport) S {
|
||||
void foo() { internal(); }
|
||||
}
|
||||
|
||||
Normally, references to `S::foo()` would use the definition in the DLL from
|
||||
which it was exported, and which presumably also has the definition of
|
||||
`internal()`. However, when using ``/Zc:dllexportInlines-``, the inline
|
||||
definition of `S::foo()` is used directly, resulting in a link error since
|
||||
`internal()` is not available. Even worse, if there is an inline definition of
|
||||
`internal()` containing a static local variable, we will now refer to a
|
||||
different instance of that variable than in the DLL:
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
inline int internal() { static int x; return x++; }
|
||||
|
||||
struct __declspec(dllimport) S {
|
||||
int foo() { return internal(); }
|
||||
}
|
||||
|
||||
This could lead to very subtle bugs. Using ``-fvisibility-inlines-hidden`` can
|
||||
lead to the same issue.
|
||||
|
||||
The /fallback Option
|
||||
^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
|
|
@ -335,8 +335,10 @@ def _SLASH_Yu : CLJoined<"Yu">,
|
|||
MetaVarName<"<filename>">;
|
||||
def _SLASH_Y_ : CLFlag<"Y-">,
|
||||
HelpText<"Disable precompiled headers, overrides /Yc and /Yu">;
|
||||
def _SLASH_Zc_dllexportInlines : CLFlag<"Zc:dllexportInlines">;
|
||||
def _SLASH_Zc_dllexportInlines_ : CLFlag<"Zc:dllexportInlines-">;
|
||||
def _SLASH_Zc_dllexportInlines : CLFlag<"Zc:dllexportInlines">,
|
||||
HelpText<"dllexport/import inline member functions of dllexport/import classes (default)">;
|
||||
def _SLASH_Zc_dllexportInlines_ : CLFlag<"Zc:dllexportInlines-">,
|
||||
HelpText<"Don't dllexport/import inline member functions of dllexport/import classes">;
|
||||
def _SLASH_Fp : CLJoined<"Fp">,
|
||||
HelpText<"Set pch filename (with /Yc and /Yu)">, MetaVarName<"<filename>">;
|
||||
|
||||
|
|
Loading…
Reference in New Issue