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(Linkage::External)), 65 visibility_(DefaultVisibility), explicit_(false) {} 66 LinkageInfo(Linkage L, Visibility V, bool E) 67 : linkage_(llvm::to_underlying(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(L); } 93 94 void mergeLinkage(Linkage L) { 95 setLinkage(minLinkage(getLinkage(), L)); 96 } 97 void mergeLinkage(LinkageInfo other) { 98 mergeLinkage(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(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(newVis, newExplicit); 131 } 132 void mergeVisibility(LinkageInfo other) { 133 mergeVisibility(other.getVisibility(), 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