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