Implement CXCursor support for walking C++ base specifiers.  This includes adding the API hooks clang_isVirtualBase() and clang_getCXXAccessSpecifier() to query properties of the base specifier.

Implements <rdar://problem/8274883>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112296 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 4ec2bf4..2361f42 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -285,6 +285,7 @@
   // Declaration visitors
   bool VisitAttributes(Decl *D);
   bool VisitBlockDecl(BlockDecl *B);
+  bool VisitCXXRecordDecl(CXXRecordDecl *D);
   bool VisitDeclContext(DeclContext *DC);
   bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
   bool VisitTypedefDecl(TypedefDecl *D);
@@ -1080,6 +1081,19 @@
   return false;
 }
 
+bool CursorVisitor::VisitCXXRecordDecl(CXXRecordDecl *D) {
+  if (D->isDefinition()) {
+    for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+         E = D->bases_end(); I != E; ++I) {
+      if (Visit(cxcursor::MakeCursorCXXBaseSpecifier(I, TU)))
+        return true;
+    }
+  }
+
+  return VisitTagDecl(D);
+}
+
+
 bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
   return Visit(B->getBlockDecl());
 }
@@ -1825,6 +1839,10 @@
       assert(OID && "getCursorSpelling(): Missing protocol decl");
       return createCXString(OID->getIdentifier()->getNameStart());
     }
+    case CXCursor_CXXBaseSpecifier: {
+      CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
+      return createCXString(B->getType().getAsString());
+    }
     case CXCursor_TypeRef: {
       TypeDecl *Type = getCursorTypeRef(C).first;
       assert(Type && "Missing type decl");
@@ -1953,6 +1971,8 @@
     return createCXString("Namespace");
   case CXCursor_LinkageSpec:
     return createCXString("LinkageSpec");
+  case CXCursor_CXXBaseSpecifier:
+    return createCXString("C++ base class specifier");  
   }
 
   llvm_unreachable("Unhandled CXCursorKind");
@@ -2076,6 +2096,11 @@
       std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
       return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
     }
+    
+    case CXCursor_CXXBaseSpecifier: {
+      // FIXME: Figure out what location to return for a CXXBaseSpecifier.
+      return clang_getNullLocation();
+    }
 
     default:
       // FIXME: Need a way to enumerate all non-reference cases.
@@ -2129,6 +2154,10 @@
 
     case CXCursor_TypeRef:
       return getCursorTypeRef(C).second;
+      
+    case CXCursor_CXXBaseSpecifier:
+      // FIXME: Figure out what source range to use for a CXBaseSpecifier.
+      return SourceRange();
 
     default:
       // FIXME: Need a way to enumerate all non-reference cases.
@@ -2202,6 +2231,12 @@
 
     case CXCursor_TypeRef:
       return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
+      
+    case CXCursor_CXXBaseSpecifier: {
+      CXXBaseSpecifier *B = cxcursor::getCursorCXXBaseSpecifier(C);
+      return clang_getTypeDeclaration(cxtype::MakeCXType(B->getType(),
+                                                         CXXUnit));
+    }
 
     default:
       // We would prefer to enumerate all non-reference cursor kinds here.