[index] Add 'Parameter' symbol kind and 'Local' symbol property to distinguish function-local symbols

Parameters have a 'child' relation to their function/method.
Also add an option '-include-locals' to 'c-index-test core' to enable indexing of function-local symbols.

Original patch from Nathan Hawes with some changes by me.
https://reviews.llvm.org/D30304

llvm-svn: 296282
diff --git a/clang/lib/Index/IndexBody.cpp b/clang/lib/Index/IndexBody.cpp
index 3aa0152..7681de7 100644
--- a/clang/lib/Index/IndexBody.cpp
+++ b/clang/lib/Index/IndexBody.cpp
@@ -269,7 +269,7 @@
       const Decl *D = *I;
       if (!D)
         continue;
-      if (!IndexCtx.isFunctionLocalDecl(D))
+      if (!isFunctionLocalSymbol(D))
         IndexCtx.indexTopLevelDecl(D);
     }
 
diff --git a/clang/lib/Index/IndexSymbol.cpp b/clang/lib/Index/IndexSymbol.cpp
index 84984fc..ba31569 100644
--- a/clang/lib/Index/IndexSymbol.cpp
+++ b/clang/lib/Index/IndexSymbol.cpp
@@ -49,6 +49,37 @@
   }
 }
 
+bool index::isFunctionLocalSymbol(const Decl *D) {
+  assert(D);
+
+  if (isa<ParmVarDecl>(D))
+    return true;
+
+  if (isa<TemplateTemplateParmDecl>(D))
+    return true;
+
+  if (isa<ObjCTypeParamDecl>(D))
+    return true;
+
+  if (!D->getParentFunctionOrMethod())
+    return false;
+
+  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
+    switch (ND->getFormalLinkage()) {
+      case NoLinkage:
+      case VisibleNoLinkage:
+      case InternalLinkage:
+        return true;
+      case UniqueExternalLinkage:
+        llvm_unreachable("Not a sema linkage");
+      case ExternalLinkage:
+        return false;
+    }
+  }
+
+  return true;
+}
+
 SymbolInfo index::getSymbolInfo(const Decl *D) {
   assert(D);
   SymbolInfo Info;
@@ -57,6 +88,10 @@
   Info.Properties = SymbolPropertySet();
   Info.Lang = SymbolLanguage::C;
 
+  if (isFunctionLocalSymbol(D)) {
+    Info.Properties |= (unsigned)SymbolProperty::Local;
+  }
+
   if (const TagDecl *TD = dyn_cast<TagDecl>(D)) {
     switch (TD->getTagKind()) {
     case TTK_Struct:
@@ -94,10 +129,13 @@
 
   } else if (auto *VD = dyn_cast<VarDecl>(D)) {
     Info.Kind = SymbolKind::Variable;
-    if (isa<CXXRecordDecl>(D->getDeclContext())) {
+    if (isa<ParmVarDecl>(D)) {
+      Info.Kind = SymbolKind::Parameter;
+    } else if (isa<CXXRecordDecl>(D->getDeclContext())) {
       Info.Kind = SymbolKind::StaticProperty;
       Info.Lang = SymbolLanguage::CXX;
     }
+
     if (isa<VarTemplatePartialSpecializationDecl>(D)) {
       Info.Lang = SymbolLanguage::CXX;
       Info.Properties |= (unsigned)SymbolProperty::Generic;
@@ -378,6 +416,7 @@
   case SymbolKind::Constructor: return "constructor";
   case SymbolKind::Destructor: return "destructor";
   case SymbolKind::ConversionFunction: return "coversion-func";
+  case SymbolKind::Parameter: return "param";
   }
   llvm_unreachable("invalid symbol kind");
 }
@@ -415,6 +454,7 @@
   APPLY_FOR_PROPERTY(IBAnnotated);
   APPLY_FOR_PROPERTY(IBOutletCollection);
   APPLY_FOR_PROPERTY(GKInspectable);
+  APPLY_FOR_PROPERTY(Local);
 
 #undef APPLY_FOR_PROPERTY
 }
@@ -434,6 +474,7 @@
     case SymbolProperty::IBAnnotated: OS << "IB"; break;
     case SymbolProperty::IBOutletCollection: OS << "IBColl"; break;
     case SymbolProperty::GKInspectable: OS << "GKI"; break;
+    case SymbolProperty::Local: OS << "local"; break;
     }
   });
 }
diff --git a/clang/lib/Index/IndexTypeSourceInfo.cpp b/clang/lib/Index/IndexTypeSourceInfo.cpp
index 38bbb30..cf32325 100644
--- a/clang/lib/Index/IndexTypeSourceInfo.cpp
+++ b/clang/lib/Index/IndexTypeSourceInfo.cpp
@@ -191,7 +191,7 @@
 }
 
 void IndexingContext::indexTagDecl(const TagDecl *D) {
-  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
     return;
 
   if (handleDecl(D)) {
diff --git a/clang/lib/Index/IndexingContext.cpp b/clang/lib/Index/IndexingContext.cpp
index 06b24ce..9a4028f 100644
--- a/clang/lib/Index/IndexingContext.cpp
+++ b/clang/lib/Index/IndexingContext.cpp
@@ -50,7 +50,7 @@
                                       ArrayRef<SymbolRelation> Relations,
                                       const Expr *RefE,
                                       const Decl *RefD) {
-  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalDecl(D))
+  if (!shouldIndexFunctionLocalSymbols() && isFunctionLocalSymbol(D))
     return true;
 
   if (isa<NonTypeTemplateParmDecl>(D) || isa<TemplateTypeParmDecl>(D))
@@ -100,34 +100,6 @@
   return DataConsumer.handleModuleOccurence(ImportD, Roles, FID, Offset);
 }
 
-bool IndexingContext::isFunctionLocalDecl(const Decl *D) {
-  assert(D);
-
-  if (isa<TemplateTemplateParmDecl>(D))
-    return true;
-
-  if (isa<ObjCTypeParamDecl>(D))
-    return true;
-
-  if (!D->getParentFunctionOrMethod())
-    return false;
-
-  if (const NamedDecl *ND = dyn_cast<NamedDecl>(D)) {
-    switch (ND->getFormalLinkage()) {
-    case NoLinkage:
-    case VisibleNoLinkage:
-    case InternalLinkage:
-      return true;
-    case UniqueExternalLinkage:
-      llvm_unreachable("Not a sema linkage");
-    case ExternalLinkage:
-      return false;
-    }
-  }
-
-  return true;
-}
-
 bool IndexingContext::isTemplateImplicitInstantiation(const Decl *D) {
   TemplateSpecializationKind TKind = TSK_Undeclared;
   if (const ClassTemplateSpecializationDecl *
@@ -316,12 +288,12 @@
   };
 
   if (Parent) {
-    if (IsRef) {
+    if (IsRef || (!isa<ParmVarDecl>(D) && isFunctionLocalSymbol(D))) {
       addRelation(SymbolRelation{
         (unsigned)SymbolRole::RelationContainedBy,
         Parent
       });
-    } else if (!cast<DeclContext>(Parent)->isFunctionOrMethod()) {
+    } else {
       addRelation(SymbolRelation{
         (unsigned)SymbolRole::RelationChildOf,
         Parent
diff --git a/clang/lib/Index/IndexingContext.h b/clang/lib/Index/IndexingContext.h
index dd1dd32..5f42158 100644
--- a/clang/lib/Index/IndexingContext.h
+++ b/clang/lib/Index/IndexingContext.h
@@ -58,7 +58,6 @@
     return false;
   }
 
-  static bool isFunctionLocalDecl(const Decl *D);
   static bool isTemplateImplicitInstantiation(const Decl *D);
 
   bool handleDecl(const Decl *D, SymbolRoleSet Roles = SymbolRoleSet(),