Change the semantics for Entity.

Entity can now refer to declarations that are not visible outside the translation unit.
It is a wrapper of a pointer union, it's either a Decl* for declarations that don't
"cross" translation units, or an EntityImpl* which is associated with the specific "visible" Decl.

Included is a test case for handling fields across translation units.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@76515 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/Index/Entity.cpp b/lib/Index/Entity.cpp
index 7a6c05c..feed3e4 100644
--- a/lib/Index/Entity.cpp
+++ b/lib/Index/Entity.cpp
@@ -12,9 +12,9 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "clang/Index/Entity.h"
-#include "clang/Index/Program.h"
+#include "EntityImpl.h"
 #include "ProgramImpl.h"
+#include "clang/Index/Program.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/ASTContext.h"
 #include "clang/AST/DeclVisitor.h"
@@ -33,97 +33,121 @@
 namespace idx {
 
 /// \brief Gets the Entity associated with a Decl.
-class EntityGetter : public DeclVisitor<EntityGetter, Entity *> {
+class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
   ProgramImpl &Prog;
-  
+
 public:
   EntityGetter(ProgramImpl &prog) : Prog(prog) { }
   
-  Entity *get(Entity *Parent, DeclarationName Name);
-  
-  Entity *VisitNamedDecl(NamedDecl *D);
-  Entity *VisitVarDecl(VarDecl *D);
-  Entity *VisitFunctionDecl(FunctionDecl *D); 
+  Entity VisitNamedDecl(NamedDecl *D);
+  Entity VisitVarDecl(VarDecl *D);
+  Entity VisitFunctionDecl(FunctionDecl *D); 
 };
 
 }
 }
 
-Entity *EntityGetter::get(Entity *Parent, DeclarationName Name) {
+Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
+  Entity Parent;
+  if (!D->getDeclContext()->isTranslationUnit()) {
+    Parent = Visit(cast<Decl>(D->getDeclContext()));
+    // FIXME: Anonymous structs ?
+    if (Parent.isInvalid())
+      return Entity();
+  }
+  if (Parent.isValid() && Parent.isInternalToTU())
+    return Entity(D);
+
   // FIXME: Only works for DeclarationNames that are identifiers.
 
+  DeclarationName Name = D->getDeclName();
+
   if (!Name.isIdentifier())
-    return 0;
+    return Entity();
 
   IdentifierInfo *II = Name.getAsIdentifierInfo();
   if (!II)
-      return 0;
+      return Entity();
 
-  ProgramImpl::IdEntryTy *Id =
+  EntityImpl::IdEntryTy *Id =
       &Prog.getIdents().GetOrCreateValue(II->getName(),
                                          II->getName() + II->getLength());
-  
+  unsigned IdNS = D->getIdentifierNamespace();
+
   llvm::FoldingSetNodeID ID;
-  Entity::Profile(ID, Parent, Id);
-  
+  EntityImpl::Profile(ID, Parent, Id, IdNS);
+
   ProgramImpl::EntitySetTy &Entities = Prog.getEntities();
   void *InsertPos = 0;
-  if (Entity *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
-    return Ent;
-  
-  void *Buf = Prog.Allocate(sizeof(Entity));
-  Entity *New = new (Buf) Entity(Parent, Id);
+  if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
+    return Entity(Ent);
+
+  void *Buf = Prog.Allocate(sizeof(EntityImpl));
+  EntityImpl *New = new (Buf) EntityImpl(Parent, Id, IdNS);
   Entities.InsertNode(New, InsertPos);
-  return New;
+  
+  return Entity(New);
 }
 
-Entity *EntityGetter::VisitNamedDecl(NamedDecl *D) {
-  // FIXME: Function declarations that are inside functions ?
-  if (!D->getDeclContext()->isFileContext())
-    return 0;
-
-  Entity *Parent = Visit(cast<Decl>(D->getDeclContext()));
-  return get(Parent, D->getDeclName());
-}
-
-Entity *EntityGetter::VisitVarDecl(VarDecl *D) {
+Entity EntityGetter::VisitVarDecl(VarDecl *D) {
   // If it's static it cannot be referred to by another translation unit.
   if (D->getStorageClass() == VarDecl::Static)
-    return 0;
+    return Entity(D);
   
   return VisitNamedDecl(D);
 }
 
-Entity *EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
+Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
   // If it's static it cannot be refered to by another translation unit.
   if (D->getStorageClass() == FunctionDecl::Static)
-    return 0;
+    return Entity(D);
   
   return VisitNamedDecl(D);
 }
 
 //===----------------------------------------------------------------------===//
+// EntityImpl Implementation
+//===----------------------------------------------------------------------===//
+
+Decl *EntityImpl::getDecl(ASTContext &AST) {
+  DeclContext *DC =
+    Parent.isInvalid() ? AST.getTranslationUnitDecl()
+                       : cast<DeclContext>(Parent.getDecl(AST));
+  if (!DC)
+    return 0; // Couldn't get the parent context.
+    
+  IdentifierInfo &II = AST.Idents.get(Id->getKeyData());
+  
+  DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II));
+  for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
+    if ((*I)->getIdentifierNamespace() == IdNS)
+      return *I;
+  }
+
+  return 0; // Failed to find a decl using this Entity.
+}
+
+/// \brief Get an Entity associated with the given Decl.
+/// \returns Null if an Entity cannot refer to this Decl.
+Entity EntityImpl::get(Decl *D, ProgramImpl &Prog) {
+  assert(D && "Passed null Decl");
+  return EntityGetter(Prog).Visit(D);
+}
+
+//===----------------------------------------------------------------------===//
 // Entity Implementation
 //===----------------------------------------------------------------------===//
 
 /// \brief Find the Decl that can be referred to by this entity.
 Decl *Entity::getDecl(ASTContext &AST) {
-  DeclContext *DC =
-    Parent == 0 ? AST.getTranslationUnitDecl()
-                : cast<DeclContext>(Parent->getDecl(AST));
-  if (!DC)
-    return 0; // Couldn't get the parent context.
-    
-  ProgramImpl::IdEntryTy *Entry = static_cast<ProgramImpl::IdEntryTy *>(Id);
-  IdentifierInfo &II = AST.Idents.get(Entry->getKeyData());
+  if (isInvalid())
+    return 0;
   
-  DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II));
-  for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
-    if (!isa<TagDecl>(*I))
-      return *I;
-  }
-
-  return 0; // Failed to find a decl using this Entity.
+  if (Decl *D = Val.dyn_cast<Decl *>())
+    // Check that the passed AST is actually the one that this Decl belongs to.
+    return (&D->getASTContext() == &AST) ? D : 0;
+  
+  return Val.get<EntityImpl *>()->getDecl(AST);
 }
 
 std::string Entity::getPrintableName(ASTContext &Ctx) {
@@ -135,8 +159,14 @@
 
 /// \brief Get an Entity associated with the given Decl.
 /// \returns Null if an Entity cannot refer to this Decl.
-Entity *Entity::get(Decl *D, Program &Prog) {
-  assert(D && "Passed null Decl");
-  ProgramImpl &Impl = *static_cast<ProgramImpl*>(Prog.Impl);
-  return EntityGetter(Impl).Visit(D);
+Entity Entity::get(Decl *D, Program &Prog) {
+  if (D == 0)
+    return Entity();
+  ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
+  return EntityImpl::get(D, ProgImpl);
+}
+
+unsigned 
+llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
+  return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
 }
diff --git a/lib/Index/EntityImpl.h b/lib/Index/EntityImpl.h
new file mode 100644
index 0000000..334dcfb
--- /dev/null
+++ b/lib/Index/EntityImpl.h
@@ -0,0 +1,63 @@
+//===--- EntityImpl.h - Internal Entity implementation---------*- C++ -*-=====//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+//  Internal implementation for the Entity class
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_INDEX_ENTITYIMPL_H
+#define LLVM_CLANG_INDEX_ENTITYIMPL_H
+
+#include "clang/Index/Entity.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/StringSet.h"
+
+namespace clang {
+
+namespace idx {
+  class ProgramImpl;
+
+class EntityImpl : public llvm::FoldingSetNode {
+public:
+  typedef llvm::StringMapEntry<char> IdEntryTy;
+
+private:
+  Entity Parent;
+  IdEntryTy *Id;
+
+  /// \brief Identifier namespace.
+  unsigned IdNS;
+
+public:
+  EntityImpl(Entity parent, IdEntryTy *id, unsigned idNS)
+    : Parent(parent), Id(id), IdNS(idNS) { }
+
+  /// \brief Find the Decl that can be referred to by this entity.
+  Decl *getDecl(ASTContext &AST);
+
+  /// \brief Get an Entity associated with the given Decl.
+  /// \returns Null if an Entity cannot refer to this Decl.
+  static Entity get(Decl *D, ProgramImpl &Prog);
+
+  void Profile(llvm::FoldingSetNodeID &ID) const {
+    Profile(ID, Parent, Id, IdNS);
+  }
+  static void Profile(llvm::FoldingSetNodeID &ID, Entity Parent, IdEntryTy *Id,
+                      unsigned IdNS) {
+    ID.AddPointer(Parent.getAsOpaquePtr());
+    ID.AddPointer(Id);
+    ID.AddInteger(IdNS);
+  }
+};
+
+} // namespace idx
+
+} // namespace clang
+
+#endif
diff --git a/lib/Index/IndexProvider.cpp b/lib/Index/IndexProvider.cpp
index 074a83d..38317eb 100644
--- a/lib/Index/IndexProvider.cpp
+++ b/lib/Index/IndexProvider.cpp
@@ -13,6 +13,7 @@
 
 #include "clang/Index/IndexProvider.h"
 #include "clang/Index/Program.h"
+#include "clang/Index/Entity.h"
 #include "clang/Index/EntityHandler.h"
 #include "clang/Index/TranslationUnit.h"
 using namespace clang;
@@ -25,7 +26,10 @@
 public:
   Indexer(TranslationUnit *tu, MapTy &map) : TU(tu), Map(map) { }
 
-  virtual void HandleEntity(Entity *Ent) {
+  virtual void HandleEntity(Entity Ent) {
+    if (Ent.isInternalToTU())
+      return;
+
     MapTy::iterator I = Map.find(Ent);
     if (I != Map.end()) {
       I->second.insert(TU);
@@ -41,25 +45,27 @@
   Prog.FindEntities(TU->getASTContext(), &Idx);
 }
 
+static IndexProvider::TUSetTy EmptySet;
+
 IndexProvider::translation_unit_iterator
-IndexProvider::translation_units_begin(Entity *Ent) const {
+IndexProvider::translation_units_begin(Entity Ent) const {
   MapTy::iterator I = Map.find(Ent);
   if (I == Map.end())
-    return translation_unit_iterator(0);
+    return EmptySet.begin();
   
   return I->second.begin();
 }
 
 IndexProvider::translation_unit_iterator
-IndexProvider::translation_units_end(Entity *Ent) const {
+IndexProvider::translation_units_end(Entity Ent) const {
   MapTy::iterator I = Map.find(Ent);
   if (I == Map.end())
-    return translation_unit_iterator(0);
+    return EmptySet.end();
   
   return I->second.end();
 }
 
-bool IndexProvider::translation_units_empty(Entity *Ent) const {
+bool IndexProvider::translation_units_empty(Entity Ent) const {
   MapTy::iterator I = Map.find(Ent);
   if (I == Map.end())
     return true;
diff --git a/lib/Index/Program.cpp b/lib/Index/Program.cpp
index 807d18c..73759dc 100644
--- a/lib/Index/Program.cpp
+++ b/lib/Index/Program.cpp
@@ -25,6 +25,8 @@
 EntityHandler::~EntityHandler() { }
 TranslationUnit::~TranslationUnit() { }
 
+void EntityHandler::HandleEntity(Entity Ent) { }
+
 Program::Program() : Impl(new ProgramImpl()) { }
 
 Program::~Program() {
@@ -34,8 +36,10 @@
 static void FindEntitiesInDC(DeclContext *DC, Program &Prog, EntityHandler *Handler) {
   for (DeclContext::decl_iterator
          I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
-    Entity *Ent = Entity::get(*I, Prog);
-    if (Ent)
+    if (I->getLocation().isInvalid())
+      continue;
+    Entity Ent = Entity::get(*I, Prog);
+    if (Ent.isValid())
       Handler->HandleEntity(Ent);
     if (DeclContext *SubDC = dyn_cast<DeclContext>(*I))
       FindEntitiesInDC(SubDC, Prog, Handler);
diff --git a/lib/Index/ProgramImpl.h b/lib/Index/ProgramImpl.h
index 52f153f..39fc184 100644
--- a/lib/Index/ProgramImpl.h
+++ b/lib/Index/ProgramImpl.h
@@ -14,8 +14,7 @@
 #ifndef LLVM_CLANG_INDEX_PROGRAMIMPL_H
 #define LLVM_CLANG_INDEX_PROGRAMIMPL_H
 
-#include "clang/Index/Entity.h"
-#include "llvm/ADT/StringSet.h"
+#include "EntityImpl.h"
 
 namespace clang {
 
@@ -24,11 +23,10 @@
 
 class ProgramImpl {
 public:
-  typedef llvm::FoldingSet<Entity> EntitySetTy;
-  typedef llvm::StringMapEntry<char> IdEntryTy;
-  
+  typedef llvm::FoldingSet<EntityImpl> EntitySetTy;
+
 private:
-  llvm::FoldingSet<Entity> Entities;
+  EntitySetTy Entities;
   llvm::StringSet<> Idents;
   llvm::BumpPtrAllocator BumpAlloc;
 
@@ -38,7 +36,7 @@
 public:
   ProgramImpl() { }
   
-  llvm::FoldingSet<Entity> &getEntities() { return Entities; }
+  EntitySetTy &getEntities() { return Entities; }
   llvm::StringSet<> &getIdents() { return Idents; }
 
   void *Allocate(unsigned Size, unsigned Align = 8) {