Clean up some mistreatment of enumerations.

llvm-svn: 313953
This commit is contained in:
Richard Smith 2017-09-22 02:22:32 +00:00
parent 6c2dbc69a7
commit fbe7b46657
3 changed files with 71 additions and 67 deletions

View File

@ -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
};

View File

@ -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 {

View File

@ -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,