1 | //===--- Visibility.h - Visibility enumeration and utilities ----*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | /// |
9 | /// \file |
10 | /// Defines the clang::Visibility enumeration and various utility |
11 | /// functions. |
12 | /// |
13 | //===----------------------------------------------------------------------===// |
14 | #ifndef LLVM_CLANG_BASIC_VISIBILITY_H |
15 | #define LLVM_CLANG_BASIC_VISIBILITY_H |
16 | |
17 | #include "clang/Basic/Linkage.h" |
18 | #include "llvm/ADT/STLForwardCompat.h" |
19 | #include <cassert> |
20 | #include <cstdint> |
21 | |
22 | namespace clang { |
23 | |
24 | /// Describes the different kinds of visibility that a declaration |
25 | /// may have. |
26 | /// |
27 | /// Visibility determines how a declaration interacts with the dynamic |
28 | /// linker. It may also affect whether the symbol can be found by runtime |
29 | /// symbol lookup APIs. |
30 | /// |
31 | /// Visibility is not described in any language standard and |
32 | /// (nonetheless) sometimes has odd behavior. Not all platforms |
33 | /// support all visibility kinds. |
34 | enum Visibility { |
35 | /// Objects with "hidden" visibility are not seen by the dynamic |
36 | /// linker. |
37 | HiddenVisibility, |
38 | |
39 | /// Objects with "protected" visibility are seen by the dynamic |
40 | /// linker but always dynamically resolve to an object within this |
41 | /// shared object. |
42 | ProtectedVisibility, |
43 | |
44 | /// Objects with "default" visibility are seen by the dynamic linker |
45 | /// and act like normal objects. |
46 | DefaultVisibility |
47 | }; |
48 | |
49 | inline Visibility minVisibility(Visibility L, Visibility R) { |
50 | return L < R ? L : R; |
51 | } |
52 | |
53 | class LinkageInfo { |
54 | LLVM_PREFERRED_TYPE(Linkage) |
55 | uint8_t linkage_ : 3; |
56 | LLVM_PREFERRED_TYPE(Visibility) |
57 | uint8_t visibility_ : 2; |
58 | LLVM_PREFERRED_TYPE(bool) |
59 | uint8_t explicit_ : 1; |
60 | |
61 | void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; } |
62 | public: |
63 | LinkageInfo() |
64 | : linkage_(llvm::to_underlying(E: Linkage::External)), |
65 | visibility_(DefaultVisibility), explicit_(false) {} |
66 | LinkageInfo(Linkage L, Visibility V, bool E) |
67 | : linkage_(llvm::to_underlying(E: L)), visibility_(V), explicit_(E) { |
68 | assert(getLinkage() == L && getVisibility() == V && |
69 | isVisibilityExplicit() == E && "Enum truncated!" ); |
70 | } |
71 | |
72 | static LinkageInfo external() { |
73 | return LinkageInfo(); |
74 | } |
75 | static LinkageInfo internal() { |
76 | return LinkageInfo(Linkage::Internal, DefaultVisibility, false); |
77 | } |
78 | static LinkageInfo uniqueExternal() { |
79 | return LinkageInfo(Linkage::UniqueExternal, DefaultVisibility, false); |
80 | } |
81 | static LinkageInfo none() { |
82 | return LinkageInfo(Linkage::None, DefaultVisibility, false); |
83 | } |
84 | static LinkageInfo visible_none() { |
85 | return LinkageInfo(Linkage::VisibleNone, DefaultVisibility, false); |
86 | } |
87 | |
88 | Linkage getLinkage() const { return static_cast<Linkage>(linkage_); } |
89 | Visibility getVisibility() const { return (Visibility)visibility_; } |
90 | bool isVisibilityExplicit() const { return explicit_; } |
91 | |
92 | void setLinkage(Linkage L) { linkage_ = llvm::to_underlying(E: L); } |
93 | |
94 | void mergeLinkage(Linkage L) { |
95 | setLinkage(minLinkage(L1: getLinkage(), L2: L)); |
96 | } |
97 | void mergeLinkage(LinkageInfo other) { |
98 | mergeLinkage(L: other.getLinkage()); |
99 | } |
100 | |
101 | void mergeExternalVisibility(Linkage L) { |
102 | Linkage ThisL = getLinkage(); |
103 | if (!isExternallyVisible(L)) { |
104 | if (ThisL == Linkage::VisibleNone) |
105 | ThisL = Linkage::None; |
106 | else if (ThisL == Linkage::External) |
107 | ThisL = Linkage::UniqueExternal; |
108 | } |
109 | setLinkage(ThisL); |
110 | } |
111 | void mergeExternalVisibility(LinkageInfo Other) { |
112 | mergeExternalVisibility(L: Other.getLinkage()); |
113 | } |
114 | |
115 | /// Merge in the visibility 'newVis'. |
116 | void mergeVisibility(Visibility newVis, bool newExplicit) { |
117 | Visibility oldVis = getVisibility(); |
118 | |
119 | // Never increase visibility. |
120 | if (oldVis < newVis) |
121 | return; |
122 | |
123 | // If the new visibility is the same as the old and the new |
124 | // visibility isn't explicit, we have nothing to add. |
125 | if (oldVis == newVis && !newExplicit) |
126 | return; |
127 | |
128 | // Otherwise, we're either decreasing visibility or making our |
129 | // existing visibility explicit. |
130 | setVisibility(V: newVis, E: newExplicit); |
131 | } |
132 | void mergeVisibility(LinkageInfo other) { |
133 | mergeVisibility(newVis: other.getVisibility(), newExplicit: other.isVisibilityExplicit()); |
134 | } |
135 | |
136 | /// Merge both linkage and visibility. |
137 | void merge(LinkageInfo other) { |
138 | mergeLinkage(other); |
139 | mergeVisibility(other); |
140 | } |
141 | |
142 | /// Merge linkage and conditionally merge visibility. |
143 | void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) { |
144 | mergeLinkage(other); |
145 | if (withVis) mergeVisibility(other); |
146 | } |
147 | }; |
148 | } |
149 | |
150 | #endif // LLVM_CLANG_BASIC_VISIBILITY_H |
151 | |