forked from OSchip/llvm-project
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:
parent
0196aa28ec
commit
457a04e3ce
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
@ -1192,6 +1233,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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
static LVPair getLVForTemplateArgumentList(const TemplateArgument *Args,
|
||||
unsigned NumArgs) {
|
||||
Linkage L = ExternalLinkage;
|
||||
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(),
|
||||
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(),
|
||||
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,13 +169,28 @@ 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
|
||||
|
@ -164,9 +198,34 @@ static Linkage getLinkageForNamespaceScopeDecl(const NamedDecl *D) {
|
|||
//
|
||||
// - 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)) {
|
||||
// From the template. Note below the restrictions on how we
|
||||
// compute template visibility.
|
||||
LV = merge(LV, Spec->getSpecializedTemplate()->getLinkageAndVisibility());
|
||||
|
||||
// The arguments at which the template was instantiated.
|
||||
const TemplateArgumentList &TemplateArgs = Spec->getTemplateArgs();
|
||||
Linkage L = getLinkageForTemplateArgumentList(TemplateArgs);
|
||||
return minLinkage(L, Spec->getSpecializedTemplate()->getLinkage());
|
||||
LV = merge(LV, getLVForTemplateArgumentList(TemplateArgs));
|
||||
|
||||
if (Spec->getTemplateSpecializationKind()
|
||||
== TSK_ExplicitInstantiationDeclaration)
|
||||
ConsiderDashFVisibility = false;
|
||||
}
|
||||
|
||||
return ExternalLinkage;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
static Linkage getLinkageForClassMember(const NamedDecl *D) {
|
||||
// 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 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 (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) {
|
||||
// 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 (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,33 +496,47 @@ 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 {
|
||||
|
|
|
@ -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;
|
||||
ensureCachedProperties();
|
||||
return TypeBits.getLinkage();
|
||||
}
|
||||
|
||||
return static_cast<clang::Linkage>(TypeBits.CachedLinkage);
|
||||
/// \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;
|
||||
ensureCachedProperties();
|
||||
return TypeBits.hasLocalOrUnnamedType();
|
||||
}
|
||||
|
||||
return TypeBits.CachedLocalOrUnnamed;
|
||||
std::pair<Linkage,Visibility> Type::getLinkageAndVisibility() const {
|
||||
if (this != CanonicalType.getTypePtr())
|
||||
return CanonicalType->getLinkageAndVisibility();
|
||||
|
||||
ensureCachedProperties();
|
||||
return std::make_pair(TypeBits.getLinkage(), TypeBits.getVisibility());
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
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(),
|
||||
|
||||
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 Cached;
|
||||
}
|
||||
|
||||
return std::make_pair(L, UnnamedOrLocal);
|
||||
Type::CachedProperties ObjCInterfaceType::getCachedProperties() const {
|
||||
std::pair<Linkage,Visibility> LV = getDecl()->getLinkageAndVisibility();
|
||||
return CachedProperties(LV.first, LV.second, false);
|
||||
}
|
||||
|
||||
std::pair<Linkage, bool> ObjCObjectType::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);
|
||||
}
|
||||
|
||||
std::pair<Linkage, bool>
|
||||
ObjCObjectPointerType::getLinkageUnnamedLocalImpl() const {
|
||||
return std::make_pair(ExternalLinkage, false);
|
||||
Type::CachedProperties ObjCObjectPointerType::getCachedProperties() const {
|
||||
return Type::getCachedProperties(PointeeType);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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));
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -6,5 +6,6 @@ struct {
|
|||
const char *name;
|
||||
param_t par;
|
||||
} *ptr;
|
||||
void test_ptr() { (void) ptr; } // forced use
|
||||
|
||||
// CHECK: type { i8*, {{i..}} }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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]
|
||||
|
|
Loading…
Reference in New Issue