[clang][Index] Mark references from Constructors and Destructors to class as NameReference

Summary:
In current indexing logic we get references to class itself when we see
a constructor/destructor which is only syntactically true. Semantically
this information is not correct. This patch marks that reference as
NameReference to let clients deal with it.

Reviewers: akyrtzi, gribozavr, nathawes, benlangmuir

Reviewed By: gribozavr, nathawes

Subscribers: nathawes, arphaman, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D58814

llvm-svn: 355668
diff --git a/clang/unittests/Index/IndexTests.cpp b/clang/unittests/Index/IndexTests.cpp
index 97051c0..59b4b2e 100644
--- a/clang/unittests/Index/IndexTests.cpp
+++ b/clang/unittests/Index/IndexTests.cpp
@@ -58,11 +58,13 @@
   Position WrittenPos;
   Position DeclPos;
   SymbolInfo SymInfo;
+  SymbolRoleSet Roles;
   // FIXME: add more information.
 };
 
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const TestSymbol &S) {
-  return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos;
+  return OS << S.QName << '[' << S.WrittenPos << ']' << '@' << S.DeclPos << '('
+            << static_cast<unsigned>(S.SymInfo.Kind) << ')';
 }
 
 class Indexer : public IndexDataConsumer {
@@ -84,6 +86,7 @@
     S.WrittenPos = Position::fromSourceLocation(Loc, AST->getSourceManager());
     S.DeclPos =
         Position::fromSourceLocation(D->getLocation(), AST->getSourceManager());
+    S.Roles = Roles;
     Symbols.push_back(std::move(S));
     return true;
   }
@@ -143,6 +146,7 @@
 MATCHER_P(WrittenAt, Pos, "") { return arg.WrittenPos == Pos; }
 MATCHER_P(DeclAt, Pos, "") { return arg.DeclPos == Pos; }
 MATCHER_P(Kind, SymKind, "") { return arg.SymInfo.Kind == SymKind; }
+MATCHER_P(HasRole, Role, "") { return arg.Roles & static_cast<unsigned>(Role); }
 
 TEST(IndexTest, Simple) {
   auto Index = std::make_shared<Indexer>();
@@ -257,6 +261,32 @@
               Contains(AllOf(QName("std::foo"), Kind(SymbolKind::Using))));
 }
 
+TEST(IndexTest, Constructors) {
+  std::string Code = R"cpp(
+    struct Foo {
+      Foo(int);
+      ~Foo();
+    };
+  )cpp";
+  auto Index = std::make_shared<Indexer>();
+  IndexingOptions Opts;
+  tooling::runToolOnCode(new IndexAction(Index, Opts), Code);
+  EXPECT_THAT(
+      Index->Symbols,
+      UnorderedElementsAre(
+          AllOf(QName("Foo"), Kind(SymbolKind::Struct),
+                WrittenAt(Position(2, 12))),
+          AllOf(QName("Foo::Foo"), Kind(SymbolKind::Constructor),
+                WrittenAt(Position(3, 7))),
+          AllOf(QName("Foo"), Kind(SymbolKind::Struct),
+                HasRole(SymbolRole::NameReference), WrittenAt(Position(3, 7))),
+          AllOf(QName("Foo::~Foo"), Kind(SymbolKind::Destructor),
+                WrittenAt(Position(4, 7))),
+          AllOf(QName("Foo"), Kind(SymbolKind::Struct),
+                HasRole(SymbolRole::NameReference),
+                WrittenAt(Position(4, 8)))));
+}
+
 } // namespace
 } // namespace index
 } // namespace clang