blob: d33110074f29c09e23beb01fbd05bab61b1bc86a [file] [log] [blame]
Chris Lattnerc3a65402009-07-12 22:33:12 +00001//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// Entity is a ASTContext-independent way to refer to declarations that are
11// visible across translation units.
12//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000015#include "EntityImpl.h"
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000016#include "ProgramImpl.h"
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000017#include "clang/Index/Program.h"
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000018#include "clang/AST/Decl.h"
19#include "clang/AST/ASTContext.h"
20#include "clang/AST/DeclVisitor.h"
21using namespace clang;
22using namespace idx;
23
24// FIXME: Entity is really really basic currently, mostly written to work
25// on variables and functions. Should support types and other decls eventually..
26
27
28//===----------------------------------------------------------------------===//
29// EntityGetter
30//===----------------------------------------------------------------------===//
31
32namespace clang {
33namespace idx {
34
35/// \brief Gets the Entity associated with a Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000036class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000037 ProgramImpl &Prog;
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000038
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000039public:
40 EntityGetter(ProgramImpl &prog) : Prog(prog) { }
41
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000042 Entity VisitNamedDecl(NamedDecl *D);
43 Entity VisitVarDecl(VarDecl *D);
44 Entity VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000045};
46
47}
48}
49
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000050Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
51 Entity Parent;
52 if (!D->getDeclContext()->isTranslationUnit()) {
53 Parent = Visit(cast<Decl>(D->getDeclContext()));
54 // FIXME: Anonymous structs ?
55 if (Parent.isInvalid())
56 return Entity();
57 }
58 if (Parent.isValid() && Parent.isInternalToTU())
59 return Entity(D);
60
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000061 // FIXME: Only works for DeclarationNames that are identifiers.
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000062 // Treats other DeclarationNames as internal Decls for now..
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000063
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000064 DeclarationName Name = D->getDeclName();
65
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000066 if (!Name.isIdentifier())
Argyrios Kyrtzidis52f1d472009-07-29 23:39:52 +000067 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000068
69 IdentifierInfo *II = Name.getAsIdentifierInfo();
Argyrios Kyrtzidisdc0b11e2009-07-17 01:19:03 +000070 if (!II)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000071 return Entity();
Argyrios Kyrtzidisdc0b11e2009-07-17 01:19:03 +000072
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000073 EntityImpl::IdEntryTy *Id =
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000074 &Prog.getIdents().GetOrCreateValue(II->getName(),
75 II->getName() + II->getLength());
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000076 unsigned IdNS = D->getIdentifierNamespace();
77
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000078 llvm::FoldingSetNodeID ID;
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000079 EntityImpl::Profile(ID, Parent, Id, IdNS);
80
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000081 ProgramImpl::EntitySetTy &Entities = Prog.getEntities();
82 void *InsertPos = 0;
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000083 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
84 return Entity(Ent);
85
86 void *Buf = Prog.Allocate(sizeof(EntityImpl));
87 EntityImpl *New = new (Buf) EntityImpl(Parent, Id, IdNS);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000088 Entities.InsertNode(New, InsertPos);
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000089
90 return Entity(New);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000091}
92
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000093Entity EntityGetter::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000094 // If it's static it cannot be referred to by another translation unit.
95 if (D->getStorageClass() == VarDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +000096 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +000097
98 return VisitNamedDecl(D);
99}
100
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000101Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000102 // If it's static it cannot be refered to by another translation unit.
103 if (D->getStorageClass() == FunctionDecl::Static)
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000104 return Entity(D);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000105
106 return VisitNamedDecl(D);
107}
108
109//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000110// EntityImpl Implementation
111//===----------------------------------------------------------------------===//
112
113Decl *EntityImpl::getDecl(ASTContext &AST) {
114 DeclContext *DC =
115 Parent.isInvalid() ? AST.getTranslationUnitDecl()
116 : cast<DeclContext>(Parent.getDecl(AST));
117 if (!DC)
118 return 0; // Couldn't get the parent context.
119
120 IdentifierInfo &II = AST.Idents.get(Id->getKeyData());
121
122 DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II));
123 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
124 if ((*I)->getIdentifierNamespace() == IdNS)
125 return *I;
126 }
127
128 return 0; // Failed to find a decl using this Entity.
129}
130
131/// \brief Get an Entity associated with the given Decl.
132/// \returns Null if an Entity cannot refer to this Decl.
133Entity EntityImpl::get(Decl *D, ProgramImpl &Prog) {
134 assert(D && "Passed null Decl");
135 return EntityGetter(Prog).Visit(D);
136}
137
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000138std::string EntityImpl::getPrintableName() {
139 return std::string(Id->getKeyData(), Id->getKeyData() + Id->getKeyLength());
140}
141
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000142//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000143// Entity Implementation
144//===----------------------------------------------------------------------===//
145
Argyrios Kyrtzidis1f717272009-07-21 02:10:32 +0000146Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
147
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000148/// \brief Find the Decl that can be referred to by this entity.
Zhongxing Xu6d8f56f2009-07-24 03:38:27 +0000149Decl *Entity::getDecl(ASTContext &AST) const {
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000150 if (isInvalid())
151 return 0;
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000152
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000153 if (Decl *D = Val.dyn_cast<Decl *>())
154 // Check that the passed AST is actually the one that this Decl belongs to.
155 return (&D->getASTContext() == &AST) ? D : 0;
156
157 return Val.get<EntityImpl *>()->getDecl(AST);
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000158}
159
Zhongxing Xuf7856432009-07-23 08:32:25 +0000160std::string Entity::getPrintableName() const {
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000161 if (isInvalid())
162 return "<< Invalid >>";
163
164 if (Decl *D = Val.dyn_cast<Decl *>()) {
165 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
166 return ND->getNameAsString();
167 else
168 return std::string();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000169 }
Argyrios Kyrtzidis4c7c5a12009-07-21 07:52:21 +0000170
171 return Val.get<EntityImpl *>()->getPrintableName();
Zhongxing Xu53363b22009-07-15 04:39:21 +0000172}
173
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000174/// \brief Get an Entity associated with the given Decl.
175/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidisf7cf15c2009-07-21 00:07:06 +0000176Entity Entity::get(Decl *D, Program &Prog) {
177 if (D == 0)
178 return Entity();
179 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
180 return EntityImpl::get(D, ProgImpl);
181}
182
183unsigned
184llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
185 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
Argyrios Kyrtzidis9eec4ed2009-07-05 22:22:19 +0000186}