aboutsummaryrefslogtreecommitdiffstats
path: root/include/clang/Basic/Linkage.h
blob: 696f85b185356b7e0186a43287f77584eeff9186 (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
//===- Linkage.h - Linkage 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 Linkage enumeration and various utility functions.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_BASIC_LINKAGE_H
#define LLVM_CLANG_BASIC_LINKAGE_H

#include <utility>

namespace clang {

/// Describes the different kinds of linkage
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
enum Linkage : unsigned char {
  /// No linkage, which means that the entity is unique and
  /// can only be referred to from within its scope.
  NoLinkage = 0,

  /// Internal linkage, which indicates that the entity can
  /// be referred to from within the translation unit (but not other
  /// translation units).
  InternalLinkage,

  /// External linkage within a unique namespace.
  ///
  /// From the language perspective, these entities have external
  /// linkage. However, since they reside in an anonymous namespace,
  /// their names are unique to this translation unit, which is
  /// equivalent to having internal linkage from the code-generation
  /// point of view.
  UniqueExternalLinkage,

  /// No linkage according to the standard, but is visible from other
  /// translation units because of types defined in a inline function.
  VisibleNoLinkage,

  /// Internal linkage according to the Modules TS, but can be referred
  /// to from other translation units indirectly through inline functions and
  /// templates in the module interface.
  ModuleInternalLinkage,

  /// Module linkage, which indicates that the entity can be referred
  /// to from other translation units within the same module, and indirectly
  /// from arbitrary other translation units through inline functions and
  /// templates in the module interface.
  ModuleLinkage,

  /// External linkage, which indicates that the entity can
  /// be referred to from other translation units.
  ExternalLinkage
};

/// Describes the different kinds of language linkage
/// (C++ [dcl.link]) that an entity may have.
enum LanguageLinkage {
  CLanguageLinkage,
  CXXLanguageLinkage,
  NoLanguageLinkage
};

/// A more specific kind of linkage than enum Linkage.
///
/// This is relevant to CodeGen and AST file reading.
enum GVALinkage {
  GVA_Internal,
  GVA_AvailableExternally,
  GVA_DiscardableODR,
  GVA_StrongExternal,
  GVA_StrongODR
};

inline bool isDiscardableGVALinkage(GVALinkage L) {
  return L <= GVA_DiscardableODR;
}

inline bool isExternallyVisible(Linkage L) {
  return L >= VisibleNoLinkage;
}

inline Linkage getFormalLinkage(Linkage L) {
  switch (L) {
  case UniqueExternalLinkage:
    return ExternalLinkage;
  case VisibleNoLinkage:
    return NoLinkage;
  case ModuleInternalLinkage:
    return InternalLinkage;
  default:
    return L;
  }
}

inline bool isExternalFormalLinkage(Linkage L) {
  return getFormalLinkage(L) == ExternalLinkage;
}

/// Compute the minimum linkage given two linkages.
///
/// The linkage can be interpreted as a pair formed by the formal linkage and
/// a boolean for external visibility. This is just what getFormalLinkage and
/// isExternallyVisible return. We want the minimum of both components. The
/// Linkage enum is defined in an order that makes this simple, we just need
/// special cases for when VisibleNoLinkage would lose the visible bit and
/// become NoLinkage.
inline Linkage minLinkage(Linkage L1, Linkage L2) {
  if (L2 == VisibleNoLinkage)
    std::swap(L1, L2);
  if (L1 == VisibleNoLinkage) {
    if (L2 == InternalLinkage)
      return NoLinkage;
    if (L2 == UniqueExternalLinkage)
      return NoLinkage;
  }
  return L1 < L2 ? L1 : L2;
}

} // namespace clang

#endif // LLVM_CLANG_BASIC_LINKAGE_H