Emulate a MSVC bug where if during an using declaration name lookup, the declaration found is unaccessible (private) and that declaration was bring into scope via another using declaration whose target declaration is accessible (public) then no error is generated.

Example:
class A { public: int f();  };
class B : public A { private: using A::f; };
class C : public B { private: using B::f; };

Here, B::f is private so this should fail in Standard C++, but because B::f refers to A::f which is public MSVC accepts it.

This fixes 1 error when parsing MFC code with clang.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@131896 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index e92d19d..0eb9854 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -146,8 +146,10 @@
                MemberNonce _,
                CXXRecordDecl *NamingClass,
                DeclAccessPair FoundDecl,
-               QualType BaseObjectType)
-    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType) {
+               QualType BaseObjectType,
+               bool IsUsingDecl = false)
+    : AccessedEntity(Context, Member, NamingClass, FoundDecl, BaseObjectType),
+      IsUsingDeclaration(IsUsingDecl) {
     initialize();
   }
 
@@ -216,6 +218,7 @@
     DeclaringClass = DeclaringClass->getCanonicalDecl();
   }
 
+  bool IsUsingDeclaration : 1;
   bool HasInstanceContext : 1;
   mutable bool CalculatedInstanceContext : 1;
   mutable const CXXRecordDecl *InstanceContext;
@@ -1129,6 +1132,44 @@
   DiagnoseAccessPath(S, EC, Entity);
 }
 
+/// MSVC has a bug where if during an using declaration name lookup, 
+/// the declaration found is unaccessible (private) and that declaration 
+/// was bring into scope via another using declaration whose target
+/// declaration is accessible (public) then no error is generated.
+/// Example:
+///   class A {
+///   public:
+///     int f();
+///   };
+///   class B : public A {
+///   private:
+///     using A::f;
+///   };
+///   class C : public B {
+///   private:
+///     using B::f;
+///   };
+///
+/// Here, B::f is private so this should fail in Standard C++, but 
+/// because B::f refers to A::f which is public MSVC accepts it.
+static bool IsMicrosoftUsingDeclarationAccessBug(Sema& S, 
+                                                 SourceLocation AccessLoc,
+                                                 AccessTarget &Entity) {
+  if (UsingShadowDecl *Shadow =
+                         dyn_cast<UsingShadowDecl>(Entity.getTargetDecl())) {
+    const NamedDecl *OrigDecl = Entity.getTargetDecl()->getUnderlyingDecl();
+    if (Entity.getTargetDecl()->getAccess() == AS_private && 
+        (OrigDecl->getAccess() == AS_public ||
+         OrigDecl->getAccess() == AS_protected)) {
+      S.Diag(AccessLoc, diag::war_ms_using_declaration_inaccessible) 
+        << Shadow->getUsingDecl()->getQualifiedNameAsString()
+        << OrigDecl->getQualifiedNameAsString();
+      return true;
+    }
+  }
+  return false;
+}
+
 /// Determines whether the accessed entity is accessible.  Public members
 /// have been weeded out by this point.
 static AccessResult IsAccessible(Sema &S,
@@ -1232,6 +1273,10 @@
                                          AccessTarget &Entity) {
   assert(Entity.getAccess() != AS_public && "called for public access!");
 
+  if (S.getLangOptions().Microsoft &&
+      IsMicrosoftUsingDeclarationAccessBug(S, Loc, Entity))
+    return AR_accessible;
+
   switch (IsAccessible(S, EC, Entity)) {
   case AR_dependent:
     DelayDependentAccess(S, EC, Loc, Entity);
@@ -1577,9 +1622,8 @@
     if (I.getAccess() != AS_public) {
       AccessTarget Entity(Context, AccessedEntity::Member,
                           R.getNamingClass(), I.getPair(),
-                          R.getBaseObjectType());
+                          R.getBaseObjectType(), R.isUsingDeclaration());
       Entity.setDiag(diag::err_access);
-
       CheckAccess(*this, R.getNameLoc(), Entity);
     }
   }
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index 4fc9bf1..8bf7cb6 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -5345,6 +5345,7 @@
   // Otherwise, look up the target name.
 
   LookupResult R(*this, NameInfo, LookupOrdinaryName);
+  R.setUsingDeclaration(true);
 
   // Unlike most lookups, we don't always want to hide tag
   // declarations: tag names are visible through the using declaration