blob: b94d48e33d6f263601529de3d83d121fbcfcd6c6 [file] [log] [blame]
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +00001//===--- 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
Argyrios Kyrtzidis818e15b2009-07-06 21:35:02 +000011// source location into a ASTLocation.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000012//
13//===----------------------------------------------------------------------===//
14
Argyrios Kyrtzidis818e15b2009-07-06 21:35:02 +000015#include "clang/Index/Utils.h"
Argyrios Kyrtzidisccbcb702009-07-06 21:34:47 +000016#include "clang/Index/ASTLocation.h"
Argyrios Kyrtzidis0c411802009-09-29 21:27:32 +000017#include "clang/AST/TypeLocVisitor.h"
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000018#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/StmtVisitor.h"
20#include "clang/Lex/Lexer.h"
21#include "clang/Basic/SourceManager.h"
22#include "llvm/Support/Compiler.h"
23using namespace clang;
Argyrios Kyrtzidisccbcb702009-07-06 21:34:47 +000024using namespace idx;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000025
26namespace {
27
28/// \brief Base for the LocResolver classes. Mostly does source range checking.
29class VISIBILITY_HIDDEN LocResolverBase {
30protected:
31 ASTContext &Ctx;
32 SourceLocation Loc;
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000033
34 ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, DeclaratorInfo *DInfo);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000035
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000036 enum RangePos {
37 BeforeLoc,
38 ContainsLoc,
39 AfterLoc
40 };
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000041
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000042 RangePos CheckRange(SourceRange Range);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000043 RangePos CheckRange(DeclaratorInfo *DInfo);
44 RangePos CheckRange(Decl *D) {
45 if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
46 if (ContainsLocation(DD->getDeclaratorInfo()))
47 return ContainsLoc;
48
49 return CheckRange(D->getSourceRange());
50 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000051 RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000052 RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000053
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000054 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000055 bool isBeforeLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000056 return CheckRange(Node) == BeforeLoc;
57 }
58
59 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000060 bool ContainsLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000061 return CheckRange(Node) == ContainsLoc;
62 }
63
64 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000065 bool isAfterLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000066 return CheckRange(Node) == AfterLoc;
67 }
68
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000069public:
70 LocResolverBase(ASTContext &ctx, SourceLocation loc)
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000071 : Ctx(ctx), Loc(loc) {}
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000072
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000073#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000074 /// \brief Debugging output.
75 void print(Decl *D);
76 /// \brief Debugging output.
77 void print(Stmt *Node);
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000078#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000079};
80
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000081/// \brief Searches a statement for the ASTLocation that corresponds to a source
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000082/// location.
83class VISIBILITY_HIDDEN StmtLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000084 public StmtVisitor<StmtLocResolver,
85 ASTLocation > {
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +000086 Decl * const Parent;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000087
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000088public:
89 StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
90 : LocResolverBase(ctx, loc), Parent(parent) {}
91
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +000092 ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000093 ASTLocation VisitDeclStmt(DeclStmt *Node);
94 ASTLocation VisitStmt(Stmt *Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000095};
96
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000097/// \brief Searches a declaration for the ASTLocation that corresponds to a
98/// source location.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000099class VISIBILITY_HIDDEN DeclLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000100 public DeclVisitor<DeclLocResolver,
101 ASTLocation > {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000102public:
103 DeclLocResolver(ASTContext &ctx, SourceLocation loc)
104 : LocResolverBase(ctx, loc) {}
105
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000106 ASTLocation VisitDeclContext(DeclContext *DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000107 ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000108 ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000109 ASTLocation VisitVarDecl(VarDecl *D);
110 ASTLocation VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000111 ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000112 ASTLocation VisitDecl(Decl *D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000113};
114
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000115class TypeLocResolver : public LocResolverBase,
116 public TypeLocVisitor<TypeLocResolver, ASTLocation> {
117 Decl * const ParentDecl;
118
119public:
120 TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
121 : LocResolverBase(ctx, loc), ParentDecl(pd) { }
122
John McCall51bd8032009-10-18 01:05:36 +0000123 ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
124 ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
125 ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
126 ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
127 ASTLocation VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000128 ASTLocation VisitTypeLoc(TypeLoc TL);
129};
130
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000131} // anonymous namespace
132
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000133ASTLocation
134StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
135 assert(ContainsLocation(Node) &&
136 "Should visit only after verifying that loc is in range");
137
138 if (Node->getNumArgs() == 1)
139 // Unary operator. Let normal child traversal handle it.
140 return VisitCallExpr(Node);
141
142 assert(Node->getNumArgs() == 2 &&
143 "Wrong args for the C++ operator call expr ?");
144
145 llvm::SmallVector<Expr *, 3> Nodes;
146 // Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
147 Nodes.push_back(Node->getArg(0));
148 Nodes.push_back(Node->getCallee());
149 Nodes.push_back(Node->getArg(1));
Mike Stump1eb44332009-09-09 15:08:12 +0000150
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000151 for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
152 RangePos RP = CheckRange(Nodes[i]);
153 if (RP == AfterLoc)
154 break;
155 if (RP == ContainsLoc)
156 return Visit(Nodes[i]);
157 }
158
159 return ASTLocation(Parent, Node);
160}
161
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000162ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000163 assert(ContainsLocation(Node) &&
164 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000165
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000166 // Search all declarations of this DeclStmt.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000167 for (DeclStmt::decl_iterator
168 I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000169 RangePos RP = CheckRange(*I);
170 if (RP == AfterLoc)
171 break;
172 if (RP == ContainsLoc)
173 return DeclLocResolver(Ctx, Loc).Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000174 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000175
176 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000177}
178
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000179ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000180 assert(ContainsLocation(Node) &&
181 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000182
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000183 // Search the child statements.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000184 for (Stmt::child_iterator
185 I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000186 if (*I == NULL)
187 continue;
188
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000189 RangePos RP = CheckRange(*I);
190 if (RP == AfterLoc)
191 break;
192 if (RP == ContainsLoc)
193 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000194 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000195
196 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000197}
198
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000199ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000200 for (DeclContext::decl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +0000201 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000202 RangePos RP = CheckRange(*I);
203 if (RP == AfterLoc)
204 break;
205 if (RP == ContainsLoc)
206 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000207 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000208
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000209 return ASTLocation(cast<Decl>(DC));
210}
211
212ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
213 ASTLocation ASTLoc = VisitDeclContext(TU);
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000214 if (ASTLoc.getParentDecl() == TU)
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000215 return ASTLocation();
216 return ASTLoc;
217}
218
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000219ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000220 assert(ContainsLocation(D) &&
221 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000222
Argyrios Kyrtzidis5a70ea62009-09-29 19:58:16 +0000223 if (ContainsLocation(D->getDeclaratorInfo()))
224 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
225
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000226 // First, search through the parameters of the function.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000227 for (FunctionDecl::param_iterator
228 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000229 RangePos RP = CheckRange(*I);
230 if (RP == AfterLoc)
231 return ASTLocation(D);
232 if (RP == ContainsLoc)
233 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000234 }
Mike Stump1eb44332009-09-09 15:08:12 +0000235
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000236 // We didn't find the location in the parameters and we didn't get passed it.
Mike Stump1eb44332009-09-09 15:08:12 +0000237
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000238 if (!D->isThisDeclarationADefinition())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000239 return ASTLocation(D);
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000240
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000241 // Second, search through the declarations that are part of the function.
242 // If we find he location there, we won't have to search through its body.
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000243
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000244 for (DeclContext::decl_iterator
245 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
246 if (isa<ParmVarDecl>(*I))
247 continue; // We already searched through the parameters.
Mike Stump1eb44332009-09-09 15:08:12 +0000248
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000249 RangePos RP = CheckRange(*I);
250 if (RP == AfterLoc)
251 break;
252 if (RP == ContainsLoc)
253 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000254 }
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000255
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000256 // We didn't find a declaration that corresponds to the source location.
Mike Stump1eb44332009-09-09 15:08:12 +0000257
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000258 // Finally, search through the body of the function.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000259 Stmt *Body = D->getBody();
260 assert(Body && "Expected definition");
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000261 assert(!isBeforeLocation(Body) &&
262 "This function is supposed to contain the loc");
263 if (isAfterLocation(Body))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000264 return ASTLocation(D);
265
266 // The body contains the location.
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000267 assert(ContainsLocation(Body));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000268 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000269}
270
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000271ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
272 assert(ContainsLocation(D) &&
273 "Should visit only after verifying that loc is in range");
274 if (ContainsLocation(D->getDeclaratorInfo()))
275 return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
276
277 return ASTLocation(D);
278}
279
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000280ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000281 assert(ContainsLocation(D) &&
282 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000283
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000284 // Check whether the location points to the init expression.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000285 Expr *Init = D->getInit();
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000286 if (Init && ContainsLocation(Init))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000287 return StmtLocResolver(Ctx, Loc, D).Visit(Init);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000288
289 if (ContainsLocation(D->getDeclaratorInfo()))
290 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000291
292 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000293}
294
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000295ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
296 assert(ContainsLocation(D) &&
297 "Should visit only after verifying that loc is in range");
298
299 // First, search through the parameters of the method.
300 for (ObjCMethodDecl::param_iterator
301 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
302 RangePos RP = CheckRange(*I);
303 if (RP == AfterLoc)
304 return ASTLocation(D);
305 if (RP == ContainsLoc)
306 return Visit(*I);
307 }
308
309 // We didn't find the location in the parameters and we didn't get passed it.
310
311 if (!D->getBody())
312 return ASTLocation(D);
313
314 // Second, search through the declarations that are part of the method.
315 // If we find he location there, we won't have to search through its body.
316
317 for (DeclContext::decl_iterator
318 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
319 if (isa<ParmVarDecl>(*I))
320 continue; // We already searched through the parameters.
321
322 RangePos RP = CheckRange(*I);
323 if (RP == AfterLoc)
324 break;
325 if (RP == ContainsLoc)
326 return Visit(*I);
327 }
328
329 // We didn't find a declaration that corresponds to the source location.
330
331 // Finally, search through the body of the method.
332 Stmt *Body = D->getBody();
333 assert(Body && "Expected definition");
334 assert(!isBeforeLocation(Body) &&
335 "This method is supposed to contain the loc");
336 if (isAfterLocation(Body))
337 return ASTLocation(D);
338
339 // The body contains the location.
340 assert(ContainsLocation(Body));
341 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
342}
343
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000344ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000345 assert(ContainsLocation(D) &&
346 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis7e4fe3b2009-07-18 00:33:40 +0000347 if (DeclContext *DC = dyn_cast<DeclContext>(D))
348 return VisitDeclContext(DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000349 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000350}
351
John McCall51bd8032009-10-18 01:05:36 +0000352ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000353 assert(ContainsLocation(TL) &&
354 "Should visit only after verifying that loc is in range");
355 if (ContainsLocation(TL.getNameLoc()))
356 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
357 return ASTLocation(ParentDecl, TL);
358}
359
John McCall51bd8032009-10-18 01:05:36 +0000360ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000361 assert(ContainsLocation(TL) &&
362 "Should visit only after verifying that loc is in range");
363
364 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
365 ParmVarDecl *Parm = TL.getArg(i);
366 RangePos RP = CheckRange(Parm);
367 if (RP == AfterLoc)
368 break;
369 if (RP == ContainsLoc)
370 return DeclLocResolver(Ctx, Loc).Visit(Parm);
371 }
372
373 return ASTLocation(ParentDecl, TL);
374}
375
John McCall51bd8032009-10-18 01:05:36 +0000376ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000377 assert(ContainsLocation(TL) &&
378 "Should visit only after verifying that loc is in range");
379
380 Expr *E = TL.getSizeExpr();
381 if (E && ContainsLocation(E))
382 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
383
384 return ASTLocation(ParentDecl, TL);
385}
386
John McCall51bd8032009-10-18 01:05:36 +0000387ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000388 assert(ContainsLocation(TL) &&
389 "Should visit only after verifying that loc is in range");
390 if (ContainsLocation(TL.getNameLoc()))
391 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
392 return ASTLocation(ParentDecl, TL);
393}
394
John McCall51bd8032009-10-18 01:05:36 +0000395ASTLocation TypeLocResolver::VisitObjCProtocolListTypeLoc(ObjCProtocolListTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000396 assert(ContainsLocation(TL) &&
397 "Should visit only after verifying that loc is in range");
398
399 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
400 SourceLocation L = TL.getProtocolLoc(i);
401 RangePos RP = CheckRange(L);
402 if (RP == AfterLoc)
403 break;
404 if (RP == ContainsLoc)
405 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
406 }
407
408 return ASTLocation(ParentDecl, TL);
409}
410
411ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
412 assert(ContainsLocation(TL) &&
413 "Should visit only after verifying that loc is in range");
414 return ASTLocation(ParentDecl, TL);
415}
416
417ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
418 DeclaratorInfo *DInfo) {
419 assert(ContainsLocation(DInfo) &&
420 "Should visit only after verifying that loc is in range");
421
422 TypeLocResolver(Ctx, Loc, D);
423 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
424 if (ContainsLocation(TL))
425 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
426
427 assert(0 && "Should have found the loc in a typeloc");
428 return ASTLocation(D, Stm);
429}
430
431LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
432 if (!DInfo)
433 return BeforeLoc; // Keep looking.
434
435 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
436 if (ContainsLocation(TL))
437 return ContainsLoc;
438
439 return BeforeLoc; // Keep looking.
440}
441
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000442LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000443 if (!Range.isValid())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000444 return BeforeLoc; // Keep looking.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000445
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000446 // Update the end source range to cover the full length of the token
447 // positioned at the end of the source range.
448 //
449 // e.g.,
450 // int foo
451 // ^ ^
452 //
453 // will be updated to
454 // int foo
455 // ^ ^
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000456 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
457 Ctx.getSourceManager(),
458 Ctx.getLangOptions());
459 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000460
Mike Stump1eb44332009-09-09 15:08:12 +0000461 SourceManager &SourceMgr = Ctx.getSourceManager();
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000462 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
463 return BeforeLoc;
Mike Stump1eb44332009-09-09 15:08:12 +0000464
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000465 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
466 return AfterLoc;
467
468 return ContainsLoc;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000469}
470
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000471#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000472void LocResolverBase::print(Decl *D) {
473 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000474 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
Argyrios Kyrtzidisf1d60ea2009-06-30 02:35:04 +0000475 D->print(OS);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000476 OS << " <";
477 D->getLocStart().print(OS, Ctx.getSourceManager());
478 OS << " > - <";
479 D->getLocEnd().print(OS, Ctx.getSourceManager());
480 OS << ">\n\n";
481 OS.flush();
482}
483
484void LocResolverBase::print(Stmt *Node) {
485 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000486 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
Chris Lattnere4f21422009-06-30 01:26:17 +0000487 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000488 OS << " <";
489 Node->getLocStart().print(OS, Ctx.getSourceManager());
490 OS << " > - <";
491 Node->getLocEnd().print(OS, Ctx.getSourceManager());
492 OS << ">\n\n";
493 OS.flush();
494}
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000495#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000496
497
498/// \brief Returns the AST node that a source location points to.
499///
Argyrios Kyrtzidis818e15b2009-07-06 21:35:02 +0000500ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000501 if (Loc.isInvalid())
Argyrios Kyrtzidis874012b2009-07-06 21:34:20 +0000502 return ASTLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000503
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000504 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000505}