forked from OSchip/llvm-project
Clean up some mistreatment of enumerations.
llvm-svn: 313953
This commit is contained in:
parent
6c2dbc69a7
commit
fbe7b46657
|
@ -349,7 +349,14 @@ public:
|
|||
|
||||
/// Kinds of explicit visibility.
|
||||
enum ExplicitVisibilityKind {
|
||||
/// Do an LV computation for, ultimately, a type.
|
||||
/// Visibility may be restricted by type visibility settings and
|
||||
/// the visibility of template arguments.
|
||||
VisibilityForType,
|
||||
|
||||
/// Do an LV computation for, ultimately, a non-type declaration.
|
||||
/// Visibility may be restricted by value visibility settings and
|
||||
/// the visibility of template arguments.
|
||||
VisibilityForValue
|
||||
};
|
||||
|
||||
|
|
|
@ -103,28 +103,22 @@ TranslationUnitDecl::TranslationUnitDecl(ASTContext &ctx)
|
|||
/// Does this computation kind permit us to consider additional
|
||||
/// visibility settings from attributes and the like?
|
||||
static bool hasExplicitVisibilityAlready(LVComputationKind computation) {
|
||||
return ((unsigned(computation) & IgnoreExplicitVisibilityBit) != 0);
|
||||
return computation.IgnoreExplicitVisibility;
|
||||
}
|
||||
|
||||
/// Given an LVComputationKind, return one of the same type/value sort
|
||||
/// that records that it already has explicit visibility.
|
||||
static LVComputationKind
|
||||
withExplicitVisibilityAlready(LVComputationKind oldKind) {
|
||||
LVComputationKind newKind =
|
||||
static_cast<LVComputationKind>(unsigned(oldKind) |
|
||||
IgnoreExplicitVisibilityBit);
|
||||
assert(oldKind != LVForType || newKind == LVForExplicitType);
|
||||
assert(oldKind != LVForValue || newKind == LVForExplicitValue);
|
||||
assert(oldKind != LVForExplicitType || newKind == LVForExplicitType);
|
||||
assert(oldKind != LVForExplicitValue || newKind == LVForExplicitValue);
|
||||
return newKind;
|
||||
withExplicitVisibilityAlready(LVComputationKind Kind) {
|
||||
Kind.IgnoreExplicitVisibility = true;
|
||||
return Kind;
|
||||
}
|
||||
|
||||
static Optional<Visibility> getExplicitVisibility(const NamedDecl *D,
|
||||
LVComputationKind kind) {
|
||||
assert(!hasExplicitVisibilityAlready(kind) &&
|
||||
assert(!kind.IgnoreExplicitVisibility &&
|
||||
"asking for explicit visibility when we shouldn't be");
|
||||
return D->getExplicitVisibility((NamedDecl::ExplicitVisibilityKind) kind);
|
||||
return D->getExplicitVisibility(kind.getExplicitVisibilityKind());
|
||||
}
|
||||
|
||||
/// Is the given declaration a "type" or a "value" for the purposes of
|
||||
|
@ -190,7 +184,7 @@ static Optional<Visibility> getVisibilityOf(const NamedDecl *D,
|
|||
|
||||
LinkageInfo LinkageComputer::getLVForType(const Type &T,
|
||||
LVComputationKind computation) {
|
||||
if (computation == LVForLinkageOnly)
|
||||
if (computation.IgnoreAllVisibility)
|
||||
return LinkageInfo(T.getLinkage(), DefaultVisibility, true);
|
||||
return getTypeLinkageAndVisibility(&T);
|
||||
}
|
||||
|
@ -359,21 +353,11 @@ void LinkageComputer::mergeTemplateLV(
|
|||
/// that would match the given rules?
|
||||
static bool hasDirectVisibilityAttribute(const NamedDecl *D,
|
||||
LVComputationKind computation) {
|
||||
switch (computation) {
|
||||
case LVForType:
|
||||
case LVForExplicitType:
|
||||
if (D->hasAttr<TypeVisibilityAttr>())
|
||||
return true;
|
||||
// fallthrough
|
||||
case LVForValue:
|
||||
case LVForExplicitValue:
|
||||
if (D->hasAttr<VisibilityAttr>())
|
||||
return true;
|
||||
if (computation.IgnoreAllVisibility)
|
||||
return false;
|
||||
case LVForLinkageOnly:
|
||||
return false;
|
||||
}
|
||||
llvm_unreachable("bad visibility computation kind");
|
||||
|
||||
return (computation.isTypeVisibility() && D->hasAttr<TypeVisibilityAttr>()) ||
|
||||
D->hasAttr<VisibilityAttr>();
|
||||
}
|
||||
|
||||
/// Should we consider visibility associated with the template
|
||||
|
@ -675,13 +659,10 @@ LinkageComputer::getLVForNamespaceScopeDecl(const NamedDecl *D,
|
|||
// Add in global settings if the above didn't give us direct visibility.
|
||||
if (!LV.isVisibilityExplicit()) {
|
||||
// Use global type/value visibility as appropriate.
|
||||
Visibility globalVisibility;
|
||||
if (computation == LVForValue) {
|
||||
globalVisibility = Context.getLangOpts().getValueVisibilityMode();
|
||||
} else {
|
||||
assert(computation == LVForType);
|
||||
globalVisibility = Context.getLangOpts().getTypeVisibilityMode();
|
||||
}
|
||||
Visibility globalVisibility =
|
||||
computation.isValueVisibility()
|
||||
? Context.getLangOpts().getValueVisibilityMode()
|
||||
: Context.getLangOpts().getTypeVisibilityMode();
|
||||
LV.mergeVisibility(globalVisibility, /*explicit*/ false);
|
||||
|
||||
// If we're paying attention to global visibility, apply
|
||||
|
@ -1011,8 +992,9 @@ bool NamedDecl::isLinkageValid() const {
|
|||
if (!hasCachedLinkage())
|
||||
return true;
|
||||
|
||||
Linkage L =
|
||||
LinkageComputer{}.computeLVForDecl(this, LVForLinkageOnly).getLinkage();
|
||||
Linkage L = LinkageComputer{}
|
||||
.computeLVForDecl(this, LVComputationKind::forLinkageOnly())
|
||||
.getLinkage();
|
||||
return L == getCachedLinkage();
|
||||
}
|
||||
|
||||
|
@ -1032,7 +1014,9 @@ ObjCStringFormatFamily NamedDecl::getObjCFStringFormattingFamily() const {
|
|||
Linkage NamedDecl::getLinkageInternal() const {
|
||||
// We don't care about visibility here, so ask for the cheapest
|
||||
// possible visibility analysis.
|
||||
return LinkageComputer{}.getLVForDecl(this, LVForLinkageOnly).getLinkage();
|
||||
return LinkageComputer{}
|
||||
.getLVForDecl(this, LVComputationKind::forLinkageOnly())
|
||||
.getLinkage();
|
||||
}
|
||||
|
||||
LinkageInfo NamedDecl::getLinkageAndVisibility() const {
|
||||
|
@ -1357,7 +1341,7 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
|
|||
if (D->hasAttr<InternalLinkageAttr>())
|
||||
return getInternalLinkageFor(D);
|
||||
|
||||
if (computation == LVForLinkageOnly && D->hasCachedLinkage())
|
||||
if (computation.IgnoreAllVisibility && D->hasCachedLinkage())
|
||||
return LinkageInfo(D->getCachedLinkage(), DefaultVisibility, false);
|
||||
|
||||
if (llvm::Optional<LinkageInfo> LI = lookup(D, computation))
|
||||
|
@ -1398,7 +1382,10 @@ LinkageInfo LinkageComputer::getLVForDecl(const NamedDecl *D,
|
|||
}
|
||||
|
||||
LinkageInfo LinkageComputer::getDeclLinkageAndVisibility(const NamedDecl *D) {
|
||||
return getLVForDecl(D, usesTypeVisibility(D) ? LVForType : LVForValue);
|
||||
return getLVForDecl(D,
|
||||
LVComputationKind(usesTypeVisibility(D)
|
||||
? NamedDecl::VisibilityForType
|
||||
: NamedDecl::VisibilityForValue));
|
||||
}
|
||||
|
||||
Module *NamedDecl::getOwningModuleForLinkage() const {
|
||||
|
|
|
@ -22,38 +22,50 @@
|
|||
#include "llvm/ADT/Optional.h"
|
||||
|
||||
namespace clang {
|
||||
enum : unsigned {
|
||||
IgnoreExplicitVisibilityBit = 2,
|
||||
IgnoreAllVisibilityBit = 4
|
||||
};
|
||||
|
||||
/// Kinds of LV computation. The linkage side of the computation is
|
||||
/// always the same, but different things can change how visibility is
|
||||
/// computed.
|
||||
enum LVComputationKind {
|
||||
/// Do an LV computation for, ultimately, a type.
|
||||
/// Visibility may be restricted by type visibility settings and
|
||||
/// the visibility of template arguments.
|
||||
LVForType = NamedDecl::VisibilityForType,
|
||||
struct LVComputationKind {
|
||||
/// The kind of entity whose visibility is ultimately being computed;
|
||||
/// visibility computations for types and non-types follow different rules.
|
||||
unsigned ExplicitKind : 1;
|
||||
/// Whether explicit visibility attributes should be ignored. When set,
|
||||
/// visibility may only be restricted by the visibility of template arguments.
|
||||
unsigned IgnoreExplicitVisibility : 1;
|
||||
/// Whether all visibility should be ignored. When set, we're only interested
|
||||
/// in computing linkage.
|
||||
unsigned IgnoreAllVisibility : 1;
|
||||
|
||||
/// Do an LV computation for, ultimately, a non-type declaration.
|
||||
/// Visibility may be restricted by value visibility settings and
|
||||
/// the visibility of template arguments.
|
||||
LVForValue = NamedDecl::VisibilityForValue,
|
||||
explicit LVComputationKind(NamedDecl::ExplicitVisibilityKind EK)
|
||||
: ExplicitKind(EK), IgnoreExplicitVisibility(false),
|
||||
IgnoreAllVisibility(false) {}
|
||||
|
||||
/// Do an LV computation for, ultimately, a type that already has
|
||||
/// some sort of explicit visibility. Visibility may only be
|
||||
/// restricted by the visibility of template arguments.
|
||||
LVForExplicitType = (LVForType | IgnoreExplicitVisibilityBit),
|
||||
NamedDecl::ExplicitVisibilityKind getExplicitVisibilityKind() const {
|
||||
return static_cast<NamedDecl::ExplicitVisibilityKind>(ExplicitKind);
|
||||
}
|
||||
|
||||
/// Do an LV computation for, ultimately, a non-type declaration
|
||||
/// that already has some sort of explicit visibility. Visibility
|
||||
/// may only be restricted by the visibility of template arguments.
|
||||
LVForExplicitValue = (LVForValue | IgnoreExplicitVisibilityBit),
|
||||
bool isTypeVisibility() const {
|
||||
return getExplicitVisibilityKind() == NamedDecl::VisibilityForType;
|
||||
}
|
||||
bool isValueVisibility() const {
|
||||
return getExplicitVisibilityKind() == NamedDecl::VisibilityForValue;
|
||||
}
|
||||
|
||||
/// Do an LV computation when we only care about the linkage.
|
||||
LVForLinkageOnly =
|
||||
LVForValue | IgnoreExplicitVisibilityBit | IgnoreAllVisibilityBit
|
||||
static LVComputationKind forLinkageOnly() {
|
||||
LVComputationKind Result(NamedDecl::VisibilityForValue);
|
||||
Result.IgnoreExplicitVisibility = true;
|
||||
Result.IgnoreAllVisibility = true;
|
||||
return Result;
|
||||
}
|
||||
|
||||
unsigned toBits() {
|
||||
unsigned Bits = 0;
|
||||
Bits = (Bits << 1) | ExplicitKind;
|
||||
Bits = (Bits << 1) | IgnoreExplicitVisibility;
|
||||
Bits = (Bits << 1) | IgnoreAllVisibility;
|
||||
return Bits;
|
||||
}
|
||||
};
|
||||
|
||||
class LinkageComputer {
|
||||
|
@ -66,14 +78,12 @@ class LinkageComputer {
|
|||
// using C = Foo<B, B>;
|
||||
// using D = Foo<C, C>;
|
||||
//
|
||||
// Note that the unsigned is actually a LVComputationKind; ubsan's enum
|
||||
// sanitizer doesn't like tombstone/empty markers outside of
|
||||
// LVComputationKind's range.
|
||||
// The unsigned represents an LVComputationKind.
|
||||
using QueryType = std::pair<const NamedDecl *, unsigned>;
|
||||
llvm::SmallDenseMap<QueryType, LinkageInfo, 8> CachedLinkageInfo;
|
||||
|
||||
static QueryType makeCacheKey(const NamedDecl *ND, LVComputationKind Kind) {
|
||||
return std::make_pair(ND, static_cast<unsigned>(Kind));
|
||||
return std::make_pair(ND, Kind.toBits());
|
||||
}
|
||||
|
||||
llvm::Optional<LinkageInfo> lookup(const NamedDecl *ND,
|
||||
|
|
Loading…
Reference in New Issue