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/AST/CXXInheritance.cpp b/lib/AST/CXXInheritance.cpp
index 92a58b7..d575ccd 100644
--- a/lib/AST/CXXInheritance.cpp
+++ b/lib/AST/CXXInheritance.cpp
@@ -61,6 +61,7 @@
   Paths.clear();
   ClassSubobjects.clear();
   ScratchPath.clear();
+  ScratchAccess.clear();
   DetectedVirtual = 0;
 }
 
@@ -145,7 +146,7 @@
                                   void *UserData,
                                   CXXBasePaths &Paths) const {
   bool FoundPath = false;
-  
+
   ASTContext &Context = getASTContext();
   for (base_class_const_iterator BaseSpec = bases_begin(),
          BaseSpecEnd = bases_end(); BaseSpec != BaseSpecEnd; ++BaseSpec) {
@@ -189,6 +190,17 @@
       else
         Element.SubobjectNumber = Subobjects.second;
       Paths.ScratchPath.push_back(Element);
+
+      // C++0x [class.access.base]p1 (paraphrased):
+      //   The access of a member of a base class is the less permissive
+      //   of its access within the base class and the access of the base
+      //   class within the derived class.
+      // We're just calculating the access along the path, so we ignore
+      // the access specifiers of whatever decls we've found.
+      AccessSpecifier PathAccess = Paths.ScratchPath.Access;
+      Paths.ScratchAccess.push_back(PathAccess);
+      Paths.ScratchPath.Access
+        = std::max(PathAccess, BaseSpec->getAccessSpecifier());
     }
         
     if (BaseMatches(BaseSpec, Paths.ScratchPath, UserData)) {
@@ -223,8 +235,12 @@
     
     // Pop this base specifier off the current path (if we're
     // collecting paths).
-    if (Paths.isRecordingPaths())
+    if (Paths.isRecordingPaths()) {
       Paths.ScratchPath.pop_back();
+      Paths.ScratchPath.Access = Paths.ScratchAccess.back();
+      Paths.ScratchAccess.pop_back();
+    }
+
     // If we set a virtual earlier, and this isn't a path, forget it again.
     if (SetVirtual && !FoundPath) {
       Paths.DetectedVirtual = 0;
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 76ff834..95b749b 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -410,9 +410,16 @@
 
 #ifndef NDEBUG
 void Decl::CheckAccessDeclContext() const {
-  // If the decl is the toplevel translation unit or if we're not in a
-  // record decl context, we don't need to check anything.
+  // Suppress this check if any of the following hold:
+  // 1. this is the translation unit (and thus has no parent)
+  // 2. this is a template parameter (and thus doesn't belong to its context)
+  // 3. this is a ParmVarDecl (which can be in a record context during
+  //    the brief period between its creation and the creation of the
+  //    FunctionDecl)
+  // 4. the context is not a record
   if (isa<TranslationUnitDecl>(this) ||
+      isTemplateParameter() ||
+      isa<ParmVarDecl>(this) ||
       !isa<CXXRecordDecl>(getDeclContext()))
     return;