Complain about attempts to use 'protected' visibility on targets
like Darwin that don't support it.  We should also complain about
invalid -fvisibility=protected, but that information doesn't seem
to exist at the most appropriate time, so I've left a FIXME behind.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149186 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Basic/Targets.cpp b/lib/Basic/Targets.cpp
index 5cdb36f..5dc63e7 100644
--- a/lib/Basic/Targets.cpp
+++ b/lib/Basic/Targets.cpp
@@ -218,6 +218,12 @@
     return "__TEXT,__StaticInit,regular,pure_instructions";
   }
 
+  /// Darwin does not support protected visibility.  Darwin's "default"
+  /// is very similar to ELF's "protected";  Darwin requires a "weak"
+  /// attribute on declarations that can be dynamically replaced.
+  virtual bool hasProtectedVisibility() const {
+    return false;
+  }
 };
 
 
diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp
index a189155..e9bb303 100644
--- a/lib/Frontend/CompilerInvocation.cpp
+++ b/lib/Frontend/CompilerInvocation.cpp
@@ -1792,6 +1792,7 @@
   else if (Vis == "hidden")
     Opts.setVisibilityMode(HiddenVisibility);
   else if (Vis == "protected")
+    // FIXME: diagnose if target does not support protected visibility
     Opts.setVisibilityMode(ProtectedVisibility);
   else
     Diags.Report(diag::err_drv_invalid_value)
diff --git a/lib/Sema/SemaDeclAttr.cpp b/lib/Sema/SemaDeclAttr.cpp
index aa827a4..d4b9988 100644
--- a/lib/Sema/SemaDeclAttr.cpp
+++ b/lib/Sema/SemaDeclAttr.cpp
@@ -1694,9 +1694,16 @@
     type = VisibilityAttr::Hidden;
   else if (TypeStr == "internal")
     type = VisibilityAttr::Hidden; // FIXME
-  else if (TypeStr == "protected")
-    type = VisibilityAttr::Protected;
-  else {
+  else if (TypeStr == "protected") {
+    // Complain about attempts to use protected visibility on targets
+    // (like Darwin) that don't support it.
+    if (!S.Context.getTargetInfo().hasProtectedVisibility()) {
+      S.Diag(Attr.getLoc(), diag::warn_attribute_protected_visibility);
+      type = VisibilityAttr::Default;
+    } else {
+      type = VisibilityAttr::Protected;
+    }
+  } else {
     S.Diag(Attr.getLoc(), diag::warn_attribute_unknown_visibility) << TypeStr;
     return;
   }