First pass at collecting access-specifier information along inheritance paths.
Triggers lots of assertions about missing access information;  fix them.

Will actually consume this information soon.



git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@94038 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Sema/Lookup.h b/lib/Sema/Lookup.h
index 33d1106..274a3da 100644
--- a/lib/Sema/Lookup.h
+++ b/lib/Sema/Lookup.h
@@ -245,10 +245,16 @@
     return IDNS;
   }
 
-  /// \brief Add a declaration to these results with no access bits.
+  /// \brief Add a declaration to these results with its natural access.
   /// Does not test the acceptance criteria.
   void addDecl(NamedDecl *D) {
-    Decls.addDecl(D);
+    addDecl(D, D->getAccess());
+  }
+
+  /// \brief Add a declaration to these results with the given access.
+  /// Does not test the acceptance criteria.
+  void addDecl(NamedDecl *D, AccessSpecifier AS) {
+    Decls.addDecl(D, AS);
     ResultKind = Found;
   }
 
diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp
index 1e46787..7e86120 100644
--- a/lib/Sema/SemaDecl.cpp
+++ b/lib/Sema/SemaDecl.cpp
@@ -1305,6 +1305,9 @@
 
   // Keep a chain of previous declarations.
   New->setPreviousDeclaration(Old);
+
+  // Inherit access appropriately.
+  New->setAccess(Old->getAccess());
 }
 
 static void MarkLive(CFGBlock *e, llvm::BitVector &live) {
@@ -3361,6 +3364,10 @@
   }
 
   if (D.getCXXScopeSpec().isSet() && !NewFD->isInvalidDecl()) {
+    // Fake up an access specifier if it's supposed to be a class member.
+    if (isa<CXXRecordDecl>(NewFD->getDeclContext()))
+      NewFD->setAccess(AS_public);
+
     // An out-of-line member function declaration must also be a
     // definition (C++ [dcl.meaning]p1).
     // Note that this is not the case for explicit specializations of
diff --git a/lib/Sema/SemaLookup.cpp b/lib/Sema/SemaLookup.cpp
index da76267..ddce4a4 100644
--- a/lib/Sema/SemaLookup.cpp
+++ b/lib/Sema/SemaLookup.cpp
@@ -445,8 +445,9 @@
 
   DeclContext::lookup_const_iterator I, E;
   for (llvm::tie(I, E) = DC->lookup(R.getLookupName()); I != E; ++I) {
-    if (R.isAcceptableDecl(*I)) {
-      R.addDecl(*I);
+    NamedDecl *D = *I;
+    if (R.isAcceptableDecl(D)) {
+      R.addDecl(D);
       Found = true;
     }
   }
@@ -1047,10 +1048,15 @@
   // FIXME: support using declarations!
   QualType SubobjectType;
   int SubobjectNumber = 0;
+  AccessSpecifier SubobjectAccess = AS_private;
   for (CXXBasePaths::paths_iterator Path = Paths.begin(), PathEnd = Paths.end();
        Path != PathEnd; ++Path) {
     const CXXBasePathElement &PathElement = Path->back();
 
+    // Pick the best (i.e. most permissive i.e. numerically lowest) access
+    // across all paths.
+    SubobjectAccess = std::min(SubobjectAccess, Path->Access);
+    
     // Determine whether we're looking at a distinct sub-object or not.
     if (SubobjectType.isNull()) {
       // This is the first subobject we've looked at. Record its type.
@@ -1106,7 +1112,7 @@
 
   DeclContext::lookup_iterator I, E;
   for (llvm::tie(I,E) = Paths.front().Decls; I != E; ++I)
-    R.addDecl(*I);
+    R.addDecl(*I, std::max(SubobjectAccess, (*I)->getAccess()));
   R.resolveKind();
   return true;
 }
diff --git a/lib/Sema/SemaTemplateInstantiateDecl.cpp b/lib/Sema/SemaTemplateInstantiateDecl.cpp
index e3a180a..c3768b3 100644
--- a/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -150,6 +150,7 @@
     Typedef->setPreviousDeclaration(cast<TypedefDecl>(InstPrev));
   }
 
+  Typedef->setAccess(D->getAccess());
   Owner->addDecl(Typedef);
 
   return Typedef;
@@ -208,6 +209,8 @@
   if (D->isOutOfLine())
     Var->setLexicalDeclContext(D->getLexicalDeclContext());
 
+  Var->setAccess(D->getAccess());
+
   // FIXME: In theory, we could have a previous declaration for variables that
   // are not static data members.
   bool Redeclaration = false;
@@ -375,6 +378,7 @@
   }
 
   Field->setImplicit(D->isImplicit());
+  Field->setAccess(D->getAccess());
   Owner->addDecl(Field);
 
   return Field;
@@ -559,6 +563,7 @@
     return Inst;
   }
   
+  Inst->setAccess(D->getAccess());
   Owner->addDecl(Inst);
   
   // First, we sort the partial specializations by location, so 
@@ -634,6 +639,8 @@
   if (!Instantiated)
     return 0;
 
+  Instantiated->setAccess(D->getAccess());
+
   // Link the instantiated function template declaration to the function
   // template from which it was instantiated.
   FunctionTemplateDecl *InstTemplate 
@@ -964,6 +971,8 @@
   if (D->isPure())
     SemaRef.CheckPureMethod(Method, SourceRange());
 
+  Method->setAccess(D->getAccess());
+
   if (!FunctionTemplate && (!Method->isInvalidDecl() || Previous.empty()) &&
       !Method->getFriendObjectKind())
     Owner->addDecl(Method);