aboutsummaryrefslogtreecommitdiffstats
path: root/contrib/libs/clang14/include/clang/Basic/Visibility.h
blob: 517b3aea6a2ff5bf8290d295c8e5410784c83426 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once

#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wunused-parameter"
#endif

//===--- Visibility.h - Visibility enumeration and utilities ----*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
///
/// \file
/// Defines the clang::Visibility enumeration and various utility
/// functions.
///
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
#define LLVM_CLANG_BASIC_VISIBILITY_H

#include "clang/Basic/Linkage.h"
#include <cassert>
#include <cstdint>

namespace clang {

/// Describes the different kinds of visibility that a declaration
/// may have.
///
/// Visibility determines how a declaration interacts with the dynamic
/// linker.  It may also affect whether the symbol can be found by runtime
/// symbol lookup APIs.
///
/// Visibility is not described in any language standard and
/// (nonetheless) sometimes has odd behavior.  Not all platforms
/// support all visibility kinds.
enum Visibility {
  /// Objects with "hidden" visibility are not seen by the dynamic
  /// linker.
  HiddenVisibility,

  /// Objects with "protected" visibility are seen by the dynamic
  /// linker but always dynamically resolve to an object within this
  /// shared object.
  ProtectedVisibility,

  /// Objects with "default" visibility are seen by the dynamic linker
  /// and act like normal objects.
  DefaultVisibility
};

inline Visibility minVisibility(Visibility L, Visibility R) {
  return L < R ? L : R;
}

class LinkageInfo {
  uint8_t linkage_    : 3;
  uint8_t visibility_ : 2;
  uint8_t explicit_   : 1;

  void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
public:
  LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
                  explicit_(false) {}
  LinkageInfo(Linkage L, Visibility V, bool E)
    : linkage_(L), visibility_(V), explicit_(E) {
    assert(getLinkage() == L && getVisibility() == V &&
           isVisibilityExplicit() == E && "Enum truncated!");
  }

  static LinkageInfo external() {
    return LinkageInfo();
  }
  static LinkageInfo internal() {
    return LinkageInfo(InternalLinkage, DefaultVisibility, false);
  }
  static LinkageInfo uniqueExternal() {
    return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
  }
  static LinkageInfo none() {
    return LinkageInfo(NoLinkage, DefaultVisibility, false);
  }
  static LinkageInfo visible_none() {
    return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false);
  }

  Linkage getLinkage() const { return (Linkage)linkage_; }
  Visibility getVisibility() const { return (Visibility)visibility_; }
  bool isVisibilityExplicit() const { return explicit_; }

  void setLinkage(Linkage L) { linkage_ = L; }

  void mergeLinkage(Linkage L) {
    setLinkage(minLinkage(getLinkage(), L));
  }
  void mergeLinkage(LinkageInfo other) {
    mergeLinkage(other.getLinkage());
  }

  void mergeExternalVisibility(Linkage L) {
    Linkage ThisL = getLinkage();
    if (!isExternallyVisible(L)) {
      if (ThisL == VisibleNoLinkage)
        ThisL = NoLinkage;
      else if (ThisL == ExternalLinkage)
        ThisL = UniqueExternalLinkage;
    }
    setLinkage(ThisL);
  }
  void mergeExternalVisibility(LinkageInfo Other) {
    mergeExternalVisibility(Other.getLinkage());
  }

  /// Merge in the visibility 'newVis'.
  void mergeVisibility(Visibility newVis, bool newExplicit) {
    Visibility oldVis = getVisibility();

    // Never increase visibility.
    if (oldVis < newVis)
      return;

    // If the new visibility is the same as the old and the new
    // visibility isn't explicit, we have nothing to add.
    if (oldVis == newVis && !newExplicit)
      return;

    // Otherwise, we're either decreasing visibility or making our
    // existing visibility explicit.
    setVisibility(newVis, newExplicit);
  }
  void mergeVisibility(LinkageInfo other) {
    mergeVisibility(other.getVisibility(), other.isVisibilityExplicit());
  }

  /// Merge both linkage and visibility.
  void merge(LinkageInfo other) {
    mergeLinkage(other);
    mergeVisibility(other);
  }

  /// Merge linkage and conditionally merge visibility.
  void mergeMaybeWithVisibility(LinkageInfo other, bool withVis) {
    mergeLinkage(other);
    if (withVis) mergeVisibility(other);
  }
};
}

#endif // LLVM_CLANG_BASIC_VISIBILITY_H

#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif