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());
 }