Merge visibility from all symbols with the same name.

The ELF spec says:

... if any reference to or definition of a name is a symbol with a
non-default visibility attribute, the visibility attribute must be
propagated to the resolving symbol in the linked object. If different
visibility attributes are specified for distinct references to or
definitions of a symbol, the most constraining visibility attribute
must be propagated to the resolving symbol in the linked object. The
attributes, ordered from least to most constraining, are:
STV_PROTECTED, STV_HIDDEN and STV_INTERNAL.

llvm-svn: 246603
diff --git a/lld/ELF/Symbols.cpp b/lld/ELF/Symbols.cpp
index f2b484d..37e0033 100644
--- a/lld/ELF/Symbols.cpp
+++ b/lld/ELF/Symbols.cpp
@@ -13,10 +13,19 @@
 #include "InputFiles.h"
 
 using namespace llvm::object;
+using namespace llvm::ELF;
 
 using namespace lld;
 using namespace lld::elf2;
 
+static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
+  if (VA == STV_DEFAULT)
+    return VB;
+  if (VB == STV_DEFAULT)
+    return VA;
+  return std::min(VA, VB);
+}
+
 // Returns 1, 0 or -1 if this symbol should take precedence
 // over the Other, tie or lose, respectively.
 template <class ELFT> int SymbolBody::compare(SymbolBody *Other) {
@@ -27,6 +36,11 @@
   if (L > R)
     return -Other->compare<ELFT>(this);
 
+  uint8_t LV = getMostConstrainingVisibility();
+  uint8_t RV = Other->getMostConstrainingVisibility();
+  MostConstrainingVisibility = getMinVisibility(LV, RV);
+  Other->MostConstrainingVisibility = MostConstrainingVisibility;
+
   if (L != R)
     return -1;