blob: c8933fa000e3d0ec82cae9c739acc82353ff405e [file] [log] [blame]
Ted Kremenek9cd9f6d2010-01-05 22:06:45 +00001//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
2//
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// This file implements the generation and use of USRs from CXEntities.
11//
12//===----------------------------------------------------------------------===//
13
14#include "CIndexer.h"
Ted Kremenek473c7a72010-01-18 20:23:29 +000015#include "CXCursor.h"
Benjamin Kramer59617be2010-01-12 11:32:40 +000016#include "clang/AST/DeclVisitor.h"
Ted Kremenek5631d2d2010-01-12 02:07:58 +000017#include "llvm/ADT/SmallString.h"
Benjamin Kramer59617be2010-01-12 11:32:40 +000018#include "llvm/Support/raw_ostream.h"
Ted Kremenek9cd9f6d2010-01-05 22:06:45 +000019
20// Some notes on CXEntity:
21//
22// - Since the 'ordinary' namespace includes functions, data, typedefs,
23// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
24// entity for 2 different types). For example:
25//
26// module1.m: @interface Foo @end Foo *x;
27// module2.m: void Foo(int);
28//
29// - Since the unique name spans translation units, static data/functions
30// within a CXTranslationUnit are *not* currently represented by entities.
31// As a result, there will be no entity for the following:
32//
33// module.m: static void Foo() { }
34//
Ted Kremeneke5f86be2010-01-11 23:56:39 +000035
36static inline Entity GetEntity(const CXEntity &E) {
37 return Entity::getFromOpaquePtr(E.data);
38}
39
40static inline ASTUnit *GetTranslationUnit(CXTranslationUnit TU) {
41 return (ASTUnit*) TU;
Ted Kremenek9cd9f6d2010-01-05 22:06:45 +000042}
43
Ted Kremeneke5f86be2010-01-11 23:56:39 +000044static inline ASTContext &GetASTContext(CXTranslationUnit TU) {
45 return GetTranslationUnit(TU)->getASTContext();
46}
47
48static inline CXEntity NullCXEntity() {
49 CXEntity CE;
50 CE.index = NULL;
51 CE.data = NULL;
52 return CE;
53}
54
55static inline CXEntity MakeEntity(CXIndex CIdx, const Entity &E) {
56 CXEntity CE;
57 CE.index = CIdx;
58 CE.data = E.getAsOpaquePtr();
59 return CE;
60}
61
62static inline Program &GetProgram(CXIndex CIdx) {
63 return ((CIndexer*) CIdx)->getProgram();
64}
Benjamin Kramer59617be2010-01-12 11:32:40 +000065
Ted Kremenekcb674f92010-01-12 23:33:42 +000066//===----------------------------------------------------------------------===//
67// USR generation.
68//===----------------------------------------------------------------------===//
69
70namespace {
Ted Kremeneke1b55252010-01-14 01:50:21 +000071class USRGenerator : public DeclVisitor<USRGenerator> {
72 llvm::raw_ostream &Out;
73public:
74 USRGenerator(llvm::raw_ostream &out) : Out(out) {}
75
76 void VisitBlockDecl(BlockDecl *D);
77 void VisitDeclContext(DeclContext *D);
Ted Kremenek8433d1d2010-01-15 20:04:31 +000078 void VisitEnumDecl(EnumDecl *D);
Ted Kremeneke1b55252010-01-14 01:50:21 +000079 void VisitFunctionDecl(FunctionDecl *D);
80 void VisitNamedDecl(NamedDecl *D);
81 void VisitNamespaceDecl(NamespaceDecl *D);
82 void VisitObjCContainerDecl(ObjCContainerDecl *CD);
83 void VisitObjCMethodDecl(ObjCMethodDecl *MD);
84 void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
85 void VisitRecordDecl(RecordDecl *D);
Ted Kremenek6b1d5502010-01-15 23:34:31 +000086 void VisitTagDeclCommon(TagDecl *D);
Ted Kremeneke1b55252010-01-14 01:50:21 +000087 void VisitTypedefDecl(TypedefDecl *D);
88};
Ted Kremenekcb674f92010-01-12 23:33:42 +000089} // end anonymous namespace
90
Ted Kremeneke1b55252010-01-14 01:50:21 +000091void USRGenerator::VisitBlockDecl(BlockDecl *D) {
92 VisitDeclContext(D->getDeclContext());
93 // FIXME: Better support for anonymous blocks.
94 Out << "@B^anon";
95}
96
97void USRGenerator::VisitDeclContext(DeclContext *DC) {
98 if (NamedDecl *D = dyn_cast<NamedDecl>(DC))
99 Visit(D);
100}
101
Ted Kremenek8433d1d2010-01-15 20:04:31 +0000102void USRGenerator::VisitEnumDecl(EnumDecl *D) {
103 VisitDeclContext(D->getDeclContext());
104 Out << "@E^";
Ted Kremenek6b1d5502010-01-15 23:34:31 +0000105 VisitTagDeclCommon(D);
Ted Kremenek8433d1d2010-01-15 20:04:31 +0000106}
107
Ted Kremeneke1b55252010-01-14 01:50:21 +0000108void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
109 VisitDeclContext(D->getDeclContext());
110 Out << "@F^" << D->getNameAsString();
111}
Ted Kremenekcb674f92010-01-12 23:33:42 +0000112
113void USRGenerator::VisitNamedDecl(NamedDecl *D) {
Ted Kremeneke1b55252010-01-14 01:50:21 +0000114 VisitDeclContext(D->getDeclContext());
Ted Kremenekcb674f92010-01-12 23:33:42 +0000115 const std::string &s = D->getNameAsString();
116 assert(!s.empty());
Ted Kremeneke1b55252010-01-14 01:50:21 +0000117 Out << "@^" << s;
118}
119
120void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
121 VisitDeclContext(D->getDeclContext());
122 Out << "@N^" << D->getNameAsString();
Ted Kremenekcb674f92010-01-12 23:33:42 +0000123}
124
125void USRGenerator::VisitRecordDecl(RecordDecl *D) {
Ted Kremeneke1b55252010-01-14 01:50:21 +0000126 VisitDeclContext(D->getDeclContext());
127 Out << "@S^";
Ted Kremenek6b1d5502010-01-15 23:34:31 +0000128 VisitTagDeclCommon(D);
Ted Kremenekcb674f92010-01-12 23:33:42 +0000129}
130
131void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
132 Visit(cast<Decl>(D->getDeclContext()));
133 Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
134 Out << DeclarationName(D->getSelector()).getAsString();
135}
136
137void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
138 switch (D->getKind()) {
139 default:
140 assert(false && "Invalid ObjC container.");
141 case Decl::ObjCInterface:
142 case Decl::ObjCImplementation:
143 Out << "objc(cs)" << D->getName();
144 break;
145 case Decl::ObjCCategory: {
146 ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
147 Out << "objc(cy)" << CD->getClassInterface()->getName()
148 << '_' << CD->getName();
149 break;
150 }
151 case Decl::ObjCCategoryImpl: {
152 ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
153 Out << "objc(cy)" << CD->getClassInterface()->getName()
154 << '_' << CD->getName();
155 break;
156 }
157 case Decl::ObjCProtocol:
158 Out << "objc(pl)" << cast<ObjCProtocolDecl>(D)->getName();
159 break;
160 }
161}
162
163void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
164 Visit(cast<Decl>(D->getDeclContext()));
165 Out << "(py)" << D->getName();
166}
167
Ted Kremenek6b1d5502010-01-15 23:34:31 +0000168void USRGenerator::VisitTagDeclCommon(TagDecl *D) {
169 // FIXME: Better support for anonymous structures and enums.
170 const std::string &s = D->getNameAsString();
171 if (s.empty()) {
172 if (TypedefDecl *TD = D->getTypedefForAnonDecl())
173 Out << "^anontd^" << TD->getNameAsString();
174 else
175 Out << "^anon";
176 }
177 else
178 Out << s;
179}
180
Ted Kremenekcb674f92010-01-12 23:33:42 +0000181void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
182 DeclContext *DC = D->getDeclContext();
183 if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
184 Visit(DCN);
185 Out << "typedef@" << D->getName();
186}
187
Ted Kremenek473c7a72010-01-18 20:23:29 +0000188// FIXME: This is a skeleton implementation. It will be overhauled.
189static CXString ConstructUSR(Decl *D) {
190 llvm::SmallString<1024> StrBuf;
191 {
192 llvm::raw_svector_ostream Out(StrBuf);
193 USRGenerator UG(Out);
194 UG.Visit(static_cast<Decl*>(D));
195 }
196
197 if (StrBuf.empty())
198 return CIndexer::createCXString(NULL);
199
200 // Return a copy of the string that must be disposed by the caller.
201 return CIndexer::createCXString(StrBuf.c_str(), true);
202}
203
204
Benjamin Kramer59617be2010-01-12 11:32:40 +0000205extern "C" {
206
Ted Kremeneke5f86be2010-01-11 23:56:39 +0000207/// clang_getDeclaration() maps from a CXEntity to the matching CXDecl (if any)
208/// in a specified translation unit.
209CXDecl clang_getDeclaration(CXEntity CE, CXTranslationUnit TU) {
210 return (CXDecl) GetEntity(CE).getDecl(GetASTContext(TU));
211}
212
213
214CXEntity clang_getEntityFromDecl(CXIndex CIdx, CXDecl CE) {
215 if (Decl *D = (Decl *) CE)
216 return MakeEntity(CIdx, Entity::get(D, GetProgram(CIdx)));
217 return NullCXEntity();
218}
Ted Kremenek5631d2d2010-01-12 02:07:58 +0000219
Ted Kremenek473c7a72010-01-18 20:23:29 +0000220CXString clang_getCursorUSR(CXCursor C) {
221 if (Decl *D = cxcursor::getCursorDecl(C))
222 return ConstructUSR(D);
223
224
225 return CIndexer::createCXString(NULL);
226}
Ted Kremenek9cd9f6d2010-01-05 22:06:45 +0000227
Ted Kremenek9cd9f6d2010-01-05 22:06:45 +0000228} // end extern "C"