blob: 4bb15943bb4d1de1b58c953b6f6f6013291a9797 [file] [log] [blame]
Shih-wei Liaof8fd82b2010-02-10 11:10:31 -08001//===--- ResolveLocation.cpp - Source location resolver ---------*- C++ -*-===//
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 defines the ResolveLocationInAST function, which resolves a
11// source location into a ASTLocation.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/Index/Utils.h"
16#include "clang/Index/ASTLocation.h"
17#include "clang/AST/TypeLocVisitor.h"
18#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/StmtVisitor.h"
20#include "clang/Lex/Lexer.h"
21#include "clang/Basic/SourceManager.h"
22using namespace clang;
23using namespace idx;
24
25namespace {
26
27/// \brief Base for the LocResolver classes. Mostly does source range checking.
28class LocResolverBase {
29protected:
30 ASTContext &Ctx;
31 SourceLocation Loc;
32
33 ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, TypeSourceInfo *TInfo);
34
35 enum RangePos {
36 BeforeLoc,
37 ContainsLoc,
38 AfterLoc
39 };
40
41 RangePos CheckRange(SourceRange Range);
42 RangePos CheckRange(TypeSourceInfo *TInfo);
43 RangePos CheckRange(Decl *D) {
44 if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
45 if (ContainsLocation(DD->getTypeSourceInfo()))
46 return ContainsLoc;
47 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
48 if (ContainsLocation(TD->getTypeSourceInfo()))
49 return ContainsLoc;
50
51 return CheckRange(D->getSourceRange());
52 }
53 RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
54 RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
55
56 template <typename T>
57 bool isBeforeLocation(T Node) {
58 return CheckRange(Node) == BeforeLoc;
59 }
60
61 template <typename T>
62 bool isAfterLocation(T Node) {
63 return CheckRange(Node) == AfterLoc;
64 }
65
66public:
67 LocResolverBase(ASTContext &ctx, SourceLocation loc)
68 : Ctx(ctx), Loc(loc) {}
69
70 template <typename T>
71 bool ContainsLocation(T Node) {
72 return CheckRange(Node) == ContainsLoc;
73 }
74
75#ifndef NDEBUG
76 /// \brief Debugging output.
77 void print(Decl *D);
78 /// \brief Debugging output.
79 void print(Stmt *Node);
80#endif
81};
82
83/// \brief Searches a statement for the ASTLocation that corresponds to a source
84/// location.
85class StmtLocResolver : public LocResolverBase,
86 public StmtVisitor<StmtLocResolver,
87 ASTLocation > {
88 Decl * const Parent;
89
90public:
91 StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
92 : LocResolverBase(ctx, loc), Parent(parent) {}
93
94 ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
95 ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
96 ASTLocation VisitDeclStmt(DeclStmt *Node);
97 ASTLocation VisitStmt(Stmt *Node);
98};
99
100/// \brief Searches a declaration for the ASTLocation that corresponds to a
101/// source location.
102class DeclLocResolver : public LocResolverBase,
103 public DeclVisitor<DeclLocResolver,
104 ASTLocation > {
105public:
106 DeclLocResolver(ASTContext &ctx, SourceLocation loc)
107 : LocResolverBase(ctx, loc) {}
108
109 ASTLocation VisitDeclContext(DeclContext *DC);
110 ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
111 ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
112 ASTLocation VisitVarDecl(VarDecl *D);
113 ASTLocation VisitFunctionDecl(FunctionDecl *D);
114 ASTLocation VisitObjCClassDecl(ObjCClassDecl *D);
115 ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
116 ASTLocation VisitTypedefDecl(TypedefDecl *D);
117 ASTLocation VisitDecl(Decl *D);
118};
119
120class TypeLocResolver : public LocResolverBase,
121 public TypeLocVisitor<TypeLocResolver, ASTLocation> {
122 Decl * const ParentDecl;
123
124public:
125 TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
126 : LocResolverBase(ctx, loc), ParentDecl(pd) { }
127
128 ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
129 ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
130 ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
131 ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
132 ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
133 ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
134 ASTLocation VisitTypeLoc(TypeLoc TL);
135};
136
137} // anonymous namespace
138
139ASTLocation
140StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
141 assert(ContainsLocation(Node) &&
142 "Should visit only after verifying that loc is in range");
143
144 if (Node->isArgumentType()) {
145 TypeSourceInfo *TInfo = Node->getArgumentTypeInfo();
146 if (ContainsLocation(TInfo))
147 return ResolveInDeclarator(Parent, Node, TInfo);
148 } else {
149 Expr *SubNode = Node->getArgumentExpr();
150 if (ContainsLocation(SubNode))
151 return Visit(SubNode);
152 }
153
154 return ASTLocation(Parent, Node);
155}
156
157
158ASTLocation
159StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
160 assert(ContainsLocation(Node) &&
161 "Should visit only after verifying that loc is in range");
162
163 if (Node->getNumArgs() == 1)
164 // Unary operator. Let normal child traversal handle it.
165 return VisitCallExpr(Node);
166
167 assert(Node->getNumArgs() == 2 &&
168 "Wrong args for the C++ operator call expr ?");
169
170 llvm::SmallVector<Expr *, 3> Nodes;
171 // Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
172 Nodes.push_back(Node->getArg(0));
173 Nodes.push_back(Node->getCallee());
174 Nodes.push_back(Node->getArg(1));
175
176 for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
177 RangePos RP = CheckRange(Nodes[i]);
178 if (RP == AfterLoc)
179 break;
180 if (RP == ContainsLoc)
181 return Visit(Nodes[i]);
182 }
183
184 return ASTLocation(Parent, Node);
185}
186
187ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
188 assert(ContainsLocation(Node) &&
189 "Should visit only after verifying that loc is in range");
190
191 // Search all declarations of this DeclStmt.
192 for (DeclStmt::decl_iterator
193 I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
194 RangePos RP = CheckRange(*I);
195 if (RP == AfterLoc)
196 break;
197 if (RP == ContainsLoc)
198 return DeclLocResolver(Ctx, Loc).Visit(*I);
199 }
200
201 return ASTLocation(Parent, Node);
202}
203
204ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
205 assert(ContainsLocation(Node) &&
206 "Should visit only after verifying that loc is in range");
207
208 // Search the child statements.
209 for (Stmt::child_iterator
210 I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
211 if (*I == NULL)
212 continue;
213
214 RangePos RP = CheckRange(*I);
215 if (RP == AfterLoc)
216 break;
217 if (RP == ContainsLoc)
218 return Visit(*I);
219 }
220
221 return ASTLocation(Parent, Node);
222}
223
224ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
225 for (DeclContext::decl_iterator
226 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
227 RangePos RP = CheckRange(*I);
228 if (RP == AfterLoc)
229 break;
230 if (RP == ContainsLoc)
231 return Visit(*I);
232 }
233
234 return ASTLocation(cast<Decl>(DC));
235}
236
237ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
238 ASTLocation ASTLoc = VisitDeclContext(TU);
239 if (ASTLoc.getParentDecl() == TU)
240 return ASTLocation();
241 return ASTLoc;
242}
243
244ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
245 assert(ContainsLocation(D) &&
246 "Should visit only after verifying that loc is in range");
247
248 if (ContainsLocation(D->getTypeSourceInfo()))
249 return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
250
251 // First, search through the parameters of the function.
252 for (FunctionDecl::param_iterator
253 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
254 RangePos RP = CheckRange(*I);
255 if (RP == AfterLoc)
256 return ASTLocation(D);
257 if (RP == ContainsLoc)
258 return Visit(*I);
259 }
260
261 // We didn't find the location in the parameters and we didn't get passed it.
262
263 if (!D->isThisDeclarationADefinition())
264 return ASTLocation(D);
265
266 // Second, search through the declarations that are part of the function.
267 // If we find the location there, we won't have to search through its body.
268
269 for (DeclContext::decl_iterator
270 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
271 if (isa<ParmVarDecl>(*I))
272 continue; // We already searched through the parameters.
273
274 RangePos RP = CheckRange(*I);
275 if (RP == AfterLoc)
276 break;
277 if (RP == ContainsLoc)
278 return Visit(*I);
279 }
280
281 // We didn't find a declaration that corresponds to the source location.
282
283 // Finally, search through the body of the function.
284 Stmt *Body = D->getBody();
285 assert(Body && "Expected definition");
286 assert(!isBeforeLocation(Body) &&
287 "This function is supposed to contain the loc");
288 if (isAfterLocation(Body))
289 return ASTLocation(D);
290
291 // The body contains the location.
292 assert(ContainsLocation(Body));
293 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
294}
295
296ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
297 assert(ContainsLocation(D) &&
298 "Should visit only after verifying that loc is in range");
299 if (ContainsLocation(D->getTypeSourceInfo()))
300 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
301
302 return ASTLocation(D);
303}
304
305ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
306 assert(ContainsLocation(D) &&
307 "Should visit only after verifying that loc is in range");
308
309 if (ContainsLocation(D->getTypeSourceInfo()))
310 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
311
312 return ASTLocation(D);
313}
314
315ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
316 assert(ContainsLocation(D) &&
317 "Should visit only after verifying that loc is in range");
318
319 // Check whether the location points to the init expression.
320 Expr *Init = D->getInit();
321 if (Init && ContainsLocation(Init))
322 return StmtLocResolver(Ctx, Loc, D).Visit(Init);
323
324 if (ContainsLocation(D->getTypeSourceInfo()))
325 return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
326
327 return ASTLocation(D);
328}
329
330ASTLocation DeclLocResolver::VisitObjCClassDecl(ObjCClassDecl *D) {
331 assert(ContainsLocation(D) &&
332 "Should visit only after verifying that loc is in range");
333
334 for (ObjCClassDecl::iterator I = D->begin(), E = D->end() ; I != E; ++I) {
335 if (CheckRange(I->getLocation()) == ContainsLoc)
336 return ASTLocation(D, I->getInterface(), I->getLocation());
337 }
338 return ASTLocation(D);
339}
340
341ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
342 assert(ContainsLocation(D) &&
343 "Should visit only after verifying that loc is in range");
344
345 // First, search through the parameters of the method.
346 for (ObjCMethodDecl::param_iterator
347 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
348 RangePos RP = CheckRange(*I);
349 if (RP == AfterLoc)
350 return ASTLocation(D);
351 if (RP == ContainsLoc)
352 return Visit(*I);
353 }
354
355 // We didn't find the location in the parameters and we didn't get passed it.
356
357 if (!D->getBody())
358 return ASTLocation(D);
359
360 // Second, search through the declarations that are part of the method.
361 // If we find he location there, we won't have to search through its body.
362
363 for (DeclContext::decl_iterator
364 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
365 if (isa<ParmVarDecl>(*I))
366 continue; // We already searched through the parameters.
367
368 RangePos RP = CheckRange(*I);
369 if (RP == AfterLoc)
370 break;
371 if (RP == ContainsLoc)
372 return Visit(*I);
373 }
374
375 // We didn't find a declaration that corresponds to the source location.
376
377 // Finally, search through the body of the method.
378 Stmt *Body = D->getBody();
379 assert(Body && "Expected definition");
380 assert(!isBeforeLocation(Body) &&
381 "This method is supposed to contain the loc");
382 if (isAfterLocation(Body))
383 return ASTLocation(D);
384
385 // The body contains the location.
386 assert(ContainsLocation(Body));
387 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
388}
389
390ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
391 assert(ContainsLocation(D) &&
392 "Should visit only after verifying that loc is in range");
393 if (DeclContext *DC = dyn_cast<DeclContext>(D))
394 return VisitDeclContext(DC);
395 return ASTLocation(D);
396}
397
398ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
399 // Continue the 'id' magic by making the builtin type (which cannot
400 // actually be spelled) map to the typedef.
401 BuiltinType *T = TL.getTypePtr();
402 if (T->getKind() == BuiltinType::ObjCId) {
403 TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
404 return ASTLocation(ParentDecl, D, TL.getNameLoc());
405 }
406
407 // Same thing with 'Class'.
408 if (T->getKind() == BuiltinType::ObjCClass) {
409 TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
410 return ASTLocation(ParentDecl, D, TL.getNameLoc());
411 }
412
413 return ASTLocation(ParentDecl, TL);
414}
415
416ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
417 assert(ContainsLocation(TL) &&
418 "Should visit only after verifying that loc is in range");
419 if (ContainsLocation(TL.getNameLoc()))
420 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
421 return ASTLocation(ParentDecl, TL);
422}
423
424ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
425 assert(ContainsLocation(TL) &&
426 "Should visit only after verifying that loc is in range");
427
428 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
429 ParmVarDecl *Parm = TL.getArg(i);
430 RangePos RP = CheckRange(Parm);
431 if (RP == AfterLoc)
432 break;
433 if (RP == ContainsLoc)
434 return DeclLocResolver(Ctx, Loc).Visit(Parm);
435 }
436
437 return ASTLocation(ParentDecl, TL);
438}
439
440ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
441 assert(ContainsLocation(TL) &&
442 "Should visit only after verifying that loc is in range");
443
444 Expr *E = TL.getSizeExpr();
445 if (E && ContainsLocation(E))
446 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
447
448 return ASTLocation(ParentDecl, TL);
449}
450
451ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
452 assert(ContainsLocation(TL) &&
453 "Should visit only after verifying that loc is in range");
454 if (ContainsLocation(TL.getNameLoc()))
455 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
456
457 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
458 SourceLocation L = TL.getProtocolLoc(i);
459 RangePos RP = CheckRange(L);
460 if (RP == AfterLoc)
461 break;
462 if (RP == ContainsLoc)
463 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
464 }
465
466 return ASTLocation(ParentDecl, TL);
467}
468
469ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
470 assert(ContainsLocation(TL) &&
471 "Should visit only after verifying that loc is in range");
472
473 if (TL.hasProtocolsAsWritten()) {
474 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
475 SourceLocation L = TL.getProtocolLoc(i);
476 RangePos RP = CheckRange(L);
477 if (RP == AfterLoc)
478 break;
479 if (RP == ContainsLoc)
480 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
481 }
482 }
483
484 return ASTLocation(ParentDecl, TL);
485}
486
487ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
488 assert(ContainsLocation(TL) &&
489 "Should visit only after verifying that loc is in range");
490 return ASTLocation(ParentDecl, TL);
491}
492
493ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
494 TypeSourceInfo *TInfo) {
495 assert(ContainsLocation(TInfo) &&
496 "Should visit only after verifying that loc is in range");
497
498 (void)TypeLocResolver(Ctx, Loc, D);
499 for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
500 if (ContainsLocation(TL))
501 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
502
503 assert(0 && "Should have found the loc in a typeloc");
504 return ASTLocation(D, Stm);
505}
506
507LocResolverBase::RangePos LocResolverBase::CheckRange(TypeSourceInfo *TInfo) {
508 if (!TInfo)
509 return BeforeLoc; // Keep looking.
510
511 for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
512 if (ContainsLocation(TL))
513 return ContainsLoc;
514
515 return BeforeLoc; // Keep looking.
516}
517
518LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
519 if (!Range.isValid())
520 return BeforeLoc; // Keep looking.
521
522 // Update the end source range to cover the full length of the token
523 // positioned at the end of the source range.
524 //
525 // e.g.,
526 // int foo
527 // ^ ^
528 //
529 // will be updated to
530 // int foo
531 // ^ ^
532 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
533 Ctx.getSourceManager(),
534 Ctx.getLangOptions());
535 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
536
537 SourceManager &SourceMgr = Ctx.getSourceManager();
538 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
539 return BeforeLoc;
540
541 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
542 return AfterLoc;
543
544 return ContainsLoc;
545}
546
547#ifndef NDEBUG
548void LocResolverBase::print(Decl *D) {
549 llvm::raw_ostream &OS = llvm::outs();
550 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
551 D->print(OS);
552 OS << " <";
553 D->getLocStart().print(OS, Ctx.getSourceManager());
554 OS << " > - <";
555 D->getLocEnd().print(OS, Ctx.getSourceManager());
556 OS << ">\n\n";
557 OS.flush();
558}
559
560void LocResolverBase::print(Stmt *Node) {
561 llvm::raw_ostream &OS = llvm::outs();
562 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
563 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
564 OS << " <";
565 Node->getLocStart().print(OS, Ctx.getSourceManager());
566 OS << " > - <";
567 Node->getLocEnd().print(OS, Ctx.getSourceManager());
568 OS << ">\n\n";
569 OS.flush();
570}
571#endif
572
573
574/// \brief Returns the AST node that a source location points to.
575///
576ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
577 ASTLocation *LastLoc) {
578 if (Loc.isInvalid())
579 return ASTLocation();
580
581 if (LastLoc && LastLoc->isValid()) {
582 DeclContext *DC = 0;
583
584 if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
585 DC = Dcl->getDeclContext();
586 } else if (LastLoc->isStmt()) {
587 Decl *Parent = LastLoc->getParentDecl();
588 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
589 DC = FD;
590 else {
591 // This is needed to handle statements within an initializer.
592 // Example:
593 // void func() { long double fabsf = __builtin_fabsl(__x); }
594 // In this case, the 'parent' of __builtin_fabsl is fabsf.
595 DC = Parent->getDeclContext();
596 }
597 } else { // We have 'N_NamedRef' or 'N_Type'
598 DC = LastLoc->getParentDecl()->getDeclContext();
599 }
600 assert(DC && "Missing DeclContext");
601
602 FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
603 DeclLocResolver DLocResolver(Ctx, Loc);
604
605 if (FD && FD->isThisDeclarationADefinition() &&
606 DLocResolver.ContainsLocation(FD)) {
607 return DLocResolver.VisitFunctionDecl(FD);
608 }
609 // Fall through and try the slow path...
610 // FIXME: Optimize more cases.
611 }
612 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
613}