1218887Sdim//===--- Visibility.h - Visibility enumeration and utilities ----*- C++ -*-===//
2218887Sdim//
3218887Sdim//                     The LLVM Compiler Infrastructure
4218887Sdim//
5218887Sdim// This file is distributed under the University of Illinois Open Source
6218887Sdim// License. See LICENSE.TXT for details.
7218887Sdim//
8218887Sdim//===----------------------------------------------------------------------===//
9245431Sdim///
10245431Sdim/// \file
11245431Sdim/// \brief Defines the clang::Visibility enumeration and various utility
12245431Sdim/// functions.
13245431Sdim///
14218887Sdim//===----------------------------------------------------------------------===//
15218887Sdim#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
16218887Sdim#define LLVM_CLANG_BASIC_VISIBILITY_H
17218887Sdim
18252723Sdim#include "clang/Basic/Linkage.h"
19252723Sdim
20218887Sdimnamespace clang {
21218887Sdim
22245431Sdim/// \brief Describes the different kinds of visibility that a declaration
23245431Sdim/// may have.
24218887Sdim///
25245431Sdim/// Visibility determines how a declaration interacts with the dynamic
26245431Sdim/// linker.  It may also affect whether the symbol can be found by runtime
27245431Sdim/// symbol lookup APIs.
28245431Sdim///
29218887Sdim/// Visibility is not described in any language standard and
30218887Sdim/// (nonetheless) sometimes has odd behavior.  Not all platforms
31218887Sdim/// support all visibility kinds.
32218887Sdimenum Visibility {
33218887Sdim  /// Objects with "hidden" visibility are not seen by the dynamic
34218887Sdim  /// linker.
35218887Sdim  HiddenVisibility,
36218887Sdim
37218887Sdim  /// Objects with "protected" visibility are seen by the dynamic
38218887Sdim  /// linker but always dynamically resolve to an object within this
39218887Sdim  /// shared object.
40218887Sdim  ProtectedVisibility,
41218887Sdim
42218887Sdim  /// Objects with "default" visibility are seen by the dynamic linker
43218887Sdim  /// and act like normal objects.
44218887Sdim  DefaultVisibility
45218887Sdim};
46218887Sdim
47218887Sdiminline Visibility minVisibility(Visibility L, Visibility R) {
48218887Sdim  return L < R ? L : R;
49218887Sdim}
50218887Sdim
51252723Sdimclass LinkageInfo {
52263509Sdim  uint8_t linkage_    : 3;
53252723Sdim  uint8_t visibility_ : 2;
54252723Sdim  uint8_t explicit_   : 1;
55252723Sdim
56252723Sdim  void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
57252723Sdimpublic:
58252723Sdim  LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
59252723Sdim                  explicit_(false) {}
60252723Sdim  LinkageInfo(Linkage L, Visibility V, bool E)
61252723Sdim    : linkage_(L), visibility_(V), explicit_(E) {
62252723Sdim    assert(getLinkage() == L && getVisibility() == V &&
63252723Sdim           isVisibilityExplicit() == E && "Enum truncated!");
64252723Sdim  }
65252723Sdim
66252723Sdim  static LinkageInfo external() {
67252723Sdim    return LinkageInfo();
68252723Sdim  }
69252723Sdim  static LinkageInfo internal() {
70252723Sdim    return LinkageInfo(InternalLinkage, DefaultVisibility, false);
71252723Sdim  }
72252723Sdim  static LinkageInfo uniqueExternal() {
73252723Sdim    return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
74252723Sdim  }
75252723Sdim  static LinkageInfo none() {
76252723Sdim    return LinkageInfo(NoLinkage, DefaultVisibility, false);
77252723Sdim  }
78252723Sdim
79252723Sdim  Linkage getLinkage() const { return (Linkage)linkage_; }
80252723Sdim  Visibility getVisibility() const { return (Visibility)visibility_; }
81252723Sdim  bool isVisibilityExplicit() const { return explicit_; }
82252723Sdim
83252723Sdim  void setLinkage(Linkage L) { linkage_ = L; }
84252723Sdim
85252723Sdim  void mergeLinkage(Linkage L) {
86252723Sdim    setLinkage(minLinkage(getLinkage(), L));
87252723Sdim  }
88252723Sdim  void mergeLinkage(LinkageInfo other) {
89252723Sdim    mergeLinkage(other.getLinkage());
90252723Sdim  }
91252723Sdim
92263509Sdim  void mergeExternalVisibility(Linkage L) {
93263509Sdim    Linkage ThisL = getLinkage();
94263509Sdim    if (!isExternallyVisible(L)) {
95263509Sdim      if (ThisL == VisibleNoLinkage)
96263509Sdim        ThisL = NoLinkage;
97263509Sdim      else if (ThisL == ExternalLinkage)
98263509Sdim        ThisL = UniqueExternalLinkage;
99263509Sdim    }
100263509Sdim    setLinkage(ThisL);
101263509Sdim  }
102263509Sdim  void mergeExternalVisibility(LinkageInfo Other) {
103263509Sdim    mergeExternalVisibility(Other.getLinkage());
104263509Sdim  }
105263509Sdim
106252723Sdim  /// Merge in the visibility 'newVis'.
107252723Sdim  void mergeVisibility(Visibility newVis, bool newExplicit) {
108252723Sdim    Visibility oldVis = getVisibility();
109252723Sdim
110252723Sdim    // Never increase visibility.
111252723Sdim    if (oldVis < newVis)
112252723Sdim      return;
113252723Sdim
114252723Sdim    // If the new visibility is the same as the old and the new
115252723Sdim    // visibility isn't explicit, we have nothing to add.
116252723Sdim    if (oldVis == newVis && !newExplicit)
117252723Sdim      return;
118252723Sdim
119252723Sdim    // Otherwise, we're either decreasing visibility or making our
120252723Sdim    // existing visibility explicit.
121252723Sdim    setVisibility(newVis, newExplicit);
122252723Sdim  }
123252723Sdim  void mergeVisibility(LinkageInfo other) {
124252723Sdim    mergeVisibility(other.getVisibility(), other.isVisibilityExplicit());
125252723Sdim  }
126252723Sdim
127252723Sdim  /// Merge both linkage and visibility.
128252723Sdim  void merge(LinkageInfo other) {
129252723Sdim    mergeLinkage(other);
130252723Sdim    mergeVisibility(other);
131252723Sdim  }
132252723Sdim
133252723Sdim  /// Merge linkage and conditionally merge visibility.
134252723Sdim  void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) {
135252723Sdim    mergeLinkage(other);
136252723Sdim    if (withVis) mergeVisibility(other);
137252723Sdim  }
138252723Sdim};
139218887Sdim}
140218887Sdim
141218887Sdim#endif // LLVM_CLANG_BASIC_VISIBILITY_H
142