Merge pull request #104 from benlangmuir/index-hash-crash-4

[index] Don't add relation to a NamedDecl with no name
diff --git a/lib/Index/IndexingContext.cpp b/lib/Index/IndexingContext.cpp
index 8a6e7fd..0af1315 100644
--- a/lib/Index/IndexingContext.cpp
+++ b/lib/Index/IndexingContext.cpp
@@ -274,6 +274,12 @@
   return false;
 }
 
+/// Whether the given NamedDecl should be skipped because it has no name.
+static bool shouldSkipNamelessDecl(const NamedDecl *ND) {
+  return ND->getDeclName().isEmpty() && !isa<TagDecl>(ND) &&
+         !isa<ObjCCategoryDecl>(ND);
+}
+
 static const Decl *adjustParent(const Decl *Parent) {
   if (!Parent)
     return nullptr;
@@ -288,8 +294,8 @@
     } else if (auto RD = dyn_cast<RecordDecl>(Parent)) {
       if (RD->isAnonymousStructOrUnion())
         continue;
-    } else if (auto FD = dyn_cast<FieldDecl>(Parent)) {
-      if (FD->getDeclName().isEmpty())
+    } else if (auto ND = dyn_cast<NamedDecl>(Parent)) {
+      if (shouldSkipNamelessDecl(ND))
         continue;
     }
     return Parent;
@@ -359,9 +365,7 @@
                                            const DeclContext *ContainerDC) {
   if (D->isImplicit() && !(isa<ObjCMethodDecl>(D) || isa<ObjCIvarDecl>(D)))
     return true;
-  if (!isa<NamedDecl>(D) ||
-      (cast<NamedDecl>(D)->getDeclName().isEmpty() &&
-       !isa<TagDecl>(D) && !isa<ObjCCategoryDecl>(D)))
+  if (!isa<NamedDecl>(D) || shouldSkipNamelessDecl(cast<NamedDecl>(D)))
     return true;
 
   SourceManager &SM = Ctx->getSourceManager();
diff --git a/test/Index/Core/index-source-invalid-name.cpp b/test/Index/Core/index-source-invalid-name.cpp
new file mode 100644
index 0000000..1b4b059
--- /dev/null
+++ b/test/Index/Core/index-source-invalid-name.cpp
@@ -0,0 +1,13 @@
+// RUN: c-index-test core -print-source-symbols -- %s -std=c++1z -target x86_64-apple-macosx10.7 | FileCheck %s
+
+namespace rdar32474406 {
+// CHECK: [[@LINE+1]]:6 | function/C | foo | c:@N@rdar32474406@F@foo# | __ZN12rdar324744063fooEv | Decl,RelChild | rel: 1
+void foo();
+// CHECK: [[@LINE+1]]:16 | type-alias/C | Func_t | c:index-source-invalid-name.cpp@N@rdar32474406@T@Func_t | <no-cgname> | Def,RelChild | rel: 1
+typedef void (*Func_t)();
+// CHECK: [[@LINE+4]]:1 | type-alias/C | Func_t | c:index-source-invalid-name.cpp@N@rdar32474406@T@Func_t | <no-cgname> | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | rdar32474406 | c:@N@rdar32474406
+// CHECK: [[@LINE+2]]:14 | function/C | foo | c:@N@rdar32474406@F@foo# | __ZN12rdar324744063fooEv | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | rdar32474406 | c:@N@rdar32474406
+Func_t[] = { foo }; // invalid decomposition
+}
diff --git a/test/Index/Store/record-hash-crash-invalid-name.cpp b/test/Index/Store/record-hash-crash-invalid-name.cpp
new file mode 100644
index 0000000..4479789
--- /dev/null
+++ b/test/Index/Store/record-hash-crash-invalid-name.cpp
@@ -0,0 +1,17 @@
+// Makes sure it doesn't crash.
+
+// XFAIL: linux
+
+// RUN: rm -rf %t
+// RUN: not %clang_cc1 %s -index-store-path %t/idx -std=c++14
+// RUN: c-index-test core -print-record %t/idx | FileCheck %s
+
+namespace rdar32474406 {
+void foo();
+typedef void (*Func_t)();
+// CHECK: [[@LINE+4]]:1 | type-alias/C | c:record-hash-crash-invalid-name.cpp@N@rdar32474406@T@Func_t | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | c:@N@rdar32474406
+// CHECK: [[@LINE+2]]:14 | function/C | c:@N@rdar32474406@F@foo# | Ref,RelCont | rel: 1
+// CHECK-NEXT: RelCont | c:@N@rdar32474406
+Func_t[] = { foo }; // invalid decomposition
+}