Better solution: calculate the visibility of functions and variables
independently of whether they're definitions, then teach IR generation to
ignore non-explicit visibility when emitting declarations. Use this to
make sure that RTTI, vtables, and VTTs get the right visibility.
More of rdar://problem/8613093
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117781 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/CodeGen/CGRTTI.cpp b/lib/CodeGen/CGRTTI.cpp
index 6dad2a0..d373b55 100644
--- a/lib/CodeGen/CGRTTI.cpp
+++ b/lib/CodeGen/CGRTTI.cpp
@@ -637,7 +637,7 @@
// compatibility.
if (const RecordType *RT = dyn_cast<RecordType>(Ty))
CGM.setTypeVisibility(GV, cast<CXXRecordDecl>(RT->getDecl()),
- /*ForRTTI*/ true);
+ /*ForRTTI*/ true, /*ForDefinition*/ true);
else if (CGM.getCodeGenOpts().HiddenWeakVTables &&
Linkage == llvm::GlobalValue::WeakODRLinkage)
GV->setVisibility(llvm::GlobalValue::HiddenVisibility);
diff --git a/lib/CodeGen/CGVTT.cpp b/lib/CodeGen/CGVTT.cpp
index 56acfc8..dccc4c8 100644
--- a/lib/CodeGen/CGVTT.cpp
+++ b/lib/CodeGen/CGVTT.cpp
@@ -397,7 +397,7 @@
llvm::GlobalVariable *OldGV = GV;
GV = new llvm::GlobalVariable(CGM.getModule(), Type, /*isConstant=*/true,
Linkage, Init, Name);
- CGM.setGlobalVisibility(GV, RD);
+ CGM.setGlobalVisibility(GV, RD, /*ForDefinition*/ GenerateDefinition);
if (OldGV) {
GV->takeName(OldGV);
diff --git a/lib/CodeGen/CGVTables.cpp b/lib/CodeGen/CGVTables.cpp
index e1ed98c..c4a0b45 100644
--- a/lib/CodeGen/CGVTables.cpp
+++ b/lib/CodeGen/CGVTables.cpp
@@ -2485,7 +2485,7 @@
static void setThunkVisibility(CodeGenModule &CGM, const CXXMethodDecl *MD,
const ThunkInfo &Thunk, llvm::Function *Fn) {
- CGM.setGlobalVisibility(Fn, MD);
+ CGM.setGlobalVisibility(Fn, MD, /*ForDef*/ true);
if (!CGM.getCodeGenOpts().HiddenWeakVTables)
return;
@@ -2989,7 +2989,7 @@
VTable->setLinkage(Linkage);
// Set the right visibility.
- CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false);
+ CGM.setTypeVisibility(VTable, RD, /*ForRTTI*/ false, /*ForDef*/ true);
}
llvm::GlobalVariable *
diff --git a/lib/CodeGen/CodeGenModule.cpp b/lib/CodeGen/CodeGenModule.cpp
index 558a8a3..d975a22 100644
--- a/lib/CodeGen/CodeGenModule.cpp
+++ b/lib/CodeGen/CodeGenModule.cpp
@@ -176,22 +176,28 @@
void CodeGenModule::setGlobalVisibility(llvm::GlobalValue *GV,
- const NamedDecl *D) const {
+ const NamedDecl *D,
+ bool IsForDefinition) const {
// Internal definitions always have default visibility.
if (GV->hasLocalLinkage()) {
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
return;
}
- GV->setVisibility(GetLLVMVisibility(D->getVisibility()));
+ // Set visibility for definitions.
+ NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
+ if (LV.visibilityExplicit() ||
+ (IsForDefinition && !GV->hasAvailableExternallyLinkage()))
+ GV->setVisibility(GetLLVMVisibility(LV.visibility()));
}
/// Set the symbol visibility of type information (vtable and RTTI)
/// associated with the given type.
void CodeGenModule::setTypeVisibility(llvm::GlobalValue *GV,
const CXXRecordDecl *RD,
- bool IsForRTTI) const {
- setGlobalVisibility(GV, RD);
+ bool IsForRTTI,
+ bool IsForDefinition) const {
+ setGlobalVisibility(GV, RD, IsForDefinition);
if (!CodeGenOpts.HiddenWeakVTables)
return;
@@ -444,7 +450,7 @@
void CodeGenModule::SetCommonAttributes(const Decl *D,
llvm::GlobalValue *GV) {
if (isa<NamedDecl>(D))
- setGlobalVisibility(GV, cast<NamedDecl>(D));
+ setGlobalVisibility(GV, cast<NamedDecl>(D), /*ForDef*/ true);
else
GV->setVisibility(llvm::GlobalValue::DefaultVisibility);
@@ -488,6 +494,11 @@
F->setLinkage(llvm::Function::ExternalWeakLinkage);
} else {
F->setLinkage(llvm::Function::ExternalLinkage);
+
+ NamedDecl::LinkageInfo LV = FD->getLinkageAndVisibility();
+ if (LV.linkage() == ExternalLinkage && LV.visibilityExplicit()) {
+ F->setVisibility(GetLLVMVisibility(LV.visibility()));
+ }
}
if (const SectionAttr *SA = FD->getAttr<SectionAttr>())
@@ -822,11 +833,11 @@
// If this the first reference to a C++ inline function in a class, queue up
// the deferred function body for emission. These are not seen as
// top-level declarations.
- if (FD->isThisDeclarationADefinition() && MayDeferGeneration(FD))
+ if (FD->isThisDeclarationADefinition() && MayDeferGeneration(FD)) {
DeferredDeclsToEmit.push_back(D);
// A called constructor which has no definition or declaration need be
// synthesized.
- else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
+ } else if (const CXXConstructorDecl *CD = dyn_cast<CXXConstructorDecl>(FD)) {
if (CD->isImplicit()) {
assert(CD->isUsed() && "Sema doesn't consider constructor as used.");
DeferredDeclsToEmit.push_back(D);
@@ -938,8 +949,8 @@
GV->setConstant(DeclIsConstantGlobal(Context, D));
// Set linkage and visibility in case we never see a definition.
- std::pair<Linkage,Visibility> LV = D->getLinkageAndVisibility();
- if (LV.first != ExternalLinkage) {
+ NamedDecl::LinkageInfo LV = D->getLinkageAndVisibility();
+ if (LV.linkage() != ExternalLinkage) {
GV->setLinkage(llvm::GlobalValue::InternalLinkage);
} else {
if (D->hasAttr<DLLImportAttr>())
@@ -947,7 +958,9 @@
else if (D->hasAttr<WeakAttr>() || D->hasAttr<WeakImportAttr>())
GV->setLinkage(llvm::GlobalValue::ExternalWeakLinkage);
- GV->setVisibility(GetLLVMVisibility(LV.second));
+ // Set visibility on a declaration only if it's explicit.
+ if (LV.visibilityExplicit())
+ GV->setVisibility(GetLLVMVisibility(LV.visibility()));
}
GV->setThreadLocal(D->isThreadSpecified());
diff --git a/lib/CodeGen/CodeGenModule.h b/lib/CodeGen/CodeGenModule.h
index 683f175..681ab0a 100644
--- a/lib/CodeGen/CodeGenModule.h
+++ b/lib/CodeGen/CodeGenModule.h
@@ -259,12 +259,13 @@
/// setGlobalVisibility - Set the visibility for the given LLVM
/// GlobalValue.
- void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D) const;
+ void setGlobalVisibility(llvm::GlobalValue *GV, const NamedDecl *D,
+ bool IsForDefinition) const;
/// setTypeVisibility - Set the visibility for the given global
/// value which holds information about a type.
void setTypeVisibility(llvm::GlobalValue *GV, const CXXRecordDecl *D,
- bool IsForRTTI) const;
+ bool IsForRTTI, bool IsForDefinition) const;
llvm::Constant *GetAddrOfGlobal(GlobalDecl GD) {
if (isa<CXXConstructorDecl>(GD.getDecl()))