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()))