Added CXAvailability_NotAccessible to indicate that a declaration is available, but not accessible from the current code completion context.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@141278 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/CodeCompleteConsumer.cpp b/lib/Sema/CodeCompleteConsumer.cpp
index 3db9e4d..ab69938 100644
--- a/lib/Sema/CodeCompleteConsumer.cpp
+++ b/lib/Sema/CodeCompleteConsumer.cpp
@@ -376,7 +376,7 @@
   }
 }
 
-void CodeCompletionResult::computeCursorKindAndAvailability() {
+void CodeCompletionResult::computeCursorKindAndAvailability(bool Accessible) {
   switch (Kind) {
   case RK_Declaration:
     // Set the availability based on attributes.
@@ -418,6 +418,9 @@
     // Do nothing: Patterns can come with cursor kinds!
     break;
   }
+
+  if (!Accessible)
+    Availability = CXAvailability_NotAccessible;
 }
 
 /// \brief Retrieve the name that should be used to order a result.
diff --git a/lib/Sema/SemaAccess.cpp b/lib/Sema/SemaAccess.cpp
index a2d078b..14c8eba 100644
--- a/lib/Sema/SemaAccess.cpp
+++ b/lib/Sema/SemaAccess.cpp
@@ -1641,6 +1641,27 @@
   }
 }
 
+/// Checks access to Decl from the given class. The check will take access
+/// specifiers into account, but no member access expressions and such.
+///
+/// \param Decl the declaration to check if it can be accessed
+/// \param Class the class/context from which to start the search
+/// \return true if the Decl is accessible from the Class, false otherwise.
+bool Sema::IsSimplyAccessible(NamedDecl *Decl, CXXRecordDecl *Class) {
+  if (!Class)
+    return true;
+
+  QualType qType = Class->getTypeForDecl()->getCanonicalTypeInternal();
+  AccessTarget Entity(Context, AccessedEntity::Member, Class,
+                      DeclAccessPair::make(Decl, Decl->getAccess()),
+                      qType);
+  if (Entity.getAccess() == AS_public)
+    return true;
+
+  EffectiveContext EC(CurContext);
+  return ::IsAccessible(*this, EC, Entity) != ::AR_inaccessible;
+}
+
 void Sema::ActOnStartSuppressingAccessChecks() {
   assert(!SuppressAccessChecking &&
          "Tried to start access check suppression when already started.");
diff --git a/lib/Sema/SemaCodeComplete.cpp b/lib/Sema/SemaCodeComplete.cpp
index 5b7f251..56b351c 100644
--- a/lib/Sema/SemaCodeComplete.cpp
+++ b/lib/Sema/SemaCodeComplete.cpp
@@ -1186,8 +1186,16 @@
     CodeCompletionDeclConsumer(ResultBuilder &Results, DeclContext *CurContext)
       : Results(Results), CurContext(CurContext) { }
     
-    virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass) {
-      Results.AddResult(ND, CurContext, Hiding, InBaseClass);
+    virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+                           bool InBaseClass) {
+      bool Accessible = true;
+      if (Ctx) {
+        if (CXXRecordDecl *Class = dyn_cast<CXXRecordDecl>(Ctx))
+          Accessible = Results.getSema().IsSimplyAccessible(ND, Class);
+        // FIXME: ObjC access checks are missing.
+      }
+      ResultBuilder::Result Result(ND, 0, false, Accessible);
+      Results.AddResult(Result, CurContext, Hiding, InBaseClass);
     }
   };
 }
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index f11737b..84ae42a 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -2701,7 +2701,7 @@
          D != DEnd; ++D) {
       if (NamedDecl *ND = dyn_cast<NamedDecl>(*D)) {
         if (Result.isAcceptableDecl(ND)) {
-          Consumer.FoundDecl(ND, Visited.checkHidden(ND), InBaseClass);
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), Ctx, InBaseClass);
           Visited.add(ND);
         }
       } else if (ObjCForwardProtocolDecl *ForwardProto
@@ -2712,14 +2712,15 @@
              P != PEnd;
              ++P) {
           if (Result.isAcceptableDecl(*P)) {
-            Consumer.FoundDecl(*P, Visited.checkHidden(*P), InBaseClass);
+            Consumer.FoundDecl(*P, Visited.checkHidden(*P), Ctx, InBaseClass);
             Visited.add(*P);
           }
         }
       } else if (ObjCClassDecl *Class = dyn_cast<ObjCClassDecl>(*D)) {
           ObjCInterfaceDecl *IFace = Class->getForwardInterfaceDecl();
           if (Result.isAcceptableDecl(IFace)) {
-            Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), InBaseClass);
+            Consumer.FoundDecl(IFace, Visited.checkHidden(IFace), Ctx,
+                               InBaseClass);
             Visited.add(IFace);
           }
       }
@@ -2861,7 +2862,7 @@
          D != DEnd; ++D) {
       if (NamedDecl *ND = dyn_cast<NamedDecl>(*D))
         if (Result.isAcceptableDecl(ND)) {
-          Consumer.FoundDecl(ND, Visited.checkHidden(ND), false);
+          Consumer.FoundDecl(ND, Visited.checkHidden(ND), 0, false);
           Visited.add(ND);
         }
     }
@@ -3043,7 +3044,8 @@
       delete I->second;
   }
   
-  virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, bool InBaseClass);
+  virtual void FoundDecl(NamedDecl *ND, NamedDecl *Hiding, DeclContext *Ctx,
+                         bool InBaseClass);
   void FoundName(StringRef Name);
   void addKeywordResult(StringRef Keyword);
   void addName(StringRef Name, NamedDecl *ND, unsigned Distance,
@@ -3074,7 +3076,7 @@
 }
 
 void TypoCorrectionConsumer::FoundDecl(NamedDecl *ND, NamedDecl *Hiding,
-                                       bool InBaseClass) {
+                                       DeclContext *Ctx, bool InBaseClass) {
   // Don't consider hidden names for typo correction.
   if (Hiding)
     return;