 |
|
 |
|
| Files: |
1 |
|
Branches Taken: |
64.5% |
468 / 726 |
| Generated: |
2010-02-10 01:31 |
|
Branches Executed: |
92.6% |
672 / 726 |
| |
|
Line Coverage: |
75.9% |
710 / 935 |
| |
 |
|
 |
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 main API hooks in the Clang-C Source Indexing
11 : // library.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "CIndexer.h"
16 : #include "CXCursor.h"
17 : #include "CXSourceLocation.h"
18 : #include "CIndexDiagnostic.h"
19 :
20 : #include "clang/Basic/Version.h"
21 :
22 : #include "clang/AST/DeclVisitor.h"
23 : #include "clang/AST/StmtVisitor.h"
24 : #include "clang/AST/TypeLocVisitor.h"
25 : #include "clang/Frontend/FrontendDiagnostic.h"
26 : #include "clang/Lex/Lexer.h"
27 : #include "clang/Lex/Preprocessor.h"
28 : #include "llvm/Support/MemoryBuffer.h"
29 : #include "llvm/System/Program.h"
30 :
31 : // Needed to define L_TMPNAM on some systems.
32 : #include <cstdio>
33 :
34 : using namespace clang;
35 : using namespace clang::cxcursor;
36 : using namespace idx;
37 :
38 : //===----------------------------------------------------------------------===//
39 : // Crash Reporting.
40 : //===----------------------------------------------------------------------===//
41 :
42 : #ifdef __APPLE__
43 : #ifndef NDEBUG
44 : #define USE_CRASHTRACER
45 : #include "clang/Analysis/Support/SaveAndRestore.h"
46 : // Integrate with crash reporter.
47 : extern "C" const char *__crashreporter_info__;
48 : #define NUM_CRASH_STRINGS 16
49 : static unsigned crashtracer_counter = 0;
50 : static unsigned crashtracer_counter_id[NUM_CRASH_STRINGS] = { 0 };
51 : static const char *crashtracer_strings[NUM_CRASH_STRINGS] = { 0 };
52 : static const char *agg_crashtracer_strings[NUM_CRASH_STRINGS] = { 0 };
53 :
54 : static unsigned SetCrashTracerInfo(const char *str,
55 : llvm::SmallString<1024> &AggStr) {
56 :
57 : unsigned slot = 0;
58 : while (crashtracer_strings[slot]) {
59 : if (++slot == NUM_CRASH_STRINGS)
60 : slot = 0;
61 : }
62 : crashtracer_strings[slot] = str;
63 : crashtracer_counter_id[slot] = ++crashtracer_counter;
64 :
65 : // We need to create an aggregate string because multiple threads
66 : // may be in this method at one time. The crash reporter string
67 : // will attempt to overapproximate the set of in-flight invocations
68 : // of this function. Race conditions can still cause this goal
69 : // to not be achieved.
70 : {
71 : llvm::raw_svector_ostream Out(AggStr);
72 : for (unsigned i = 0; i < NUM_CRASH_STRINGS; ++i)
73 : if (crashtracer_strings[i]) Out << crashtracer_strings[i] << '\n';
74 : }
75 : __crashreporter_info__ = agg_crashtracer_strings[slot] = AggStr.c_str();
76 : return slot;
77 : }
78 :
79 : static void ResetCrashTracerInfo(unsigned slot) {
80 : unsigned max_slot = 0;
81 : unsigned max_value = 0;
82 :
83 : crashtracer_strings[slot] = agg_crashtracer_strings[slot] = 0;
84 :
85 : for (unsigned i = 0 ; i < NUM_CRASH_STRINGS; ++i)
86 : if (agg_crashtracer_strings[i] &&
87 : crashtracer_counter_id[i] > max_value) {
88 : max_slot = i;
89 : max_value = crashtracer_counter_id[i];
90 : }
91 :
92 : __crashreporter_info__ = agg_crashtracer_strings[max_slot];
93 : }
94 :
95 : namespace {
96 : class ArgsCrashTracerInfo {
97 : llvm::SmallString<1024> CrashString;
98 : llvm::SmallString<1024> AggregateString;
99 : unsigned crashtracerSlot;
100 : public:
101 : ArgsCrashTracerInfo(llvm::SmallVectorImpl<const char*> &Args)
102 : : crashtracerSlot(0)
103 : {
104 : {
105 : llvm::raw_svector_ostream Out(CrashString);
106 : Out << "ClangCIndex [createTranslationUnitFromSourceFile]: clang";
107 : for (llvm::SmallVectorImpl<const char*>::iterator I=Args.begin(),
108 : E=Args.end(); I!=E; ++I)
109 : Out << ' ' << *I;
110 : }
111 : crashtracerSlot = SetCrashTracerInfo(CrashString.c_str(),
112 : AggregateString);
113 : }
114 :
115 : ~ArgsCrashTracerInfo() {
116 : ResetCrashTracerInfo(crashtracerSlot);
117 : }
118 : };
119 : }
120 : #endif
121 : #endif
122 :
123 : /// \brief The result of comparing two source ranges.
124 : enum RangeComparisonResult {
125 : /// \brief Either the ranges overlap or one of the ranges is invalid.
126 : RangeOverlap,
127 :
128 : /// \brief The first range ends before the second range starts.
129 : RangeBefore,
130 :
131 : /// \brief The first range starts after the second range ends.
132 : RangeAfter
133 : };
134 :
135 : /// \brief Compare two source ranges to determine their relative position in
136 : /// the translation unit.
137 : static RangeComparisonResult RangeCompare(SourceManager &SM,
138 : SourceRange R1,
139 122878: SourceRange R2) {
122878: branch 1 taken
0: branch 2 not taken
140 122878: assert(R1.isValid() && "First range is invalid?");
122878: branch 1 taken
0: branch 2 not taken
141 122878: assert(R2.isValid() && "Second range is invalid?");
118870: branch 3 taken
4008: branch 4 taken
142 122878: if (SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
143 118870: return RangeBefore;
2517: branch 3 taken
1491: branch 4 taken
144 4008: if (SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
145 2517: return RangeAfter;
146 1491: return RangeOverlap;
147 : }
148 :
149 :
150 : //===----------------------------------------------------------------------===//
151 : // Cursor visitor.
152 : //===----------------------------------------------------------------------===//
153 :
154 : namespace {
155 :
156 : // Cursor visitor.
157 : class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
158 : public TypeLocVisitor<CursorVisitor, bool>,
159 : public StmtVisitor<CursorVisitor, bool>
160 : {
161 : /// \brief The translation unit we are traversing.
162 : ASTUnit *TU;
163 :
164 : /// \brief The parent cursor whose children we are traversing.
165 : CXCursor Parent;
166 :
167 : /// \brief The declaration that serves at the parent of any statement or
168 : /// expression nodes.
169 : Decl *StmtParent;
170 :
171 : /// \brief The visitor function.
172 : CXCursorVisitor Visitor;
173 :
174 : /// \brief The opaque client data, to be passed along to the visitor.
175 : CXClientData ClientData;
176 :
177 : // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
178 : // to the visitor. Declarations with a PCH level greater than this value will
179 : // be suppressed.
180 : unsigned MaxPCHLevel;
181 :
182 : /// \brief When valid, a source range to which the cursor should restrict
183 : /// its search.
184 : SourceRange RegionOfInterest;
185 :
186 : using DeclVisitor<CursorVisitor, bool>::Visit;
187 : using TypeLocVisitor<CursorVisitor, bool>::Visit;
188 : using StmtVisitor<CursorVisitor, bool>::Visit;
189 :
190 : /// \brief Determine whether this particular source range comes before, comes
191 : /// after, or overlaps the region of interest.
192 : ///
193 : /// \param R a source range retrieved from the abstract syntax tree.
194 : RangeComparisonResult CompareRegionOfInterest(SourceRange R);
195 :
196 : /// \brief Determine whether this particular source range comes before, comes
197 : /// after, or overlaps the region of interest.
198 : ///
199 : /// \param CXR a source range retrieved from a cursor.
200 : RangeComparisonResult CompareRegionOfInterest(CXSourceRange CXR);
201 :
202 : public:
203 : CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData,
204 : unsigned MaxPCHLevel,
205 12836: SourceRange RegionOfInterest = SourceRange())
206 : : TU(TU), Visitor(Visitor), ClientData(ClientData),
207 12836: MaxPCHLevel(MaxPCHLevel), RegionOfInterest(RegionOfInterest)
208 : {
209 12836: Parent.kind = CXCursor_NoDeclFound;
210 12836: Parent.data[0] = 0;
211 12836: Parent.data[1] = 0;
212 12836: Parent.data[2] = 0;
213 12836: StmtParent = 0;
214 12836: }
215 :
216 : bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
217 : bool VisitChildren(CXCursor Parent);
218 :
219 : // Declaration visitors
220 : bool VisitDeclContext(DeclContext *DC);
221 : bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
222 : bool VisitTypedefDecl(TypedefDecl *D);
223 : bool VisitTagDecl(TagDecl *D);
224 : bool VisitEnumConstantDecl(EnumConstantDecl *D);
225 : bool VisitDeclaratorDecl(DeclaratorDecl *DD);
226 : bool VisitFunctionDecl(FunctionDecl *ND);
227 : bool VisitFieldDecl(FieldDecl *D);
228 : bool VisitVarDecl(VarDecl *);
229 : bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
230 : bool VisitObjCContainerDecl(ObjCContainerDecl *D);
231 : bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
232 : bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
233 : bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
234 : bool VisitObjCImplDecl(ObjCImplDecl *D);
235 : bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
236 : bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
237 : // FIXME: ObjCPropertyDecl requires TypeSourceInfo, getter/setter locations,
238 : // etc.
239 : // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
240 : bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
241 : bool VisitObjCClassDecl(ObjCClassDecl *D);
242 :
243 : // Type visitors
244 : // FIXME: QualifiedTypeLoc doesn't provide any location information
245 : bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
246 : bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
247 : bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
248 : bool VisitTagTypeLoc(TagTypeLoc TL);
249 : // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
250 : bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
251 : bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
252 : bool VisitPointerTypeLoc(PointerTypeLoc TL);
253 : bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
254 : bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
255 : bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
256 : bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
257 : bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
258 : bool VisitArrayTypeLoc(ArrayTypeLoc TL);
259 : // FIXME: Implement for TemplateSpecializationTypeLoc
260 : // FIXME: Implement visitors here when the unimplemented TypeLocs get
261 : // implemented
262 : bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
263 : bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
264 :
265 : // Statement visitors
266 : bool VisitStmt(Stmt *S);
267 : bool VisitDeclStmt(DeclStmt *S);
268 : // FIXME: LabelStmt label?
269 : bool VisitIfStmt(IfStmt *S);
270 : bool VisitSwitchStmt(SwitchStmt *S);
271 : bool VisitWhileStmt(WhileStmt *S);
272 : bool VisitForStmt(ForStmt *S);
273 :
274 : // Expression visitors
275 : bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
276 : bool VisitExplicitCastExpr(ExplicitCastExpr *E);
277 : bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
278 : };
279 :
280 : } // end anonymous namespace
281 :
282 122878: RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
122878: branch 1 taken
0: branch 2 not taken
283 122878: assert(RegionOfInterest.isValid() && "RangeCompare called with invalid range");
0: branch 1 not taken
122878: branch 2 taken
284 122878: if (R.isInvalid())
285 0: return RangeOverlap;
286 :
287 : // Move the end of the input range to the end of the last token in that
288 : // range.
289 : SourceLocation NewEnd
290 122878: = TU->getPreprocessor().getLocForEndOfToken(R.getEnd(), 1);
122878: branch 1 taken
0: branch 2 not taken
291 122878: if (NewEnd.isValid())
292 122878: R.setEnd(NewEnd);
293 122878: return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
294 : }
295 :
296 3191: RangeComparisonResult CursorVisitor::CompareRegionOfInterest(CXSourceRange CXR) {
297 3191: return CompareRegionOfInterest(cxloc::translateSourceRange(CXR));
298 : }
299 :
300 : /// \brief Visit the given cursor and, if requested by the visitor,
301 : /// its children.
302 : ///
303 : /// \param Cursor the cursor to visit.
304 : ///
305 : /// \param CheckRegionOfInterest if true, then the caller already checked that
306 : /// this cursor is within the region of interest.
307 : ///
308 : /// \returns true if the visitation should be aborted, false if it
309 : /// should continue.
310 4246: bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
0: branch 1 not taken
4246: branch 2 taken
311 4246: if (clang_isInvalid(Cursor.kind))
312 0: return false;
313 :
1572: branch 1 taken
2674: branch 2 taken
314 4246: if (clang_isDeclaration(Cursor.kind)) {
315 1572: Decl *D = getCursorDecl(Cursor);
0: branch 0 not taken
1572: branch 1 taken
316 1572: assert(D && "Invalid declaration cursor");
3: branch 1 taken
1569: branch 2 taken
317 1572: if (D->getPCHLevel() > MaxPCHLevel)
318 3: return false;
319 :
5: branch 1 taken
1564: branch 2 taken
320 1569: if (D->isImplicit())
321 5: return false;
322 : }
323 :
324 : // If we have a range of interest, and this cursor doesn't intersect with it,
325 : // we're done.
4001: branch 1 taken
237: branch 2 taken
3191: branch 3 taken
810: branch 4 taken
3191: branch 5 taken
1047: branch 6 taken
326 4238: if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
327 3191: CXSourceRange Range = clang_getCursorExtent(Cursor);
3191: branch 2 taken
0: branch 3 not taken
2510: branch 5 taken
681: branch 6 taken
2510: branch 7 taken
681: branch 8 taken
328 3191: if (cxloc::translateSourceRange(Range).isInvalid() ||
329 : CompareRegionOfInterest(Range))
330 2510: return false;
331 : }
332 :
0: branch 1 not taken
0: branch 2 not taken
1728: branch 3 taken
0: branch 4 not taken
333 1728: switch (Visitor(Cursor, Parent, ClientData)) {
334 : case CXChildVisit_Break:
335 0: return true;
336 :
337 : case CXChildVisit_Continue:
338 0: return false;
339 :
340 : case CXChildVisit_Recurse:
341 1728: return VisitChildren(Cursor);
342 : }
343 :
344 0: return false;
345 : }
346 :
347 : /// \brief Visit the children of the given cursor.
348 : ///
349 : /// \returns true if the visitation should be aborted, false if it
350 : /// should continue.
351 14564: bool CursorVisitor::VisitChildren(CXCursor Cursor) {
88: branch 1 taken
14476: branch 2 taken
352 14564: if (clang_isReference(Cursor.kind)) {
353 : // By definition, references have no children.
354 88: return false;
355 : }
356 :
357 : // Set the Parent field to Cursor, then back to its old value once we're
358 : // done.
359 : class SetParentRAII {
360 : CXCursor &Parent;
361 : Decl *&StmtParent;
362 : CXCursor OldParent;
363 :
364 : public:
365 14476: SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
366 14476: : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
367 : {
368 14476: Parent = NewParent;
1037: branch 1 taken
13439: branch 2 taken
369 14476: if (clang_isDeclaration(Parent.kind))
370 1037: StmtParent = getCursorDecl(Parent);
371 14476: }
372 :
373 14476: ~SetParentRAII() {
374 14476: Parent = OldParent;
498: branch 1 taken
13978: branch 2 taken
375 14476: if (clang_isDeclaration(Parent.kind))
376 498: StmtParent = getCursorDecl(Parent);
377 14476: }
378 14476: } SetParent(Parent, StmtParent, Cursor);
379 :
1037: branch 1 taken
13439: branch 2 taken
380 14476: if (clang_isDeclaration(Cursor.kind)) {
381 1037: Decl *D = getCursorDecl(Cursor);
0: branch 0 not taken
1037: branch 1 taken
382 1037: assert(D && "Invalid declaration cursor");
383 1037: return Visit(D);
384 : }
385 :
330: branch 1 taken
13109: branch 2 taken
386 13439: if (clang_isStatement(Cursor.kind))
387 330: return Visit(getCursorStmt(Cursor));
273: branch 1 taken
12836: branch 2 taken
388 13109: if (clang_isExpression(Cursor.kind))
389 273: return Visit(getCursorExpr(Cursor));
390 :
12836: branch 1 taken
0: branch 2 not taken
391 12836: if (clang_isTranslationUnit(Cursor.kind)) {
392 12836: ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
9: branch 1 taken
12827: branch 2 taken
1: branch 4 taken
8: branch 5 taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
12835: branch 10 taken
393 12836: if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
394 : RegionOfInterest.isInvalid()) {
395 1: const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
2: branch 3 taken
1: branch 4 taken
396 4: for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
397 1: ie = TLDs.end(); it != ie; ++it) {
0: branch 3 not taken
2: branch 4 taken
398 2: if (Visit(MakeCXCursor(*it, CXXUnit), true))
399 0: return true;
400 : }
401 : } else {
402 : return VisitDeclContext(
12835: branch 2 taken
0: branch 3 not taken
403 12835: CXXUnit->getASTContext().getTranslationUnitDecl());
404 : }
405 :
406 1: return false;
407 : }
408 :
409 : // Nothing to visit at the moment.
410 0: return false;
411 : }
412 :
413 13197: bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
183881: branch 2 taken
11543: branch 3 taken
414 195424: for (DeclContext::decl_iterator
415 13197: I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
183792: branch 1 taken
89: branch 2 taken
416 183881: if (RegionOfInterest.isValid()) {
417 183792: SourceRange R = (*I)->getSourceRange();
119687: branch 1 taken
64105: branch 2 taken
418 183792: if (R.isInvalid())
419 64105: continue;
420 :
117223: branch 1 taken
1654: branch 2 taken
810: branch 3 taken
421 119687: switch (CompareRegionOfInterest(R)) {
422 : case RangeBefore:
423 : // This declaration comes before the region of interest; skip it.
424 117223: continue;
425 :
426 : case RangeAfter:
427 : // This declaration comes after the region of interest; we're done.
428 1654: return false;
429 :
430 : case RangeOverlap:
431 : // This declaration overlaps the region of interest; visit it.
432 : break;
433 : }
434 : }
435 :
0: branch 3 not taken
899: branch 4 taken
436 899: if (Visit(MakeCXCursor(*I, TU), true))
437 0: return true;
438 : }
439 :
440 11543: return false;
441 : }
442 :
443 0: bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
444 0: llvm_unreachable("Translation units are visited directly by Visit()");
445 : return false;
446 : }
447 :
448 28: bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
28: branch 1 taken
0: branch 2 not taken
449 28: if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
450 28: return Visit(TSInfo->getTypeLoc());
451 :
452 0: return false;
453 : }
454 :
455 26: bool CursorVisitor::VisitTagDecl(TagDecl *D) {
26: branch 0 taken
0: branch 1 not taken
456 26: return VisitDeclContext(D);
457 : }
458 :
459 9: bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
0: branch 1 not taken
9: branch 2 taken
460 9: if (Expr *Init = D->getInitExpr())
461 0: return Visit(MakeCXCursor(Init, StmtParent, TU));
462 9: return false;
463 : }
464 :
465 493: bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
493: branch 1 taken
0: branch 2 not taken
466 493: if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
0: branch 2 not taken
493: branch 3 taken
467 493: if (Visit(TSInfo->getTypeLoc()))
468 0: return true;
469 :
470 493: return false;
471 : }
472 :
473 323: bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
0: branch 1 not taken
323: branch 2 taken
474 323: if (VisitDeclaratorDecl(ND))
475 0: return true;
476 :
318: branch 1 taken
5: branch 2 taken
0: branch 6 not taken
318: branch 7 taken
0: branch 8 not taken
323: branch 9 taken
477 323: if (ND->isThisDeclarationADefinition() &&
478 : Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
479 0: return true;
480 :
481 323: return false;
482 : }
483 :
484 24: bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
0: branch 1 not taken
24: branch 2 taken
485 24: if (VisitDeclaratorDecl(D))
486 0: return true;
487 :
0: branch 1 not taken
24: branch 2 taken
488 24: if (Expr *BitWidth = D->getBitWidth())
489 0: return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
490 :
491 24: return false;
492 : }
493 :
494 146: bool CursorVisitor::VisitVarDecl(VarDecl *D) {
0: branch 1 not taken
146: branch 2 taken
495 146: if (VisitDeclaratorDecl(D))
496 0: return true;
497 :
54: branch 1 taken
92: branch 2 taken
498 146: if (Expr *Init = D->getInit())
499 54: return Visit(MakeCXCursor(Init, StmtParent, TU));
500 :
501 92: return false;
502 : }
503 :
504 123: bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
505 : // FIXME: We really need a TypeLoc covering Objective-C method declarations.
506 : // At the moment, we don't have information about locations in the return
507 : // type.
41: branch 1 taken
123: branch 2 taken
508 287: for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
509 123: PEnd = ND->param_end();
510 : P != PEnd; ++P) {
0: branch 2 not taken
41: branch 3 taken
511 41: if (Visit(MakeCXCursor(*P, TU)))
512 0: return true;
513 : }
514 :
0: branch 1 not taken
123: branch 2 taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
123: branch 9 taken
515 123: if (ND->isThisDeclarationADefinition() &&
516 : Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
517 0: return true;
518 :
519 123: return false;
520 : }
521 :
522 336: bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
336: branch 0 taken
0: branch 1 not taken
523 336: return VisitDeclContext(D);
524 : }
525 :
526 93: bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
0: branch 4 not taken
93: branch 5 taken
527 93: if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
528 : TU)))
529 0: return true;
530 :
531 93: ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
0: branch 1 not taken
93: branch 2 taken
532 186: for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
533 93: E = ND->protocol_end(); I != E; ++I, ++PL)
0: branch 2 not taken
0: branch 3 not taken
534 0: if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
535 0: return true;
536 :
537 93: return VisitObjCContainerDecl(ND);
538 : }
539 :
540 72: bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
541 72: ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
40: branch 1 taken
72: branch 2 taken
542 184: for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
543 72: E = PID->protocol_end(); I != E; ++I, ++PL)
0: branch 2 not taken
40: branch 3 taken
544 40: if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
545 0: return true;
546 :
547 72: return VisitObjCContainerDecl(PID);
548 : }
549 :
550 171: bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
551 : // Issue callbacks for super class.
109: branch 1 taken
62: branch 2 taken
0: branch 7 not taken
109: branch 8 taken
0: branch 9 not taken
171: branch 10 taken
552 171: if (D->getSuperClass() &&
553 : Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
554 : D->getSuperClassLoc(),
555 : TU)))
556 0: return true;
557 :
558 171: ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
77: branch 1 taken
171: branch 2 taken
559 419: for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
560 171: E = D->protocol_end(); I != E; ++I, ++PL)
0: branch 2 not taken
77: branch 3 taken
561 77: if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
562 0: return true;
563 :
564 171: return VisitObjCContainerDecl(D);
565 : }
566 :
567 0: bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
568 0: return VisitObjCContainerDecl(D);
569 : }
570 :
571 0: bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
0: branch 5 not taken
0: branch 6 not taken
572 0: if (Visit(MakeCursorObjCClassRef(D->getCategoryDecl()->getClassInterface(),
573 : D->getLocation(), TU)))
574 0: return true;
575 :
576 0: return VisitObjCImplDecl(D);
577 : }
578 :
579 0: bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
580 : #if 0
581 : // Issue callbacks for super class.
582 : // FIXME: No source location information!
583 : if (D->getSuperClass() &&
584 : Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
585 : D->getSuperClassLoc(),
586 : TU)))
587 : return true;
588 : #endif
589 :
590 0: return VisitObjCImplDecl(D);
591 : }
592 :
593 0: bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
594 0: ObjCForwardProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
0: branch 1 not taken
0: branch 2 not taken
595 0: for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
596 0: E = D->protocol_end();
597 : I != E; ++I, ++PL)
0: branch 2 not taken
0: branch 3 not taken
598 0: if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
599 0: return true;
600 :
601 0: return false;
602 : }
603 :
604 22: bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
22: branch 2 taken
22: branch 3 taken
605 44: for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
0: branch 4 not taken
22: branch 5 taken
606 22: if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
607 0: return true;
608 :
609 22: return false;
610 : }
611 :
612 441: bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
613 441: ASTContext &Context = TU->getASTContext();
614 :
615 : // Some builtin types (such as Objective-C's "id", "sel", and
616 : // "Class") have associated declarations. Create cursors for those.
617 441: QualType VisitType;
400: branch 4 taken
0: branch 5 not taken
38: branch 6 taken
0: branch 7 not taken
3: branch 8 taken
0: branch 9 not taken
618 441: switch (TL.getType()->getAs<BuiltinType>()->getKind()) {
619 : case BuiltinType::Void:
620 : case BuiltinType::Bool:
621 : case BuiltinType::Char_U:
622 : case BuiltinType::UChar:
623 : case BuiltinType::Char16:
624 : case BuiltinType::Char32:
625 : case BuiltinType::UShort:
626 : case BuiltinType::UInt:
627 : case BuiltinType::ULong:
628 : case BuiltinType::ULongLong:
629 : case BuiltinType::UInt128:
630 : case BuiltinType::Char_S:
631 : case BuiltinType::SChar:
632 : case BuiltinType::WChar:
633 : case BuiltinType::Short:
634 : case BuiltinType::Int:
635 : case BuiltinType::Long:
636 : case BuiltinType::LongLong:
637 : case BuiltinType::Int128:
638 : case BuiltinType::Float:
639 : case BuiltinType::Double:
640 : case BuiltinType::LongDouble:
641 : case BuiltinType::NullPtr:
642 : case BuiltinType::Overload:
643 : case BuiltinType::Dependent:
644 400: break;
645 :
646 : case BuiltinType::UndeducedAuto: // FIXME: Deserves a cursor?
647 0: break;
648 :
649 : case BuiltinType::ObjCId:
650 38: VisitType = Context.getObjCIdType();
651 38: break;
652 :
653 : case BuiltinType::ObjCClass:
654 0: VisitType = Context.getObjCClassType();
655 0: break;
656 :
657 : case BuiltinType::ObjCSel:
658 3: VisitType = Context.getObjCSelType();
659 : break;
660 : }
661 :
41: branch 1 taken
400: branch 2 taken
662 441: if (!VisitType.isNull()) {
41: branch 2 taken
0: branch 3 not taken
663 41: if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
664 : return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
665 41: TU));
666 : }
667 :
668 400: return false;
669 : }
670 :
671 32: bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
672 32: return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU));
673 : }
674 :
675 0: bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
676 0: return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
677 : }
678 :
679 7: bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
680 7: return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
681 : }
682 :
683 30: bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
0: branch 4 not taken
30: branch 5 taken
684 30: if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
685 0: return true;
686 :
0: branch 1 not taken
30: branch 2 taken
687 30: for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
0: branch 4 not taken
0: branch 5 not taken
688 0: if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
689 : TU)))
690 0: return true;
691 : }
692 :
693 30: return false;
694 : }
695 :
696 74: bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
68: branch 1 taken
6: branch 2 taken
0: branch 5 not taken
68: branch 6 taken
0: branch 7 not taken
74: branch 8 taken
697 74: if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseTypeLoc()))
698 0: return true;
699 :
38: branch 1 taken
36: branch 2 taken
700 74: if (TL.hasProtocolsAsWritten()) {
38: branch 1 taken
38: branch 2 taken
701 76: for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
0: branch 4 not taken
38: branch 5 taken
702 38: if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I),
703 : TL.getProtocolLoc(I),
704 : TU)))
705 0: return true;
706 : }
707 : }
708 :
709 74: return false;
710 : }
711 :
712 74: bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
713 74: return Visit(TL.getPointeeLoc());
714 : }
715 :
716 0: bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
717 0: return Visit(TL.getPointeeLoc());
718 : }
719 :
720 0: bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
721 0: return Visit(TL.getPointeeLoc());
722 : }
723 :
724 0: bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
725 0: return Visit(TL.getPointeeLoc());
726 : }
727 :
728 0: bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
729 0: return Visit(TL.getPointeeLoc());
730 : }
731 :
732 323: bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
0: branch 2 not taken
323: branch 3 taken
733 323: if (Visit(TL.getResultLoc()))
734 0: return true;
735 :
549: branch 1 taken
323: branch 2 taken
736 872: for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
0: branch 3 not taken
549: branch 4 taken
737 549: if (Visit(MakeCXCursor(TL.getArg(I), TU)))
738 0: return true;
739 :
740 323: return false;
741 : }
742 :
743 15: bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
0: branch 2 not taken
15: branch 3 taken
744 15: if (Visit(TL.getElementLoc()))
745 0: return true;
746 :
3: branch 1 taken
12: branch 2 taken
747 15: if (Expr *Size = TL.getSizeExpr())
748 3: return Visit(MakeCXCursor(Size, StmtParent, TU));
749 :
750 12: return false;
751 : }
752 :
753 0: bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
754 0: return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
755 : }
756 :
757 0: bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
0: branch 1 not taken
0: branch 2 not taken
758 0: if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
759 0: return Visit(TSInfo->getTypeLoc());
760 :
761 0: return false;
762 : }
763 :
764 520: bool CursorVisitor::VisitStmt(Stmt *S) {
1803: branch 4 taken
520: branch 5 taken
765 2323: for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
766 : Child != ChildEnd; ++Child) {
1800: branch 1 taken
3: branch 2 taken
0: branch 6 not taken
1800: branch 7 taken
0: branch 8 not taken
1803: branch 9 taken
767 1803: if (*Child && Visit(MakeCXCursor(*Child, StmtParent, TU)))
768 0: return true;
769 : }
770 :
771 520: return false;
772 : }
773 :
774 77: bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
77: branch 2 taken
77: branch 3 taken
775 154: for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
776 : D != DEnd; ++D) {
77: branch 0 taken
0: branch 1 not taken
0: branch 4 not taken
77: branch 5 taken
0: branch 6 not taken
77: branch 7 taken
777 77: if (*D && Visit(MakeCXCursor(*D, TU)))
778 0: return true;
779 : }
780 :
781 77: return false;
782 : }
783 :
784 1: bool CursorVisitor::VisitIfStmt(IfStmt *S) {
1: branch 1 taken
0: branch 2 not taken
785 1: if (VarDecl *Var = S->getConditionVariable()) {
0: branch 2 not taken
1: branch 3 taken
786 1: if (Visit(MakeCXCursor(Var, TU)))
787 0: return true;
788 : }
789 :
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
790 1: if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
791 0: return true;
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
792 1: if (S->getThen() && Visit(MakeCXCursor(S->getThen(), StmtParent, TU)))
793 0: return true;
0: branch 1 not taken
1: branch 2 taken
0: branch 6 not taken
0: branch 7 not taken
0: branch 8 not taken
1: branch 9 taken
794 1: if (S->getElse() && Visit(MakeCXCursor(S->getElse(), StmtParent, TU)))
795 0: return true;
796 :
797 1: return false;
798 : }
799 :
800 1: bool CursorVisitor::VisitSwitchStmt(SwitchStmt *S) {
1: branch 1 taken
0: branch 2 not taken
801 1: if (VarDecl *Var = S->getConditionVariable()) {
0: branch 2 not taken
1: branch 3 taken
802 1: if (Visit(MakeCXCursor(Var, TU)))
803 0: return true;
804 : }
805 :
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
806 1: if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
807 0: return true;
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
808 1: if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
809 0: return true;
810 :
811 1: return false;
812 : }
813 :
814 1: bool CursorVisitor::VisitWhileStmt(WhileStmt *S) {
1: branch 1 taken
0: branch 2 not taken
815 1: if (VarDecl *Var = S->getConditionVariable()) {
0: branch 2 not taken
1: branch 3 taken
816 1: if (Visit(MakeCXCursor(Var, TU)))
817 0: return true;
818 : }
819 :
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
820 1: if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
821 0: return true;
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
822 1: if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
823 0: return true;
824 :
825 1: return false;
826 : }
827 :
828 1: bool CursorVisitor::VisitForStmt(ForStmt *S) {
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
829 1: if (S->getInit() && Visit(MakeCXCursor(S->getInit(), StmtParent, TU)))
830 0: return true;
1: branch 1 taken
0: branch 2 not taken
831 1: if (VarDecl *Var = S->getConditionVariable()) {
0: branch 2 not taken
1: branch 3 taken
832 1: if (Visit(MakeCXCursor(Var, TU)))
833 0: return true;
834 : }
835 :
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
836 1: if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
837 0: return true;
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
838 1: if (S->getInc() && Visit(MakeCXCursor(S->getInc(), StmtParent, TU)))
839 0: return true;
1: branch 1 taken
0: branch 2 not taken
0: branch 6 not taken
1: branch 7 taken
0: branch 8 not taken
1: branch 9 taken
840 1: if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
841 0: return true;
842 :
843 1: return false;
844 : }
845 :
846 2: bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
2: branch 1 taken
0: branch 2 not taken
847 2: if (E->isArgumentType()) {
2: branch 1 taken
0: branch 2 not taken
848 2: if (TypeSourceInfo *TSInfo = E->getArgumentTypeInfo())
849 2: return Visit(TSInfo->getTypeLoc());
850 :
851 0: return false;
852 : }
853 :
854 0: return VisitExpr(E);
855 : }
856 :
857 23: bool CursorVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
23: branch 1 taken
0: branch 2 not taken
858 23: if (TypeSourceInfo *TSInfo = E->getTypeInfoAsWritten())
0: branch 2 not taken
23: branch 3 taken
859 23: if (Visit(TSInfo->getTypeLoc()))
860 0: return true;
861 :
862 23: return VisitCastExpr(E);
863 : }
864 :
865 2: bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
2: branch 1 taken
0: branch 2 not taken
866 2: if (TypeSourceInfo *TSInfo = E->getTypeSourceInfo())
0: branch 2 not taken
2: branch 3 taken
867 2: if (Visit(TSInfo->getTypeLoc()))
868 0: return true;
869 :
870 2: return VisitExpr(E);
871 : }
872 :
873 378: CXString CIndexer::createCXString(const char *String, bool DupString){
874 : CXString Str;
62: branch 0 taken
316: branch 1 taken
875 378: if (DupString) {
876 62: Str.Spelling = strdup(String);
877 62: Str.MustFreeString = 1;
878 : } else {
879 316: Str.Spelling = String;
880 316: Str.MustFreeString = 0;
881 : }
882 : return Str;
883 : }
884 :
885 89: CXString CIndexer::createCXString(llvm::StringRef String, bool DupString) {
886 : CXString Result;
2: branch 0 taken
87: branch 1 taken
2: branch 3 taken
0: branch 4 not taken
0: branch 7 not taken
2: branch 8 taken
87: branch 9 taken
2: branch 10 taken
887 89: if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
888 87: char *Spelling = (char *)malloc(String.size() + 1);
889 87: memmove(Spelling, String.data(), String.size());
890 87: Spelling[String.size()] = 0;
891 87: Result.Spelling = Spelling;
892 87: Result.MustFreeString = 1;
893 : } else {
894 2: Result.Spelling = String.data();
895 2: Result.MustFreeString = 0;
896 : }
897 : return Result;
898 : }
899 :
900 : extern "C" {
901 69: CXIndex clang_createIndex(int excludeDeclarationsFromPCH) {
902 69: CIndexer *CIdxr = new CIndexer();
8: branch 0 taken
61: branch 1 taken
903 69: if (excludeDeclarationsFromPCH)
904 8: CIdxr->setOnlyLocalDecls();
905 69: return CIdxr;
906 : }
907 :
908 54: void clang_disposeIndex(CXIndex CIdx) {
54: branch 0 taken
0: branch 1 not taken
909 54: if (CIdx)
54: branch 0 taken
0: branch 1 not taken
910 54: delete static_cast<CIndexer *>(CIdx);
911 54: }
912 :
913 1: void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) {
1: branch 0 taken
0: branch 1 not taken
914 1: if (CIdx) {
915 1: CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
916 1: CXXIdx->setUseExternalASTGeneration(value);
917 : }
918 1: }
919 :
920 : CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
921 : const char *ast_filename,
922 : CXDiagnosticCallback diag_callback,
923 8: CXClientData diag_client_data) {
0: branch 0 not taken
8: branch 1 taken
924 8: if (!CIdx)
925 0: return 0;
926 :
927 8: CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
928 :
929 : // Configure the diagnostics.
930 8: DiagnosticOptions DiagOpts;
931 8: llvm::OwningPtr<Diagnostic> Diags;
932 8: Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
933 8: CIndexDiagnosticClient DiagClient(diag_callback, diag_client_data);
934 8: Diags->setClient(&DiagClient);
935 :
936 : return ASTUnit::LoadFromPCHFile(ast_filename, *Diags,
937 : CXXIdx->getOnlyLocalDecls(),
938 8: /* UseBumpAllocator = */ true);
939 : }
940 :
941 : CXTranslationUnit
942 : clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
943 : const char *source_filename,
944 : int num_command_line_args,
945 : const char **command_line_args,
946 : unsigned num_unsaved_files,
947 : struct CXUnsavedFile *unsaved_files,
948 : CXDiagnosticCallback diag_callback,
949 10: CXClientData diag_client_data) {
0: branch 0 not taken
10: branch 1 taken
950 10: if (!CIdx)
951 0: return 0;
952 :
953 10: CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
954 :
955 : // Configure the diagnostics.
956 10: DiagnosticOptions DiagOpts;
957 10: llvm::OwningPtr<Diagnostic> Diags;
958 10: Diags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
959 10: CIndexDiagnosticClient DiagClient(diag_callback, diag_client_data);
960 10: Diags->setClient(&DiagClient);
961 :
962 10: llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
4: branch 0 taken
10: branch 1 taken
963 14: for (unsigned I = 0; I != num_unsaved_files; ++I) {
964 : const llvm::MemoryBuffer *Buffer
965 : = llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
966 : unsaved_files[I].Contents + unsaved_files[I].Length,
967 4: unsaved_files[I].Filename);
968 : RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
969 4: Buffer));
970 : }
971 :
9: branch 1 taken
1: branch 2 taken
972 10: if (!CXXIdx->getUseExternalASTGeneration()) {
973 9: llvm::SmallVector<const char *, 16> Args;
974 :
975 : // The 'source_filename' argument is optional. If the caller does not
976 : // specify it then it is assumed that the source file is specified
977 : // in the actual argument list.
3: branch 0 taken
6: branch 1 taken
978 9: if (source_filename)
979 3: Args.push_back(source_filename);
980 : Args.insert(Args.end(), command_line_args,
981 9: command_line_args + num_command_line_args);
982 :
983 9: unsigned NumErrors = Diags->getNumErrors();
984 :
985 : #ifdef USE_CRASHTRACER
986 : ArgsCrashTracerInfo ACTI(Args);
987 : #endif
988 :
989 : llvm::OwningPtr<ASTUnit> Unit(
990 : ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(),
991 : *Diags,
992 : CXXIdx->getClangResourcesPath(),
993 : CXXIdx->getOnlyLocalDecls(),
994 : /* UseBumpAllocator = */ true,
995 : RemappedFiles.data(),
996 9: RemappedFiles.size()));
997 :
998 : // FIXME: Until we have broader testing, just drop the entire AST if we
999 : // encountered an error.
1: branch 2 taken
8: branch 3 taken
1000 9: if (NumErrors != Diags->getNumErrors())
1001 1: return 0;
1002 :
1003 8: return Unit.take();
1004 : }
1005 :
1006 : // Build up the arguments for invoking 'clang'.
1007 1: std::vector<const char *> argv;
1008 :
1009 : // First add the complete path to the 'clang' executable.
1010 1: llvm::sys::Path ClangPath = static_cast<CIndexer *>(CIdx)->getClangPath();
1011 1: argv.push_back(ClangPath.c_str());
1012 :
1013 : // Add the '-emit-ast' option as our execution mode for 'clang'.
1014 1: argv.push_back("-emit-ast");
1015 :
1016 : // The 'source_filename' argument is optional. If the caller does not
1017 : // specify it then it is assumed that the source file is specified
1018 : // in the actual argument list.
0: branch 0 not taken
1: branch 1 taken
1019 1: if (source_filename)
1020 0: argv.push_back(source_filename);
1021 :
1022 : // Generate a temporary name for the AST file.
1023 1: argv.push_back("-o");
1024 : char astTmpFile[L_tmpnam];
1025 1: argv.push_back(tmpnam(astTmpFile));
1026 :
1027 : // Remap any unsaved files to temporary files.
1028 1: std::vector<llvm::sys::Path> TemporaryFiles;
1029 1: std::vector<std::string> RemapArgs;
0: branch 1 not taken
1: branch 2 taken
1030 1: if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
1031 0: return 0;
1032 :
1033 : // The pointers into the elements of RemapArgs are stable because we
1034 : // won't be adding anything to RemapArgs after this point.
4: branch 1 taken
1: branch 2 taken
1035 5: for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
1036 4: argv.push_back(RemapArgs[i].c_str());
1037 :
1038 : // Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
1: branch 0 taken
1: branch 1 taken
1039 2: for (int i = 0; i < num_command_line_args; ++i)
1: branch 0 taken
0: branch 1 not taken
1040 1: if (const char *arg = command_line_args[i]) {
0: branch 1 not taken
1: branch 2 taken
1041 1: if (strcmp(arg, "-o") == 0) {
1042 0: ++i; // Also skip the matching argument.
1043 0: continue;
1044 : }
1: branch 1 taken
0: branch 2 not taken
1: branch 4 taken
0: branch 5 not taken
0: branch 7 not taken
1: branch 8 taken
1045 1: if (strcmp(arg, "-emit-ast") == 0 ||
1046 : strcmp(arg, "-c") == 0 ||
1047 : strcmp(arg, "-fsyntax-only") == 0) {
1048 0: continue;
1049 : }
1050 :
1051 : // Keep the argument.
1052 1: argv.push_back(arg);
1053 : }
1054 :
1055 : // Generate a temporary name for the diagnostics file.
1056 : char tmpFileResults[L_tmpnam];
1057 1: char *tmpResultsFileName = tmpnam(tmpFileResults);
1058 1: llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
1059 1: TemporaryFiles.push_back(DiagnosticsFile);
1060 1: argv.push_back("-fdiagnostics-binary");
1061 :
1062 : // Add the null terminator.
1063 1: argv.push_back(NULL);
1064 :
1065 : // Invoke 'clang'.
1066 1: llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
1067 : // on Unix or NUL (Windows).
1068 1: std::string ErrMsg;
1069 : const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DiagnosticsFile,
1070 1: NULL };
1071 : llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
1072 : /* redirects */ &Redirects[0],
1073 1: /* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
1074 :
0: branch 1 not taken
1: branch 2 taken
1075 1: if (!ErrMsg.empty()) {
1076 0: std::string AllArgs;
0: branch 4 not taken
0: branch 5 not taken
1077 0: for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
1078 : I != E; ++I) {
1079 0: AllArgs += ' ';
0: branch 1 not taken
0: branch 2 not taken
1080 0: if (*I)
1081 0: AllArgs += *I;
1082 : }
1083 :
1084 0: Diags->Report(diag::err_fe_clang) << AllArgs << ErrMsg;
1085 : }
1086 :
1087 : // FIXME: Parse the (redirected) standard error to emit diagnostics.
1088 :
1089 : ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, *Diags,
1090 : CXXIdx->getOnlyLocalDecls(),
1091 : /* UseBumpAllocator = */ true,
1092 : RemappedFiles.data(),
1093 1: RemappedFiles.size());
1: branch 0 taken
0: branch 1 not taken
1094 1: if (ATU)
1095 1: ATU->unlinkTemporaryFile();
1096 :
1097 : // FIXME: Currently we don't report diagnostics on invalid ASTs.
1: branch 0 taken
0: branch 1 not taken
1098 1: if (ATU)
1099 : ReportSerializedDiagnostics(DiagnosticsFile, *Diags,
1100 : num_unsaved_files, unsaved_files,
1101 1: ATU->getASTContext().getLangOptions());
1102 :
2: branch 1 taken
1: branch 2 taken
1103 3: for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
1104 2: TemporaryFiles[i].eraseFromDisk();
1105 :
1106 1: return ATU;
1107 : }
1108 :
1109 14: void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
14: branch 0 taken
0: branch 1 not taken
1110 14: if (CTUnit)
14: branch 0 taken
0: branch 1 not taken
1111 14: delete static_cast<ASTUnit *>(CTUnit);
1112 14: }
1113 :
1114 0: CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
0: branch 0 not taken
0: branch 1 not taken
1115 0: if (!CTUnit)
1116 0: return CIndexer::createCXString("");
1117 :
1118 0: ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
1119 : return CIndexer::createCXString(CXXUnit->getOriginalSourceFileName().c_str(),
1120 0: true);
1121 : }
1122 :
1123 12836: CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
1124 12836: CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
1125 : return Result;
1126 : }
1127 :
1128 : } // end: extern "C"
1129 :
1130 : //===----------------------------------------------------------------------===//
1131 : // CXSourceLocation and CXSourceRange Operations.
1132 : //===----------------------------------------------------------------------===//
1133 :
1134 : extern "C" {
1135 3: CXSourceLocation clang_getNullLocation() {
1136 3: CXSourceLocation Result = { { 0, 0 }, 0 };
1137 : return Result;
1138 : }
1139 :
1140 2: unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
1141 : return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
1142 : loc1.ptr_data[1] == loc2.ptr_data[1] &&
0: branch 0 not taken
2: branch 1 taken
2: branch 2 taken
2: branch 3 taken
2: branch 4 taken
2: branch 5 taken
1143 2: loc1.int_data == loc2.int_data);
1144 : }
1145 :
1146 : CXSourceLocation clang_getLocation(CXTranslationUnit tu,
1147 : CXFile file,
1148 : unsigned line,
1149 12827: unsigned column) {
0: branch 0 not taken
12827: branch 1 taken
1150 12827: if (!tu)
1151 0: return clang_getNullLocation();
1152 :
1153 12827: ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
1154 : SourceLocation SLoc
1155 : = CXXUnit->getSourceManager().getLocation(
1156 : static_cast<const FileEntry *>(file),
1157 12827: line, column);
1158 :
1159 12827: return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc, false);
1160 : }
1161 :
1162 1: CXSourceRange clang_getNullRange() {
1163 1: CXSourceRange Result = { { 0, 0 }, 0, 0 };
1164 : return Result;
1165 : }
1166 :
1167 1: CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
1: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
1: branch 3 taken
1168 1: if (begin.ptr_data[0] != end.ptr_data[0] ||
1169 : begin.ptr_data[1] != end.ptr_data[1])
1170 0: return clang_getNullRange();
1171 :
1172 : CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
1173 1: begin.int_data, end.int_data };
1174 1: return Result;
1175 : }
1176 :
1177 : void clang_getInstantiationLocation(CXSourceLocation location,
1178 : CXFile *file,
1179 : unsigned *line,
1180 : unsigned *column,
1181 1430: unsigned *offset) {
1182 : cxloc::CXSourceLocationPtr Ptr
1183 1430: = cxloc::CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data[0]);
1184 1430: SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
1185 :
1430: branch 1 taken
0: branch 2 not taken
96: branch 4 taken
1334: branch 5 taken
96: branch 6 taken
1334: branch 7 taken
1186 1430: if (!Ptr.getPointer() || Loc.isInvalid()) {
54: branch 0 taken
42: branch 1 taken
1187 96: if (file)
1188 54: *file = 0;
78: branch 0 taken
18: branch 1 taken
1189 96: if (line)
1190 78: *line = 0;
78: branch 0 taken
18: branch 1 taken
1191 96: if (column)
1192 78: *column = 0;
0: branch 0 not taken
96: branch 1 taken
1193 96: if (offset)
1194 0: *offset = 0;
1195 96: return;
1196 : }
1197 :
1198 : // FIXME: This is largely copy-paste from
1199 : ///TextDiagnosticPrinter::HighlightRange. When it is clear that this is
1200 : // what we want the two routines should be refactored.
1201 1334: const SourceManager &SM = *Ptr.getPointer();
1202 1334: SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
1203 :
283: branch 1 taken
1051: branch 2 taken
1204 1334: if (Ptr.getInt()) {
1205 : // We want the last character in this location, so we will adjust
1206 : // the instantiation location accordingly.
1207 :
1208 : // If the location is from a macro instantiation, get the end of
1209 : // the instantiation range.
0: branch 1 not taken
283: branch 2 taken
1210 283: if (Loc.isMacroID())
1211 0: InstLoc = SM.getInstantiationRange(Loc).second;
1212 :
1213 : // Measure the length token we're pointing at, so we can adjust
1214 : // the physical location in the file to point at the last
1215 : // character.
1216 : // FIXME: This won't cope with trigraphs or escaped newlines
1217 : // well. For that, we actually need a preprocessor, which isn't
1218 : // currently available here. Eventually, we'll switch the pointer
1219 : // data of CXSourceLocation/CXSourceRange to a translation unit
1220 : // (CXXUnit), so that the preprocessor will be available here. At
1221 : // that point, we can use Preprocessor::getLocForEndOfToken().
1222 : unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM,
1223 283: *static_cast<LangOptions *>(location.ptr_data[1]));
283: branch 0 taken
0: branch 1 not taken
1224 283: if (Length > 0)
1225 283: InstLoc = InstLoc.getFileLocWithOffset(Length - 1);
1226 : }
1227 :
742: branch 0 taken
592: branch 1 taken
1228 1334: if (file)
1229 742: *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
1115: branch 0 taken
219: branch 1 taken
1230 1334: if (line)
1231 1115: *line = SM.getInstantiationLineNumber(InstLoc);
1115: branch 0 taken
219: branch 1 taken
1232 1334: if (column)
1233 1115: *column = SM.getInstantiationColumnNumber(InstLoc);
0: branch 0 not taken
1334: branch 1 taken
1234 1334: if (offset)
1235 0: *offset = SM.getDecomposedLoc(InstLoc).second;
1236 : }
1237 :
1238 301: CXSourceLocation clang_getRangeStart(CXSourceRange range) {
1239 : CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
1240 301: range.begin_int_data };
1241 : return Result;
1242 : }
1243 :
1244 301: CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
1245 301: cxloc::CXSourceLocationPtr Ptr;
1246 301: Ptr.setPointer(static_cast<SourceManager *>(range.ptr_data[0]));
1247 301: Ptr.setInt(true);
1248 : CXSourceLocation Result = { { Ptr.getOpaqueValue(), range.ptr_data[1] },
1249 301: range.end_int_data };
1250 : return Result;
1251 : }
1252 :
1253 : } // end: extern "C"
1254 :
1255 : //===----------------------------------------------------------------------===//
1256 : // CXFile Operations.
1257 : //===----------------------------------------------------------------------===//
1258 :
1259 : extern "C" {
1260 298: const char *clang_getFileName(CXFile SFile) {
53: branch 0 taken
245: branch 1 taken
1261 298: if (!SFile)
1262 53: return 0;
1263 :
1264 245: FileEntry *FEnt = static_cast<FileEntry *>(SFile);
1265 245: return FEnt->getName();
1266 : }
1267 :
1268 0: time_t clang_getFileTime(CXFile SFile) {
0: branch 0 not taken
0: branch 1 not taken
1269 0: if (!SFile)
1270 0: return 0;
1271 :
1272 0: FileEntry *FEnt = static_cast<FileEntry *>(SFile);
1273 0: return FEnt->getModificationTime();
1274 : }
1275 :
1276 8: CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
0: branch 0 not taken
8: branch 1 taken
1277 8: if (!tu)
1278 0: return 0;
1279 :
1280 8: ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
1281 :
1282 8: FileManager &FMgr = CXXUnit->getFileManager();
1283 8: const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name));
1284 8: return const_cast<FileEntry *>(File);
1285 : }
1286 :
1287 : } // end: extern "C"
1288 :
1289 : //===----------------------------------------------------------------------===//
1290 : // CXCursor Operations.
1291 : //===----------------------------------------------------------------------===//
1292 :
1293 233: static Decl *getDeclFromExpr(Stmt *E) {
111: branch 1 taken
122: branch 2 taken
1294 233: if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
1295 111: return RefExpr->getDecl();
0: branch 1 not taken
122: branch 2 taken
1296 122: if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
1297 0: return ME->getMemberDecl();
0: branch 1 not taken
122: branch 2 taken
1298 122: if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
1299 0: return RE->getDecl();
1300 :
8: branch 1 taken
114: branch 2 taken
1301 122: if (CallExpr *CE = dyn_cast<CallExpr>(E))
1302 8: return getDeclFromExpr(CE->getCallee());
38: branch 1 taken
76: branch 2 taken
1303 114: if (CastExpr *CE = dyn_cast<CastExpr>(E))
1304 38: return getDeclFromExpr(CE->getSubExpr());
32: branch 1 taken
44: branch 2 taken
1305 76: if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
1306 32: return OME->getMethodDecl();
1307 :
1308 44: return 0;
1309 : }
1310 :
1311 129: static SourceLocation getLocationFromExpr(Expr *E) {
10: branch 1 taken
119: branch 2 taken
1312 129: if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
1313 10: return /*FIXME:*/Msg->getLeftLoc();
55: branch 1 taken
64: branch 2 taken
1314 119: if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
1315 55: return DRE->getLocation();
0: branch 1 not taken
64: branch 2 taken
1316 64: if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
1317 0: return Member->getMemberLoc();
0: branch 1 not taken
64: branch 2 taken
1318 64: if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
1319 0: return Ivar->getLocation();
1320 64: return E->getLocStart();
1321 : }
1322 :
1323 : extern "C" {
1324 :
1325 : unsigned clang_visitChildren(CXCursor parent,
1326 : CXCursorVisitor visitor,
1327 10: CXClientData client_data) {
1328 10: ASTUnit *CXXUnit = getCursorASTUnit(parent);
1329 :
1330 10: unsigned PCHLevel = Decl::MaxPCHLevel;
1331 :
1332 : // Set the PCHLevel to filter out unwanted decls if requested.
4: branch 1 taken
6: branch 2 taken
1333 10: if (CXXUnit->getOnlyLocalDecls()) {
1334 4: PCHLevel = 0;
1335 :
1336 : // If the main input was an AST, bump the level.
3: branch 1 taken
1: branch 2 taken
1337 4: if (CXXUnit->isMainFileAST())
1338 3: ++PCHLevel;
1339 : }
1340 :
1341 10: CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
1342 10: return CursorVis.VisitChildren(parent);
1343 : }
1344 :
1345 240: static CXString getDeclSpelling(Decl *D) {
1346 240: NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D);
4: branch 0 taken
236: branch 1 taken
1347 240: if (!ND)
1348 4: return CIndexer::createCXString("");
1349 :
31: branch 1 taken
205: branch 2 taken
1350 236: if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
1351 : return CIndexer::createCXString(OMD->getSelector().getAsString().c_str(),
1352 31: true);
1353 :
0: branch 1 not taken
205: branch 2 taken
1354 205: if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
1355 : // No, this isn't the same as the code below. getIdentifier() is non-virtual
1356 : // and returns different names. NamedDecl returns the class name and
1357 : // ObjCCategoryImplDecl returns the category name.
1358 0: return CIndexer::createCXString(CIMP->getIdentifier()->getNameStart());
1359 :
200: branch 1 taken
5: branch 2 taken
1360 205: if (ND->getIdentifier())
1361 200: return CIndexer::createCXString(ND->getIdentifier()->getNameStart());
1362 :
1363 5: return CIndexer::createCXString("");
1364 : }
1365 :
1366 359: CXString clang_getCursorSpelling(CXCursor C) {
0: branch 1 not taken
359: branch 2 taken
1367 359: if (clang_isTranslationUnit(C.kind))
1368 0: return clang_getTranslationUnitSpelling(C.data[2]);
1369 :
55: branch 1 taken
304: branch 2 taken
1370 359: if (clang_isReference(C.kind)) {
4: branch 0 taken
12: branch 1 taken
8: branch 2 taken
31: branch 3 taken
0: branch 4 not taken
1371 55: switch (C.kind) {
1372 : case CXCursor_ObjCSuperClassRef: {
1373 4: ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
1374 4: return CIndexer::createCXString(Super->getIdentifier()->getNameStart());
1375 : }
1376 : case CXCursor_ObjCClassRef: {
1377 12: ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
1378 12: return CIndexer::createCXString(Class->getIdentifier()->getNameStart());
1379 : }
1380 : case CXCursor_ObjCProtocolRef: {
1381 8: ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
0: branch 0 not taken
8: branch 1 taken
1382 8: assert(OID && "getCursorSpelling(): Missing protocol decl");
1383 8: return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
1384 : }
1385 : case CXCursor_TypeRef: {
1386 31: TypeDecl *Type = getCursorTypeRef(C).first;
0: branch 0 not taken
31: branch 1 taken
1387 31: assert(Type && "Missing type decl");
1388 :
1389 : return CIndexer::createCXString(
1390 : getCursorContext(C).getTypeDeclType(Type).getAsString().c_str(),
1391 31: true);
1392 : }
1393 :
1394 : default:
1395 0: return CIndexer::createCXString("<not implemented>");
1396 : }
1397 : }
1398 :
92: branch 1 taken
212: branch 2 taken
1399 304: if (clang_isExpression(C.kind)) {
1400 92: Decl *D = getDeclFromExpr(getCursorExpr(C));
70: branch 0 taken
22: branch 1 taken
1401 92: if (D)
1402 70: return getDeclSpelling(D);
1403 22: return CIndexer::createCXString("");
1404 : }
1405 :
170: branch 1 taken
42: branch 2 taken
1406 212: if (clang_isDeclaration(C.kind))
1407 170: return getDeclSpelling(getCursorDecl(C));
1408 :
1409 42: return CIndexer::createCXString("");
1410 : }
1411 :
1412 2106: const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) {
31: branch 0 taken
43: branch 1 taken
3: branch 2 taken
3: branch 3 taken
9: branch 4 taken
0: branch 5 not taken
0: branch 6 not taken
21: branch 7 taken
26: branch 8 taken
25: branch 9 taken
43: branch 10 taken
18: branch 11 taken
12: branch 12 taken
13: branch 13 taken
7: branch 14 taken
50: branch 15 taken
9: branch 16 taken
0: branch 17 not taken
0: branch 18 not taken
4: branch 19 taken
4: branch 20 taken
8: branch 21 taken
12: branch 22 taken
31: branch 23 taken
33: branch 24 taken
40: branch 25 taken
0: branch 26 not taken
4: branch 27 taken
15: branch 28 taken
42: branch 29 taken
0: branch 30 not taken
16: branch 31 taken
1584: branch 32 taken
0: branch 33 not taken
0: branch 34 not taken
1413 2106: switch (Kind) {
1414 31: case CXCursor_FunctionDecl: return "FunctionDecl";
1415 43: case CXCursor_TypedefDecl: return "TypedefDecl";
1416 3: case CXCursor_EnumDecl: return "EnumDecl";
1417 3: case CXCursor_EnumConstantDecl: return "EnumConstantDecl";
1418 9: case CXCursor_StructDecl: return "StructDecl";
1419 0: case CXCursor_UnionDecl: return "UnionDecl";
1420 0: case CXCursor_ClassDecl: return "ClassDecl";
1421 21: case CXCursor_FieldDecl: return "FieldDecl";
1422 26: case CXCursor_VarDecl: return "VarDecl";
1423 25: case CXCursor_ParmDecl: return "ParmDecl";
1424 43: case CXCursor_ObjCInterfaceDecl: return "ObjCInterfaceDecl";
1425 18: case CXCursor_ObjCCategoryDecl: return "ObjCCategoryDecl";
1426 12: case CXCursor_ObjCProtocolDecl: return "ObjCProtocolDecl";
1427 13: case CXCursor_ObjCPropertyDecl: return "ObjCPropertyDecl";
1428 7: case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
1429 50: case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
1430 9: case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
1431 0: case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl";
1432 0: case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl";
1433 4: case CXCursor_UnexposedDecl: return "UnexposedDecl";
1434 4: case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
1435 8: case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
1436 12: case CXCursor_ObjCClassRef: return "ObjCClassRef";
1437 31: case CXCursor_TypeRef: return "TypeRef";
1438 33: case CXCursor_UnexposedExpr: return "UnexposedExpr";
1439 40: case CXCursor_DeclRefExpr: return "DeclRefExpr";
1440 0: case CXCursor_MemberRefExpr: return "MemberRefExpr";
1441 4: case CXCursor_CallExpr: return "CallExpr";
1442 15: case CXCursor_ObjCMessageExpr: return "ObjCMessageExpr";
1443 42: case CXCursor_UnexposedStmt: return "UnexposedStmt";
1444 0: case CXCursor_InvalidFile: return "InvalidFile";
1445 16: case CXCursor_NoDeclFound: return "NoDeclFound";
1446 1584: case CXCursor_NotImplemented: return "NotImplemented";
1447 0: case CXCursor_TranslationUnit: return "TranslationUnit";
1448 : }
1449 :
1450 0: llvm_unreachable("Unhandled CXCursorKind");
1451 : return NULL;
1452 : }
1453 :
1454 : enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
1455 : CXCursor parent,
1456 1460: CXClientData client_data) {
1457 1460: CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
1458 1460: *BestCursor = cursor;
1459 1460: return CXChildVisit_Recurse;
1460 : }
1461 :
1462 12825: CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
0: branch 0 not taken
12825: branch 1 taken
1463 12825: if (!TU)
1464 0: return clang_getNullCursor();
1465 :
1466 12825: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
1467 :
1468 12825: SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
1469 12825: CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
12825: branch 1 taken
0: branch 2 not taken
1470 12825: if (SLoc.isValid()) {
1471 : SourceRange RegionOfInterest(SLoc,
1472 12825: CXXUnit->getPreprocessor().getLocForEndOfToken(SLoc, 1));
1473 :
1474 : // FIXME: Would be great to have a "hint" cursor, then walk from that
1475 : // hint cursor upward until we find a cursor whose source range encloses
1476 : // the region of interest, rather than starting from the translation unit.
1477 12825: CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
1478 : CursorVisitor CursorVis(CXXUnit, GetCursorVisitor, &Result,
1479 12825: Decl::MaxPCHLevel, RegionOfInterest);
1480 12825: CursorVis.VisitChildren(Parent);
1481 : }
1482 12825: return Result;
1483 : }
1484 :
1485 524: CXCursor clang_getNullCursor(void) {
1486 524: return MakeCXCursorInvalid(CXCursor_InvalidFile);
1487 : }
1488 :
1489 13180: unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
1490 13180: return X == Y;
1491 : }
1492 :
1493 5204: unsigned clang_isInvalid(enum CXCursorKind K) {
2514: branch 0 taken
2690: branch 1 taken
55: branch 2 taken
2459: branch 3 taken
1494 5204: return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
1495 : }
1496 :
1497 48808: unsigned clang_isDeclaration(enum CXCursorKind K) {
48808: branch 0 taken
0: branch 1 not taken
4829: branch 2 taken
43979: branch 3 taken
1498 48808: return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
1499 : }
1500 :
1501 19426: unsigned clang_isReference(enum CXCursorKind K) {
16771: branch 0 taken
2655: branch 1 taken
767: branch 2 taken
16004: branch 3 taken
1502 19426: return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
1503 : }
1504 :
1505 17442: unsigned clang_isExpression(enum CXCursorKind K) {
15769: branch 0 taken
1673: branch 1 taken
1722: branch 2 taken
14047: branch 3 taken
1506 17442: return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
1507 : }
1508 :
1509 15261: unsigned clang_isStatement(enum CXCursorKind K) {
14234: branch 0 taken
1027: branch 1 taken
1398: branch 2 taken
12836: branch 3 taken
1510 15261: return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
1511 : }
1512 :
1513 13195: unsigned clang_isTranslationUnit(enum CXCursorKind K) {
1514 13195: return K == CXCursor_TranslationUnit;
1515 : }
1516 :
1517 31: CXCursorKind clang_getCursorKind(CXCursor C) {
1518 31: return C.kind;
1519 : }
1520 :
1521 782: CXSourceLocation clang_getCursorLocation(CXCursor C) {
75: branch 1 taken
707: branch 2 taken
1522 782: if (clang_isReference(C.kind)) {
4: branch 0 taken
8: branch 1 taken
12: branch 2 taken
51: branch 3 taken
0: branch 4 not taken
1523 75: switch (C.kind) {
1524 : case CXCursor_ObjCSuperClassRef: {
1525 : std::pair<ObjCInterfaceDecl *, SourceLocation> P
1526 4: = getCursorObjCSuperClassRef(C);
1527 4: return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
1528 : }
1529 :
1530 : case CXCursor_ObjCProtocolRef: {
1531 : std::pair<ObjCProtocolDecl *, SourceLocation> P
1532 8: = getCursorObjCProtocolRef(C);
1533 8: return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
1534 : }
1535 :
1536 : case CXCursor_ObjCClassRef: {
1537 : std::pair<ObjCInterfaceDecl *, SourceLocation> P
1538 12: = getCursorObjCClassRef(C);
1539 12: return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
1540 : }
1541 :
1542 : case CXCursor_TypeRef: {
1543 51: std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
1544 51: return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
1545 : }
1546 :
1547 : default:
1548 : // FIXME: Need a way to enumerate all non-reference cases.
1549 0: llvm_unreachable("Missed a reference kind");
1550 : }
1551 : }
1552 :
129: branch 1 taken
578: branch 2 taken
1553 707: if (clang_isExpression(C.kind))
1554 : return cxloc::translateSourceLocation(getCursorContext(C),
1555 129: getLocationFromExpr(getCursorExpr(C)));
1556 :
0: branch 1 not taken
578: branch 2 taken
1557 578: if (!getCursorDecl(C))
1558 0: return clang_getNullLocation();
1559 :
1560 578: Decl *D = getCursorDecl(C);
1561 578: SourceLocation Loc = D->getLocation();
39: branch 1 taken
539: branch 2 taken
1562 578: if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
1563 39: Loc = Class->getClassLoc();
1564 578: return cxloc::translateSourceLocation(D->getASTContext(), Loc);
1565 : }
1566 :
1567 3428: CXSourceRange clang_getCursorExtent(CXCursor C) {
489: branch 1 taken
2939: branch 2 taken
1568 3428: if (clang_isReference(C.kind)) {
109: branch 0 taken
155: branch 1 taken
145: branch 2 taken
80: branch 3 taken
0: branch 4 not taken
1569 489: switch (C.kind) {
1570 : case CXCursor_ObjCSuperClassRef: {
1571 : std::pair<ObjCInterfaceDecl *, SourceLocation> P
1572 109: = getCursorObjCSuperClassRef(C);
1573 109: return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
1574 : }
1575 :
1576 : case CXCursor_ObjCProtocolRef: {
1577 : std::pair<ObjCProtocolDecl *, SourceLocation> P
1578 155: = getCursorObjCProtocolRef(C);
1579 155: return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
1580 : }
1581 :
1582 : case CXCursor_ObjCClassRef: {
1583 : std::pair<ObjCInterfaceDecl *, SourceLocation> P
1584 145: = getCursorObjCClassRef(C);
1585 :
1586 145: return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
1587 : }
1588 :
1589 : case CXCursor_TypeRef: {
1590 80: std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
1591 80: return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
1592 : }
1593 :
1594 : default:
1595 : // FIXME: Need a way to enumerate all non-reference cases.
1596 0: llvm_unreachable("Missed a reference kind");
1597 : }
1598 : }
1599 :
1117: branch 1 taken
1822: branch 2 taken
1600 2939: if (clang_isExpression(C.kind))
1601 : return cxloc::translateSourceRange(getCursorContext(C),
1602 1117: getCursorExpr(C)->getSourceRange());
1603 :
1068: branch 1 taken
754: branch 2 taken
1604 1822: if (clang_isStatement(C.kind))
1605 : return cxloc::translateSourceRange(getCursorContext(C),
1606 1068: getCursorStmt(C)->getSourceRange());
1607 :
0: branch 1 not taken
754: branch 2 taken
1608 754: if (!getCursorDecl(C))
1609 0: return clang_getNullRange();
1610 :
1611 754: Decl *D = getCursorDecl(C);
1612 754: return cxloc::translateSourceRange(D->getASTContext(), D->getSourceRange());
1613 : }
1614 :
1615 362: CXCursor clang_getCursorReferenced(CXCursor C) {
0: branch 1 not taken
362: branch 2 taken
1616 362: if (clang_isInvalid(C.kind))
1617 0: return clang_getNullCursor();
1618 :
1619 362: ASTUnit *CXXUnit = getCursorASTUnit(C);
170: branch 1 taken
192: branch 2 taken
1620 362: if (clang_isDeclaration(C.kind))
1621 170: return C;
1622 :
95: branch 1 taken
97: branch 2 taken
1623 192: if (clang_isExpression(C.kind)) {
1624 95: Decl *D = getDeclFromExpr(getCursorExpr(C));
73: branch 0 taken
22: branch 1 taken
1625 95: if (D)
1626 73: return MakeCXCursor(D, CXXUnit);
1627 22: return clang_getNullCursor();
1628 : }
1629 :
42: branch 1 taken
55: branch 2 taken
1630 97: if (!clang_isReference(C.kind))
1631 42: return clang_getNullCursor();
1632 :
4: branch 0 taken
8: branch 1 taken
12: branch 2 taken
31: branch 3 taken
0: branch 4 not taken
1633 55: switch (C.kind) {
1634 : case CXCursor_ObjCSuperClassRef:
1635 4: return MakeCXCursor(getCursorObjCSuperClassRef(C).first, CXXUnit);
1636 :
1637 : case CXCursor_ObjCProtocolRef: {
1638 8: return MakeCXCursor(getCursorObjCProtocolRef(C).first, CXXUnit);
1639 :
1640 : case CXCursor_ObjCClassRef:
1641 12: return MakeCXCursor(getCursorObjCClassRef(C).first, CXXUnit);
1642 :
1643 : case CXCursor_TypeRef:
1644 31: return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
1645 :
1646 : default:
1647 : // We would prefer to enumerate all non-reference cursor kinds here.
1648 0: llvm_unreachable("Unhandled reference cursor kind");
1649 : break;
1650 : }
1651 : }
1652 :
1653 : return clang_getNullCursor();
1654 : }
1655 :
1656 170: CXCursor clang_getCursorDefinition(CXCursor C) {
0: branch 1 not taken
170: branch 2 taken
1657 170: if (clang_isInvalid(C.kind))
1658 0: return clang_getNullCursor();
1659 :
1660 170: ASTUnit *CXXUnit = getCursorASTUnit(C);
1661 :
1662 170: bool WasReference = false;
170: branch 1 taken
0: branch 2 not taken
0: branch 4 not taken
170: branch 5 taken
0: branch 6 not taken
170: branch 7 taken
1663 170: if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
1664 0: C = clang_getCursorReferenced(C);
1665 0: WasReference = true;
1666 : }
1667 :
0: branch 1 not taken
170: branch 2 taken
1668 170: if (!clang_isDeclaration(C.kind))
1669 0: return clang_getNullCursor();
1670 :
1671 170: Decl *D = getCursorDecl(C);
0: branch 0 not taken
170: branch 1 taken
1672 170: if (!D)
1673 0: return clang_getNullCursor();
1674 :
72: branch 1 taken
0: branch 2 not taken
0: branch 3 not taken
0: branch 4 not taken
0: branch 5 not taken
9: branch 6 taken
19: branch 7 taken
24: branch 8 taken
0: branch 9 not taken
0: branch 10 not taken
0: branch 11 not taken
0: branch 12 not taken
15: branch 13 taken
5: branch 14 taken
7: branch 15 taken
15: branch 16 taken
0: branch 17 not taken
0: branch 18 not taken
0: branch 19 not taken
4: branch 20 taken
0: branch 21 not taken
0: branch 22 not taken
0: branch 23 not taken
1675 170: switch (D->getKind()) {
1676 : // Declaration kinds that don't really separate the notions of
1677 : // declaration and definition.
1678 : case Decl::Namespace:
1679 : case Decl::Typedef:
1680 : case Decl::TemplateTypeParm:
1681 : case Decl::EnumConstant:
1682 : case Decl::Field:
1683 : case Decl::ObjCIvar:
1684 : case Decl::ObjCAtDefsField:
1685 : case Decl::ImplicitParam:
1686 : case Decl::ParmVar:
1687 : case Decl::NonTypeTemplateParm:
1688 : case Decl::TemplateTemplateParm:
1689 : case Decl::ObjCCategoryImpl:
1690 : case Decl::ObjCImplementation:
1691 : case Decl::LinkageSpec:
1692 : case Decl::ObjCPropertyImpl:
1693 : case Decl::FileScopeAsm:
1694 : case Decl::StaticAssert:
1695 : case Decl::Block:
1696 72: return C;
1697 :
1698 : // Declaration kinds that don't make any sense here, but are
1699 : // nonetheless harmless.
1700 : case Decl::TranslationUnit:
1701 : case Decl::Template:
1702 : case Decl::ObjCContainer:
1703 0: break;
1704 :
1705 : // Declaration kinds for which the definition is not resolvable.
1706 : case Decl::UnresolvedUsingTypename:
1707 : case Decl::UnresolvedUsingValue:
1708 0: break;
1709 :
1710 : case Decl::UsingDirective:
1711 : return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
1712 0: CXXUnit);
1713 :
1714 : case Decl::NamespaceAlias:
1715 0: return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), CXXUnit);
1716 :
1717 : case Decl::Enum:
1718 : case Decl::Record:
1719 : case Decl::CXXRecord:
1720 : case Decl::ClassTemplateSpecialization:
1721 : case Decl::ClassTemplatePartialSpecialization:
9: branch 3 taken
0: branch 4 not taken
1722 9: if (TagDecl *Def = cast<TagDecl>(D)->getDefinition(D->getASTContext()))
1723 9: return MakeCXCursor(Def, CXXUnit);
1724 0: return clang_getNullCursor();
1725 :
1726 : case Decl::Function:
1727 : case Decl::CXXMethod:
1728 : case Decl::CXXConstructor:
1729 : case Decl::CXXDestructor:
1730 : case Decl::CXXConversion: {
1731 19: const FunctionDecl *Def = 0;
14: branch 2 taken
5: branch 3 taken
1732 19: if (cast<FunctionDecl>(D)->getBody(Def))
1733 14: return MakeCXCursor(const_cast<FunctionDecl *>(Def), CXXUnit);
1734 5: return clang_getNullCursor();
1735 : }
1736 :
1737 : case Decl::Var: {
1738 : // Ask the variable if it has a definition.
22: branch 2 taken
2: branch 3 taken
1739 24: if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
1740 22: return MakeCXCursor(Def, CXXUnit);
1741 2: return clang_getNullCursor();
1742 : }
1743 :
1744 : case Decl::FunctionTemplate: {
1745 0: const FunctionDecl *Def = 0;
0: branch 3 not taken
0: branch 4 not taken
1746 0: if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
1747 0: return MakeCXCursor(Def->getDescribedFunctionTemplate(), CXXUnit);
1748 0: return clang_getNullCursor();
1749 : }
1750 :
1751 : case Decl::ClassTemplate: {
0: branch 0 not taken
0: branch 1 not taken
1752 0: if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
1753 0: ->getDefinition(D->getASTContext()))
1754 : return MakeCXCursor(
1755 : cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
1756 0: CXXUnit);
1757 0: return clang_getNullCursor();
1758 : }
1759 :
1760 : case Decl::Using: {
1761 0: UsingDecl *Using = cast<UsingDecl>(D);
1762 0: CXCursor Def = clang_getNullCursor();
0: branch 3 not taken
0: branch 4 not taken
1763 0: for (UsingDecl::shadow_iterator S = Using->shadow_begin(),
1764 0: SEnd = Using->shadow_end();
1765 : S != SEnd; ++S) {
0: branch 2 not taken
0: branch 3 not taken
1766 0: if (Def != clang_getNullCursor()) {
1767 : // FIXME: We have no way to return multiple results.
1768 0: return clang_getNullCursor();
1769 : }
1770 :
1771 : Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl(),
1772 0: CXXUnit));
1773 : }
1774 :
1775 0: return Def;
1776 : }
1777 :
1778 : case Decl::UsingShadow:
1779 : return clang_getCursorDefinition(
1780 : MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
1781 0: CXXUnit));
1782 :
1783 : case Decl::ObjCMethod: {
1784 15: ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
0: branch 1 not taken
15: branch 2 taken
1785 15: if (Method->isThisDeclarationADefinition())
1786 0: return C;
1787 :
1788 : // Dig out the method definition in the associated
1789 : // @implementation, if we have it.
1790 : // FIXME: The ASTs should make finding the definition easier.
6: branch 0 taken
9: branch 1 taken
1791 15: if (ObjCInterfaceDecl *Class
1792 15: = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
0: branch 1 not taken
6: branch 2 taken
1793 6: if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
0: branch 0 not taken
0: branch 1 not taken
1794 0: if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
1795 0: Method->isInstanceMethod()))
0: branch 1 not taken
0: branch 2 not taken
1796 0: if (Def->isThisDeclarationADefinition())
1797 0: return MakeCXCursor(Def, CXXUnit);
1798 :
1799 15: return clang_getNullCursor();
1800 : }
1801 :
1802 : case Decl::ObjCCategory:
0: branch 0 not taken
5: branch 1 taken
1803 5: if (ObjCCategoryImplDecl *Impl
1804 5: = cast<ObjCCategoryDecl>(D)->getImplementation())
1805 0: return MakeCXCursor(Impl, CXXUnit);
1806 5: return clang_getNullCursor();
1807 :
1808 : case Decl::ObjCProtocol:
7: branch 2 taken
0: branch 3 not taken
1809 7: if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
1810 7: return C;
1811 0: return clang_getNullCursor();
1812 :
1813 : case Decl::ObjCInterface:
1814 : // There are two notions of a "definition" for an Objective-C
1815 : // class: the interface and its implementation. When we resolved a
1816 : // reference to an Objective-C class, produce the @interface as
1817 : // the definition; when we were provided with the interface,
1818 : // produce the @implementation as the definition.
0: branch 0 not taken
15: branch 1 taken
1819 15: if (WasReference) {
0: branch 2 not taken
0: branch 3 not taken
1820 0: if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
1821 0: return C;
0: branch 0 not taken
15: branch 1 taken
1822 15: } else if (ObjCImplementationDecl *Impl
1823 15: = cast<ObjCInterfaceDecl>(D)->getImplementation())
1824 0: return MakeCXCursor(Impl, CXXUnit);
1825 15: return clang_getNullCursor();
1826 :
1827 : case Decl::ObjCProperty:
1828 : // FIXME: We don't really know where to find the
1829 : // ObjCPropertyImplDecls that implement this property.
1830 0: return clang_getNullCursor();
1831 :
1832 : case Decl::ObjCCompatibleAlias:
0: branch 0 not taken
0: branch 1 not taken
1833 0: if (ObjCInterfaceDecl *Class
1834 0: = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
0: branch 1 not taken
0: branch 2 not taken
1835 0: if (!Class->isForwardDecl())
1836 0: return MakeCXCursor(Class, CXXUnit);
1837 :
1838 0: return clang_getNullCursor();
1839 :
1840 : case Decl::ObjCForwardProtocol: {
1841 0: ObjCForwardProtocolDecl *Forward = cast<ObjCForwardProtocolDecl>(D);
0: branch 1 not taken
0: branch 2 not taken
1842 0: if (Forward->protocol_size() == 1)
1843 : return clang_getCursorDefinition(
1844 : MakeCXCursor(*Forward->protocol_begin(),
1845 0: CXXUnit));
1846 :
1847 : // FIXME: Cannot return multiple definitions.
1848 0: return clang_getNullCursor();
1849 : }
1850 :
1851 : case Decl::ObjCClass: {
1852 4: ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
4: branch 1 taken
0: branch 2 not taken
1853 4: if (Class->size() == 1) {
1854 4: ObjCInterfaceDecl *IFace = Class->begin()->getInterface();
2: branch 1 taken
2: branch 2 taken
1855 4: if (!IFace->isForwardDecl())
1856 2: return MakeCXCursor(IFace, CXXUnit);
1857 2: return clang_getNullCursor();
1858 : }
1859 :
1860 : // FIXME: Cannot return multiple definitions.
1861 0: return clang_getNullCursor();
1862 : }
1863 :
1864 : case Decl::Friend:
0: branch 2 not taken
0: branch 3 not taken
1865 0: if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
1866 0: return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
1867 0: return clang_getNullCursor();
1868 :
1869 : case Decl::FriendTemplate:
0: branch 2 not taken
0: branch 3 not taken
1870 0: if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
1871 0: return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
1872 0: return clang_getNullCursor();
1873 : }
1874 :
1875 0: return clang_getNullCursor();
1876 : }
1877 :
1878 359: unsigned clang_isCursorDefinition(CXCursor C) {
189: branch 1 taken
170: branch 2 taken
1879 359: if (!clang_isDeclaration(C.kind))
1880 189: return 0;
1881 :
1882 170: return clang_getCursorDefinition(C) == C;
1883 : }
1884 :
1885 : void clang_getDefinitionSpellingAndExtent(CXCursor C,
1886 : const char **startBuf,
1887 : const char **endBuf,
1888 : unsigned *startLine,
1889 : unsigned *startColumn,
1890 : unsigned *endLine,
1891 0: unsigned *endColumn) {
0: branch 1 not taken
0: branch 2 not taken
1892 0: assert(getCursorDecl(C) && "CXCursor has null decl");
1893 0: NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
1894 0: FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
1895 0: CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
1896 :
1897 0: SourceManager &SM = FD->getASTContext().getSourceManager();
1898 0: *startBuf = SM.getCharacterData(Body->getLBracLoc());
1899 0: *endBuf = SM.getCharacterData(Body->getRBracLoc());
1900 0: *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
1901 0: *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
1902 0: *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
1903 0: *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
1904 0: }
1905 :
1906 : } // end: extern "C"
1907 :
1908 : //===----------------------------------------------------------------------===//
1909 : // Token-based Operations.
1910 : //===----------------------------------------------------------------------===//
1911 :
1912 : /* CXToken layout:
1913 : * int_data[0]: a CXTokenKind
1914 : * int_data[1]: starting token location
1915 : * int_data[2]: token length
1916 : * int_data[3]: reserved
1917 : * ptr_data: for identifiers and keywords, an IdentifierInfo*.
1918 : * otherwise unused.
1919 : */
1920 : extern "C" {
1921 :
1922 102: CXTokenKind clang_getTokenKind(CXToken CXTok) {
1923 102: return static_cast<CXTokenKind>(CXTok.int_data[0]);
1924 : }
1925 :
1926 51: CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
19: branch 1 taken
3: branch 2 taken
29: branch 3 taken
1927 51: switch (clang_getTokenKind(CXTok)) {
1928 : case CXToken_Identifier:
1929 : case CXToken_Keyword:
1930 : // We know we have an IdentifierInfo*, so use that.
1931 : return CIndexer::createCXString(
1932 19: static_cast<IdentifierInfo *>(CXTok.ptr_data)->getNameStart());
1933 :
1934 : case CXToken_Literal: {
1935 : // We have stashed the starting pointer in the ptr_data field. Use it.
1936 3: const char *Text = static_cast<const char *>(CXTok.ptr_data);
1937 : return CIndexer::createCXString(llvm::StringRef(Text, CXTok.int_data[2]),
1938 3: true);
1939 : }
1940 :
1941 : case CXToken_Punctuation:
1942 : case CXToken_Comment:
1943 : break;
1944 : }
1945 :
1946 : // We have to find the starting buffer pointer the hard way, by
1947 : // deconstructing the source location.
1948 29: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
0: branch 0 not taken
29: branch 1 taken
1949 29: if (!CXXUnit)
1950 0: return CIndexer::createCXString("");
1951 :
1952 29: SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
1953 : std::pair<FileID, unsigned> LocInfo
1954 29: = CXXUnit->getSourceManager().getDecomposedLoc(Loc);
1955 : std::pair<const char *,const char *> Buffer
1956 29: = CXXUnit->getSourceManager().getBufferData(LocInfo.first);
1957 :
1958 : return CIndexer::createCXString(llvm::StringRef(Buffer.first+LocInfo.second,
1959 : CXTok.int_data[2]),
1960 29: true);
1961 : }
1962 :
1963 2: CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
1964 2: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
0: branch 0 not taken
2: branch 1 taken
1965 2: if (!CXXUnit)
1966 0: return clang_getNullLocation();
1967 :
1968 : return cxloc::translateSourceLocation(CXXUnit->getASTContext(),
1969 2: SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
1970 : }
1971 :
1972 51: CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
1973 51: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
0: branch 0 not taken
51: branch 1 taken
1974 51: if (!CXXUnit)
1975 0: return clang_getNullRange();
1976 :
1977 : return cxloc::translateSourceRange(CXXUnit->getASTContext(),
1978 51: SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
1979 : }
1980 :
1981 : void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
1982 1: CXToken **Tokens, unsigned *NumTokens) {
1: branch 0 taken
0: branch 1 not taken
1983 1: if (Tokens)
1984 1: *Tokens = 0;
1: branch 0 taken
0: branch 1 not taken
1985 1: if (NumTokens)
1986 1: *NumTokens = 0;
1987 :
1988 1: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
1: branch 0 taken
0: branch 1 not taken
1: branch 2 taken
0: branch 3 not taken
0: branch 4 not taken
1: branch 5 taken
1989 1: if (!CXXUnit || !Tokens || !NumTokens)
1990 0: return;
1991 :
1992 1: SourceRange R = cxloc::translateSourceRange(Range);
0: branch 1 not taken
1: branch 2 taken
1993 1: if (R.isInvalid())
1994 0: return;
1995 :
1996 1: SourceManager &SourceMgr = CXXUnit->getSourceManager();
1997 : std::pair<FileID, unsigned> BeginLocInfo
1998 1: = SourceMgr.getDecomposedLoc(R.getBegin());
1999 : std::pair<FileID, unsigned> EndLocInfo
2000 1: = SourceMgr.getDecomposedLoc(R.getEnd());
2001 :
2002 : // Cannot tokenize across files.
0: branch 1 not taken
1: branch 2 taken
2003 1: if (BeginLocInfo.first != EndLocInfo.first)
2004 0: return;
2005 :
2006 : // Create a lexer
2007 : std::pair<const char *,const char *> Buffer
2008 1: = SourceMgr.getBufferData(BeginLocInfo.first);
2009 : Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
2010 : CXXUnit->getASTContext().getLangOptions(),
2011 1: Buffer.first, Buffer.first + BeginLocInfo.second, Buffer.second);
2012 1: Lex.SetCommentRetentionState(true);
2013 :
2014 : // Lex tokens until we hit the end of the range.
2015 1: const char *EffectiveBufferEnd = Buffer.first + EndLocInfo.second;
2016 1: llvm::SmallVector<CXToken, 32> CXTokens;
2017 1: Token Tok;
50: branch 1 taken
1: branch 2 taken
2018 51: do {
2019 : // Lex the next token
2020 51: Lex.LexFromRawLexer(Tok);
0: branch 1 not taken
51: branch 2 taken
2021 51: if (Tok.is(tok::eof))
2022 0: break;
2023 :
2024 : // Initialize the CXToken.
2025 : CXToken CXTok;
2026 :
2027 : // - Common fields
2028 51: CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
2029 51: CXTok.int_data[2] = Tok.getLength();
2030 51: CXTok.int_data[3] = 0;
2031 :
2032 : // - Kind-specific fields
3: branch 1 taken
48: branch 2 taken
2033 51: if (Tok.isLiteral()) {
2034 3: CXTok.int_data[0] = CXToken_Literal;
2035 3: CXTok.ptr_data = (void *)Tok.getLiteralData();
19: branch 1 taken
29: branch 2 taken
2036 48: } else if (Tok.is(tok::identifier)) {
2037 : // Lookup the identifier to determine whether we have a
2038 : std::pair<FileID, unsigned> LocInfo
2039 19: = SourceMgr.getDecomposedLoc(Tok.getLocation());
2040 : const char *StartPos
2041 : = CXXUnit->getSourceManager().getBufferData(LocInfo.first).first +
2042 19: LocInfo.second;
2043 : IdentifierInfo *II
2044 19: = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok, StartPos);
2045 : CXTok.int_data[0] = II->getTokenID() == tok::identifier?
2046 : CXToken_Identifier
12: branch 1 taken
7: branch 2 taken
2047 19: : CXToken_Keyword;
2048 19: CXTok.ptr_data = II;
1: branch 1 taken
28: branch 2 taken
2049 29: } else if (Tok.is(tok::comment)) {
2050 1: CXTok.int_data[0] = CXToken_Comment;
2051 1: CXTok.ptr_data = 0;
2052 : } else {
2053 28: CXTok.int_data[0] = CXToken_Punctuation;
2054 28: CXTok.ptr_data = 0;
2055 : }
2056 51: CXTokens.push_back(CXTok);
2057 : } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
2058 :
0: branch 1 not taken
1: branch 2 taken
2059 1: if (CXTokens.empty())
2060 0: return;
2061 :
2062 1: *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
2063 1: memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
1: branch 2 taken
0: branch 3 not taken
1: branch 5 taken
0: branch 6 not taken
2064 1: *NumTokens = CXTokens.size();
2065 : }
2066 :
2067 : typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;
2068 :
2069 : enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
2070 : CXCursor parent,
2071 31: CXClientData client_data) {
2072 31: AnnotateTokensData *Data = static_cast<AnnotateTokensData *>(client_data);
2073 :
2074 : // We only annotate the locations of declarations, simple
2075 : // references, and expressions which directly reference something.
2076 31: CXCursorKind Kind = clang_getCursorKind(cursor);
26: branch 1 taken
5: branch 2 taken
5: branch 4 taken
21: branch 5 taken
21: branch 6 taken
10: branch 7 taken
2077 31: if (clang_isDeclaration(Kind) || clang_isReference(Kind)) {
2078 : // Okay: We can annotate the location of this declaration with the
2079 : // declaration or reference
16: branch 1 taken
5: branch 2 taken
2080 21: } else if (clang_isExpression(cursor.kind)) {
13: branch 0 taken
3: branch 1 taken
13: branch 2 taken
0: branch 3 not taken
13: branch 4 taken
0: branch 5 not taken
2081 16: if (Kind != CXCursor_DeclRefExpr &&
2082 : Kind != CXCursor_MemberRefExpr &&
2083 : Kind != CXCursor_ObjCMessageExpr)
2084 13: return CXChildVisit_Recurse;
2085 :
2086 3: CXCursor Referenced = clang_getCursorReferenced(cursor);
3: branch 1 taken
0: branch 2 not taken
0: branch 5 not taken
3: branch 6 taken
0: branch 7 not taken
3: branch 8 taken
2087 3: if (Referenced == cursor || Referenced == clang_getNullCursor())
2088 0: return CXChildVisit_Recurse;
2089 :
2090 : // Okay: we can annotate the location of this expression
2091 : } else {
2092 : // Nothing to annotate
2093 5: return CXChildVisit_Recurse;
2094 : }
2095 :
2096 13: CXSourceLocation Loc = clang_getCursorLocation(cursor);
2097 13: (*Data)[Loc.int_data] = cursor;
2098 13: return CXChildVisit_Recurse;
2099 : }
2100 :
2101 : void clang_annotateTokens(CXTranslationUnit TU,
2102 : CXToken *Tokens, unsigned NumTokens,
2103 1: CXCursor *Cursors) {
0: branch 0 not taken
1: branch 1 taken
2104 1: if (NumTokens == 0)
2105 0: return;
2106 :
2107 : // Any token we don't specifically annotate will have a NULL cursor.
51: branch 0 taken
1: branch 1 taken
2108 52: for (unsigned I = 0; I != NumTokens; ++I)
2109 51: Cursors[I] = clang_getNullCursor();
2110 :
2111 1: ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
1: branch 0 taken
0: branch 1 not taken
0: branch 2 not taken
1: branch 3 taken
2112 1: if (!CXXUnit || !Tokens)
2113 0: return;
2114 :
2115 : // Annotate all of the source locations in the region of interest that map
2116 1: SourceRange RegionOfInterest;
2117 : RegionOfInterest.setBegin(
2118 1: cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
2119 : SourceLocation End
2120 : = cxloc::translateSourceLocation(clang_getTokenLocation(TU,
2121 1: Tokens[NumTokens - 1]));
2122 : RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End,
2123 1: 1));
2124 : // FIXME: Would be great to have a "hint" cursor, then walk from that
2125 : // hint cursor upward until we find a cursor whose source range encloses
2126 : // the region of interest, rather than starting from the translation unit.
2127 1: AnnotateTokensData Annotated;
2128 1: CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
2129 : CursorVisitor AnnotateVis(CXXUnit, AnnotateTokensVisitor, &Annotated,
2130 1: Decl::MaxPCHLevel, RegionOfInterest);
2131 1: AnnotateVis.VisitChildren(Parent);
2132 :
51: branch 0 taken
1: branch 1 taken
2133 52: for (unsigned I = 0; I != NumTokens; ++I) {
2134 : // Determine whether we saw a cursor at this token's location.
2135 51: AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
39: branch 3 taken
12: branch 4 taken
2136 51: if (Pos == Annotated.end())
2137 39: continue;
2138 :
2139 12: Cursors[I] = Pos->second;
2140 1: }
2141 : }
2142 :
2143 : void clang_disposeTokens(CXTranslationUnit TU,
2144 0: CXToken *Tokens, unsigned NumTokens) {
2145 0: free(Tokens);
2146 0: }
2147 :
2148 : } // end: extern "C"
2149 :
2150 : //===----------------------------------------------------------------------===//
2151 : // CXString Operations.
2152 : //===----------------------------------------------------------------------===//
2153 :
2154 : extern "C" {
2155 522: const char *clang_getCString(CXString string) {
2156 522: return string.Spelling;
2157 : }
2158 :
2159 416: void clang_disposeString(CXString string) {
117: branch 0 taken
299: branch 1 taken
117: branch 2 taken
0: branch 3 not taken
2160 416: if (string.MustFreeString && string.Spelling)
2161 117: free((void*)string.Spelling);
2162 416: }
2163 :
2164 : } // end: extern "C"
2165 :
2166 : //===----------------------------------------------------------------------===//
2167 : // Misc. utility functions.
2168 : //===----------------------------------------------------------------------===//
2169 :
2170 : extern "C" {
2171 :
2172 0: const char *clang_getClangVersion() {
2173 0: return getClangFullVersion();
2174 : }
2175 :
2176 : } // end: extern "C"
2177 :
Generated: 2010-02-10 01:31 by zcov