1============== 2LTO Visibility 3============== 4 5*LTO visibility* is a property of an entity that specifies whether it can be 6referenced from outside the current LTO unit. A *linkage unit* is a set of 7translation units linked together into an executable or DSO, and a linkage 8unit's *LTO unit* is the subset of the linkage unit that is linked together 9using link-time optimization; in the case where LTO is not being used, the 10linkage unit's LTO unit is empty. Each linkage unit has only a single LTO unit. 11 12The LTO visibility of a class is used by the compiler to determine which 13classes the whole-program devirtualization (``-fwhole-program-vtables``) and 14control flow integrity (``-fsanitize=cfi-vcall`` and ``-fsanitize=cfi-mfcall``) 15features apply to. These features use whole-program information, so they 16require the entire class hierarchy to be visible in order to work correctly. 17 18If any translation unit in the program uses either of the whole-program 19devirtualization or control flow integrity features, it is effectively an ODR 20violation to define a class with hidden LTO visibility in multiple linkage 21units. A class with public LTO visibility may be defined in multiple linkage 22units, but the tradeoff is that the whole-program devirtualization and 23control flow integrity features can only be applied to classes with hidden LTO 24visibility. A class's LTO visibility is treated as an ODR-relevant property 25of its definition, so it must be consistent between translation units. 26 27In translation units built with LTO, LTO visibility is based on the 28class's symbol visibility as expressed at the source level (i.e. the 29``__attribute__((visibility("...")))`` attribute, or the ``-fvisibility=`` 30flag) or, on the Windows platform, the dllimport and dllexport attributes. When 31targeting non-Windows platforms, classes with a visibility other than hidden 32visibility receive public LTO visibility. When targeting Windows, classes 33with dllimport or dllexport attributes receive public LTO visibility. All 34other classes receive hidden LTO visibility. Classes with internal linkage 35(e.g. classes declared in unnamed namespaces) also receive hidden LTO 36visibility. 37 38A class defined in a translation unit built without LTO receives public 39LTO visibility regardless of its object file visibility, linkage or other 40attributes. 41 42This mechanism will produce the correct result in most cases, but there are 43two cases where it may wrongly infer hidden LTO visibility. 44 451. As a corollary of the above rules, if a linkage unit is produced from a 46 combination of LTO object files and non-LTO object files, any hidden 47 visibility class defined in both a translation unit built with LTO and 48 a translation unit built without LTO must be defined with public LTO 49 visibility in order to avoid an ODR violation. 50 512. Some ABIs provide the ability to define an abstract base class without 52 visibility attributes in multiple linkage units and have virtual calls 53 to derived classes in other linkage units work correctly. One example of 54 this is COM on Windows platforms. If the ABI allows this, any base class 55 used in this way must be defined with public LTO visibility. 56 57Classes that fall into either of these categories can be marked up with the 58``[[clang::lto_visibility_public]]`` attribute. To specifically handle the 59COM case, classes with the ``__declspec(uuid())`` attribute receive public 60LTO visibility. On Windows platforms, clang-cl's ``/MT`` and ``/MTd`` 61flags statically link the program against a prebuilt standard library; 62these flags imply public LTO visibility for every class declared in the 63``std`` and ``stdext`` namespaces. 64 65Example 66======= 67 68The following example shows how LTO visibility works in practice in several 69cases involving two linkage units, ``main`` and ``dso.so``. 70 71.. code-block:: none 72 73 +-----------------------------------------------------------+ +----------------------------------------------------+ 74 | main (clang++ -fvisibility=hidden): | | dso.so (clang++ -fvisibility=hidden): | 75 | | | | 76 | +-----------------------------------------------------+ | | struct __attribute__((visibility("default"))) C { | 77 | | LTO unit (clang++ -fvisibility=hidden -flto): | | | virtual void f(); | 78 | | | | | } | 79 | | struct A { ... }; | | | void C::f() {} | 80 | | struct [[clang::lto_visibility_public]] B { ... }; | | | struct D { | 81 | | struct __attribute__((visibility("default"))) C { | | | virtual void g() = 0; | 82 | | virtual void f(); | | | }; | 83 | | }; | | | struct E : D { | 84 | | struct [[clang::lto_visibility_public]] D { | | | virtual void g() { ... } | 85 | | virtual void g() = 0; | | | }; | 86 | | }; | | | __attribute__((visibility("default"))) D *mkE() { | 87 | | | | | return new E; | 88 | +-----------------------------------------------------+ | | } | 89 | | | | 90 | struct B { ... }; | +----------------------------------------------------+ 91 | | 92 +-----------------------------------------------------------+ 93 94We will now describe the LTO visibility of each of the classes defined in 95these linkage units. 96 97Class ``A`` is not defined outside of ``main``'s LTO unit, so it can have 98hidden LTO visibility. This is inferred from the object file visibility 99specified on the command line. 100 101Class ``B`` is defined in ``main``, both inside and outside its LTO unit. The 102definition outside the LTO unit has public LTO visibility, so the definition 103inside the LTO unit must also have public LTO visibility in order to avoid 104an ODR violation. 105 106Class ``C`` is defined in both ``main`` and ``dso.so`` and therefore must 107have public LTO visibility. This is correctly inferred from the ``visibility`` 108attribute. 109 110Class ``D`` is an abstract base class with a derived class ``E`` defined 111in ``dso.so``. This is an example of the COM scenario; the definition of 112``D`` in ``main``'s LTO unit must have public LTO visibility in order to be 113compatible with the definition of ``D`` in ``dso.so``, which is observable 114by calling the function ``mkE``. 115