reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    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
//===--- 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