blob: b6fb17fc2b143dde3c8dcefc5c8e45b9aec76ca5 [file] [log] [blame]
Chris Lattnerc9f6c332009-07-12 22:33:12 +00001//===--- Entity.cpp - Cross-translation-unit "token" for decls ------------===//
Argyrios Kyrtzidisfe37cc82009-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 Kyrtzidis05ac8272009-07-21 00:07:06 +000015#include "EntityImpl.h"
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000016#include "ProgramImpl.h"
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000017#include "clang/Index/Program.h"
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000018#include "clang/Index/GlobalSelector.h"
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000019#include "clang/AST/Decl.h"
20#include "clang/AST/ASTContext.h"
21#include "clang/AST/DeclVisitor.h"
22using namespace clang;
23using namespace idx;
24
25// FIXME: Entity is really really basic currently, mostly written to work
26// on variables and functions. Should support types and other decls eventually..
27
28
29//===----------------------------------------------------------------------===//
30// EntityGetter
31//===----------------------------------------------------------------------===//
32
33namespace clang {
34namespace idx {
35
36/// \brief Gets the Entity associated with a Decl.
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000037class EntityGetter : public DeclVisitor<EntityGetter, Entity> {
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000038 Program &Prog;
39 ProgramImpl &ProgImpl;
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000040
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000041public:
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000042 EntityGetter(Program &prog, ProgramImpl &progImpl)
43 : Prog(prog), ProgImpl(progImpl) { }
Mike Stump11289f42009-09-09 15:08:12 +000044
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000045 Entity VisitNamedDecl(NamedDecl *D);
46 Entity VisitVarDecl(VarDecl *D);
Zhongxing Xu5776d432010-07-05 01:44:14 +000047 Entity VisitFieldDecl(FieldDecl *D);
Mike Stump11289f42009-09-09 15:08:12 +000048 Entity VisitFunctionDecl(FunctionDecl *D);
Zhongxing Xu74458782010-07-05 02:35:40 +000049 Entity VisitTypeDecl(TypeDecl *D);
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000050};
51
52}
53}
54
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000055Entity EntityGetter::VisitNamedDecl(NamedDecl *D) {
56 Entity Parent;
57 if (!D->getDeclContext()->isTranslationUnit()) {
58 Parent = Visit(cast<Decl>(D->getDeclContext()));
59 // FIXME: Anonymous structs ?
60 if (Parent.isInvalid())
61 return Entity();
62 }
63 if (Parent.isValid() && Parent.isInternalToTU())
64 return Entity(D);
65
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000066 // FIXME: Only works for DeclarationNames that are identifiers and selectors.
Argyrios Kyrtzidisaf792962009-07-29 23:39:52 +000067 // Treats other DeclarationNames as internal Decls for now..
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000068
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000069 DeclarationName LocalName = D->getDeclName();
70 if (!LocalName)
Argyrios Kyrtzidisaf792962009-07-29 23:39:52 +000071 return Entity(D);
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +000072
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000073 DeclarationName GlobName;
Argyrios Kyrtzidisbffa89f2009-07-17 01:19:03 +000074
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000075 if (IdentifierInfo *II = LocalName.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam47b55962010-03-12 09:33:31 +000076 IdentifierInfo *GlobII = &ProgImpl.getIdents().get(II->getName());
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000077 GlobName = DeclarationName(GlobII);
78 } else {
79 Selector LocalSel = LocalName.getObjCSelector();
80
81 // Treats other DeclarationNames as internal Decls for now..
82 if (LocalSel.isNull())
83 return Entity(D);
Mike Stump11289f42009-09-09 15:08:12 +000084
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000085 Selector GlobSel =
86 (uintptr_t)GlobalSelector::get(LocalSel, Prog).getAsOpaquePtr();
87 GlobName = DeclarationName(GlobSel);
88 }
Mike Stump11289f42009-09-09 15:08:12 +000089
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000090 assert(GlobName);
91
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000092 unsigned IdNS = D->getIdentifierNamespace();
93
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000094 ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
95 bool isObjCInstanceMethod = MD && MD->isInstanceMethod();
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +000096
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +000097 llvm::FoldingSetNodeID ID;
98 EntityImpl::Profile(ID, Parent, GlobName, IdNS, isObjCInstanceMethod);
99
100 ProgramImpl::EntitySetTy &Entities = ProgImpl.getEntities();
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000101 void *InsertPos = 0;
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000102 if (EntityImpl *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
103 return Entity(Ent);
104
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000105 void *Buf = ProgImpl.Allocate(sizeof(EntityImpl));
106 EntityImpl *New =
107 new (Buf) EntityImpl(Parent, GlobName, IdNS, isObjCInstanceMethod);
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000108 Entities.InsertNode(New, InsertPos);
Mike Stump11289f42009-09-09 15:08:12 +0000109
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000110 return Entity(New);
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000111}
112
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000113Entity EntityGetter::VisitVarDecl(VarDecl *D) {
Zhongxing Xuf894cfb2010-07-06 01:20:49 +0000114 // Local variables have no linkage, make invalid Entities.
115 if (D->hasLocalStorage())
116 return Entity();
117
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000118 // If it's static it cannot be referred to by another translation unit.
119 if (D->getStorageClass() == VarDecl::Static)
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000120 return Entity(D);
Mike Stump11289f42009-09-09 15:08:12 +0000121
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000122 return VisitNamedDecl(D);
123}
124
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000125Entity EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000126 // If it's static it cannot be refered to by another translation unit.
127 if (D->getStorageClass() == FunctionDecl::Static)
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000128 return Entity(D);
Mike Stump11289f42009-09-09 15:08:12 +0000129
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000130 return VisitNamedDecl(D);
131}
132
Zhongxing Xu5776d432010-07-05 01:44:14 +0000133Entity EntityGetter::VisitFieldDecl(FieldDecl *D) {
Zhongxing Xu57012ee2010-07-05 02:31:16 +0000134 // Make FieldDecl an invalid Entity since it has no linkage.
135 return Entity();
Zhongxing Xu5776d432010-07-05 01:44:14 +0000136}
137
Zhongxing Xu74458782010-07-05 02:35:40 +0000138Entity EntityGetter::VisitTypeDecl(TypeDecl *D) {
Zhongxing Xu1bbbc2e2010-07-05 02:36:16 +0000139 // Although in C++ class name has external linkage, usually the definition of
140 // the class is available in the same translation unit when it's needed. So we
141 // make all of them invalid Entity.
Zhongxing Xu74458782010-07-05 02:35:40 +0000142 return Entity();
143}
144
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000145//===----------------------------------------------------------------------===//
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000146// EntityImpl Implementation
147//===----------------------------------------------------------------------===//
148
149Decl *EntityImpl::getDecl(ASTContext &AST) {
150 DeclContext *DC =
151 Parent.isInvalid() ? AST.getTranslationUnitDecl()
152 : cast<DeclContext>(Parent.getDecl(AST));
153 if (!DC)
154 return 0; // Couldn't get the parent context.
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000155
156 DeclarationName LocalName;
157
158 if (IdentifierInfo *GlobII = Name.getAsIdentifierInfo()) {
Kovarththanan Rajaratnam47b55962010-03-12 09:33:31 +0000159 IdentifierInfo &II = AST.Idents.get(GlobII->getName());
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000160 LocalName = DeclarationName(&II);
161 } else {
162 Selector GlobSel = Name.getObjCSelector();
163 assert(!GlobSel.isNull() && "A not handled yet declaration name");
164 GlobalSelector GSel =
165 GlobalSelector::getFromOpaquePtr(GlobSel.getAsOpaquePtr());
166 LocalName = GSel.getSelector(AST);
167 }
168
169 assert(LocalName);
170
171 DeclContext::lookup_result Res = DC->lookup(LocalName);
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000172 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000173 Decl *D = *I;
174 if (D->getIdentifierNamespace() == IdNS) {
175 if (ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D)) {
176 if (MD->isInstanceMethod() == IsObjCInstanceMethod)
177 return MD;
178 } else
179 return D;
180 }
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000181 }
182
183 return 0; // Failed to find a decl using this Entity.
184}
185
186/// \brief Get an Entity associated with the given Decl.
187/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000188Entity EntityImpl::get(Decl *D, Program &Prog, ProgramImpl &ProgImpl) {
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000189 assert(D && "Passed null Decl");
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000190 return EntityGetter(Prog, ProgImpl).Visit(D);
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000191}
192
Argyrios Kyrtzidis8274ad52009-07-21 07:52:21 +0000193std::string EntityImpl::getPrintableName() {
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000194 return Name.getAsString();
Argyrios Kyrtzidis8274ad52009-07-21 07:52:21 +0000195}
196
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000197//===----------------------------------------------------------------------===//
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000198// Entity Implementation
199//===----------------------------------------------------------------------===//
200
Argyrios Kyrtzidis3b4e2a72009-07-21 02:10:32 +0000201Entity::Entity(Decl *D) : Val(D->getCanonicalDecl()) { }
202
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000203/// \brief Find the Decl that can be referred to by this entity.
Zhongxing Xu6c823132009-07-24 03:38:27 +0000204Decl *Entity::getDecl(ASTContext &AST) const {
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000205 if (isInvalid())
206 return 0;
Mike Stump11289f42009-09-09 15:08:12 +0000207
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000208 if (Decl *D = Val.dyn_cast<Decl *>())
209 // Check that the passed AST is actually the one that this Decl belongs to.
210 return (&D->getASTContext() == &AST) ? D : 0;
Mike Stump11289f42009-09-09 15:08:12 +0000211
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000212 return Val.get<EntityImpl *>()->getDecl(AST);
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000213}
214
Zhongxing Xufdd52922009-07-23 08:32:25 +0000215std::string Entity::getPrintableName() const {
Argyrios Kyrtzidis8274ad52009-07-21 07:52:21 +0000216 if (isInvalid())
217 return "<< Invalid >>";
Mike Stump11289f42009-09-09 15:08:12 +0000218
Argyrios Kyrtzidis8274ad52009-07-21 07:52:21 +0000219 if (Decl *D = Val.dyn_cast<Decl *>()) {
220 if (NamedDecl *ND = dyn_cast<NamedDecl>(D))
221 return ND->getNameAsString();
222 else
223 return std::string();
Zhongxing Xu12b1d132009-07-15 04:39:21 +0000224 }
Argyrios Kyrtzidis8274ad52009-07-21 07:52:21 +0000225
226 return Val.get<EntityImpl *>()->getPrintableName();
Zhongxing Xu12b1d132009-07-15 04:39:21 +0000227}
228
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000229/// \brief Get an Entity associated with the given Decl.
230/// \returns Null if an Entity cannot refer to this Decl.
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000231Entity Entity::get(Decl *D, Program &Prog) {
232 if (D == 0)
233 return Entity();
234 ProgramImpl &ProgImpl = *static_cast<ProgramImpl*>(Prog.Impl);
Argyrios Kyrtzidis2eff9052009-07-29 23:41:46 +0000235 return EntityImpl::get(D, Prog, ProgImpl);
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000236}
237
Mike Stump11289f42009-09-09 15:08:12 +0000238unsigned
Argyrios Kyrtzidis05ac8272009-07-21 00:07:06 +0000239llvm::DenseMapInfo<Entity>::getHashValue(Entity E) {
240 return DenseMapInfo<void*>::getHashValue(E.getAsOpaquePtr());
Argyrios Kyrtzidisfe37cc82009-07-05 22:22:19 +0000241}