Skip to content

Commit 8775947

Browse files
authored
[clang][NFC] Refactor clang::Linkage (llvm#71049)
This patch introduces a new enumerator `Invalid = 0`, shifting other enumerators by +1. Contrary to how it might sound, this actually affirms status quo of how this enum is stored in `clang::Decl`: ``` /// If 0, we have not computed the linkage of this declaration. /// Otherwise, it is the linkage + 1. mutable unsigned CacheValidAndLinkage : 3; ``` This patch makes debuggers to not be mistaken about enumerator stored in this bit-field. It also converts `clang::Linkage` to a scoped enum.
1 parent 8a3e4b5 commit 8775947

28 files changed

+169
-130
lines changed

clang-tools-extra/clang-doc/Serialize.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ static bool isPublic(const clang::AccessSpecifier AS,
257257
const clang::Linkage Link) {
258258
if (AS == clang::AccessSpecifier::AS_private)
259259
return false;
260-
else if ((Link == clang::Linkage::ModuleLinkage) ||
261-
(Link == clang::Linkage::ExternalLinkage))
260+
else if ((Link == clang::Linkage::Module) ||
261+
(Link == clang::Linkage::External))
262262
return true;
263263
return false; // otherwise, linkage is some form of internal linkage
264264
}

clang-tools-extra/clangd/Quality.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -274,7 +274,8 @@ computeScope(const NamedDecl *D) {
274274
return SymbolRelevanceSignals::ClassScope;
275275
// ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
276276
// Avoid caching linkage if it may change after enclosing code completion.
277-
if (hasUnstableLinkage(D) || D->getLinkageInternal() < ExternalLinkage)
277+
if (hasUnstableLinkage(D) || llvm::to_underlying(D->getLinkageInternal()) <
278+
llvm::to_underlying(Linkage::External))
278279
return SymbolRelevanceSignals::FileScope;
279280
return SymbolRelevanceSignals::GlobalScope;
280281
}

clang-tools-extra/clangd/SemanticHighlighting.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -617,7 +617,8 @@ std::optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {
617617
if (DC->isTranslationUnit() && D->isTemplateParameter())
618618
return std::nullopt;
619619
// ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
620-
if (D->getLinkageInternal() < ExternalLinkage)
620+
if (llvm::to_underlying(D->getLinkageInternal()) <
621+
llvm::to_underlying(Linkage::External))
621622
return HighlightingModifier::FileScope;
622623
return HighlightingModifier::GlobalScope;
623624
}

clang/include/clang/AST/DeclBase.h

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ class ExternalSourceSymbolAttr;
4949
class FunctionDecl;
5050
class FunctionType;
5151
class IdentifierInfo;
52-
enum Linkage : unsigned char;
52+
enum class Linkage : unsigned char;
5353
class LinkageSpecDecl;
5454
class Module;
5555
class NamedDecl;
@@ -335,7 +335,6 @@ class alignas(8) Decl {
335335
unsigned IdentifierNamespace : 14;
336336

337337
/// If 0, we have not computed the linkage of this declaration.
338-
/// Otherwise, it is the linkage + 1.
339338
mutable unsigned CacheValidAndLinkage : 3;
340339

341340
/// Allocate memory for a deserialized declaration.
@@ -386,7 +385,7 @@ class alignas(8) Decl {
386385
Implicit(false), Used(false), Referenced(false),
387386
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
388387
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
389-
CacheValidAndLinkage(0) {
388+
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
390389
if (StatisticsEnabled) add(DK);
391390
}
392391

@@ -395,7 +394,7 @@ class alignas(8) Decl {
395394
Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
396395
Access(AS_none), FromASTFile(0),
397396
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
398-
CacheValidAndLinkage(0) {
397+
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
399398
if (StatisticsEnabled) add(DK);
400399
}
401400

@@ -405,11 +404,11 @@ class alignas(8) Decl {
405404
void updateOutOfDate(IdentifierInfo &II) const;
406405

407406
Linkage getCachedLinkage() const {
408-
return Linkage(CacheValidAndLinkage - 1);
407+
return static_cast<Linkage>(CacheValidAndLinkage);
409408
}
410409

411410
void setCachedLinkage(Linkage L) const {
412-
CacheValidAndLinkage = L + 1;
411+
CacheValidAndLinkage = llvm::to_underlying(L);
413412
}
414413

415414
bool hasCachedLinkage() const {

clang/include/clang/AST/Type.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2043,7 +2043,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
20432043
TypeBits.Dependence = static_cast<unsigned>(Dependence);
20442044
TypeBits.CacheValid = false;
20452045
TypeBits.CachedLocalOrUnnamed = false;
2046-
TypeBits.CachedLinkage = NoLinkage;
2046+
TypeBits.CachedLinkage = llvm::to_underlying(Linkage::Invalid);
20472047
TypeBits.FromAST = false;
20482048
}
20492049

clang/include/clang/Basic/Linkage.h

Lines changed: 34 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,25 @@
1414
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
1515
#define LLVM_CLANG_BASIC_LINKAGE_H
1616

17+
#include "llvm/Support/ErrorHandling.h"
1718
#include <utility>
1819

1920
namespace clang {
2021

2122
/// Describes the different kinds of linkage
2223
/// (C++ [basic.link], C99 6.2.2) that an entity may have.
23-
enum Linkage : unsigned char {
24+
enum class Linkage : unsigned char {
25+
// Linkage hasn't been computed.
26+
Invalid = 0,
27+
2428
/// No linkage, which means that the entity is unique and
2529
/// can only be referred to from within its scope.
26-
NoLinkage = 0,
30+
None,
2731

2832
/// Internal linkage, which indicates that the entity can
2933
/// be referred to from within the translation unit (but not other
3034
/// translation units).
31-
InternalLinkage,
35+
Internal,
3236

3337
/// External linkage within a unique namespace.
3438
///
@@ -37,21 +41,21 @@ enum Linkage : unsigned char {
3741
/// their names are unique to this translation unit, which is
3842
/// equivalent to having internal linkage from the code-generation
3943
/// point of view.
40-
UniqueExternalLinkage,
44+
UniqueExternal,
4145

4246
/// No linkage according to the standard, but is visible from other
4347
/// translation units because of types defined in a inline function.
44-
VisibleNoLinkage,
48+
VisibleNone,
4549

4650
/// Module linkage, which indicates that the entity can be referred
4751
/// to from other translation units within the same module, and indirectly
4852
/// from arbitrary other translation units through inline functions and
4953
/// templates in the module interface.
50-
ModuleLinkage,
54+
Module,
5155

5256
/// External linkage, which indicates that the entity can
5357
/// be referred to from other translation units.
54-
ExternalLinkage
58+
External
5559
};
5660

5761
/// Describes the different kinds of language linkage
@@ -84,22 +88,33 @@ inline bool isUniqueGVALinkage(GVALinkage L) {
8488
}
8589

8690
inline bool isExternallyVisible(Linkage L) {
87-
return L >= VisibleNoLinkage;
91+
switch (L) {
92+
case Linkage::Invalid:
93+
llvm_unreachable("Linkage hasn't been computed!");
94+
case Linkage::None:
95+
case Linkage::Internal:
96+
case Linkage::UniqueExternal:
97+
return false;
98+
case Linkage::VisibleNone:
99+
case Linkage::Module:
100+
case Linkage::External:
101+
return true;
102+
}
88103
}
89104

90105
inline Linkage getFormalLinkage(Linkage L) {
91106
switch (L) {
92-
case UniqueExternalLinkage:
93-
return ExternalLinkage;
94-
case VisibleNoLinkage:
95-
return NoLinkage;
107+
case Linkage::UniqueExternal:
108+
return Linkage::External;
109+
case Linkage::VisibleNone:
110+
return Linkage::None;
96111
default:
97112
return L;
98113
}
99114
}
100115

101116
inline bool isExternalFormalLinkage(Linkage L) {
102-
return getFormalLinkage(L) == ExternalLinkage;
117+
return getFormalLinkage(L) == Linkage::External;
103118
}
104119

105120
/// Compute the minimum linkage given two linkages.
@@ -111,13 +126,13 @@ inline bool isExternalFormalLinkage(Linkage L) {
111126
/// special cases for when VisibleNoLinkage would lose the visible bit and
112127
/// become NoLinkage.
113128
inline Linkage minLinkage(Linkage L1, Linkage L2) {
114-
if (L2 == VisibleNoLinkage)
129+
if (L2 == Linkage::VisibleNone)
115130
std::swap(L1, L2);
116-
if (L1 == VisibleNoLinkage) {
117-
if (L2 == InternalLinkage)
118-
return NoLinkage;
119-
if (L2 == UniqueExternalLinkage)
120-
return NoLinkage;
131+
if (L1 == Linkage::VisibleNone) {
132+
if (L2 == Linkage::Internal)
133+
return Linkage::None;
134+
if (L2 == Linkage::UniqueExternal)
135+
return Linkage::None;
121136
}
122137
return L1 < L2 ? L1 : L2;
123138
}

clang/include/clang/Basic/Visibility.h

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#define LLVM_CLANG_BASIC_VISIBILITY_H
1616

1717
#include "clang/Basic/Linkage.h"
18+
#include "llvm/ADT/STLForwardCompat.h"
1819
#include <cassert>
1920
#include <cstdint>
2021

@@ -56,10 +57,11 @@ class LinkageInfo {
5657

5758
void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
5859
public:
59-
LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
60-
explicit_(false) {}
60+
LinkageInfo()
61+
: linkage_(llvm::to_underlying(Linkage::External)),
62+
visibility_(DefaultVisibility), explicit_(false) {}
6163
LinkageInfo(Linkage L, Visibility V, bool E)
62-
: linkage_(L), visibility_(V), explicit_(E) {
64+
: linkage_(llvm::to_underlying(L)), visibility_(V), explicit_(E) {
6365
assert(getLinkage() == L && getVisibility() == V &&
6466
isVisibilityExplicit() == E && "Enum truncated!");
6567
}
@@ -68,23 +70,23 @@ class LinkageInfo {
6870
return LinkageInfo();
6971
}
7072
static LinkageInfo internal() {
71-
return LinkageInfo(InternalLinkage, DefaultVisibility, false);
73+
return LinkageInfo(Linkage::Internal, DefaultVisibility, false);
7274
}
7375
static LinkageInfo uniqueExternal() {
74-
return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
76+
return LinkageInfo(Linkage::UniqueExternal, DefaultVisibility, false);
7577
}
7678
static LinkageInfo none() {
77-
return LinkageInfo(NoLinkage, DefaultVisibility, false);
79+
return LinkageInfo(Linkage::None, DefaultVisibility, false);
7880
}
7981
static LinkageInfo visible_none() {
80-
return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false);
82+
return LinkageInfo(Linkage::VisibleNone, DefaultVisibility, false);
8183
}
8284

83-
Linkage getLinkage() const { return (Linkage)linkage_; }
85+
Linkage getLinkage() const { return static_cast<Linkage>(linkage_); }
8486
Visibility getVisibility() const { return (Visibility)visibility_; }
8587
bool isVisibilityExplicit() const { return explicit_; }
8688

87-
void setLinkage(Linkage L) { linkage_ = L; }
89+
void setLinkage(Linkage L) { linkage_ = llvm::to_underlying(L); }
8890

8991
void mergeLinkage(Linkage L) {
9092
setLinkage(minLinkage(getLinkage(), L));
@@ -96,10 +98,10 @@ class LinkageInfo {
9698
void mergeExternalVisibility(Linkage L) {
9799
Linkage ThisL = getLinkage();
98100
if (!isExternallyVisible(L)) {
99-
if (ThisL == VisibleNoLinkage)
100-
ThisL = NoLinkage;
101-
else if (ThisL == ExternalLinkage)
102-
ThisL = UniqueExternalLinkage;
101+
if (ThisL == Linkage::VisibleNone)
102+
ThisL = Linkage::None;
103+
else if (ThisL == Linkage::External)
104+
ThisL = Linkage::UniqueExternal;
103105
}
104106
setLinkage(ThisL);
105107
}

clang/lib/AST/APValue.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1115,7 +1115,7 @@ LinkageInfo LinkageComputer::getLVForValue(const APValue &V,
11151115

11161116
auto MergeLV = [&](LinkageInfo MergeLV) {
11171117
LV.merge(MergeLV);
1118-
return LV.getLinkage() == InternalLinkage;
1118+
return LV.getLinkage() == Linkage::Internal;
11191119
};
11201120
auto Merge = [&](const APValue &V) {
11211121
return MergeLV(getLVForValue(V, computation));

clang/lib/AST/Decl.cpp

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,12 +1204,11 @@ Linkage NamedDecl::getFormalLinkage() const {
12041204
// [basic.namespace.general]/p2
12051205
// A namespace is never attached to a named module and never has a name with
12061206
// module linkage.
1207-
if (isInModulePurview(this) &&
1208-
InternalLinkage == ExternalLinkage &&
1207+
if (isInModulePurview(this) && InternalLinkage == Linkage::External &&
12091208
!isExportedFromModuleInterfaceUnit(
12101209
cast<NamedDecl>(this->getCanonicalDecl())) &&
12111210
!isa<NamespaceDecl>(this))
1212-
InternalLinkage = ModuleLinkage;
1211+
InternalLinkage = Linkage::Module;
12131212

12141213
return clang::getFormalLinkage(InternalLinkage);
12151214
}
@@ -1337,7 +1336,7 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
13371336
// visible, then the lambda is too. We apply the same rules to blocks.
13381337
if (!isExternallyVisible(OwnerLV.getLinkage()))
13391338
return LinkageInfo::none();
1340-
return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
1339+
return LinkageInfo(Linkage::VisibleNone, OwnerLV.getVisibility(),
13411340
OwnerLV.isVisibilityExplicit());
13421341
}
13431342

@@ -1382,7 +1381,7 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
13821381

13831382
if (const VarDecl *Prev = Var->getPreviousDecl()) {
13841383
LinkageInfo PrevLV = getLVForDecl(Prev, computation);
1385-
if (PrevLV.getLinkage())
1384+
if (PrevLV.getLinkage() != Linkage::Invalid)
13861385
LV.setLinkage(PrevLV.getLinkage());
13871386
LV.mergeVisibility(PrevLV);
13881387
}
@@ -1433,14 +1432,14 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
14331432
computation.isValueVisibility()
14341433
? Context.getLangOpts().getValueVisibilityMode()
14351434
: Context.getLangOpts().getTypeVisibilityMode();
1436-
return LinkageInfo(VisibleNoLinkage, globalVisibility,
1435+
return LinkageInfo(Linkage::VisibleNone, globalVisibility,
14371436
/*visibilityExplicit=*/false);
14381437
}
14391438
}
14401439
}
14411440
if (!isExternallyVisible(LV.getLinkage()))
14421441
return LinkageInfo::none();
1443-
return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
1442+
return LinkageInfo(Linkage::VisibleNone, LV.getVisibility(),
14441443
LV.isVisibilityExplicit());
14451444
}
14461445

@@ -1921,7 +1920,20 @@ bool NamedDecl::declarationReplaces(NamedDecl *OldD, bool IsKnownNewer) const {
19211920
}
19221921

19231922
bool NamedDecl::hasLinkage() const {
1924-
return getFormalLinkage() != NoLinkage;
1923+
switch (getFormalLinkage()) {
1924+
case Linkage::Invalid:
1925+
llvm_unreachable("Linkage hasn't been computed!");
1926+
case Linkage::None:
1927+
return false;
1928+
case Linkage::Internal:
1929+
return true;
1930+
case Linkage::UniqueExternal:
1931+
case Linkage::VisibleNone:
1932+
llvm_unreachable("Non-formal linkage is not allowed here!");
1933+
case Linkage::Module:
1934+
case Linkage::External:
1935+
return true;
1936+
}
19251937
}
19261938

19271939
NamedDecl *NamedDecl::getUnderlyingDeclImpl() {

clang/lib/AST/ItaniumMangle.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -708,7 +708,7 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
708708
}
709709

710710
bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) {
711-
if (ND && ND->getFormalLinkage() == InternalLinkage &&
711+
if (ND && ND->getFormalLinkage() == Linkage::Internal &&
712712
!ND->isExternallyVisible() &&
713713
getEffectiveDeclContext(ND)->isFileContext() &&
714714
!ND->isInAnonymousNamespace())
@@ -790,7 +790,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
790790
if (DC->isFunctionOrMethod() && D->hasLinkage())
791791
while (!DC->isFileContext())
792792
DC = getEffectiveParentContext(DC);
793-
if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
793+
if (DC->isTranslationUnit() && D->getFormalLinkage() != Linkage::Internal &&
794794
!CXXNameMangler::shouldHaveAbiTags(*this, VD) &&
795795
!isa<VarTemplateSpecializationDecl>(VD) &&
796796
!VD->getOwningModuleForLinkage())

clang/lib/AST/MicrosoftMangle.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -539,9 +539,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
539539
while (!DC->isNamespace() && !DC->isTranslationUnit())
540540
DC = getEffectiveParentContext(DC);
541541

542-
if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
543-
!isa<VarTemplateSpecializationDecl>(D) &&
544-
D->getIdentifier() != nullptr)
542+
if (DC->isTranslationUnit() && D->getFormalLinkage() == Linkage::Internal &&
543+
!isa<VarTemplateSpecializationDecl>(D) && D->getIdentifier() != nullptr)
545544
return false;
546545
}
547546

0 commit comments

Comments
 (0)