Treat visibility on an enclosing namespace as a non-explicit source of
visibility.  Fixes PR8713.

I've disabled a test which was testing that you can #pragma pop visibility
to get out of a namespace's visibility attribute.  We should probably just
diagnose that as an error unless it's instrumental to someone's system
headers.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@121459 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAttr.cpp b/lib/Sema/SemaAttr.cpp
index 02b8289..de1e1bf 100644
--- a/lib/Sema/SemaAttr.cpp
+++ b/lib/Sema/SemaAttr.cpp
@@ -296,8 +296,8 @@
   }
 }
 
-typedef std::vector<std::pair<VisibilityAttr::VisibilityType,
-                              SourceLocation> > VisStack;
+typedef std::vector<std::pair<unsigned, SourceLocation> > VisStack;
+enum { NoVisibility = (unsigned) -1 };
 
 void Sema::AddPushedVisibilityAttribute(Decl *D) {
   if (!VisContext)
@@ -307,7 +307,11 @@
     return;
 
   VisStack *Stack = static_cast<VisStack*>(VisContext);
-  VisibilityAttr::VisibilityType type = Stack->back().first;
+  unsigned rawType = Stack->back().first;
+  if (rawType == NoVisibility) return;
+
+  VisibilityAttr::VisibilityType type
+    = (VisibilityAttr::VisibilityType) rawType;
   SourceLocation loc = Stack->back().second;
 
   D->addAttr(::new (Context) VisibilityAttr(loc, Context, type));
@@ -319,8 +323,7 @@
   VisContext = 0;
 }
 
-static void PushPragmaVisibility(Sema &S, VisibilityAttr::VisibilityType type,
-                                 SourceLocation loc) {
+static void PushPragmaVisibility(Sema &S, unsigned type, SourceLocation loc) {
   // Put visibility on stack.
   if (!S.VisContext)
     S.VisContext = new VisStack;
@@ -353,8 +356,12 @@
   }
 }
 
-void Sema::PushVisibilityAttr(const VisibilityAttr *Attr) {
-  PushPragmaVisibility(*this, Attr->getVisibility(), Attr->getLocation());
+void Sema::PushNamespaceVisibilityAttr(const VisibilityAttr *Attr) {
+  // Visibility calculations will consider the namespace's visibility.
+  // Here we just want to note that we're in a visibility context
+  // which overrides any enclosing #pragma context, but doesn't itself
+  // contribute visibility.
+  PushPragmaVisibility(*this, NoVisibility, SourceLocation());
 }
 
 void Sema::PopPragmaVisibility() {
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index bf9e935..b5e6321 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -3194,8 +3194,8 @@
 
   ProcessDeclAttributeList(DeclRegionScope, Namespc, AttrList);
 
-  if (const VisibilityAttr *attr = Namespc->getAttr<VisibilityAttr>())
-    PushVisibilityAttr(attr);
+  if (const VisibilityAttr *Attr = Namespc->getAttr<VisibilityAttr>())
+    PushNamespaceVisibilityAttr(Attr);
 
   if (II) {
     // C++ [namespace.def]p2: