Substantially revise how clang computes the visibility of a declaration to

more closely parallel the computation of linkage.  This gets us to a state
much closer to what gcc emits, modulo bugs, which will undoubtedly arise in
abundance.

llvm-svn: 117147
This commit is contained in:
John McCall 2010-10-22 21:05:15 +00:00
parent 0196aa28ec
commit 457a04e3ce
17 changed files with 554 additions and 311 deletions

View File

@ -197,7 +197,13 @@ public:
bool isCXXInstanceMember() const;
/// \brief Determine what kind of linkage this entity has.
Linkage getLinkage() const;
Linkage getLinkage() const { return getLinkageAndVisibility().first; }
/// \brief Determines the visibility of this entity.
Visibility getVisibility() const { return getLinkageAndVisibility().second; }
/// \brief Determines the linkage and visibility of this entity.
std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
/// \brief Looks through UsingDecls and ObjCCompatibleAliasDecls for
/// the underlying named decl.

View File

@ -18,6 +18,7 @@
#include "clang/Basic/IdentifierTable.h"
#include "clang/Basic/Linkage.h"
#include "clang/Basic/PartialDiagnostic.h"
#include "clang/Basic/Visibility.h"
#include "clang/AST/NestedNameSpecifier.h"
#include "clang/AST/TemplateName.h"
#include "llvm/Support/Casting.h"
@ -800,9 +801,10 @@ private:
/// \brief Whether this type is a variably-modified type (C99 6.7.5).
unsigned VariablyModified : 1;
/// \brief Whether the linkage of this type along with the presence of any
/// local or unnamed types is already known.
mutable unsigned LinkageKnown : 1;
/// \brief Nonzero if the cache (i.e. the bitfields here starting
/// with 'Cache') is valid. If so, then this is a
/// LangOptions::VisibilityMode+1.
mutable unsigned CacheValidAndVisibility : 2;
/// \brief Linkage of this type.
mutable unsigned CachedLinkage : 2;
@ -813,7 +815,21 @@ private:
/// \brief FromAST - Whether this type comes from an AST file.
mutable unsigned FromAST : 1;
unsigned SpareBit : 1;
bool isCacheValid() const {
return (CacheValidAndVisibility != 0);
}
Visibility getVisibility() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return static_cast<Visibility>(CacheValidAndVisibility-1);
}
Linkage getLinkage() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return static_cast<Linkage>(CachedLinkage);
}
bool hasLocalOrUnnamedType() const {
assert(isCacheValid() && "getting linkage from invalid cache");
return CachedLocalOrUnnamed;
}
};
enum { NumTypeBits = 16 };
@ -938,10 +954,35 @@ private:
TypeBits.FromAST = V;
}
void ensureCachedProperties() const;
protected:
/// \brief Compute the linkage of this type along with the presence of
/// any local or unnamed types.
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
/// \brief Compute the cached properties of this type.
class CachedProperties {
char linkage;
char visibility;
bool local;
public:
CachedProperties(Linkage linkage, Visibility visibility, bool local)
: linkage(linkage), visibility(visibility), local(local) {}
Linkage getLinkage() const { return (Linkage) linkage; }
Visibility getVisibility() const { return (Visibility) visibility; }
bool hasLocalOrUnnamedType() const { return local; }
friend CachedProperties merge(CachedProperties L, CachedProperties R) {
return CachedProperties(minLinkage(L.getLinkage(), R.getLinkage()),
minVisibility(L.getVisibility(), R.getVisibility()),
L.hasLocalOrUnnamedType() | R.hasLocalOrUnnamedType());
}
};
virtual CachedProperties getCachedProperties() const;
static CachedProperties getCachedProperties(QualType T) {
return getCachedProperties(T.getTypePtr());
}
static CachedProperties getCachedProperties(const Type *T);
// silence VC++ warning C4355: 'this' : used in base member initializer list
Type *this_() { return this; }
@ -950,7 +991,7 @@ protected:
TypeBits.TC = tc;
TypeBits.Dependent = Dependent;
TypeBits.VariablyModified = VariablyModified;
TypeBits.LinkageKnown = false;
TypeBits.CacheValidAndVisibility = 0;
TypeBits.CachedLocalOrUnnamed = false;
TypeBits.CachedLinkage = NoLinkage;
TypeBits.FromAST = false;
@ -1191,6 +1232,12 @@ public:
/// \brief Determine the linkage of this type.
Linkage getLinkage() const;
/// \brief Determine the visibility of this type.
Visibility getVisibility() const;
/// \brief Determine the linkage and visibility of this type.
std::pair<Linkage,Visibility> getLinkageAndVisibility() const;
/// \brief Note that the linkage is no longer known.
void ClearLinkageCache();
@ -1278,7 +1325,7 @@ public:
};
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
BuiltinType(Kind K)
@ -1334,7 +1381,7 @@ class ComplexType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
QualType getElementType() const { return ElementType; }
@ -1366,7 +1413,7 @@ class PointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
@ -1400,7 +1447,7 @@ class BlockPointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
@ -1437,7 +1484,7 @@ protected:
ReferenceTypeBits.InnerRef = Referencee->isReferenceType();
}
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
bool isSpelledAsLValue() const { return ReferenceTypeBits.SpelledAsLValue; }
@ -1521,7 +1568,7 @@ class MemberPointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
QualType getPointeeType() const { return PointeeType; }
@ -1590,7 +1637,7 @@ protected:
friend class ASTContext; // ASTContext creates these.
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
QualType getElementType() const { return ElementType; }
@ -1893,7 +1940,7 @@ protected:
}
friend class ASTContext; // ASTContext creates these.
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
@ -2123,7 +2170,7 @@ class FunctionNoProtoType : public FunctionType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
// No additional state past what FunctionType provides.
@ -2179,7 +2226,7 @@ class FunctionProtoType : public FunctionType, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
unsigned getNumArgs() const { return NumArgs; }
@ -2421,7 +2468,7 @@ class TagType : public Type {
protected:
TagType(TypeClass TC, const TagDecl *D, QualType can);
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
TagDecl *getDecl() const;
@ -3084,7 +3131,7 @@ protected:
}
protected:
std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const; // key function
CachedProperties getCachedProperties() const; // key function
public:
/// getBaseType - Gets the base type of this object type. This is
@ -3192,6 +3239,10 @@ class ObjCInterfaceType : public ObjCObjectType {
: ObjCObjectType(Nonce_ObjCInterface),
Decl(const_cast<ObjCInterfaceDecl*>(D)) {}
friend class ASTContext; // ASTContext creates these.
protected:
virtual CachedProperties getCachedProperties() const;
public:
/// getDecl - Get the declaration of this interface.
ObjCInterfaceDecl *getDecl() const { return Decl; }
@ -3242,7 +3293,7 @@ class ObjCObjectPointerType : public Type, public llvm::FoldingSetNode {
friend class ASTContext; // ASTContext creates these.
protected:
virtual std::pair<Linkage, bool> getLinkageUnnamedLocalImpl() const;
virtual CachedProperties getCachedProperties() const;
public:
/// getPointeeType - Gets the type pointed to by this ObjC pointer.

View File

@ -15,6 +15,7 @@
#define LLVM_CLANG_LANGOPTIONS_H
#include <string>
#include "clang/Basic/Visibility.h"
namespace clang {
@ -131,11 +132,6 @@ public:
enum GCMode { NonGC, GCOnly, HybridGC };
enum StackProtectorMode { SSPOff, SSPOn, SSPReq };
enum VisibilityMode {
Default,
Protected,
Hidden
};
enum SignedOverflowBehaviorTy {
SOB_Undefined, // Default C standard behavior.
@ -161,7 +157,7 @@ public:
HeinousExtensions = 0;
AltiVec = OpenCL = StackProtector = 0;
SymbolVisibility = (unsigned) Default;
SymbolVisibility = (unsigned) DefaultVisibility;
ThreadsafeStatics = 1;
POSIXThreads = 0;
@ -208,10 +204,10 @@ public:
StackProtector = static_cast<unsigned>(m);
}
VisibilityMode getVisibilityMode() const {
return (VisibilityMode) SymbolVisibility;
Visibility getVisibilityMode() const {
return (Visibility) SymbolVisibility;
}
void setVisibilityMode(VisibilityMode v) { SymbolVisibility = (unsigned) v; }
void setVisibilityMode(Visibility v) { SymbolVisibility = (unsigned) v; }
SignedOverflowBehaviorTy getSignedOverflowBehavior() const {
return (SignedOverflowBehaviorTy)SignedOverflowBehavior;

View File

@ -0,0 +1,48 @@
//===--- Visibility.h - Visibility enumeration and utilities ----*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines the Visibility enumeration and various utility
// functions.
//
//===----------------------------------------------------------------------===//
#ifndef LLVM_CLANG_BASIC_VISIBILITY_H
#define LLVM_CLANG_BASIC_VISIBILITY_H
namespace clang {
/// \link Describes the different kinds of visibility that a
/// declaration may have. Visibility determines how a declaration
/// interacts with the dynamic linker. It may also affect whether the
/// symbol can be found by runtime symbol lookup APIs.
///
/// Visibility is not described in any language standard and
/// (nonetheless) sometimes has odd behavior. Not all platforms
/// support all visibility kinds.
enum Visibility {
/// Objects with "hidden" visibility are not seen by the dynamic
/// linker.
HiddenVisibility,
/// Objects with "protected" visibility are seen by the dynamic
/// linker but always dynamically resolve to an object within this
/// shared object.
ProtectedVisibility,
/// Objects with "default" visibility are seen by the dynamic linker
/// and act like normal objects.
DefaultVisibility
};
inline Visibility minVisibility(Visibility L, Visibility R) {
return L < R ? L : R;
}
}
#endif // LLVM_CLANG_BASIC_VISIBILITY_H

View File

@ -32,35 +32,53 @@ using namespace clang;
// NamedDecl Implementation
//===----------------------------------------------------------------------===//
static Visibility GetVisibilityFromAttr(const VisibilityAttr *A) {
switch (A->getVisibility()) {
case VisibilityAttr::Default:
return DefaultVisibility;
case VisibilityAttr::Hidden:
return HiddenVisibility;
case VisibilityAttr::Protected:
return ProtectedVisibility;
}
return DefaultVisibility;
}
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));
}
/// \brief Get the most restrictive linkage for the types in the given
/// template parameter list.
static Linkage
getLinkageForTemplateParameterList(const TemplateParameterList *Params) {
Linkage L = ExternalLinkage;
static LVPair
getLVForTemplateParameterList(const TemplateParameterList *Params) {
LVPair LV(ExternalLinkage, DefaultVisibility);
for (TemplateParameterList::const_iterator P = Params->begin(),
PEnd = Params->end();
P != PEnd; ++P) {
if (NonTypeTemplateParmDecl *NTTP = dyn_cast<NonTypeTemplateParmDecl>(*P))
if (!NTTP->getType()->isDependentType()) {
L = minLinkage(L, NTTP->getType()->getLinkage());
LV = merge(LV, NTTP->getType()->getLinkageAndVisibility());
continue;
}
if (TemplateTemplateParmDecl *TTP
= dyn_cast<TemplateTemplateParmDecl>(*P)) {
L = minLinkage(L,
getLinkageForTemplateParameterList(TTP->getTemplateParameters()));
LV =
merge(LV, getLVForTemplateParameterList(TTP->getTemplateParameters()));
}
}
return L;
return LV;
}
/// \brief Get the most restrictive linkage for the types and
/// declarations in the given template argument list.
static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs) {
Linkage L = ExternalLinkage;
static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
unsigned NumArgs) {
LVPair LV(ExternalLinkage, DefaultVisibility);
for (unsigned I = 0; I != NumArgs; ++I) {
switch (Args[I].getKind()) {
@ -70,40 +88,41 @@ static Linkage getLinkageForTemplateArgumentList(const TemplateArgument *Args,
break;
case TemplateArgument::Type:
L = minLinkage(L, Args[I].getAsType()->getLinkage());
LV = merge(LV, Args[I].getAsType()->getLinkageAndVisibility());
break;
case TemplateArgument::Declaration:
if (NamedDecl *ND = dyn_cast<NamedDecl>(Args[I].getAsDecl()))
L = minLinkage(L, ND->getLinkage());
if (ValueDecl *VD = dyn_cast<ValueDecl>(Args[I].getAsDecl()))
L = minLinkage(L, VD->getType()->getLinkage());
// The decl can validly be null as the representation of nullptr
// arguments, valid only in C++0x.
if (Decl *D = Args[I].getAsDecl()) {
if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
LV = merge(LV, ND->getLinkageAndVisibility());
if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
LV = merge(LV, VD->getType()->getLinkageAndVisibility());
}
break;
case TemplateArgument::Template:
if (TemplateDecl *Template
= Args[I].getAsTemplate().getAsTemplateDecl())
L = minLinkage(L, Template->getLinkage());
if (TemplateDecl *Template = Args[I].getAsTemplate().getAsTemplateDecl())
LV = merge(LV, Template->getLinkageAndVisibility());
break;
case TemplateArgument::Pack:
L = minLinkage(L,
getLinkageForTemplateArgumentList(Args[I].pack_begin(),
Args[I].pack_size()));
LV = merge(LV, getLVForTemplateArgumentList(Args[I].pack_begin(),
Args[I].pack_size()));
break;
}
}
return L;
return LV;
}
static Linkage
getLinkageForTemplateArgumentList(const TemplateArgumentList &TArgs) {
return getLinkageForTemplateArgumentList(TArgs.getFlatArgumentList(),
TArgs.flat_size());
static LVPair getLVForTemplateArgumentList(const TemplateArgumentList &TArgs) {
return getLVForTemplateArgumentList(TArgs.getFlatArgumentList(),
TArgs.flat_size());
}
static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
static LVPair getLVForNamespaceScopeDecl(const NamedDecl *D) {
assert(D->getDeclContext()->getRedeclContext()->isFileContext() &&
"Not a name having namespace scope");
ASTContext &Context = D->getASTContext();
@ -117,7 +136,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Explicitly declared static.
if (Var->getStorageClass() == SC_Static)
return InternalLinkage;
return LVPair(InternalLinkage, DefaultVisibility);
// - an object or reference that is explicitly declared const
// and neither explicitly declared extern nor previously
@ -135,7 +154,7 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
FoundExtern = true;
if (!FoundExtern)
return InternalLinkage;
return LVPair(InternalLinkage, DefaultVisibility);
}
} else if (isa<FunctionDecl>(D) || isa<FunctionTemplateDecl>(D)) {
// C++ [temp]p4:
@ -150,23 +169,63 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// Explicitly declared static.
if (Function->getStorageClass() == SC_Static)
return InternalLinkage;
return LVPair(InternalLinkage, DefaultVisibility);
} else if (const FieldDecl *Field = dyn_cast<FieldDecl>(D)) {
// - a data member of an anonymous union.
if (cast<RecordDecl>(Field->getDeclContext())->isAnonymousStructOrUnion())
return InternalLinkage;
return LVPair(InternalLinkage, DefaultVisibility);
}
if (D->isInAnonymousNamespace())
return LVPair(UniqueExternalLinkage, DefaultVisibility);
// Set up the defaults.
// C99 6.2.2p5:
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
LVPair LV(ExternalLinkage, DefaultVisibility);
// We ignore -fvisibility on non-definitions and explicit
// instantiation declarations.
bool ConsiderDashFVisibility = true;
// C++ [basic.link]p4:
// A name having namespace scope has external linkage if it is the
// name of
//
// - an object or reference, unless it has internal linkage; or
if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
// Modify the variable's LV by the LV of its type unless this is
// C or extern "C". This follows from [basic.link]p9:
// A type without linkage shall not be used as the type of a
// variable or function with external linkage unless
// - the entity has C language linkage, or
// - the entity is declared within an unnamed namespace, or
// - the entity is not used or is defined in the same
// translation unit.
// and [basic.link]p10:
// ...the types specified by all declarations referring to a
// given variable or function shall be identical...
// C does not have an equivalent rule.
//
// 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)
return LVPair(UniqueExternalLinkage, DefaultVisibility);
LV.second = minVisibility(LV.second, TypeLV.second);
}
if (!Context.getLangOptions().CPlusPlus &&
(Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern)) {
if (Var->getStorageClass() == SC_PrivateExtern)
LV.second = HiddenVisibility;
// C99 6.2.2p4:
// For an identifier declared with the storage-class specifier
// extern in a scope in which a prior declaration of that
@ -177,23 +236,23 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const VarDecl *PrevVar = Var->getPreviousDeclaration()) {
if (Linkage L = PrevVar->getLinkage())
return L;
LVPair PrevLV = PrevVar->getLinkageAndVisibility();
if (PrevLV.first) LV.first = PrevLV.first;
LV.second = minVisibility(LV.second, PrevLV.second);
}
}
// C99 6.2.2p5:
// If the declaration of an identifier for an object has file
// scope and no storage-class specifier, its linkage is
// external.
if (Var->isInAnonymousNamespace())
return UniqueExternalLinkage;
return ExternalLinkage;
}
// - a function, unless it has internal linkage; or
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
} else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
// Modify the function's LV by the LV of its type unless this is
// C or extern "C". See the comment above about variables.
if (Context.getLangOptions().CPlusPlus && !Function->isExternC()) {
LVPair TypeLV = Function->getType()->getLinkageAndVisibility();
if (TypeLV.first != ExternalLinkage)
return LVPair(UniqueExternalLinkage, DefaultVisibility);
LV.second = minVisibility(LV.second, TypeLV.second);
}
// C99 6.2.2p5:
// If the declaration of an identifier for a function has no
// storage-class specifier, its linkage is determined exactly
@ -213,24 +272,25 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// is visible, or if the prior declaration specifies no
// linkage, then the identifier has external linkage.
if (const FunctionDecl *PrevFunc = Function->getPreviousDeclaration()) {
if (Linkage L = PrevFunc->getLinkage())
return L;
LVPair PrevLV = PrevFunc->getLinkageAndVisibility();
if (PrevLV.first) LV.first = PrevLV.first;
LV.second = minVisibility(LV.second, PrevLV.second);
}
}
if (Function->isInAnonymousNamespace())
return UniqueExternalLinkage;
if (FunctionTemplateSpecializationInfo *SpecInfo
= Function->getTemplateSpecializationInfo()) {
Linkage L = SpecInfo->getTemplate()->getLinkage();
LV = merge(LV, SpecInfo->getTemplate()->getLinkageAndVisibility());
const TemplateArgumentList &TemplateArgs = *SpecInfo->TemplateArguments;
L = minLinkage(L, getLinkageForTemplateArgumentList(TemplateArgs));
return L;
LV = merge(LV, getLVForTemplateArgumentList(TemplateArgs));
if (SpecInfo->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
ConsiderDashFVisibility = false;
}
return ExternalLinkage;
}
if (ConsiderDashFVisibility)
ConsiderDashFVisibility = Function->hasBody();
// - a named class (Clause 9), or an unnamed class defined in a
// typedef declaration in which the class has the typedef name
@ -238,116 +298,180 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
// - a named enumeration (7.2), or an unnamed enumeration
// defined in a typedef declaration in which the enumeration
// has the typedef name for linkage purposes (7.1.3); or
if (const TagDecl *Tag = dyn_cast<TagDecl>(D))
if (Tag->getDeclName() || Tag->getTypedefForAnonDecl()) {
if (Tag->isInAnonymousNamespace())
return UniqueExternalLinkage;
} else if (const TagDecl *Tag = dyn_cast<TagDecl>(D)) {
// Unnamed tags have no linkage.
if (!Tag->getDeclName() && !Tag->getTypedefForAnonDecl())
return LVPair(NoLinkage, DefaultVisibility);
// If this is a class template specialization, consider the
// linkage of the template and template arguments.
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
}
// If this is a class template specialization, consider the
// linkage of the template and template arguments.
if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(Tag)) {
// From the template. Note below the restrictions on how we
// compute template visibility.
LV = merge(LV, Spec->getSpecializedTemplate()->getLinkageAndVisibility());
return ExternalLinkage;
// The arguments at which the template was instantiated.
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
LV = merge(LV, getLVForTemplateArgumentList(TemplateArgs));
if (Spec->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
ConsiderDashFVisibility = false;
}
if (ConsiderDashFVisibility)
ConsiderDashFVisibility = Tag->isDefinition();
// - an enumerator belonging to an enumeration with external linkage;
if (isa<EnumConstantDecl>(D)) {
Linkage L = cast<NamedDecl>(D->getDeclContext())->getLinkage();
if (isExternalLinkage(L))
return L;
}
} else if (isa<EnumConstantDecl>(D)) {
LVPair EnumLV =
cast<NamedDecl>(D->getDeclContext())->getLinkageAndVisibility();
if (!isExternalLinkage(EnumLV.first))
return LVPair(NoLinkage, DefaultVisibility);
LV = merge(LV, EnumLV);
// - a template, unless it is a function template that has
// internal linkage (Clause 14);
if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
if (D->isInAnonymousNamespace())
return UniqueExternalLinkage;
} else if (const TemplateDecl *Template = dyn_cast<TemplateDecl>(D)) {
LV = merge(LV, getLVForTemplateParameterList(
Template->getTemplateParameters()));
return getLinkageForTemplateParameterList(
Template->getTemplateParameters());
}
// We do not want to consider attributes or global settings when
// computing template visibility.
return LV;
// - a namespace (7.3), unless it is declared within an unnamed
// namespace.
if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace())
return ExternalLinkage;
} else if (isa<NamespaceDecl>(D) && !D->isInAnonymousNamespace()) {
return LV;
return NoLinkage;
// By extension, we assign external linkage to Objective-C
// interfaces.
} else if (isa<ObjCInterfaceDecl>(D)) {
// fallout
// Everything not covered here has no linkage.
} else {
return LVPair(NoLinkage, DefaultVisibility);
}
// If we ended up with non-external linkage, visibility should
// always be default.
if (LV.first != ExternalLinkage)
return LVPair(LV.first, DefaultVisibility);
// If we didn't end up with hidden visibility, consider attributes
// and -fvisibility.
if (LV.second != HiddenVisibility) {
Visibility StandardV;
// If we have an explicit visibility attribute, merge that in.
const VisibilityAttr *VA = D->getAttr<VisibilityAttr>();
if (VA)
StandardV = GetVisibilityFromAttr(VA);
else if (ConsiderDashFVisibility)
StandardV = Context.getLangOptions().getVisibilityMode();
else
StandardV = DefaultVisibility; // no-op
LV.second = minVisibility(LV.second, StandardV);
}
return LV;
}
static Linkage getLinkageForClassMember(const NamedDecl *D) {
static LVPair getLVForClassMember(const NamedDecl *D) {
// Only certain class members have linkage. Note that fields don't
// really have linkage, but it's convenient to say they do for the
// purposes of calculating linkage of pointer-to-data-member
// template arguments.
if (!(isa<CXXMethodDecl>(D) ||
isa<VarDecl>(D) ||
isa<FieldDecl>(D) ||
(isa<TagDecl>(D) &&
(D->getDeclName() || cast<TagDecl>(D)->getTypedefForAnonDecl()))))
return NoLinkage;
return LVPair(NoLinkage, DefaultVisibility);
// Class members only have linkage if their class has external linkage.
Linkage L = cast<RecordDecl>(D->getDeclContext())->getLinkage();
if (!isExternalLinkage(L)) return NoLinkage;
LVPair ClassLV =
cast<RecordDecl>(D->getDeclContext())->getLinkageAndVisibility();
if (!isExternalLinkage(ClassLV.first))
return LVPair(NoLinkage, DefaultVisibility);
// If the class already has unique-external linkage, we can't improve.
if (L == UniqueExternalLinkage) return UniqueExternalLinkage;
if (ClassLV.first == UniqueExternalLinkage)
return LVPair(UniqueExternalLinkage, DefaultVisibility);
// Start with the class's linkage and visibility.
LVPair LV = ClassLV;
// If we have an explicit visibility attribute, merge that in.
const VisibilityAttr *VA = D->getAttr<VisibilityAttr>();
if (VA) LV.second = minVisibility(LV.second, GetVisibilityFromAttr(VA));
// If it's a value declaration, apply the LV from its type.
// See the comment about namespace-scope variable decls above.
if (isa<ValueDecl>(D)) {
LVPair TypeLV = cast<ValueDecl>(D)->getType()->getLinkageAndVisibility();
if (TypeLV.first != ExternalLinkage)
LV.first = minLinkage(LV.first, UniqueExternalLinkage);
LV.second = minVisibility(LV.second, TypeLV.second);
}
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
if (FunctionTemplateSpecializationInfo *SpecInfo
// If this is a method template specialization, use the linkage for
// the template parameters and arguments.
if (FunctionTemplateSpecializationInfo *Spec
= MD->getTemplateSpecializationInfo()) {
Linkage ArgLinkage =
getLinkageForTemplateArgumentList(*SpecInfo->TemplateArguments);
Linkage ParamLinkage =
getLinkageForTemplateParameterList(
SpecInfo->getTemplate()->getTemplateParameters());
return minLinkage(ArgLinkage, ParamLinkage);
LV = merge(LV, getLVForTemplateArgumentList(*Spec->TemplateArguments));
LV = merge(LV, getLVForTemplateParameterList(
Spec->getTemplate()->getTemplateParameters()));
}
// If -fvisibility-inlines-hidden was provided, then inline C++
// member functions get "hidden" visibility if they don't have an
// explicit visibility attribute.
if (!VA && MD->isInlined() && LV.second > HiddenVisibility &&
D->getASTContext().getLangOptions().InlineVisibilityHidden)
LV.second = HiddenVisibility;
// Similarly for member class template specializations.
} else if (const ClassTemplateSpecializationDecl *Spec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {
Linkage ArgLinkage =
getLinkageForTemplateArgumentList(Spec->getTemplateArgs());
Linkage ParamLinkage =
getLinkageForTemplateParameterList(
Spec->getSpecializedTemplate()->getTemplateParameters());
return minLinkage(ArgLinkage, ParamLinkage);
LV = merge(LV, getLVForTemplateArgumentList(Spec->getTemplateArgs()));
LV = merge(LV, getLVForTemplateParameterList(
Spec->getSpecializedTemplate()->getTemplateParameters()));
}
return ExternalLinkage;
return LV;
}
Linkage NamedDecl::getLinkage() const {
LVPair NamedDecl::getLinkageAndVisibility() const {
// Objective-C: treat all Objective-C declarations as having external
// linkage.
switch (getKind()) {
default:
break;
case Decl::TemplateTemplateParm: // count these as external
case Decl::NonTypeTemplateParm:
case Decl::ObjCAtDefsField:
case Decl::ObjCCategory:
case Decl::ObjCCategoryImpl:
case Decl::ObjCClass:
case Decl::ObjCCompatibleAlias:
case Decl::ObjCForwardProtocol:
case Decl::ObjCImplementation:
case Decl::ObjCInterface:
case Decl::ObjCIvar:
case Decl::ObjCMethod:
case Decl::ObjCProperty:
case Decl::ObjCPropertyImpl:
case Decl::ObjCProtocol:
return ExternalLinkage;
return LVPair(ExternalLinkage, DefaultVisibility);
}
// Handle linkage for namespace-scope names.
if (getDeclContext()->getRedeclContext()->isFileContext())
if (Linkage L = getLinkageForNamespaceScopeDecl(this))
return L;
return getLVForNamespaceScopeDecl(this);
// C++ [basic.link]p5:
// In addition, a member function, static data member, a named
@ -357,7 +481,7 @@ Linkage NamedDecl::getLinkage() const {
// purposes (7.1.3), has external linkage if the name of the class
// has external linkage.
if (getDeclContext()->isRecord())
return getLinkageForClassMember(this);
return getLVForClassMember(this);
// C++ [basic.link]p6:
// The name of a function declared in block scope and the name of
@ -372,34 +496,48 @@ Linkage NamedDecl::getLinkage() const {
// external linkage.
if (getLexicalDeclContext()->isFunctionOrMethod()) {
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(this)) {
if (Function->getPreviousDeclaration())
if (Linkage L = Function->getPreviousDeclaration()->getLinkage())
return L;
if (Function->isInAnonymousNamespace())
return UniqueExternalLinkage;
return LVPair(UniqueExternalLinkage, DefaultVisibility);
return ExternalLinkage;
LVPair LV(ExternalLinkage, DefaultVisibility);
if (const VisibilityAttr *VA = Function->getAttr<VisibilityAttr>())
LV.second = GetVisibilityFromAttr(VA);
if (const FunctionDecl *Prev = Function->getPreviousDeclaration()) {
LVPair PrevLV = Prev->getLinkageAndVisibility();
if (PrevLV.first) LV.first = PrevLV.first;
LV.second = minVisibility(LV.second, PrevLV.second);
}
return LV;
}
if (const VarDecl *Var = dyn_cast<VarDecl>(this))
if (Var->getStorageClass() == SC_Extern ||
Var->getStorageClass() == SC_PrivateExtern) {
if (Var->getPreviousDeclaration())
if (Linkage L = Var->getPreviousDeclaration()->getLinkage())
return L;
if (Var->isInAnonymousNamespace())
return UniqueExternalLinkage;
return LVPair(UniqueExternalLinkage, DefaultVisibility);
return ExternalLinkage;
LVPair LV(ExternalLinkage, DefaultVisibility);
if (Var->getStorageClass() == SC_PrivateExtern)
LV.second = HiddenVisibility;
else if (const VisibilityAttr *VA = Var->getAttr<VisibilityAttr>())
LV.second = GetVisibilityFromAttr(VA);
if (const VarDecl *Prev = Var->getPreviousDeclaration()) {
LVPair PrevLV = Prev->getLinkageAndVisibility();
if (PrevLV.first) LV.first = PrevLV.first;
LV.second = minVisibility(LV.second, PrevLV.second);
}
return LV;
}
}
// C++ [basic.link]p6:
// Names not covered by these rules have no linkage.
return NoLinkage;
}
return LVPair(NoLinkage, DefaultVisibility);
}
std::string NamedDecl::getQualifiedNameAsString() const {
return getQualifiedNameAsString(getASTContext().getLangOptions());

View File

@ -1268,129 +1268,154 @@ void ObjCObjectTypeImpl::Profile(llvm::FoldingSetNodeID &ID) {
Profile(ID, getBaseType(), qual_begin(), getNumProtocols());
}
void Type::ensureCachedProperties() const {
if (!TypeBits.isCacheValid()) {
CachedProperties Result = getCachedProperties();
TypeBits.CacheValidAndVisibility = Result.getVisibility() + 1U;
assert(TypeBits.isCacheValid() &&
TypeBits.getVisibility() == Result.getVisibility());
TypeBits.CachedLinkage = Result.getLinkage();
TypeBits.CachedLocalOrUnnamed = Result.hasLocalOrUnnamedType();
}
}
/// \brief Determine the linkage of this type.
Linkage Type::getLinkage() const {
if (this != CanonicalType.getTypePtr())
return CanonicalType->getLinkage();
if (!TypeBits.LinkageKnown) {
std::pair<Linkage, bool> Result = getLinkageUnnamedLocalImpl();
TypeBits.CachedLinkage = Result.first;
TypeBits.CachedLocalOrUnnamed = Result.second;
TypeBits.LinkageKnown = true;
}
return static_cast<clang::Linkage>(TypeBits.CachedLinkage);
ensureCachedProperties();
return TypeBits.getLinkage();
}
/// \brief Determine the linkage of this type.
Visibility Type::getVisibility() const {
if (this != CanonicalType.getTypePtr())
return CanonicalType->getVisibility();
ensureCachedProperties();
return TypeBits.getVisibility();
}
bool Type::hasUnnamedOrLocalType() const {
if (this != CanonicalType.getTypePtr())
return CanonicalType->hasUnnamedOrLocalType();
if (!TypeBits.LinkageKnown) {
std::pair<Linkage, bool> Result = getLinkageUnnamedLocalImpl();
TypeBits.CachedLinkage = Result.first;
TypeBits.CachedLocalOrUnnamed = Result.second;
TypeBits.LinkageKnown = true;
}
return TypeBits.CachedLocalOrUnnamed;
ensureCachedProperties();
return TypeBits.hasLocalOrUnnamedType();
}
std::pair<Linkage, bool> Type::getLinkageUnnamedLocalImpl() const {
// C++ [basic.link]p8:
// Names not covered by these rules have no linkage.
return std::make_pair(NoLinkage, false);
std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const {
if (this != CanonicalType.getTypePtr())
return CanonicalType->getLinkageAndVisibility();
ensureCachedProperties();
return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility());
}
Type::CachedProperties Type::getCachedProperties(const Type *T) {
T = T->CanonicalType.getTypePtr();
T->ensureCachedProperties();
return CachedProperties(T->TypeBits.getLinkage(),
T->TypeBits.getVisibility(),
T->TypeBits.hasLocalOrUnnamedType());
}
void Type::ClearLinkageCache() {
if (this != CanonicalType.getTypePtr())
CanonicalType->ClearLinkageCache();
else
TypeBits.LinkageKnown = false;
TypeBits.CacheValidAndVisibility = 0;
}
std::pair<Linkage, bool> BuiltinType::getLinkageUnnamedLocalImpl() const {
Type::CachedProperties Type::getCachedProperties() const {
// Treat dependent types as external.
if (isDependentType())
return CachedProperties(ExternalLinkage, DefaultVisibility, false);
// C++ [basic.link]p8:
// Names not covered by these rules have no linkage.
return CachedProperties(NoLinkage, DefaultVisibility, false);
}
Type::CachedProperties BuiltinType::getCachedProperties() const {
// 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 std::make_pair(ExternalLinkage, false);
return CachedProperties(ExternalLinkage, DefaultVisibility, false);
}
std::pair<Linkage, bool> TagType::getLinkageUnnamedLocalImpl() const {
Type::CachedProperties TagType::getCachedProperties() const {
// C++ [basic.link]p8:
// - it is a class or enumeration type that is named (or has a name for
// linkage purposes (7.1.3)) and the name has linkage; or
// - it is a specialization of a class template (14); or
return std::make_pair(getDecl()->getLinkage(),
getDecl()->getDeclContext()->isFunctionOrMethod() ||
std::pair<Linkage,Visibility> LV = getDecl()->getLinkageAndVisibility();
bool IsLocalOrUnnamed =
getDecl()->getDeclContext()->isFunctionOrMethod() ||
(!getDecl()->getIdentifier() &&
!getDecl()->getTypedefForAnonDecl()));
!getDecl()->getTypedefForAnonDecl());
return CachedProperties(LV.first, LV.second, IsLocalOrUnnamed);
}
// C++ [basic.link]p8:
// - it is a compound type (3.9.2) other than a class or enumeration,
// compounded exclusively from types that have linkage; or
std::pair<Linkage, bool> ComplexType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(ElementType->getLinkage(),
ElementType->hasUnnamedOrLocalType());
Type::CachedProperties ComplexType::getCachedProperties() const {
return Type::getCachedProperties(ElementType);
}
std::pair<Linkage, bool> PointerType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(PointeeType->getLinkage(),
PointeeType->hasUnnamedOrLocalType());
Type::CachedProperties PointerType::getCachedProperties() const {
return Type::getCachedProperties(PointeeType);
}
std::pair<Linkage, bool> BlockPointerType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(PointeeType->getLinkage(),
PointeeType->hasUnnamedOrLocalType());
Type::CachedProperties BlockPointerType::getCachedProperties() const {
return Type::getCachedProperties(PointeeType);
}
std::pair<Linkage, bool> ReferenceType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(PointeeType->getLinkage(),
PointeeType->hasUnnamedOrLocalType());
Type::CachedProperties ReferenceType::getCachedProperties() const {
return Type::getCachedProperties(PointeeType);
}
std::pair<Linkage, bool> MemberPointerType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(minLinkage(Class->getLinkage(),
PointeeType->getLinkage()),
Class->hasUnnamedOrLocalType() ||
PointeeType->hasUnnamedOrLocalType());
Type::CachedProperties MemberPointerType::getCachedProperties() const {
return merge(Type::getCachedProperties(Class),
Type::getCachedProperties(PointeeType));
}
std::pair<Linkage, bool> ArrayType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(ElementType->getLinkage(),
ElementType->hasUnnamedOrLocalType());
Type::CachedProperties ArrayType::getCachedProperties() const {
return Type::getCachedProperties(ElementType);
}
std::pair<Linkage, bool> VectorType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(ElementType->getLinkage(),
ElementType->hasUnnamedOrLocalType());
Type::CachedProperties VectorType::getCachedProperties() const {
return Type::getCachedProperties(ElementType);
}
std::pair<Linkage, bool>
FunctionNoProtoType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(getResultType()->getLinkage(),
getResultType()->hasUnnamedOrLocalType());
Type::CachedProperties FunctionNoProtoType::getCachedProperties() const {
return Type::getCachedProperties(getResultType());
}
std::pair<Linkage, bool> FunctionProtoType::getLinkageUnnamedLocalImpl() const {
Linkage L = getResultType()->getLinkage();
bool UnnamedOrLocal = getResultType()->hasUnnamedOrLocalType();
Type::CachedProperties FunctionProtoType::getCachedProperties() const {
CachedProperties Cached = Type::getCachedProperties(getResultType());
for (arg_type_iterator A = arg_type_begin(), AEnd = arg_type_end();
A != AEnd; ++A) {
L = minLinkage(L, (*A)->getLinkage());
UnnamedOrLocal = UnnamedOrLocal || (*A)->hasUnnamedOrLocalType();
Cached = merge(Cached, Type::getCachedProperties(*A));
}
return std::make_pair(L, UnnamedOrLocal);
return Cached;
}
std::pair<Linkage, bool> ObjCObjectType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(ExternalLinkage, false);
Type::CachedProperties ObjCInterfaceType::getCachedProperties() const {
std::pair<Linkage,Visibility> LV = getDecl()->getLinkageAndVisibility();
return CachedProperties(LV.first, LV.second, false);
}
std::pair<Linkage, bool>
ObjCObjectPointerType::getLinkageUnnamedLocalImpl() const {
return std::make_pair(ExternalLinkage, false);
Type::CachedProperties ObjCObjectType::getCachedProperties() const {
if (const ObjCInterfaceType *T = getBaseType()->getAs<ObjCInterfaceType>())
return Type::getCachedProperties(T);
return CachedProperties(ExternalLinkage, DefaultVisibility, false);
}
Type::CachedProperties ObjCObjectPointerType::getCachedProperties() const {
return Type::getCachedProperties(PointeeType);
}

View File

@ -180,7 +180,7 @@ bool CodeGenModule::TryEmitDefinitionAsAlias(GlobalDecl AliasDecl,
}
// Finally, set up the alias with its proper name and attributes.
SetCommonAttributes(AliasDecl.getDecl(), Alias);
SetCommonAttributes(cast<NamedDecl>(AliasDecl.getDecl()), Alias);
return false;
}

View File

@ -2197,7 +2197,7 @@ void CGObjCMac::GenerateClass(const ObjCImplementationDecl *ID) {
CGM.getContext().getASTObjCImplementationLayout(ID).getSize() / 8;
// FIXME: Set CXX-structors flag.
if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Flags |= eClassFlags_Hidden;
std::vector<llvm::Constant*> InstanceMethods, ClassMethods;
@ -2282,7 +2282,7 @@ llvm::Constant *CGObjCMac::EmitMetaClass(const ObjCImplementationDecl *ID,
unsigned Flags = eClassFlags_Meta;
unsigned Size = CGM.getTargetData().getTypeAllocSize(ObjCTypes.ClassTy);
if (CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden)
if (ID->getClassInterface()->getVisibility() == HiddenVisibility)
Flags |= eClassFlags_Hidden;
std::vector<llvm::Constant*> Values(12);
@ -4968,7 +4968,7 @@ void CGObjCNonFragileABIMac::GenerateClass(const ObjCImplementationDecl *ID) {
llvm::GlobalVariable *SuperClassGV, *IsAGV;
bool classIsHidden =
CGM.getDeclVisibilityMode(ID->getClassInterface()) == LangOptions::Hidden;
ID->getClassInterface()->getVisibility() == HiddenVisibility;
if (classIsHidden)
flags |= OBJC2_CLS_HIDDEN;
if (ID->getNumIvarInitializers())
@ -5263,7 +5263,7 @@ CGObjCNonFragileABIMac::EmitIvarOffsetVar(const ObjCInterfaceDecl *ID,
// well (i.e., in ObjCIvarOffsetVariable).
if (Ivar->getAccessControl() == ObjCIvarDecl::Private ||
Ivar->getAccessControl() == ObjCIvarDecl::Package ||
CGM.getDeclVisibilityMode(ID) == LangOptions::Hidden)
ID->getVisibility() == HiddenVisibility)
IvarOffsetGV->setVisibility(llvm::GlobalValue::HiddenVisibility);
else
IvarOffsetGV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@ -6237,7 +6237,7 @@ CGObjCNonFragileABIMac::GetInterfaceEHType(const ObjCInterfaceDecl *ID,
ID->getIdentifier()->getName()));
}
if (CGM.getLangOptions().getVisibilityMode() == LangOptions::Hidden)
if (CGM.getLangOptions().getVisibilityMode() == HiddenVisibility)
Entry->setVisibility(llvm::GlobalValue::HiddenVisibility);
Entry->setAlignment(CGM.getTargetData().getABITypeAlignment(
ObjCTypes.EHTypeTy));

View File

@ -113,7 +113,7 @@ public:
}
if (const RecordType *RT = Ty->getAs<RecordType>())
if (const CXXRecordDecl *RD = dyn_cast<CXXRecordDecl>(RT->getDecl()))
return CGM.getDeclVisibilityMode(RD) == LangOptions::Hidden;
return RD->getVisibility() == HiddenVisibility;
return false;
}

View File

@ -164,81 +164,23 @@ void CodeGenModule::ErrorUnsupported(const Decl *D, const char *Type,
getDiags().Report(Context.getFullLoc(D->getLocation()), DiagID) << Msg;
}
LangOptions::VisibilityMode
CodeGenModule::getDeclVisibilityMode(const Decl *D) const {
if (const VarDecl *VD = dyn_cast<VarDecl>(D))
if (VD->getStorageClass() == SC_PrivateExtern)
return LangOptions::Hidden;
if (const VisibilityAttr *attr = D->getAttr<VisibilityAttr>()) {
switch (attr->getVisibility()) {
default: assert(0 && "Unknown visibility!");
case VisibilityAttr::Default:
return LangOptions::Default;
case VisibilityAttr::Hidden:
return LangOptions::Hidden;
case VisibilityAttr::Protected:
return LangOptions::Protected;
}
}
if (getLangOptions().CPlusPlus) {
// Entities subject to an explicit instantiation declaration get default
// visibility.
if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
if (Function->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
return LangOptions::Default;
} else if (const ClassTemplateSpecializationDecl *ClassSpec
= dyn_cast<ClassTemplateSpecializationDecl>(D)) {
if (ClassSpec->getSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
return LangOptions::Default;
} else if (const CXXRecordDecl *Record = dyn_cast<CXXRecordDecl>(D)) {
if (Record->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration)
return LangOptions::Default;
} else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
if (Var->isStaticDataMember() &&
(Var->getTemplateSpecializationKind()
== TSK_ExplicitInstantiationDeclaration))
return LangOptions::Default;
}
// If -fvisibility-inlines-hidden was provided, then inline C++ member
// functions get "hidden" visibility by default.
if (getLangOptions().InlineVisibilityHidden)
if (const CXXMethodDecl *Method = dyn_cast<CXXMethodDecl>(D))
if (Method->isInlined())
return LangOptions::Hidden;
}
// If this decl is contained in a class, it should have the same visibility
// as the parent class.
if (const DeclContext *DC = D->getDeclContext())
if (DC->isRecord())
return getDeclVisibilityMode(cast<Decl>(DC));
return getLangOptions().getVisibilityMode();
}
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
const Decl *D) const {
const NamedDecl *D) const {
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
return;
}
switch (getDeclVisibilityMode(D)) {
default: assert(0 && "Unknown visibility!");
case LangOptions::Default:
switch (D->getVisibility()) {
case DefaultVisibility:
return GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
case LangOptions::Hidden:
case HiddenVisibility:
return GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
case LangOptions::Protected:
case ProtectedVisibility:
return GV->setVisibility(llvm::GlobalValue::ProtectedVisibility);
}
llvm_unreachable("unknown visibility!");
}
/// Set the symbol visibility of type information (vtable and RTTI)
@ -498,7 +440,10 @@ void CodeGenModule::SetLLVMFunctionAttributesForDefinition(const Decl *D,
void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
setGlobalVisibility(GV, D);
if (isa<NamedDecl>(D))
setGlobalVisibility(GV, cast<NamedDecl>(D));
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
if (D->hasAttr<UsedAttr>())
AddUsedGlobal(GV);

View File

@ -257,12 +257,9 @@ public:
static void DecorateInstruction(llvm::Instruction *Inst,
llvm::MDNode *TBAAInfo);
/// getDeclVisibilityMode - Compute the visibility of the decl \arg D.
LangOptions::VisibilityMode getDeclVisibilityMode(const Decl *D) const;
/// setGlobalVisibility - Set the visibility for the given LLVM
/// GlobalValue.
void setGlobalVisibility(llvm::GlobalValue *GV, const Decl *D) const;
void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
/// setTypeVisibility - Set the visibility for the given global
/// value which holds information about a type.

View File

@ -624,12 +624,12 @@ static void LangOptsToArgs(const LangOptions &Opts,
Res.push_back("-fobjc-gc-only");
}
}
if (Opts.getVisibilityMode() != LangOptions::Default) {
if (Opts.getVisibilityMode() != DefaultVisibility) {
Res.push_back("-fvisibility");
if (Opts.getVisibilityMode() == LangOptions::Hidden) {
if (Opts.getVisibilityMode() == HiddenVisibility) {
Res.push_back("hidden");
} else {
assert(Opts.getVisibilityMode() == LangOptions::Protected &&
assert(Opts.getVisibilityMode() == ProtectedVisibility &&
"Invalid visibility!");
Res.push_back("protected");
}
@ -1304,11 +1304,11 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
llvm::StringRef Vis = Args.getLastArgValue(OPT_fvisibility, "default");
if (Vis == "default")
Opts.setVisibilityMode(LangOptions::Default);
Opts.setVisibilityMode(DefaultVisibility);
else if (Vis == "hidden")
Opts.setVisibilityMode(LangOptions::Hidden);
Opts.setVisibilityMode(HiddenVisibility);
else if (Vis == "protected")
Opts.setVisibilityMode(LangOptions::Protected);
Opts.setVisibilityMode(ProtectedVisibility);
else
Diags.Report(diag::err_drv_invalid_value)
<< Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis;

View File

@ -2526,7 +2526,7 @@ bool ASTReader::ParseLanguageOptions(
PARSE_LANGOPT(CharIsSigned);
PARSE_LANGOPT(ShortWChar);
LangOpts.setGCMode((LangOptions::GCMode)Record[Idx++]);
LangOpts.setVisibilityMode((LangOptions::VisibilityMode)Record[Idx++]);
LangOpts.setVisibilityMode((Visibility)Record[Idx++]);
LangOpts.setStackProtectorMode((LangOptions::StackProtectorMode)
Record[Idx++]);
PARSE_LANGOPT(InstantiationDepth);

View File

@ -6,5 +6,6 @@ struct {
const char *name;
param_t par;
} *ptr;
void test_ptr() { (void) ptr; } // forced use
// CHECK: type { i8*, {{i..}} }

View File

@ -18,23 +18,26 @@ namespace ZeroInit {
// CHECK: @_ZN8ZeroInit1bE = global i64 -1,
int A::* b = 0;
// CHECK: @_ZN8ZeroInit2saE = global %struct.anon { i64 -1 }
// CHECK: @_ZN8ZeroInit2saE = internal global %struct.anon { i64 -1 }
struct {
int A::*a;
} sa;
void test_sa() { (void) sa; } // force emission
// CHECK: @_ZN8ZeroInit3ssaE =
// CHECK: @_ZN8ZeroInit3ssaE = internal
// CHECK: [2 x i64] [i64 -1, i64 -1]
struct {
int A::*aa[2];
} ssa[2];
void test_ssa() { (void) ssa; }
// CHECK: @_ZN8ZeroInit2ssE = global %1 { %struct.anon { i64 -1 } }
// CHECK: @_ZN8ZeroInit2ssE = internal global %1 { %struct.anon { i64 -1 } }
struct {
struct {
int A::*pa;
} s;
} ss;
void test_ss() { (void) ss; }
struct A {
int A::*a;

View File

@ -1,11 +1,15 @@
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
// RUN: %clang_cc1 %s -triple=x86_64-apple-darwin10 -fvisibility hidden -emit-llvm -o - | FileCheck %s -check-prefix=CHECK-HIDDEN
#define HIDDEN __attribute__((visibility("hidden")))
#define PROTECTED __attribute__((visibility("protected")))
#define DEFAULT __attribute__((visibility("default")))
// CHECK: @_ZN5Test425VariableInHiddenNamespaceE = hidden global i32 10
// CHECK: @_ZN5Test71aE = hidden global
// CHECK: @_ZN5Test71bE = global
// CHECK: @_ZTVN5Test63fooE = weak_odr hidden constant
namespace Test1 {
// CHECK: define hidden void @_ZN5Test11fEv
void HIDDEN f() { }
@ -82,3 +86,32 @@ namespace Test6 {
barc::barc() {}
}
namespace Test7 {
class HIDDEN A {};
A a; // top of file
template <A&> struct Aref {
static void foo() {}
};
class B : public A {};
B b; // top of file
// CHECK: define linkonce_odr hidden void @_ZN5Test74ArefILZNS_1aEEE3fooEv()
void test() {
Aref<a>::foo();
}
}
namespace Test8 {
void foo();
void bar() {}
// CHECK-HIDDEN: define hidden void @_ZN5Test83barEv()
// CHECK-HIDDEN: declare void @_ZN5Test83fooEv()
void test() {
foo();
bar();
}
}

View File

@ -192,7 +192,7 @@ struct SuperPair : Pair<int, int>, Pair<T, U> { };
// CHECK-USRS: index-templates.cpp c:index-templates.cpp@210 Extent=[8:19 - 8:20]
// CHECK-USRS: index-templates.cpp c:index-templates.cpp@222 Extent=[8:31 - 8:36]
// CHECK-USRS: index-templates.cpp c:@CT>2#T#T@vector@F@clear# Extent=[10:8 - 10:15]
// CHECK-USRS: index-templates.cpp c:index-templates.cpp@280@CP>1#T@vector>#*t0.0#>@CT>1#T@allocator1S0_ Extent=[13:1 - 14:21]
// CHECK-USRS: index-templates.cpp c:@CP>1#T@vector>#*t0.0#>@CT>1#T@allocator1S0_ Extent=[13:1 - 14:21]
// CHECK-USRS: index-templates.cpp c:index-templates.cpp@298 Extent=[13:19 - 13:20]
// CHECK-USRS: index-templates.cpp c:@S@Z1 Extent=[16:1 - 16:14]
// CHECK-USRS: index-templates.cpp c:@C@vector>#$@S@Z1#$@C@allocator>#S0_ Extent=[18:1 - 18:22]