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

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