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