10b57cec5SDimitry Andric //===- Linkage.h - Linkage enumeration and utilities ------------*- C++ -*-===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric /// \file
100b57cec5SDimitry Andric /// Defines the Linkage enumeration and various utility functions.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #ifndef LLVM_CLANG_BASIC_LINKAGE_H
150b57cec5SDimitry Andric #define LLVM_CLANG_BASIC_LINKAGE_H
160b57cec5SDimitry Andric 
175f757f3fSDimitry Andric #include "llvm/Support/ErrorHandling.h"
180b57cec5SDimitry Andric #include <utility>
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric namespace clang {
210b57cec5SDimitry Andric 
220b57cec5SDimitry Andric /// Describes the different kinds of linkage
230b57cec5SDimitry Andric /// (C++ [basic.link], C99 6.2.2) that an entity may have.
245f757f3fSDimitry Andric enum class Linkage : unsigned char {
255f757f3fSDimitry Andric   // Linkage hasn't been computed.
265f757f3fSDimitry Andric   Invalid = 0,
275f757f3fSDimitry Andric 
280b57cec5SDimitry Andric   /// No linkage, which means that the entity is unique and
290b57cec5SDimitry Andric   /// can only be referred to from within its scope.
305f757f3fSDimitry Andric   None,
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric   /// Internal linkage, which indicates that the entity can
330b57cec5SDimitry Andric   /// be referred to from within the translation unit (but not other
340b57cec5SDimitry Andric   /// translation units).
355f757f3fSDimitry Andric   Internal,
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   /// External linkage within a unique namespace.
380b57cec5SDimitry Andric   ///
390b57cec5SDimitry Andric   /// From the language perspective, these entities have external
400b57cec5SDimitry Andric   /// linkage. However, since they reside in an anonymous namespace,
410b57cec5SDimitry Andric   /// their names are unique to this translation unit, which is
420b57cec5SDimitry Andric   /// equivalent to having internal linkage from the code-generation
430b57cec5SDimitry Andric   /// point of view.
445f757f3fSDimitry Andric   UniqueExternal,
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   /// No linkage according to the standard, but is visible from other
470b57cec5SDimitry Andric   /// translation units because of types defined in a inline function.
485f757f3fSDimitry Andric   VisibleNone,
490b57cec5SDimitry Andric 
500b57cec5SDimitry Andric   /// Module linkage, which indicates that the entity can be referred
510b57cec5SDimitry Andric   /// to from other translation units within the same module, and indirectly
520b57cec5SDimitry Andric   /// from arbitrary other translation units through inline functions and
530b57cec5SDimitry Andric   /// templates in the module interface.
545f757f3fSDimitry Andric   Module,
550b57cec5SDimitry Andric 
560b57cec5SDimitry Andric   /// External linkage, which indicates that the entity can
570b57cec5SDimitry Andric   /// be referred to from other translation units.
585f757f3fSDimitry Andric   External
590b57cec5SDimitry Andric };
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric /// Describes the different kinds of language linkage
620b57cec5SDimitry Andric /// (C++ [dcl.link]) that an entity may have.
630b57cec5SDimitry Andric enum LanguageLinkage {
640b57cec5SDimitry Andric   CLanguageLinkage,
650b57cec5SDimitry Andric   CXXLanguageLinkage,
660b57cec5SDimitry Andric   NoLanguageLinkage
670b57cec5SDimitry Andric };
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric /// A more specific kind of linkage than enum Linkage.
700b57cec5SDimitry Andric ///
710b57cec5SDimitry Andric /// This is relevant to CodeGen and AST file reading.
720b57cec5SDimitry Andric enum GVALinkage {
730b57cec5SDimitry Andric   GVA_Internal,
740b57cec5SDimitry Andric   GVA_AvailableExternally,
750b57cec5SDimitry Andric   GVA_DiscardableODR,
760b57cec5SDimitry Andric   GVA_StrongExternal,
770b57cec5SDimitry Andric   GVA_StrongODR
780b57cec5SDimitry Andric };
790b57cec5SDimitry Andric 
isDiscardableGVALinkage(GVALinkage L)800b57cec5SDimitry Andric inline bool isDiscardableGVALinkage(GVALinkage L) {
810b57cec5SDimitry Andric   return L <= GVA_DiscardableODR;
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
84a7dea167SDimitry Andric /// Do we know that this will be the only definition of this symbol (excluding
85a7dea167SDimitry Andric /// inlining-only definitions)?
isUniqueGVALinkage(GVALinkage L)86a7dea167SDimitry Andric inline bool isUniqueGVALinkage(GVALinkage L) {
87a7dea167SDimitry Andric   return L == GVA_Internal || L == GVA_StrongExternal;
88a7dea167SDimitry Andric }
89a7dea167SDimitry Andric 
isExternallyVisible(Linkage L)900b57cec5SDimitry Andric inline bool isExternallyVisible(Linkage L) {
915f757f3fSDimitry Andric   switch (L) {
925f757f3fSDimitry Andric   case Linkage::Invalid:
935f757f3fSDimitry Andric     llvm_unreachable("Linkage hasn't been computed!");
945f757f3fSDimitry Andric   case Linkage::None:
955f757f3fSDimitry Andric   case Linkage::Internal:
965f757f3fSDimitry Andric   case Linkage::UniqueExternal:
975f757f3fSDimitry Andric     return false;
985f757f3fSDimitry Andric   case Linkage::VisibleNone:
995f757f3fSDimitry Andric   case Linkage::Module:
1005f757f3fSDimitry Andric   case Linkage::External:
1015f757f3fSDimitry Andric     return true;
1025f757f3fSDimitry Andric   }
1035f757f3fSDimitry Andric   llvm_unreachable("Unhandled Linkage enum");
1040b57cec5SDimitry Andric }
1050b57cec5SDimitry Andric 
getFormalLinkage(Linkage L)1060b57cec5SDimitry Andric inline Linkage getFormalLinkage(Linkage L) {
1070b57cec5SDimitry Andric   switch (L) {
1085f757f3fSDimitry Andric   case Linkage::UniqueExternal:
1095f757f3fSDimitry Andric     return Linkage::External;
1105f757f3fSDimitry Andric   case Linkage::VisibleNone:
1115f757f3fSDimitry Andric     return Linkage::None;
1120b57cec5SDimitry Andric   default:
1130b57cec5SDimitry Andric     return L;
1140b57cec5SDimitry Andric   }
1150b57cec5SDimitry Andric }
1160b57cec5SDimitry Andric 
isExternalFormalLinkage(Linkage L)1170b57cec5SDimitry Andric inline bool isExternalFormalLinkage(Linkage L) {
1185f757f3fSDimitry Andric   return getFormalLinkage(L) == Linkage::External;
1190b57cec5SDimitry Andric }
1200b57cec5SDimitry Andric 
1210b57cec5SDimitry Andric /// Compute the minimum linkage given two linkages.
1220b57cec5SDimitry Andric ///
1230b57cec5SDimitry Andric /// The linkage can be interpreted as a pair formed by the formal linkage and
1240b57cec5SDimitry Andric /// a boolean for external visibility. This is just what getFormalLinkage and
1250b57cec5SDimitry Andric /// isExternallyVisible return. We want the minimum of both components. The
1260b57cec5SDimitry Andric /// Linkage enum is defined in an order that makes this simple, we just need
1270b57cec5SDimitry Andric /// special cases for when VisibleNoLinkage would lose the visible bit and
1280b57cec5SDimitry Andric /// become NoLinkage.
minLinkage(Linkage L1,Linkage L2)1290b57cec5SDimitry Andric inline Linkage minLinkage(Linkage L1, Linkage L2) {
1305f757f3fSDimitry Andric   if (L2 == Linkage::VisibleNone)
1310b57cec5SDimitry Andric     std::swap(L1, L2);
1325f757f3fSDimitry Andric   if (L1 == Linkage::VisibleNone) {
1335f757f3fSDimitry Andric     if (L2 == Linkage::Internal)
1345f757f3fSDimitry Andric       return Linkage::None;
1355f757f3fSDimitry Andric     if (L2 == Linkage::UniqueExternal)
1365f757f3fSDimitry Andric       return Linkage::None;
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric   return L1 < L2 ? L1 : L2;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
1410b57cec5SDimitry Andric } // namespace clang
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric #endif // LLVM_CLANG_BASIC_LINKAGE_H
144