blob: 2620f88a9585bd96b7df4d3c3f8d4302d2b2480f [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
15#include "clang/Index/Entity.h"
16#include "clang/Index/Program.h"
17#include "ProgramImpl.h"
18#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.
36class EntityGetter : public DeclVisitor<EntityGetter, Entity *> {
37 ProgramImpl &Prog;
38
39public:
40 EntityGetter(ProgramImpl &prog) : Prog(prog) { }
41
42 Entity *get(Entity *Parent, DeclarationName Name);
43
44 Entity *VisitNamedDecl(NamedDecl *D);
45 Entity *VisitVarDecl(VarDecl *D);
46 Entity *VisitFunctionDecl(FunctionDecl *D);
47};
48
49}
50}
51
52Entity *EntityGetter::get(Entity *Parent, DeclarationName Name) {
53 // FIXME: Only works for DeclarationNames that are identifiers.
54
55 if (!Name.isIdentifier())
56 return 0;
57
58 IdentifierInfo *II = Name.getAsIdentifierInfo();
59 ProgramImpl::IdEntryTy *Id =
60 &Prog.getIdents().GetOrCreateValue(II->getName(),
61 II->getName() + II->getLength());
62
63 llvm::FoldingSetNodeID ID;
64 Entity::Profile(ID, Parent, Id);
65
66 ProgramImpl::EntitySetTy &Entities = Prog.getEntities();
67 void *InsertPos = 0;
68 if (Entity *Ent = Entities.FindNodeOrInsertPos(ID, InsertPos))
69 return Ent;
70
71 void *Buf = Prog.Allocate(sizeof(Entity));
72 Entity *New = new (Buf) Entity(Parent, Id);
73 Entities.InsertNode(New, InsertPos);
74 return New;
75}
76
77Entity *EntityGetter::VisitNamedDecl(NamedDecl *D) {
78 // FIXME: Function declarations that are inside functions ?
79 if (!D->getDeclContext()->isFileContext())
80 return 0;
81
82 Entity *Parent = Visit(cast<Decl>(D->getDeclContext()));
83 return get(Parent, D->getDeclName());
84}
85
86Entity *EntityGetter::VisitVarDecl(VarDecl *D) {
87 // If it's static it cannot be referred to by another translation unit.
88 if (D->getStorageClass() == VarDecl::Static)
89 return 0;
90
91 return VisitNamedDecl(D);
92}
93
94Entity *EntityGetter::VisitFunctionDecl(FunctionDecl *D) {
95 // If it's static it cannot be refered to by another translation unit.
96 if (D->getStorageClass() == FunctionDecl::Static)
97 return 0;
98
99 return VisitNamedDecl(D);
100}
101
102//===----------------------------------------------------------------------===//
103// Entity Implementation
104//===----------------------------------------------------------------------===//
105
106/// \brief Find the Decl that can be referred to by this entity.
107Decl *Entity::getDecl(ASTContext &AST) {
108 DeclContext *DC =
109 Parent == 0 ? AST.getTranslationUnitDecl()
110 : cast<DeclContext>(Parent->getDecl(AST));
111 if (!DC)
112 return 0; // Couldn't get the parent context.
113
114 ProgramImpl::IdEntryTy *Entry = static_cast<ProgramImpl::IdEntryTy *>(Id);
115 IdentifierInfo &II = AST.Idents.get(Entry->getKeyData());
116
117 DeclContext::lookup_result Res = DC->lookup(DeclarationName(&II));
118 for (DeclContext::lookup_iterator I = Res.first, E = Res.second; I!=E; ++I) {
119 if (!isa<TagDecl>(*I))
120 return *I;
121 }
122
123 return 0; // Failed to find a decl using this Entity.
124}
125
126/// \brief Get an Entity associated with the given Decl.
127/// \returns Null if an Entity cannot refer to this Decl.
128Entity *Entity::get(Decl *D, Program &Prog) {
129 assert(D && "Passed null Decl");
130 ProgramImpl &Impl = *static_cast<ProgramImpl*>(Prog.Impl);
131 return EntityGetter(Impl).Visit(D);
132}