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>
|
/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>
|
/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
|
/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- Disable C++14 sized global deallocation functions
|
||||||
/Zc:sizedDealloc Enable C++14 sized global deallocation functions
|
/Zc:sizedDealloc Enable C++14 sized global deallocation functions
|
||||||
/Zc:strictStrings Treat string literals as const
|
/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
|
arguments are treated as if they were passed at the end of the clang-cl command
|
||||||
line.
|
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
|
The /fallback Option
|
||||||
^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
|
|
@ -335,8 +335,10 @@ def _SLASH_Yu : CLJoined<"Yu">,
|
||||||
MetaVarName<"<filename>">;
|
MetaVarName<"<filename>">;
|
||||||
def _SLASH_Y_ : CLFlag<"Y-">,
|
def _SLASH_Y_ : CLFlag<"Y-">,
|
||||||
HelpText<"Disable precompiled headers, overrides /Yc and /Yu">;
|
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">,
|
def _SLASH_Fp : CLJoined<"Fp">,
|
||||||
HelpText<"Set pch filename (with /Yc and /Yu)">, MetaVarName<"<filename>">;
|
HelpText<"Set pch filename (with /Yc and /Yu)">, MetaVarName<"<filename>">;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue