Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][NFC] Refactor clang::Linkage #71049

Merged
merged 4 commits into from
Nov 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang-tools-extra/clang-doc/Serialize.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -257,8 +257,8 @@ static bool isPublic(const clang::AccessSpecifier AS,
const clang::Linkage Link) {
if (AS == clang::AccessSpecifier::AS_private)
return false;
else if ((Link == clang::Linkage::ModuleLinkage) ||
(Link == clang::Linkage::ExternalLinkage))
else if ((Link == clang::Linkage::Module) ||
(Link == clang::Linkage::External))
return true;
return false; // otherwise, linkage is some form of internal linkage
}
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clangd/Quality.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -274,7 +274,8 @@ computeScope(const NamedDecl *D) {
return SymbolRelevanceSignals::ClassScope;
// ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
// Avoid caching linkage if it may change after enclosing code completion.
if (hasUnstableLinkage(D) || D->getLinkageInternal() < ExternalLinkage)
if (hasUnstableLinkage(D) || llvm::to_underlying(D->getLinkageInternal()) <
llvm::to_underlying(Linkage::External))
return SymbolRelevanceSignals::FileScope;
return SymbolRelevanceSignals::GlobalScope;
}
Expand Down
3 changes: 2 additions & 1 deletion clang-tools-extra/clangd/SemanticHighlighting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,8 @@ std::optional<HighlightingModifier> scopeModifier(const NamedDecl *D) {
if (DC->isTranslationUnit() && D->isTemplateParameter())
return std::nullopt;
// ExternalLinkage threshold could be tweaked, e.g. module-visible as global.
if (D->getLinkageInternal() < ExternalLinkage)
if (llvm::to_underlying(D->getLinkageInternal()) <
llvm::to_underlying(Linkage::External))
return HighlightingModifier::FileScope;
return HighlightingModifier::GlobalScope;
}
Expand Down
11 changes: 5 additions & 6 deletions clang/include/clang/AST/DeclBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ExternalSourceSymbolAttr;
class FunctionDecl;
class FunctionType;
class IdentifierInfo;
enum Linkage : unsigned char;
enum class Linkage : unsigned char;
class LinkageSpecDecl;
class Module;
class NamedDecl;
Expand Down Expand Up @@ -335,7 +335,6 @@ class alignas(8) Decl {
unsigned IdentifierNamespace : 14;

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

/// Allocate memory for a deserialized declaration.
Expand Down Expand Up @@ -386,7 +385,7 @@ class alignas(8) Decl {
Implicit(false), Used(false), Referenced(false),
TopLevelDeclInObjCContainer(false), Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
if (StatisticsEnabled) add(DK);
}

Expand All @@ -395,7 +394,7 @@ class alignas(8) Decl {
Used(false), Referenced(false), TopLevelDeclInObjCContainer(false),
Access(AS_none), FromASTFile(0),
IdentifierNamespace(getIdentifierNamespaceForKind(DK)),
CacheValidAndLinkage(0) {
CacheValidAndLinkage(llvm::to_underlying(Linkage::Invalid)) {
if (StatisticsEnabled) add(DK);
}

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

Linkage getCachedLinkage() const {
return Linkage(CacheValidAndLinkage - 1);
return static_cast<Linkage>(CacheValidAndLinkage);
}

void setCachedLinkage(Linkage L) const {
CacheValidAndLinkage = L + 1;
CacheValidAndLinkage = llvm::to_underlying(L);
}

bool hasCachedLinkage() const {
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1996,7 +1996,7 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
TypeBits.Dependence = static_cast<unsigned>(Dependence);
TypeBits.CacheValid = false;
TypeBits.CachedLocalOrUnnamed = false;
TypeBits.CachedLinkage = NoLinkage;
TypeBits.CachedLinkage = llvm::to_underlying(Linkage::Invalid);
Endilll marked this conversation as resolved.
Show resolved Hide resolved
TypeBits.FromAST = false;
}

Expand Down
53 changes: 34 additions & 19 deletions clang/include/clang/Basic/Linkage.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,25 @@
#ifndef LLVM_CLANG_BASIC_LINKAGE_H
#define LLVM_CLANG_BASIC_LINKAGE_H

#include "llvm/Support/ErrorHandling.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 {
enum class Linkage : unsigned char {
// Linkage hasn't been computed.
Invalid = 0,

/// No linkage, which means that the entity is unique and
/// can only be referred to from within its scope.
NoLinkage = 0,
None,

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

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

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

/// 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,
Module,

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

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

inline bool isExternallyVisible(Linkage L) {
return L >= VisibleNoLinkage;
switch (L) {
case Linkage::Invalid:
llvm_unreachable("Linkage hasn't been computed!");
Endilll marked this conversation as resolved.
Show resolved Hide resolved
case Linkage::None:
case Linkage::Internal:
case Linkage::UniqueExternal:
return false;
case Linkage::VisibleNone:
case Linkage::Module:
case Linkage::External:
return true;
}
}

inline Linkage getFormalLinkage(Linkage L) {
switch (L) {
case UniqueExternalLinkage:
return ExternalLinkage;
case VisibleNoLinkage:
return NoLinkage;
case Linkage::UniqueExternal:
return Linkage::External;
case Linkage::VisibleNone:
return Linkage::None;
default:
return L;
}
}

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

/// Compute the minimum linkage given two linkages.
Expand All @@ -111,13 +126,13 @@ inline bool isExternalFormalLinkage(Linkage L) {
/// special cases for when VisibleNoLinkage would lose the visible bit and
/// become NoLinkage.
inline Linkage minLinkage(Linkage L1, Linkage L2) {
if (L2 == VisibleNoLinkage)
if (L2 == Linkage::VisibleNone)
std::swap(L1, L2);
if (L1 == VisibleNoLinkage) {
if (L2 == InternalLinkage)
return NoLinkage;
if (L2 == UniqueExternalLinkage)
return NoLinkage;
if (L1 == Linkage::VisibleNone) {
if (L2 == Linkage::Internal)
return Linkage::None;
if (L2 == Linkage::UniqueExternal)
return Linkage::None;
}
return L1 < L2 ? L1 : L2;
}
Expand Down
28 changes: 15 additions & 13 deletions clang/include/clang/Basic/Visibility.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#define LLVM_CLANG_BASIC_VISIBILITY_H

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

Expand Down Expand Up @@ -56,10 +57,11 @@ class LinkageInfo {

void setVisibility(Visibility V, bool E) { visibility_ = V; explicit_ = E; }
public:
LinkageInfo() : linkage_(ExternalLinkage), visibility_(DefaultVisibility),
explicit_(false) {}
LinkageInfo()
: linkage_(llvm::to_underlying(Linkage::External)),
visibility_(DefaultVisibility), explicit_(false) {}
LinkageInfo(Linkage L, Visibility V, bool E)
: linkage_(L), visibility_(V), explicit_(E) {
: linkage_(llvm::to_underlying(L)), visibility_(V), explicit_(E) {
assert(getLinkage() == L && getVisibility() == V &&
isVisibilityExplicit() == E && "Enum truncated!");
}
Expand All @@ -68,23 +70,23 @@ class LinkageInfo {
return LinkageInfo();
}
static LinkageInfo internal() {
return LinkageInfo(InternalLinkage, DefaultVisibility, false);
return LinkageInfo(Linkage::Internal, DefaultVisibility, false);
}
static LinkageInfo uniqueExternal() {
return LinkageInfo(UniqueExternalLinkage, DefaultVisibility, false);
return LinkageInfo(Linkage::UniqueExternal, DefaultVisibility, false);
}
static LinkageInfo none() {
return LinkageInfo(NoLinkage, DefaultVisibility, false);
return LinkageInfo(Linkage::None, DefaultVisibility, false);
}
static LinkageInfo visible_none() {
return LinkageInfo(VisibleNoLinkage, DefaultVisibility, false);
return LinkageInfo(Linkage::VisibleNone, DefaultVisibility, false);
}

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

void setLinkage(Linkage L) { linkage_ = L; }
void setLinkage(Linkage L) { linkage_ = llvm::to_underlying(L); }

void mergeLinkage(Linkage L) {
setLinkage(minLinkage(getLinkage(), L));
Expand All @@ -96,10 +98,10 @@ class LinkageInfo {
void mergeExternalVisibility(Linkage L) {
Linkage ThisL = getLinkage();
if (!isExternallyVisible(L)) {
if (ThisL == VisibleNoLinkage)
ThisL = NoLinkage;
else if (ThisL == ExternalLinkage)
ThisL = UniqueExternalLinkage;
if (ThisL == Linkage::VisibleNone)
ThisL = Linkage::None;
else if (ThisL == Linkage::External)
ThisL = Linkage::UniqueExternal;
}
setLinkage(ThisL);
}
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/AST/APValue.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1115,7 +1115,7 @@ LinkageInfo LinkageComputer::getLVForValue(const APValue &V,

auto MergeLV = [&](LinkageInfo MergeLV) {
LV.merge(MergeLV);
return LV.getLinkage() == InternalLinkage;
return LV.getLinkage() == Linkage::Internal;
};
auto Merge = [&](const APValue &V) {
return MergeLV(getLVForValue(V, computation));
Expand Down
28 changes: 20 additions & 8 deletions clang/lib/AST/Decl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1204,12 +1204,11 @@ Linkage NamedDecl::getFormalLinkage() const {
// [basic.namespace.general]/p2
// A namespace is never attached to a named module and never has a name with
// module linkage.
if (isInModulePurview(this) &&
InternalLinkage == ExternalLinkage &&
if (isInModulePurview(this) && InternalLinkage == Linkage::External &&
!isExportedFromModuleInterfaceUnit(
cast<NamedDecl>(this->getCanonicalDecl())) &&
!isa<NamespaceDecl>(this))
InternalLinkage = ModuleLinkage;
InternalLinkage = Linkage::Module;

return clang::getFormalLinkage(InternalLinkage);
}
Expand Down Expand Up @@ -1337,7 +1336,7 @@ LinkageInfo LinkageComputer::getLVForClosure(const DeclContext *DC,
// visible, then the lambda is too. We apply the same rules to blocks.
if (!isExternallyVisible(OwnerLV.getLinkage()))
return LinkageInfo::none();
return LinkageInfo(VisibleNoLinkage, OwnerLV.getVisibility(),
return LinkageInfo(Linkage::VisibleNone, OwnerLV.getVisibility(),
OwnerLV.isVisibilityExplicit());
}

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

if (const VarDecl *Prev = Var->getPreviousDecl()) {
LinkageInfo PrevLV = getLVForDecl(Prev, computation);
if (PrevLV.getLinkage())
if (PrevLV.getLinkage() != Linkage::Invalid)
LV.setLinkage(PrevLV.getLinkage());
LV.mergeVisibility(PrevLV);
}
Expand Down Expand Up @@ -1433,14 +1432,14 @@ LinkageInfo LinkageComputer::getLVForLocalDecl(const NamedDecl *D,
computation.isValueVisibility()
? Context.getLangOpts().getValueVisibilityMode()
: Context.getLangOpts().getTypeVisibilityMode();
return LinkageInfo(VisibleNoLinkage, globalVisibility,
return LinkageInfo(Linkage::VisibleNone, globalVisibility,
/*visibilityExplicit=*/false);
}
}
}
if (!isExternallyVisible(LV.getLinkage()))
return LinkageInfo::none();
return LinkageInfo(VisibleNoLinkage, LV.getVisibility(),
return LinkageInfo(Linkage::VisibleNone, LV.getVisibility(),
LV.isVisibilityExplicit());
}

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

bool NamedDecl::hasLinkage() const {
return getFormalLinkage() != NoLinkage;
switch (getFormalLinkage()) {
case Linkage::Invalid:
llvm_unreachable("Linkage hasn't been computed!");
case Linkage::None:
return false;
case Linkage::Internal:
return true;
case Linkage::UniqueExternal:
case Linkage::VisibleNone:
llvm_unreachable("Non-formal linkage is not allowed here!");
AaronBallman marked this conversation as resolved.
Show resolved Hide resolved
case Linkage::Module:
case Linkage::External:
return true;
}
}

NamedDecl *NamedDecl::getUnderlyingDeclImpl() {
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/AST/ItaniumMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,7 @@ ItaniumMangleContextImpl::getEffectiveDeclContext(const Decl *D) {
}

bool ItaniumMangleContextImpl::isInternalLinkageDecl(const NamedDecl *ND) {
if (ND && ND->getFormalLinkage() == InternalLinkage &&
if (ND && ND->getFormalLinkage() == Linkage::Internal &&
!ND->isExternallyVisible() &&
getEffectiveDeclContext(ND)->isFileContext() &&
!ND->isInAnonymousNamespace())
Expand Down Expand Up @@ -790,7 +790,7 @@ bool ItaniumMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
if (DC->isFunctionOrMethod() && D->hasLinkage())
while (!DC->isFileContext())
DC = getEffectiveParentContext(DC);
if (DC->isTranslationUnit() && D->getFormalLinkage() != InternalLinkage &&
if (DC->isTranslationUnit() && D->getFormalLinkage() != Linkage::Internal &&
!CXXNameMangler::shouldHaveAbiTags(*this, VD) &&
!isa<VarTemplateSpecializationDecl>(VD) &&
!VD->getOwningModuleForLinkage())
Expand Down
5 changes: 2 additions & 3 deletions clang/lib/AST/MicrosoftMangle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -539,9 +539,8 @@ bool MicrosoftMangleContextImpl::shouldMangleCXXName(const NamedDecl *D) {
while (!DC->isNamespace() && !DC->isTranslationUnit())
DC = getEffectiveParentContext(DC);

if (DC->isTranslationUnit() && D->getFormalLinkage() == InternalLinkage &&
!isa<VarTemplateSpecializationDecl>(D) &&
D->getIdentifier() != nullptr)
if (DC->isTranslationUnit() && D->getFormalLinkage() == Linkage::Internal &&
!isa<VarTemplateSpecializationDecl>(D) && D->getIdentifier() != nullptr)
return false;
}

Expand Down