}
void mergeVisibility(Visibility V, bool E = false) {
+ // If one has explicit visibility and the other doesn't, keep the
+ // explicit one.
+ if (visibilityExplicit() && !E)
+ return;
+ if (!visibilityExplicit() && E)
+ setVisibility(V, E);
+
+ // If both are explicit or both are implicit, keep the minimum.
setVisibility(minVisibility(visibility(), V), visibilityExplicit() || E);
}
void mergeVisibility(LinkageInfo Other) {
mergeLinkage(Other);
mergeVisibility(Other);
}
- void merge(std::pair<Linkage,Visibility> LV) {
- mergeLinkage(LV.first);
- mergeVisibility(LV.second);
- }
friend LinkageInfo merge(LinkageInfo L, LinkageInfo R) {
L.merge(R);
/// LangOptions::VisibilityMode+1.
mutable unsigned CacheValidAndVisibility : 2;
+ /// \brief True if the visibility was set explicitly in the source code.
+ mutable unsigned CachedExplicitVisibility : 1;
+
/// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2;
assert(isCacheValid() && "getting linkage from invalid cache");
return static_cast<Visibility>(CacheValidAndVisibility-1);
}
+ bool isVisibilityExplicit() const {
+ assert(isCacheValid() && "getting linkage from invalid cache");
+ return CachedExplicitVisibility;
+ }
Linkage getLinkage() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return static_cast<Linkage>(CachedLinkage);
return CachedLocalOrUnnamed;
}
};
- enum { NumTypeBits = 18 };
+ enum { NumTypeBits = 19 };
protected:
// These classes allow subclasses to somewhat cleanly pack bitfields
TypeBits.VariablyModified = VariablyModified;
TypeBits.ContainsUnexpandedParameterPack = ContainsUnexpandedParameterPack;
TypeBits.CacheValidAndVisibility = 0;
+ TypeBits.CachedExplicitVisibility = false;
TypeBits.CachedLocalOrUnnamed = false;
TypeBits.CachedLinkage = NoLinkage;
TypeBits.FromAST = false;
/// \brief Determine the visibility of this type.
Visibility getVisibility() const;
+ /// \brief Return true if the visibility was explicitly set is the code.
+ bool isVisibilityExplicit() const;
+
/// \brief Determine the linkage and visibility of this type.
std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
}
typedef NamedDecl::LinkageInfo LinkageInfo;
-typedef std::pair<Linkage,Visibility> LVPair;
-
-static LVPair merge(LVPair L, LVPair R) {
- return LVPair(minLinkage(L.first, R.first),
- minVisibility(L.second, R.second));
-}
-
-static LVPair merge(LVPair L, LinkageInfo R) {
- return LVPair(minLinkage(L.first, R.linkage()),
- minVisibility(L.second, R.visibility()));
-}
namespace {
/// Flags controlling the computation of linkage and visibility.
};
} // end anonymous namespace
+static LinkageInfo getLVForType(QualType T) {
+ std::pair<Linkage,Visibility> P = T->getLinkageAndVisibility();
+ return LinkageInfo(P.first, P.second, T->isVisibilityExplicit());
+}
+
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list.
-static LVPair
+static LinkageInfo
getLVForTemplateParameterList(const TemplateParameterList *Params) {
- LVPair LV(ExternalLinkage, DefaultVisibility);
+ LinkageInfo LV(ExternalLinkage, DefaultVisibility, false);
for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
for (unsigned I = 0, N = NTTP->getNumExpansionTypes(); I != N; ++I) {
QualType T = NTTP->getExpansionType(I);
if (!T->isDependentType())
- LV = merge(LV, T->getLinkageAndVisibility());
+ LV.merge(getLVForType(T));
}
continue;
}
if (!NTTP->getType()->isDependentType()) {
- LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
+ LV.merge(getLVForType(NTTP->getType()));
continue;
}
}
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
- LV = merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters()));
+ LV.merge(getLVForTemplateParameterList(TTP->getTemplateParameters()));
}
}
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
-static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
- unsigned NumArgs,
- LVFlags &F) {
- LVPair LV(ExternalLinkage, DefaultVisibility);
+static LinkageInfo getLVForTemplateArgumentList(const TemplateArgument *Args,
+ unsigned NumArgs,
+ LVFlags &F) {
+ LinkageInfo LV(ExternalLinkage, DefaultVisibility, false);
for (unsigned I = 0; I != NumArgs; ++I) {
switch (Args[I].getKind()) {
break;
case TemplateArgument::Type:
- LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility());
+ LV.merge(getLVForType(Args[I].getAsType()));
break;
case TemplateArgument::Declaration:
case TemplateArgument::TemplateExpansion:
if (TemplateDecl *Template
= Args[I].getAsTemplateOrTemplatePattern().getAsTemplateDecl())
- LV = merge(LV, getLVForDecl(Template, F));
+ LV.merge(getLVForDecl(Template, F));
break;
case TemplateArgument::Pack:
- LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
- Args[I].pack_size(),
- F));
+ LV.merge(getLVForTemplateArgumentList(Args[I].pack_begin(),
+ Args[I].pack_size(),
+ F));
break;
}
}
return LV;
}
-static LVPair
+static LinkageInfo
getLVForTemplateArgumentList(const TemplateArgumentList &TArgs,
LVFlags &F) {
return getLVForTemplateArgumentList(TArgs.data(), TArgs.size(), F);
// Note that we don't want to make the variable non-external
// because of this, but unique-external linkage suits us.
if (Context.getLangOptions().CPlusPlus && !Var->isExternC()) {
- LVPair TypeLV = Var->getType()->getLinkageAndVisibility();
- if (TypeLV.first != ExternalLinkage)
+ LinkageInfo TypeLV = getLVForType(Var->getType());
+ if (TypeLV.linkage() != ExternalLinkage)
return LinkageInfo::uniqueExternal();
if (!LV.visibilityExplicit())
- LV.mergeVisibility(TypeLV.second);
+ LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
}
if (Var->getStorageClass() == SC_PrivateExtern)
} else if (const VarDecl *VD = dyn_cast<VarDecl>(D)) {
// Modify the variable's linkage by its type, but ignore the
// type's visibility unless it's a definition.
- LVPair TypeLV = VD->getType()->getLinkageAndVisibility();
- if (TypeLV.first != ExternalLinkage)
+ LinkageInfo TypeLV = getLVForType(VD->getType());
+ if (TypeLV.linkage() != ExternalLinkage)
LV.mergeLinkage(UniqueExternalLinkage);
if (!LV.visibilityExplicit())
- LV.mergeVisibility(TypeLV.second);
+ LV.mergeVisibility(TypeLV.visibility(), TypeLV.visibilityExplicit());
}
F.ConsiderGlobalVisibility &= !LV.visibilityExplicit();
/// \brief The cached properties of a type.
class CachedProperties {
- char linkage;
- char visibility;
+ NamedDecl::LinkageInfo LV;
bool local;
public:
- CachedProperties(Linkage linkage, Visibility visibility, bool local)
- : linkage(linkage), visibility(visibility), local(local) {}
+ CachedProperties(NamedDecl::LinkageInfo LV, bool local)
+ : LV(LV), local(local) {}
- Linkage getLinkage() const { return (Linkage) linkage; }
- Visibility getVisibility() const { return (Visibility) visibility; }
+ Linkage getLinkage() const { return LV.linkage(); }
+ Visibility getVisibility() const { return LV.visibility(); }
+ bool isVisibilityExplicit() const { return LV.visibilityExplicit(); }
bool hasLocalOrUnnamedType() const { return local; }
friend CachedProperties merge(CachedProperties L, CachedProperties R) {
- return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
- minVisibility(L.getVisibility(), R.getVisibility()),
+ NamedDecl::LinkageInfo MergedLV = L.LV;
+ MergedLV.merge(R.LV);
+ return CachedProperties(MergedLV,
L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
}
};
static CachedProperties get(const Type *T) {
ensure(T);
- return CachedProperties(T->TypeBits.getLinkage(),
- T->TypeBits.getVisibility(),
- T->TypeBits.hasLocalOrUnnamedType());
+ NamedDecl::LinkageInfo LV(T->TypeBits.getLinkage(),
+ T->TypeBits.getVisibility(),
+ T->TypeBits.isVisibilityExplicit());
+ return CachedProperties(LV, T->TypeBits.hasLocalOrUnnamedType());
}
static void ensure(const Type *T) {
ensure(CT);
T->TypeBits.CacheValidAndVisibility =
CT->TypeBits.CacheValidAndVisibility;
+ T->TypeBits.CachedExplicitVisibility =
+ CT->TypeBits.CachedExplicitVisibility;
T->TypeBits.CachedLinkage = CT->TypeBits.CachedLinkage;
T->TypeBits.CachedLocalOrUnnamed = CT->TypeBits.CachedLocalOrUnnamed;
return;
// Compute the cached properties and then set the cache.
CachedProperties Result = computeCachedProperties(T);
T->TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
+ T->TypeBits.CachedExplicitVisibility = Result.isVisibilityExplicit();
assert(T->TypeBits.isCacheValid() &&
T->TypeBits.getVisibility() == Result.getVisibility());
T->TypeBits.CachedLinkage = Result.getLinkage();
#include "clang/AST/TypeNodes.def"
// Treat instantiation-dependent types as external.
assert(T->isInstantiationDependentType());
- return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+ return CachedProperties(NamedDecl::LinkageInfo(), false);
case Type::Builtin:
// C++ [basic.link]p8:
// A type is said to have linkage if and only if:
// - it is a fundamental type (3.9.1); or
- return CachedProperties(ExternalLinkage, DefaultVisibility, false);
+ return CachedProperties(NamedDecl::LinkageInfo(), false);
case Type::Record:
case Type::Enum: {
bool IsLocalOrUnnamed =
Tag->getDeclContext()->isFunctionOrMethod() ||
(!Tag->getIdentifier() && !Tag->getTypedefNameForAnonDecl());
- return CachedProperties(LV.linkage(), LV.visibility(), IsLocalOrUnnamed);
+ return CachedProperties(LV, IsLocalOrUnnamed);
}
// C++ [basic.link]p8:
case Type::ObjCInterface: {
NamedDecl::LinkageInfo LV =
cast<ObjCInterfaceType>(T)->getDecl()->getLinkageAndVisibility();
- return CachedProperties(LV.linkage(), LV.visibility(), false);
+ return CachedProperties(LV, false);
}
case Type::ObjCObject:
return Cache::get(cast<ObjCObjectType>(T)->getBaseType());
// C++ [basic.link]p8:
// Names not covered by these rules have no linkage.
- return CachedProperties(NoLinkage, DefaultVisibility, false);
+ NamedDecl::LinkageInfo LV(NoLinkage, DefaultVisibility, false);
+ return CachedProperties(LV, false);
}
/// \brief Determine the linkage of this type.
return TypeBits.getVisibility();
}
+bool Type::isVisibilityExplicit() const {
+ Cache::ensure(this);
+ return TypeBits.isVisibilityExplicit();
+}
+
bool Type::hasUnnamedOrLocalType() const {
Cache::ensure(this);
return TypeBits.hasLocalOrUnnamedType();
B<A<2> >::test4();
}
- // CHECK: declare void @_ZN6Test201BINS_1AILj2EEEE5test5Ev()
- // (but explicit visibility on a template argument doesn't count as
- // explicit visibility for the template for purposes of deciding
- // whether an external symbol gets visibility)
+ // CHECK: declare hidden void @_ZN6Test201BINS_1AILj2EEEE5test5Ev()
void test5() {
B<A<2> >::test5();
}
template class foo::bar<char>;
// CHECK: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
// CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barIcE3zedEv
+
+ struct zed {
+ };
+ template class foo::bar<zed>;
+ // CHECK: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN7PR101133foo3barINS_3zedEE3zedEv
}
namespace PR11690 {
// CHECK-HIDDEN: define weak_odr void @_ZNK7PR116905ClassIcE4sizeEv
template<class T> void Method() {}
- template __attribute__((visibility("default"))) void Method<char>();
+ template DEFAULT void Method<char>();
// CHECK: define weak_odr void @_ZN7PR116906MethodIcEEvv
// CHECK-HIDDEN: define weak_odr void @_ZN7PR116906MethodIcEEvv
}
+
+namespace PR11690_2 {
+ namespace foo DEFAULT {
+ class bar;
+ template<typename T1, typename T2 = bar>
+ class zed {
+ void bar() {
+ }
+ };
+ }
+ struct baz {
+ };
+ template class foo::zed<baz>;
+ // CHECK: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+ // CHECK-HIDDEN: define weak_odr void @_ZN9PR11690_23foo3zedINS_3bazENS0_3barEE3barEv
+}