blob: ec8c1dcb3813484175eae80322f24d9d8ee014e2 [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;
John McCallba6a9bd2009-10-24 08:00:42 +000048 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
49 if (ContainsLocation(TD->getTypeDeclaratorInfo()))
50 return ContainsLoc;
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000051
52 return CheckRange(D->getSourceRange());
53 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000054 RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000055 RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000056
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000057 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000058 bool isBeforeLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000059 return CheckRange(Node) == BeforeLoc;
60 }
61
62 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000063 bool isAfterLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000064 return CheckRange(Node) == AfterLoc;
65 }
66
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000067public:
68 LocResolverBase(ASTContext &ctx, SourceLocation loc)
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000069 : Ctx(ctx), Loc(loc) {}
Steve Narofff96b5242009-10-28 20:44:47 +000070
71 template <typename T>
72 bool ContainsLocation(T Node) {
73 return CheckRange(Node) == ContainsLoc;
74 }
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000075
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000076#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000077 /// \brief Debugging output.
78 void print(Decl *D);
79 /// \brief Debugging output.
80 void print(Stmt *Node);
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000081#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000082};
83
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000084/// \brief Searches a statement for the ASTLocation that corresponds to a source
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000085/// location.
86class VISIBILITY_HIDDEN StmtLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000087 public StmtVisitor<StmtLocResolver,
88 ASTLocation > {
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +000089 Decl * const Parent;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000090
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000091public:
92 StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
93 : LocResolverBase(ctx, loc), Parent(parent) {}
94
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +000095 ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000096 ASTLocation VisitDeclStmt(DeclStmt *Node);
97 ASTLocation VisitStmt(Stmt *Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000098};
99
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000100/// \brief Searches a declaration for the ASTLocation that corresponds to a
101/// source location.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000102class VISIBILITY_HIDDEN DeclLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000103 public DeclVisitor<DeclLocResolver,
104 ASTLocation > {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000105public:
106 DeclLocResolver(ASTContext &ctx, SourceLocation loc)
107 : LocResolverBase(ctx, loc) {}
108
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000109 ASTLocation VisitDeclContext(DeclContext *DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000110 ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000111 ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000112 ASTLocation VisitVarDecl(VarDecl *D);
113 ASTLocation VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000114 ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
John McCallba6a9bd2009-10-24 08:00:42 +0000115 ASTLocation VisitTypedefDecl(TypedefDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000116 ASTLocation VisitDecl(Decl *D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000117};
118
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000119class TypeLocResolver : public LocResolverBase,
120 public TypeLocVisitor<TypeLocResolver, ASTLocation> {
121 Decl * const ParentDecl;
122
123public:
124 TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
125 : LocResolverBase(ctx, loc), ParentDecl(pd) { }
126
John McCall54e14c42009-10-22 22:37:11 +0000127 ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
John McCall51bd8032009-10-18 01:05:36 +0000128 ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
129 ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
130 ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
131 ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
John McCall54e14c42009-10-22 22:37:11 +0000132 ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000133 ASTLocation VisitTypeLoc(TypeLoc TL);
134};
135
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000136} // anonymous namespace
137
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000138ASTLocation
139StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
140 assert(ContainsLocation(Node) &&
141 "Should visit only after verifying that loc is in range");
142
143 if (Node->getNumArgs() == 1)
144 // Unary operator. Let normal child traversal handle it.
145 return VisitCallExpr(Node);
146
147 assert(Node->getNumArgs() == 2 &&
148 "Wrong args for the C++ operator call expr ?");
149
150 llvm::SmallVector<Expr *, 3> Nodes;
151 // Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
152 Nodes.push_back(Node->getArg(0));
153 Nodes.push_back(Node->getCallee());
154 Nodes.push_back(Node->getArg(1));
Mike Stump1eb44332009-09-09 15:08:12 +0000155
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000156 for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
157 RangePos RP = CheckRange(Nodes[i]);
158 if (RP == AfterLoc)
159 break;
160 if (RP == ContainsLoc)
161 return Visit(Nodes[i]);
162 }
163
164 return ASTLocation(Parent, Node);
165}
166
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000167ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000168 assert(ContainsLocation(Node) &&
169 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000170
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000171 // Search all declarations of this DeclStmt.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000172 for (DeclStmt::decl_iterator
173 I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000174 RangePos RP = CheckRange(*I);
175 if (RP == AfterLoc)
176 break;
177 if (RP == ContainsLoc)
178 return DeclLocResolver(Ctx, Loc).Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000179 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000180
181 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000182}
183
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000184ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000185 assert(ContainsLocation(Node) &&
186 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000187
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000188 // Search the child statements.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000189 for (Stmt::child_iterator
190 I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000191 if (*I == NULL)
192 continue;
193
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000194 RangePos RP = CheckRange(*I);
195 if (RP == AfterLoc)
196 break;
197 if (RP == ContainsLoc)
198 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000199 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000200
201 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000202}
203
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000204ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000205 for (DeclContext::decl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +0000206 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000207 RangePos RP = CheckRange(*I);
208 if (RP == AfterLoc)
209 break;
210 if (RP == ContainsLoc)
211 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000212 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000213
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000214 return ASTLocation(cast<Decl>(DC));
215}
216
217ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
218 ASTLocation ASTLoc = VisitDeclContext(TU);
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000219 if (ASTLoc.getParentDecl() == TU)
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000220 return ASTLocation();
221 return ASTLoc;
222}
223
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000224ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000225 assert(ContainsLocation(D) &&
226 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000227
Argyrios Kyrtzidis5a70ea62009-09-29 19:58:16 +0000228 if (ContainsLocation(D->getDeclaratorInfo()))
229 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
230
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000231 // First, search through the parameters of the function.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000232 for (FunctionDecl::param_iterator
233 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000234 RangePos RP = CheckRange(*I);
235 if (RP == AfterLoc)
236 return ASTLocation(D);
237 if (RP == ContainsLoc)
238 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000239 }
Mike Stump1eb44332009-09-09 15:08:12 +0000240
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000241 // We didn't find the location in the parameters and we didn't get passed it.
Mike Stump1eb44332009-09-09 15:08:12 +0000242
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000243 if (!D->isThisDeclarationADefinition())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000244 return ASTLocation(D);
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000245
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000246 // Second, search through the declarations that are part of the function.
247 // If we find he location there, we won't have to search through its body.
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000248
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000249 for (DeclContext::decl_iterator
250 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
251 if (isa<ParmVarDecl>(*I))
252 continue; // We already searched through the parameters.
Mike Stump1eb44332009-09-09 15:08:12 +0000253
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000254 RangePos RP = CheckRange(*I);
255 if (RP == AfterLoc)
256 break;
257 if (RP == ContainsLoc)
258 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000259 }
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000260
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000261 // We didn't find a declaration that corresponds to the source location.
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000263 // Finally, search through the body of the function.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000264 Stmt *Body = D->getBody();
265 assert(Body && "Expected definition");
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000266 assert(!isBeforeLocation(Body) &&
267 "This function is supposed to contain the loc");
268 if (isAfterLocation(Body))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000269 return ASTLocation(D);
270
271 // The body contains the location.
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000272 assert(ContainsLocation(Body));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000273 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000274}
275
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000276ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
277 assert(ContainsLocation(D) &&
278 "Should visit only after verifying that loc is in range");
279 if (ContainsLocation(D->getDeclaratorInfo()))
280 return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
281
282 return ASTLocation(D);
283}
284
John McCallba6a9bd2009-10-24 08:00:42 +0000285ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
286 assert(ContainsLocation(D) &&
287 "Should visit only after verifying that loc is in range");
288
289 if (ContainsLocation(D->getTypeDeclaratorInfo()))
290 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeDeclaratorInfo());
291
292 return ASTLocation(D);
293}
294
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000295ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000296 assert(ContainsLocation(D) &&
297 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000298
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000299 // Check whether the location points to the init expression.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000300 Expr *Init = D->getInit();
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000301 if (Init && ContainsLocation(Init))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000302 return StmtLocResolver(Ctx, Loc, D).Visit(Init);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000303
304 if (ContainsLocation(D->getDeclaratorInfo()))
305 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000306
307 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000308}
309
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000310ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
311 assert(ContainsLocation(D) &&
312 "Should visit only after verifying that loc is in range");
313
314 // First, search through the parameters of the method.
315 for (ObjCMethodDecl::param_iterator
316 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
317 RangePos RP = CheckRange(*I);
318 if (RP == AfterLoc)
319 return ASTLocation(D);
320 if (RP == ContainsLoc)
321 return Visit(*I);
322 }
323
324 // We didn't find the location in the parameters and we didn't get passed it.
325
326 if (!D->getBody())
327 return ASTLocation(D);
328
329 // Second, search through the declarations that are part of the method.
330 // If we find he location there, we won't have to search through its body.
331
332 for (DeclContext::decl_iterator
333 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
334 if (isa<ParmVarDecl>(*I))
335 continue; // We already searched through the parameters.
336
337 RangePos RP = CheckRange(*I);
338 if (RP == AfterLoc)
339 break;
340 if (RP == ContainsLoc)
341 return Visit(*I);
342 }
343
344 // We didn't find a declaration that corresponds to the source location.
345
346 // Finally, search through the body of the method.
347 Stmt *Body = D->getBody();
348 assert(Body && "Expected definition");
349 assert(!isBeforeLocation(Body) &&
350 "This method is supposed to contain the loc");
351 if (isAfterLocation(Body))
352 return ASTLocation(D);
353
354 // The body contains the location.
355 assert(ContainsLocation(Body));
356 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
357}
358
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000359ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000360 assert(ContainsLocation(D) &&
361 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis7e4fe3b2009-07-18 00:33:40 +0000362 if (DeclContext *DC = dyn_cast<DeclContext>(D))
363 return VisitDeclContext(DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000364 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000365}
366
John McCall54e14c42009-10-22 22:37:11 +0000367ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
368 // Continue the 'id' magic by making the builtin type (which cannot
369 // actually be spelled) map to the typedef.
370 BuiltinType *T = TL.getTypePtr();
371 if (T->getKind() == BuiltinType::ObjCId) {
372 TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
373 return ASTLocation(ParentDecl, D, TL.getNameLoc());
374 }
375
376 // Same thing with 'Class'.
377 if (T->getKind() == BuiltinType::ObjCClass) {
378 TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
379 return ASTLocation(ParentDecl, D, TL.getNameLoc());
380 }
381
382 return ASTLocation(ParentDecl, TL);
383}
384
John McCall51bd8032009-10-18 01:05:36 +0000385ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000386 assert(ContainsLocation(TL) &&
387 "Should visit only after verifying that loc is in range");
388 if (ContainsLocation(TL.getNameLoc()))
389 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
390 return ASTLocation(ParentDecl, TL);
391}
392
John McCall51bd8032009-10-18 01:05:36 +0000393ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000394 assert(ContainsLocation(TL) &&
395 "Should visit only after verifying that loc is in range");
396
397 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
398 ParmVarDecl *Parm = TL.getArg(i);
399 RangePos RP = CheckRange(Parm);
400 if (RP == AfterLoc)
401 break;
402 if (RP == ContainsLoc)
403 return DeclLocResolver(Ctx, Loc).Visit(Parm);
404 }
405
406 return ASTLocation(ParentDecl, TL);
407}
408
John McCall51bd8032009-10-18 01:05:36 +0000409ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000410 assert(ContainsLocation(TL) &&
411 "Should visit only after verifying that loc is in range");
412
413 Expr *E = TL.getSizeExpr();
414 if (E && ContainsLocation(E))
415 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
416
417 return ASTLocation(ParentDecl, TL);
418}
419
John McCall51bd8032009-10-18 01:05:36 +0000420ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000421 assert(ContainsLocation(TL) &&
422 "Should visit only after verifying that loc is in range");
423 if (ContainsLocation(TL.getNameLoc()))
424 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000425
426 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
427 SourceLocation L = TL.getProtocolLoc(i);
428 RangePos RP = CheckRange(L);
429 if (RP == AfterLoc)
430 break;
431 if (RP == ContainsLoc)
432 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
433 }
434
435 return ASTLocation(ParentDecl, TL);
436}
437
John McCall54e14c42009-10-22 22:37:11 +0000438ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
439 assert(ContainsLocation(TL) &&
440 "Should visit only after verifying that loc is in range");
441
442 if (TL.hasProtocolsAsWritten()) {
443 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
444 SourceLocation L = TL.getProtocolLoc(i);
445 RangePos RP = CheckRange(L);
446 if (RP == AfterLoc)
447 break;
448 if (RP == ContainsLoc)
449 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
450 }
451 }
452
453 return ASTLocation(ParentDecl, TL);
454}
455
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000456ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
457 assert(ContainsLocation(TL) &&
458 "Should visit only after verifying that loc is in range");
459 return ASTLocation(ParentDecl, TL);
460}
461
462ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
463 DeclaratorInfo *DInfo) {
464 assert(ContainsLocation(DInfo) &&
465 "Should visit only after verifying that loc is in range");
466
467 TypeLocResolver(Ctx, Loc, D);
468 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
469 if (ContainsLocation(TL))
470 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
471
472 assert(0 && "Should have found the loc in a typeloc");
473 return ASTLocation(D, Stm);
474}
475
476LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
477 if (!DInfo)
478 return BeforeLoc; // Keep looking.
479
480 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
481 if (ContainsLocation(TL))
482 return ContainsLoc;
483
484 return BeforeLoc; // Keep looking.
485}
486
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000487LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000488 if (!Range.isValid())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000489 return BeforeLoc; // Keep looking.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000490
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000491 // Update the end source range to cover the full length of the token
492 // positioned at the end of the source range.
493 //
494 // e.g.,
495 // int foo
496 // ^ ^
497 //
498 // will be updated to
499 // int foo
500 // ^ ^
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000501 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
502 Ctx.getSourceManager(),
503 Ctx.getLangOptions());
504 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000505
Mike Stump1eb44332009-09-09 15:08:12 +0000506 SourceManager &SourceMgr = Ctx.getSourceManager();
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000507 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
508 return BeforeLoc;
Mike Stump1eb44332009-09-09 15:08:12 +0000509
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000510 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
511 return AfterLoc;
512
513 return ContainsLoc;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000514}
515
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000516#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000517void LocResolverBase::print(Decl *D) {
518 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000519 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
Argyrios Kyrtzidisf1d60ea2009-06-30 02:35:04 +0000520 D->print(OS);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000521 OS << " <";
522 D->getLocStart().print(OS, Ctx.getSourceManager());
523 OS << " > - <";
524 D->getLocEnd().print(OS, Ctx.getSourceManager());
525 OS << ">\n\n";
526 OS.flush();
527}
528
529void LocResolverBase::print(Stmt *Node) {
530 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000531 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
Chris Lattnere4f21422009-06-30 01:26:17 +0000532 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000533 OS << " <";
534 Node->getLocStart().print(OS, Ctx.getSourceManager());
535 OS << " > - <";
536 Node->getLocEnd().print(OS, Ctx.getSourceManager());
537 OS << ">\n\n";
538 OS.flush();
539}
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000540#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000541
542
543/// \brief Returns the AST node that a source location points to.
544///
Steve Naroff6a6de8b2009-10-21 13:56:23 +0000545ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
Steve Narofff96b5242009-10-28 20:44:47 +0000546 ASTLocation *LastLoc) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000547 if (Loc.isInvalid())
Argyrios Kyrtzidis874012b2009-07-06 21:34:20 +0000548 return ASTLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000549
Steve Narofff96b5242009-10-28 20:44:47 +0000550 if (LastLoc && LastLoc->isValid()) {
551 DeclContext *DC = 0;
552
553 if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
554 DC = Dcl->getDeclContext();
555 } else if (LastLoc->isStmt()) {
556 Decl *Parent = LastLoc->getParentDecl();
557 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
558 DC = FD;
559 else {
560 // This is needed to handle statements within an initializer.
561 // Example:
562 // void func() { long double fabsf = __builtin_fabsl(__x); }
563 // In this case, the 'parent' of __builtin_fabsl is fabsf.
564 DC = Parent->getDeclContext();
565 }
566 } else { // We have 'N_NamedRef' or 'N_Type'
567 DC = LastLoc->getParentDecl()->getDeclContext();
568 }
569 assert(DC && "Missing DeclContext");
570
571 FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
572 DeclLocResolver DLocResolver(Ctx, Loc);
573
574 if (FD && FD->isThisDeclarationADefinition() &&
575 DLocResolver.ContainsLocation(FD)) {
576 return DLocResolver.VisitFunctionDecl(FD);
577 }
578 // Fall through and try the slow path...
579 // FIXME: Optimize more cases.
580 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000581 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000582}