]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/CIndex/CIndex.cpp
Update clang to r84949.
[FreeBSD/FreeBSD.git] / tools / CIndex / CIndex.cpp
1 //===- CIndex.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 Clang-C Source Indexing library.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "clang-c/Index.h"
15 #include "clang/Index/Program.h"
16 #include "clang/Index/Indexer.h"
17 #include "clang/Index/ASTLocation.h"
18 #include "clang/Index/Utils.h"
19 #include "clang/AST/DeclVisitor.h"
20 #include "clang/AST/StmtVisitor.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/Basic/FileManager.h"
23 #include "clang/Basic/SourceManager.h"
24 #include "clang/Frontend/ASTUnit.h"
25 #include "llvm/Config/config.h"
26 #include "llvm/Support/Compiler.h"
27 #include "llvm/Support/MemoryBuffer.h"
28 #include "llvm/System/Path.h"
29 #include "llvm/System/Program.h"
30 #include "llvm/Support/raw_ostream.h"
31
32 #include <cstdio>
33 #include <vector>
34
35 #ifdef LLVM_ON_WIN32
36 #define WIN32_LEAN_AND_MEAN
37 #include <windows.h>
38 #else
39 #include <dlfcn.h>
40 #endif
41
42 using namespace clang;
43 using namespace idx;
44
45 namespace {
46 static enum CXCursorKind TranslateDeclRefExpr(DeclRefExpr *DRE) 
47 {
48   NamedDecl *D = DRE->getDecl();
49   if (isa<VarDecl>(D))
50     return CXCursor_VarRef;
51   else if (isa<FunctionDecl>(D))
52     return CXCursor_FunctionRef;
53   else if (isa<EnumConstantDecl>(D))
54     return CXCursor_EnumConstantRef;
55   else 
56     return CXCursor_NotImplemented;
57 }
58
59 #if 0
60 // Will be useful one day.
61 class CRefVisitor : public StmtVisitor<CRefVisitor> {
62   CXDecl CDecl;
63   CXDeclIterator Callback;
64   CXClientData CData;
65   
66   void Call(enum CXCursorKind CK, Stmt *SRef) {
67     CXCursor C = { CK, CDecl, SRef };
68     Callback(CDecl, C, CData);
69   }
70
71 public:
72   CRefVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) : 
73     CDecl(C), Callback(cback), CData(D) {}
74   
75   void VisitStmt(Stmt *S) {
76     for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
77          C != CEnd; ++C)
78       Visit(*C);
79   }
80   void VisitDeclRefExpr(DeclRefExpr *Node) {
81     Call(TranslateDeclRefExpr(Node), Node);
82   }
83   void VisitMemberExpr(MemberExpr *Node) {
84     Call(CXCursor_MemberRef, Node);
85   }
86   void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
87     Call(CXCursor_ObjCSelectorRef, Node);
88   }
89   void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
90     Call(CXCursor_ObjCIvarRef, Node);
91   }
92 };
93 #endif
94   
95 /// IgnoreDiagnosticsClient - A DiagnosticsClient that just ignores emitted
96 /// warnings and errors.
97 class VISIBILITY_HIDDEN IgnoreDiagnosticsClient : public DiagnosticClient {
98 public:
99   virtual ~IgnoreDiagnosticsClient() {}
100   virtual void HandleDiagnostic(Diagnostic::Level, const DiagnosticInfo &) {}  
101 };
102
103 // Translation Unit Visitor.
104 class TUVisitor : public DeclVisitor<TUVisitor> {
105   CXTranslationUnit TUnit;
106   CXTranslationUnitIterator Callback;
107   CXClientData CData;
108   
109   // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
110   // to the visitor. Declarations with a PCH level greater than this value will
111   // be suppressed.
112   unsigned MaxPCHLevel;
113   
114   void Call(enum CXCursorKind CK, NamedDecl *ND) {
115     // Filter any declarations that have a PCH level greater than what we allow.
116     if (ND->getPCHLevel() > MaxPCHLevel)
117       return;
118     
119     CXCursor C = { CK, ND, 0 };
120     Callback(TUnit, C, CData);
121   }
122 public:
123   TUVisitor(CXTranslationUnit CTU, 
124             CXTranslationUnitIterator cback, CXClientData D,
125             unsigned MaxPCHLevel) : 
126     TUnit(CTU), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
127   
128   void VisitTranslationUnitDecl(TranslationUnitDecl *D) {
129     VisitDeclContext(dyn_cast<DeclContext>(D));
130   }
131   void VisitDeclContext(DeclContext *DC) {
132     for (DeclContext::decl_iterator
133            I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
134       Visit(*I);
135   }
136   void VisitTypedefDecl(TypedefDecl *ND) { 
137     Call(CXCursor_TypedefDecl, ND); 
138   }
139   void VisitTagDecl(TagDecl *ND) {
140     switch (ND->getTagKind()) {
141       case TagDecl::TK_struct:
142         Call(CXCursor_StructDecl, ND);
143         break;
144       case TagDecl::TK_class:
145         Call(CXCursor_ClassDecl, ND);
146         break;
147       case TagDecl::TK_union:
148         Call(CXCursor_UnionDecl, ND);
149         break;
150       case TagDecl::TK_enum:
151         Call(CXCursor_EnumDecl, ND);
152         break;
153     }
154   }
155   void VisitVarDecl(VarDecl *ND) {
156     Call(CXCursor_VarDecl, ND);
157   }
158   void VisitFunctionDecl(FunctionDecl *ND) {
159     Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
160                                             : CXCursor_FunctionDecl, ND);
161   }
162   void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
163     Call(CXCursor_ObjCInterfaceDecl, ND);
164   }
165   void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
166     Call(CXCursor_ObjCCategoryDecl, ND);
167   }
168   void VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
169     Call(CXCursor_ObjCProtocolDecl, ND);
170   }
171   void VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
172     Call(CXCursor_ObjCClassDefn, ND);
173   }
174   void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
175     Call(CXCursor_ObjCCategoryDefn, ND);
176   }
177 };
178
179 // Declaration visitor.
180 class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
181   CXDecl CDecl;
182   CXDeclIterator Callback;
183   CXClientData CData;
184   
185   // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
186   // to the visitor. Declarations with a PCH level greater than this value will
187   // be suppressed.
188   unsigned MaxPCHLevel;
189   
190   void Call(enum CXCursorKind CK, NamedDecl *ND) {
191     // Disable the callback when the context is equal to the visiting decl.
192     if (CDecl == ND && !clang_isReference(CK))
193       return;
194     
195     // Filter any declarations that have a PCH level greater than what we allow.
196     if (ND->getPCHLevel() > MaxPCHLevel)
197       return;
198     
199     CXCursor C = { CK, ND, 0 };
200     Callback(CDecl, C, CData);
201   }
202 public:
203   CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D, 
204                unsigned MaxPCHLevel) : 
205     CDecl(C), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
206     
207   void VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
208     // Issue callbacks for the containing class.
209     Call(CXCursor_ObjCClassRef, ND);
210     // FIXME: Issue callbacks for protocol refs.
211     VisitDeclContext(dyn_cast<DeclContext>(ND));
212   }
213   void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
214     // Issue callbacks for super class.
215     if (D->getSuperClass())
216       Call(CXCursor_ObjCSuperClassRef, D);
217
218     for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(), 
219          E = D->protocol_end(); I != E; ++I)
220       Call(CXCursor_ObjCProtocolRef, *I);
221     VisitDeclContext(dyn_cast<DeclContext>(D));
222   }
223   void VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
224     for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(), 
225          E = PID->protocol_end(); I != E; ++I)
226       Call(CXCursor_ObjCProtocolRef, *I);
227       
228     VisitDeclContext(dyn_cast<DeclContext>(PID));
229   }
230   void VisitTagDecl(TagDecl *D) {
231     VisitDeclContext(dyn_cast<DeclContext>(D));
232   }
233   void VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
234     VisitDeclContext(dyn_cast<DeclContext>(D));
235   }
236   void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
237     VisitDeclContext(dyn_cast<DeclContext>(D));
238   }
239   void VisitDeclContext(DeclContext *DC) {
240     for (DeclContext::decl_iterator
241            I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
242       Visit(*I);
243   }
244   void VisitEnumConstantDecl(EnumConstantDecl *ND) {
245     Call(CXCursor_EnumConstantDecl, ND);
246   }
247   void VisitFieldDecl(FieldDecl *ND) {
248     Call(CXCursor_FieldDecl, ND);
249   }
250   void VisitVarDecl(VarDecl *ND) {
251     Call(CXCursor_VarDecl, ND);
252   }
253   void VisitParmVarDecl(ParmVarDecl *ND) {
254     Call(CXCursor_ParmDecl, ND);
255   }
256   void VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
257     Call(CXCursor_ObjCPropertyDecl, ND);
258   }
259   void VisitObjCIvarDecl(ObjCIvarDecl *ND) {
260     Call(CXCursor_ObjCIvarDecl, ND);
261   }
262   void VisitFunctionDecl(FunctionDecl *ND) {
263     if (ND->isThisDeclarationADefinition()) {
264       VisitDeclContext(dyn_cast<DeclContext>(ND));
265 #if 0
266       // Not currently needed.
267       CompoundStmt *Body = dyn_cast<CompoundStmt>(ND->getBody());
268       CRefVisitor RVisit(CDecl, Callback, CData);
269       RVisit.Visit(Body);
270 #endif
271     }
272   }
273   void VisitObjCMethodDecl(ObjCMethodDecl *ND) {
274     if (ND->getBody()) {
275       Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
276                                   : CXCursor_ObjCClassMethodDefn, ND);
277       VisitDeclContext(dyn_cast<DeclContext>(ND));
278     } else
279       Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
280                                   : CXCursor_ObjCClassMethodDecl, ND);
281   }
282 };
283
284 class CIndexer : public Indexer {
285 public:  
286   explicit CIndexer(Program *prog) : Indexer(*prog), 
287                                      OnlyLocalDecls(false), 
288                                      DisplayDiagnostics(false) {}
289
290   virtual ~CIndexer() { delete &getProgram(); }
291
292   /// \brief Whether we only want to see "local" declarations (that did not
293   /// come from a previous precompiled header). If false, we want to see all
294   /// declarations.
295   bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
296   void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; }
297
298   void setDisplayDiagnostics(bool Display = true) { 
299     DisplayDiagnostics = Display;
300   }
301   bool getDisplayDiagnostics() const { return DisplayDiagnostics; }
302   
303   /// \brief Get the path of the clang binary.
304   const llvm::sys::Path& getClangPath();
305 private:
306   bool OnlyLocalDecls;
307   bool DisplayDiagnostics;
308   
309   llvm::sys::Path ClangPath;
310 };
311
312 const llvm::sys::Path& CIndexer::getClangPath() {
313   // Did we already compute the path?
314   if (!ClangPath.empty())
315     return ClangPath;
316
317   // Find the location where this library lives (libCIndex.dylib).
318 #ifdef LLVM_ON_WIN32
319   MEMORY_BASIC_INFORMATION mbi;
320   char path[MAX_PATH];
321   VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
322                sizeof(mbi));
323   GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
324
325   llvm::sys::Path CIndexPath(path);
326 #else
327   // This silly cast below avoids a C++ warning.
328   Dl_info info;
329   if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
330     assert(0 && "Call to dladdr() failed");
331
332   llvm::sys::Path CIndexPath(info.dli_fname);
333 #endif
334
335   // We now have the CIndex directory, locate clang relative to it.
336   CIndexPath.eraseComponent();
337   CIndexPath.eraseComponent();
338   CIndexPath.appendComponent("bin");
339   CIndexPath.appendComponent("clang");
340
341   // Cache our result.
342   ClangPath = CIndexPath;
343   return ClangPath;
344 }
345
346 }
347
348 extern "C" {
349
350 CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
351                           int displayDiagnostics) 
352 {  
353   CIndexer *CIdxr = new CIndexer(new Program());
354   if (excludeDeclarationsFromPCH)
355     CIdxr->setOnlyLocalDecls();
356   if (displayDiagnostics)
357     CIdxr->setDisplayDiagnostics();
358   return CIdxr;
359 }
360
361 void clang_disposeIndex(CXIndex CIdx)
362 {
363   assert(CIdx && "Passed null CXIndex");
364   delete static_cast<CIndexer *>(CIdx);
365 }
366
367 // FIXME: need to pass back error info.
368 CXTranslationUnit clang_createTranslationUnit(
369   CXIndex CIdx, const char *ast_filename) 
370 {
371   assert(CIdx && "Passed null CXIndex");
372   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
373   std::string astName(ast_filename);
374   std::string ErrMsg;
375   
376   CXTranslationUnit TU =
377     ASTUnit::LoadFromPCHFile(astName, &ErrMsg, 
378                            CXXIdx->getDisplayDiagnostics() ? 
379                            NULL : new IgnoreDiagnosticsClient(),
380                            CXXIdx->getOnlyLocalDecls(),
381                            /* UseBumpAllocator = */ true);
382   
383   if (!ErrMsg.empty()) {
384     (llvm::errs() << "clang_createTranslationUnit: " << ErrMsg 
385                   << '\n').flush();
386   }
387   
388   return TU;
389 }
390
391 CXTranslationUnit clang_createTranslationUnitFromSourceFile(
392   CXIndex CIdx, 
393   const char *source_filename,
394   int num_command_line_args, const char **command_line_args)  {
395   assert(CIdx && "Passed null CXIndex");
396   CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
397
398   // Build up the arguments for invoking 'clang'.
399   std::vector<const char *> argv;
400   
401   // First add the complete path to the 'clang' executable.
402   llvm::sys::Path ClangPath = static_cast<CIndexer *>(CIdx)->getClangPath();
403   argv.push_back(ClangPath.c_str());
404   
405   // Add the '-emit-ast' option as our execution mode for 'clang'.
406   argv.push_back("-emit-ast");
407   
408   // The 'source_filename' argument is optional.  If the caller does not
409   // specify it then it is assumed that the source file is specified
410   // in the actual argument list.
411   if (source_filename)  
412     argv.push_back(source_filename);  
413
414   // Generate a temporary name for the AST file.
415   argv.push_back("-o");
416   char astTmpFile[L_tmpnam];
417   argv.push_back(tmpnam(astTmpFile));
418
419   // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
420   for (int i = 0; i < num_command_line_args; ++i)
421     if (const char *arg = command_line_args[i]) {
422       if (strcmp(arg, "-o") == 0) {
423         ++i; // Also skip the matching argument.
424         continue;
425       }
426       if (strcmp(arg, "-emit-ast") == 0 ||
427           strcmp(arg, "-c") == 0 ||
428           strcmp(arg, "-fsyntax-only") == 0) {
429         continue;
430       }
431
432       // Keep the argument.
433       argv.push_back(arg);
434     }
435     
436   // Add the null terminator.
437   argv.push_back(NULL);
438
439 #ifndef LLVM_ON_WIN32
440   llvm::sys::Path DevNull("/dev/null");
441   std::string ErrMsg;
442   const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DevNull, NULL };
443   llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
444       /* redirects */ !CXXIdx->getDisplayDiagnostics() ? &Redirects[0] : NULL,
445       /* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
446   
447   if (!ErrMsg.empty()) {
448     llvm::errs() << "clang_createTranslationUnitFromSourceFile: " << ErrMsg 
449       << '\n' << "Arguments: \n";
450     for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
451          I!=E; ++I)
452       if (*I) llvm::errs() << ' ' << *I << '\n';
453      
454     (llvm::errs() << '\n').flush();
455   }
456 #else
457   // FIXME: I don't know what is the equivalent '/dev/null' redirect for
458   // Windows for this API.
459   llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0]);
460 #endif
461
462   // Finally, we create the translation unit from the ast file.
463   ASTUnit *ATU = static_cast<ASTUnit *>(
464                    clang_createTranslationUnit(CIdx, astTmpFile));
465   if (ATU)
466     ATU->unlinkTemporaryFile();
467   return ATU;
468 }
469
470 void clang_disposeTranslationUnit(
471   CXTranslationUnit CTUnit) 
472 {
473   assert(CTUnit && "Passed null CXTranslationUnit");
474   delete static_cast<ASTUnit *>(CTUnit);
475 }
476   
477 const char *clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit)
478 {
479   assert(CTUnit && "Passed null CXTranslationUnit");
480   ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
481   return CXXUnit->getOriginalSourceFileName().c_str();
482 }
483
484 void clang_loadTranslationUnit(CXTranslationUnit CTUnit, 
485                                CXTranslationUnitIterator callback,
486                                CXClientData CData)
487 {
488   assert(CTUnit && "Passed null CXTranslationUnit");
489   ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
490   ASTContext &Ctx = CXXUnit->getASTContext();
491   
492   TUVisitor DVisit(CTUnit, callback, CData, 
493                    CXXUnit->getOnlyLocalDecls()? 1 : Decl::MaxPCHLevel);
494   DVisit.Visit(Ctx.getTranslationUnitDecl());
495 }
496
497 void clang_loadDeclaration(CXDecl Dcl, 
498                            CXDeclIterator callback, 
499                            CXClientData CData)
500 {
501   assert(Dcl && "Passed null CXDecl");
502   
503   CDeclVisitor DVisit(Dcl, callback, CData,
504                       static_cast<Decl *>(Dcl)->getPCHLevel());
505   DVisit.Visit(static_cast<Decl *>(Dcl));
506 }
507
508 // Some notes on CXEntity:
509 //
510 // - Since the 'ordinary' namespace includes functions, data, typedefs, 
511 // ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one 
512 // entity for 2 different types). For example:
513 //
514 // module1.m: @interface Foo @end Foo *x;
515 // module2.m: void Foo(int);
516 //
517 // - Since the unique name spans translation units, static data/functions 
518 // within a CXTranslationUnit are *not* currently represented by entities.
519 // As a result, there will be no entity for the following:
520 //
521 // module.m: static void Foo() { }
522 //
523
524
525 const char *clang_getDeclarationName(CXEntity)
526 {
527   return "";
528 }
529 const char *clang_getURI(CXEntity)
530 {
531   return "";
532 }
533
534 CXEntity clang_getEntity(const char *URI)
535 {
536   return 0;
537 }
538
539 //
540 // CXDecl Operations.
541 //
542 CXEntity clang_getEntityFromDecl(CXDecl)
543 {
544   return 0;
545 }
546 const char *clang_getDeclSpelling(CXDecl AnonDecl)
547 {
548   assert(AnonDecl && "Passed null CXDecl");
549   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
550   
551   if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND)) {
552     return OMD->getSelector().getAsString().c_str();
553   }    
554   if (ND->getIdentifier())
555     return ND->getIdentifier()->getNameStart();
556   else 
557     return "";
558 }
559
560 unsigned clang_getDeclLine(CXDecl AnonDecl)
561 {
562   assert(AnonDecl && "Passed null CXDecl");
563   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
564   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
565   return SourceMgr.getSpellingLineNumber(ND->getLocation());
566 }
567
568 unsigned clang_getDeclColumn(CXDecl AnonDecl)
569 {
570   assert(AnonDecl && "Passed null CXDecl");
571   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
572   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
573   return SourceMgr.getSpellingColumnNumber(ND->getLocation());
574 }
575
576 const char *clang_getDeclSource(CXDecl AnonDecl) 
577 {
578   assert(AnonDecl && "Passed null CXDecl");
579   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
580   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
581   return SourceMgr.getBufferName(ND->getLocation());
582 }
583
584 const char *clang_getCursorSpelling(CXCursor C)
585 {
586   assert(C.decl && "CXCursor has null decl");
587   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
588   
589   if (clang_isReference(C.kind)) {
590     switch (C.kind) {
591       case CXCursor_ObjCSuperClassRef: {
592         ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
593         assert(OID && "clang_getCursorLine(): Missing interface decl");
594         return OID->getSuperClass()->getIdentifier()->getNameStart();
595       }
596       case CXCursor_ObjCClassRef: {
597         if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND)) {
598           return OID->getIdentifier()->getNameStart();
599         }
600         ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
601         assert(OID && "clang_getCursorLine(): Missing category decl");
602         return OID->getClassInterface()->getIdentifier()->getNameStart();
603       }
604       case CXCursor_ObjCProtocolRef: {
605         ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
606         assert(OID && "clang_getCursorLine(): Missing protocol decl");
607         return OID->getIdentifier()->getNameStart();
608       }
609       case CXCursor_ObjCSelectorRef: {
610         ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
611                                  static_cast<Stmt *>(C.stmt));
612         assert(OME && "clang_getCursorLine(): Missing message expr");
613         return OME->getSelector().getAsString().c_str();
614       }
615       case CXCursor_VarRef:
616       case CXCursor_FunctionRef:
617       case CXCursor_EnumConstantRef: {
618         DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
619                                  static_cast<Stmt *>(C.stmt));
620         assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
621         return DRE->getDecl()->getIdentifier()->getNameStart();
622       }
623       default:
624         return "<not implemented>";
625     }
626   }
627   return clang_getDeclSpelling(C.decl);
628 }
629
630 const char *clang_getCursorKindSpelling(enum CXCursorKind Kind)
631 {
632   switch (Kind) {
633    case CXCursor_FunctionDecl: return "FunctionDecl";
634    case CXCursor_TypedefDecl: return "TypedefDecl";
635    case CXCursor_EnumDecl: return "EnumDecl";
636    case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
637    case CXCursor_StructDecl: return "StructDecl";
638    case CXCursor_UnionDecl: return "UnionDecl";
639    case CXCursor_ClassDecl: return "ClassDecl";
640    case CXCursor_FieldDecl: return "FieldDecl";
641    case CXCursor_VarDecl: return "VarDecl";
642    case CXCursor_ParmDecl: return "ParmDecl";
643    case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
644    case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
645    case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
646    case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
647    case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
648    case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
649    case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
650    case CXCursor_FunctionDefn: return "FunctionDefn";
651    case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
652    case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
653    case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
654    case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
655    case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
656    case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
657    case CXCursor_ObjCClassRef: return "ObjCClassRef";
658    case CXCursor_ObjCSelectorRef: return "ObjCSelectorRef";
659    
660    case CXCursor_VarRef: return "VarRef";
661    case CXCursor_FunctionRef: return "FunctionRef";
662    case CXCursor_EnumConstantRef: return "EnumConstantRef";
663    case CXCursor_MemberRef: return "MemberRef";
664    
665    case CXCursor_InvalidFile: return "InvalidFile";
666    case CXCursor_NoDeclFound: return "NoDeclFound";
667    case CXCursor_NotImplemented: return "NotImplemented";
668    default: return "<not implemented>";
669   }
670 }
671
672 static enum CXCursorKind TranslateKind(Decl *D) {
673   switch (D->getKind()) {
674     case Decl::Function: return CXCursor_FunctionDecl;
675     case Decl::Typedef: return CXCursor_TypedefDecl;
676     case Decl::Enum: return CXCursor_EnumDecl;
677     case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
678     case Decl::Record: return CXCursor_StructDecl; // FIXME: union/class
679     case Decl::Field: return CXCursor_FieldDecl;
680     case Decl::Var: return CXCursor_VarDecl;
681     case Decl::ParmVar: return CXCursor_ParmDecl;
682     case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
683     case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
684     case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
685     case Decl::ObjCMethod: {
686       ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
687       if (MD->isInstanceMethod())
688         return CXCursor_ObjCInstanceMethodDecl;
689       return CXCursor_ObjCClassMethodDecl;
690     }
691     default: break;
692   }
693   return CXCursor_NotImplemented;
694 }
695 //
696 // CXCursor Operations.
697 //
698 void clang_initCXLookupHint(CXLookupHint *hint) {
699   memset(hint, 0, sizeof(*hint));
700 }
701
702 CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name, 
703                          unsigned line, unsigned column) {
704   return clang_getCursorWithHint(CTUnit, source_name, line, column, NULL);
705 }
706   
707 CXCursor clang_getCursorWithHint(CXTranslationUnit CTUnit,
708                                  const char *source_name, 
709                                  unsigned line, unsigned column, 
710                                  CXLookupHint *hint)
711 {
712   assert(CTUnit && "Passed null CXTranslationUnit");
713   ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
714   
715   // FIXME: Make this better.
716   CXDecl RelativeToDecl = hint ? hint->decl : NULL;
717   
718   FileManager &FMgr = CXXUnit->getFileManager();
719   const FileEntry *File = FMgr.getFile(source_name, 
720                                        source_name+strlen(source_name));  
721   if (!File) {
722     CXCursor C = { CXCursor_InvalidFile, 0, 0 };
723     return C;
724   }
725   SourceLocation SLoc = 
726     CXXUnit->getSourceManager().getLocation(File, line, column);
727                                                                 
728   ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
729                                       static_cast<NamedDecl *>(RelativeToDecl));
730   
731   Decl *Dcl = ALoc.getParentDecl();
732   if (ALoc.isNamedRef())
733     Dcl = ALoc.AsNamedRef().ND;
734   Stmt *Stm = ALoc.dyn_AsStmt();
735   if (Dcl) {
736     if (Stm) {
737       if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Stm)) {
738         CXCursor C = { TranslateDeclRefExpr(DRE), Dcl, Stm };
739         return C;
740       } else if (ObjCMessageExpr *MExp = dyn_cast<ObjCMessageExpr>(Stm)) {
741         CXCursor C = { CXCursor_ObjCSelectorRef, Dcl, MExp };
742         return C;
743       } 
744       // Fall through...treat as a decl, not a ref.
745     }
746     if (ALoc.isNamedRef()) {
747       if (isa<ObjCInterfaceDecl>(Dcl)) {
748         CXCursor C = { CXCursor_ObjCClassRef, Dcl, ALoc.getParentDecl() };
749         return C;
750       }
751       if (isa<ObjCProtocolDecl>(Dcl)) {
752         CXCursor C = { CXCursor_ObjCProtocolRef, Dcl, ALoc.getParentDecl() };
753         return C;
754       }
755     }
756           CXCursor C = { TranslateKind(Dcl), Dcl, 0 };
757     return C;
758   }
759   CXCursor C = { CXCursor_NoDeclFound, 0, 0 };
760   return C;
761 }
762
763 CXCursor clang_getCursorFromDecl(CXDecl AnonDecl)
764 {
765   assert(AnonDecl && "Passed null CXDecl");
766   NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
767   
768   CXCursor C = { TranslateKind(ND), ND, 0 };
769   return C;
770 }
771
772 unsigned clang_isInvalid(enum CXCursorKind K)
773 {
774   return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
775 }
776
777 unsigned clang_isDeclaration(enum CXCursorKind K)
778 {
779   return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
780 }
781
782 unsigned clang_isReference(enum CXCursorKind K)
783 {
784   return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
785 }
786
787 unsigned clang_isDefinition(enum CXCursorKind K)
788 {
789   return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
790 }
791
792 CXCursorKind clang_getCursorKind(CXCursor C)
793 {
794   return C.kind;
795 }
796
797 static Decl *getDeclFromExpr(Stmt *E) {
798   if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
799     return RefExpr->getDecl();
800   if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
801     return ME->getMemberDecl();
802   if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
803     return RE->getDecl();
804
805   if (CallExpr *CE = dyn_cast<CallExpr>(E))
806     return getDeclFromExpr(CE->getCallee());
807   if (CastExpr *CE = dyn_cast<CastExpr>(E))
808     return getDeclFromExpr(CE->getSubExpr());
809   if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
810     return OME->getMethodDecl();
811
812   return 0;
813 }
814
815 CXDecl clang_getCursorDecl(CXCursor C) 
816 {
817   if (clang_isDeclaration(C.kind))
818     return C.decl;
819     
820   if (clang_isReference(C.kind)) {
821     if (C.stmt) {
822       if (C.kind == CXCursor_ObjCClassRef || 
823           C.kind == CXCursor_ObjCProtocolRef)
824         return static_cast<Stmt *>(C.stmt);
825       else
826         return getDeclFromExpr(static_cast<Stmt *>(C.stmt));
827     } else
828       return C.decl;
829   }
830   return 0;
831 }
832
833   
834 static SourceLocation getLocationFromCursor(CXCursor C, 
835                                             SourceManager &SourceMgr,
836                                             NamedDecl *ND) {
837   if (clang_isReference(C.kind)) {
838     switch (C.kind) {
839       case CXCursor_ObjCClassRef: {
840         if (isa<ObjCInterfaceDecl>(ND)) {
841           // FIXME: This is a hack (storing the parent decl in the stmt slot).
842           NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt);
843           return parentDecl->getLocation();
844         }
845         ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
846         assert(OID && "clang_getCursorLine(): Missing category decl");
847         return OID->getClassInterface()->getLocation();
848       }
849       case CXCursor_ObjCSuperClassRef: {
850         ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
851         assert(OID && "clang_getCursorLine(): Missing interface decl");
852         return OID->getSuperClassLoc();
853       }
854       case CXCursor_ObjCProtocolRef: {
855         ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
856         assert(OID && "clang_getCursorLine(): Missing protocol decl");
857         return OID->getLocation();
858       }
859       case CXCursor_ObjCSelectorRef: {
860         ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
861                                  static_cast<Stmt *>(C.stmt));
862         assert(OME && "clang_getCursorLine(): Missing message expr");
863         return OME->getLeftLoc(); /* FIXME: should be a range */
864       }
865       case CXCursor_VarRef:
866       case CXCursor_FunctionRef:
867       case CXCursor_EnumConstantRef: {
868         DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
869                                  static_cast<Stmt *>(C.stmt));
870         assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
871         return DRE->getLocation();
872       }
873       default:
874         return SourceLocation();
875     }
876   } else { // We have a declaration or a definition.
877     SourceLocation SLoc;
878     switch (ND->getKind()) {
879       case Decl::ObjCInterface: {
880         SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
881         break;
882       }
883       case Decl::ObjCProtocol: {
884         SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
885         break;
886       }
887       default: {
888         SLoc = ND->getLocation();
889         break;
890       }
891     }
892     if (SLoc.isInvalid())
893       return SourceLocation();
894     return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
895   }
896 }
897
898 unsigned clang_getCursorLine(CXCursor C)
899 {
900   assert(C.decl && "CXCursor has null decl");
901   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
902   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
903   
904   SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
905   return SourceMgr.getSpellingLineNumber(SLoc);
906 }
907
908 unsigned clang_getCursorColumn(CXCursor C)
909 {
910   assert(C.decl && "CXCursor has null decl");
911   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
912   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
913   
914   SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
915   return SourceMgr.getSpellingColumnNumber(SLoc);
916 }
917 const char *clang_getCursorSource(CXCursor C) 
918 {
919   assert(C.decl && "CXCursor has null decl");
920   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
921   SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
922   
923   SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
924   if (SLoc.isFileID())
925     return SourceMgr.getBufferName(SLoc);
926
927   // Retrieve the file in which the macro was instantiated, then provide that
928   // buffer name.
929   // FIXME: Do we want to give specific macro-instantiation information?
930   const llvm::MemoryBuffer *Buffer 
931     = SourceMgr.getBuffer(SourceMgr.getDecomposedSpellingLoc(SLoc).first);
932   if (!Buffer)
933     return 0;
934
935   return Buffer->getBufferIdentifier();
936 }
937
938 void clang_getDefinitionSpellingAndExtent(CXCursor C, 
939                                           const char **startBuf,
940                                           const char **endBuf,
941                                           unsigned *startLine,
942                                           unsigned *startColumn,
943                                           unsigned *endLine,
944                                           unsigned *endColumn) 
945 {
946   assert(C.decl && "CXCursor has null decl");
947   NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
948   FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
949   CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
950   
951   SourceManager &SM = FD->getASTContext().getSourceManager();
952   *startBuf = SM.getCharacterData(Body->getLBracLoc());
953   *endBuf = SM.getCharacterData(Body->getRBracLoc());
954   *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
955   *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
956   *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
957   *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
958 }
959
960
961 } // end extern "C"