blob: 73b584b5205d1662d70d095ce0d52939f2157851 [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
John McCall5ab75172009-11-04 07:28:41 +000095 ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +000096 ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000097 ASTLocation VisitDeclStmt(DeclStmt *Node);
98 ASTLocation VisitStmt(Stmt *Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000099};
100
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000101/// \brief Searches a declaration for the ASTLocation that corresponds to a
102/// source location.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000103class VISIBILITY_HIDDEN DeclLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000104 public DeclVisitor<DeclLocResolver,
105 ASTLocation > {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000106public:
107 DeclLocResolver(ASTContext &ctx, SourceLocation loc)
108 : LocResolverBase(ctx, loc) {}
109
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000110 ASTLocation VisitDeclContext(DeclContext *DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000111 ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000112 ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000113 ASTLocation VisitVarDecl(VarDecl *D);
114 ASTLocation VisitFunctionDecl(FunctionDecl *D);
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000115 ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
John McCallba6a9bd2009-10-24 08:00:42 +0000116 ASTLocation VisitTypedefDecl(TypedefDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000117 ASTLocation VisitDecl(Decl *D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000118};
119
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000120class 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
John McCall54e14c42009-10-22 22:37:11 +0000128 ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
John McCall51bd8032009-10-18 01:05:36 +0000129 ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
130 ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
131 ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
132 ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
John McCall54e14c42009-10-22 22:37:11 +0000133 ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000134 ASTLocation VisitTypeLoc(TypeLoc TL);
135};
136
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000137} // anonymous namespace
138
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000139ASTLocation
John McCall5ab75172009-11-04 07:28:41 +0000140StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
141 assert(ContainsLocation(Node) &&
142 "Should visit only after verifying that loc is in range");
143
144 if (Node->isArgumentType()) {
145 DeclaratorInfo *DInfo = Node->getArgumentTypeInfo();
146 if (ContainsLocation(DInfo))
147 return ResolveInDeclarator(Parent, Node, DInfo);
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
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000159StmtLocResolver::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));
Mike Stump1eb44332009-09-09 15:08:12 +0000175
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000176 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
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000187ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000188 assert(ContainsLocation(Node) &&
189 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000190
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000191 // Search all declarations of this DeclStmt.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000192 for (DeclStmt::decl_iterator
193 I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000194 RangePos RP = CheckRange(*I);
195 if (RP == AfterLoc)
196 break;
197 if (RP == ContainsLoc)
198 return DeclLocResolver(Ctx, Loc).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 Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000204ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000205 assert(ContainsLocation(Node) &&
206 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000207
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000208 // Search the child statements.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000209 for (Stmt::child_iterator
210 I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000211 if (*I == NULL)
212 continue;
213
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000214 RangePos RP = CheckRange(*I);
215 if (RP == AfterLoc)
216 break;
217 if (RP == ContainsLoc)
218 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000219 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000220
221 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000222}
223
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000224ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000225 for (DeclContext::decl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +0000226 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000227 RangePos RP = CheckRange(*I);
228 if (RP == AfterLoc)
229 break;
230 if (RP == ContainsLoc)
231 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000232 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000233
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000234 return ASTLocation(cast<Decl>(DC));
235}
236
237ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
238 ASTLocation ASTLoc = VisitDeclContext(TU);
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000239 if (ASTLoc.getParentDecl() == TU)
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000240 return ASTLocation();
241 return ASTLoc;
242}
243
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000244ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000245 assert(ContainsLocation(D) &&
246 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000247
Argyrios Kyrtzidis5a70ea62009-09-29 19:58:16 +0000248 if (ContainsLocation(D->getDeclaratorInfo()))
249 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
250
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000251 // First, search through the parameters of the function.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000252 for (FunctionDecl::param_iterator
253 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000254 RangePos RP = CheckRange(*I);
255 if (RP == AfterLoc)
256 return ASTLocation(D);
257 if (RP == ContainsLoc)
258 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000259 }
Mike Stump1eb44332009-09-09 15:08:12 +0000260
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000261 // We didn't find the location in the parameters and we didn't get passed it.
Mike Stump1eb44332009-09-09 15:08:12 +0000262
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000263 if (!D->isThisDeclarationADefinition())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000264 return ASTLocation(D);
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000265
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000266 // Second, search through the declarations that are part of the function.
267 // If we find he location there, we won't have to search through its body.
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000268
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000269 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.
Mike Stump1eb44332009-09-09 15:08:12 +0000273
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000274 RangePos RP = CheckRange(*I);
275 if (RP == AfterLoc)
276 break;
277 if (RP == ContainsLoc)
278 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000279 }
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000280
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000281 // We didn't find a declaration that corresponds to the source location.
Mike Stump1eb44332009-09-09 15:08:12 +0000282
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000283 // Finally, search through the body of the function.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000284 Stmt *Body = D->getBody();
285 assert(Body && "Expected definition");
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000286 assert(!isBeforeLocation(Body) &&
287 "This function is supposed to contain the loc");
288 if (isAfterLocation(Body))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000289 return ASTLocation(D);
290
291 // The body contains the location.
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000292 assert(ContainsLocation(Body));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000293 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000294}
295
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000296ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
297 assert(ContainsLocation(D) &&
298 "Should visit only after verifying that loc is in range");
299 if (ContainsLocation(D->getDeclaratorInfo()))
300 return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
301
302 return ASTLocation(D);
303}
304
John McCallba6a9bd2009-10-24 08:00:42 +0000305ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
306 assert(ContainsLocation(D) &&
307 "Should visit only after verifying that loc is in range");
308
309 if (ContainsLocation(D->getTypeDeclaratorInfo()))
310 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeDeclaratorInfo());
311
312 return ASTLocation(D);
313}
314
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000315ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000316 assert(ContainsLocation(D) &&
317 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000318
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000319 // Check whether the location points to the init expression.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000320 Expr *Init = D->getInit();
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000321 if (Init && ContainsLocation(Init))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000322 return StmtLocResolver(Ctx, Loc, D).Visit(Init);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000323
324 if (ContainsLocation(D->getDeclaratorInfo()))
325 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000326
327 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000328}
329
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000330ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
331 assert(ContainsLocation(D) &&
332 "Should visit only after verifying that loc is in range");
333
334 // First, search through the parameters of the method.
335 for (ObjCMethodDecl::param_iterator
336 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
337 RangePos RP = CheckRange(*I);
338 if (RP == AfterLoc)
339 return ASTLocation(D);
340 if (RP == ContainsLoc)
341 return Visit(*I);
342 }
343
344 // We didn't find the location in the parameters and we didn't get passed it.
345
346 if (!D->getBody())
347 return ASTLocation(D);
348
349 // Second, search through the declarations that are part of the method.
350 // If we find he location there, we won't have to search through its body.
351
352 for (DeclContext::decl_iterator
353 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
354 if (isa<ParmVarDecl>(*I))
355 continue; // We already searched through the parameters.
356
357 RangePos RP = CheckRange(*I);
358 if (RP == AfterLoc)
359 break;
360 if (RP == ContainsLoc)
361 return Visit(*I);
362 }
363
364 // We didn't find a declaration that corresponds to the source location.
365
366 // Finally, search through the body of the method.
367 Stmt *Body = D->getBody();
368 assert(Body && "Expected definition");
369 assert(!isBeforeLocation(Body) &&
370 "This method is supposed to contain the loc");
371 if (isAfterLocation(Body))
372 return ASTLocation(D);
373
374 // The body contains the location.
375 assert(ContainsLocation(Body));
376 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
377}
378
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000379ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000380 assert(ContainsLocation(D) &&
381 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis7e4fe3b2009-07-18 00:33:40 +0000382 if (DeclContext *DC = dyn_cast<DeclContext>(D))
383 return VisitDeclContext(DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000384 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000385}
386
John McCall54e14c42009-10-22 22:37:11 +0000387ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
388 // Continue the 'id' magic by making the builtin type (which cannot
389 // actually be spelled) map to the typedef.
390 BuiltinType *T = TL.getTypePtr();
391 if (T->getKind() == BuiltinType::ObjCId) {
392 TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
393 return ASTLocation(ParentDecl, D, TL.getNameLoc());
394 }
395
396 // Same thing with 'Class'.
397 if (T->getKind() == BuiltinType::ObjCClass) {
398 TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
399 return ASTLocation(ParentDecl, D, TL.getNameLoc());
400 }
401
402 return ASTLocation(ParentDecl, TL);
403}
404
John McCall51bd8032009-10-18 01:05:36 +0000405ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000406 assert(ContainsLocation(TL) &&
407 "Should visit only after verifying that loc is in range");
408 if (ContainsLocation(TL.getNameLoc()))
409 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
410 return ASTLocation(ParentDecl, TL);
411}
412
John McCall51bd8032009-10-18 01:05:36 +0000413ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000414 assert(ContainsLocation(TL) &&
415 "Should visit only after verifying that loc is in range");
416
417 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
418 ParmVarDecl *Parm = TL.getArg(i);
419 RangePos RP = CheckRange(Parm);
420 if (RP == AfterLoc)
421 break;
422 if (RP == ContainsLoc)
423 return DeclLocResolver(Ctx, Loc).Visit(Parm);
424 }
425
426 return ASTLocation(ParentDecl, TL);
427}
428
John McCall51bd8032009-10-18 01:05:36 +0000429ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000430 assert(ContainsLocation(TL) &&
431 "Should visit only after verifying that loc is in range");
432
433 Expr *E = TL.getSizeExpr();
434 if (E && ContainsLocation(E))
435 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
436
437 return ASTLocation(ParentDecl, TL);
438}
439
John McCall51bd8032009-10-18 01:05:36 +0000440ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000441 assert(ContainsLocation(TL) &&
442 "Should visit only after verifying that loc is in range");
443 if (ContainsLocation(TL.getNameLoc()))
444 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000445
446 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
447 SourceLocation L = TL.getProtocolLoc(i);
448 RangePos RP = CheckRange(L);
449 if (RP == AfterLoc)
450 break;
451 if (RP == ContainsLoc)
452 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
453 }
454
455 return ASTLocation(ParentDecl, TL);
456}
457
John McCall54e14c42009-10-22 22:37:11 +0000458ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
459 assert(ContainsLocation(TL) &&
460 "Should visit only after verifying that loc is in range");
461
462 if (TL.hasProtocolsAsWritten()) {
463 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
464 SourceLocation L = TL.getProtocolLoc(i);
465 RangePos RP = CheckRange(L);
466 if (RP == AfterLoc)
467 break;
468 if (RP == ContainsLoc)
469 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
470 }
471 }
472
473 return ASTLocation(ParentDecl, TL);
474}
475
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000476ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
477 assert(ContainsLocation(TL) &&
478 "Should visit only after verifying that loc is in range");
479 return ASTLocation(ParentDecl, TL);
480}
481
482ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
483 DeclaratorInfo *DInfo) {
484 assert(ContainsLocation(DInfo) &&
485 "Should visit only after verifying that loc is in range");
486
487 TypeLocResolver(Ctx, Loc, D);
488 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
489 if (ContainsLocation(TL))
490 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
491
492 assert(0 && "Should have found the loc in a typeloc");
493 return ASTLocation(D, Stm);
494}
495
496LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
497 if (!DInfo)
498 return BeforeLoc; // Keep looking.
499
500 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
501 if (ContainsLocation(TL))
502 return ContainsLoc;
503
504 return BeforeLoc; // Keep looking.
505}
506
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000507LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000508 if (!Range.isValid())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000509 return BeforeLoc; // Keep looking.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000510
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000511 // Update the end source range to cover the full length of the token
512 // positioned at the end of the source range.
513 //
514 // e.g.,
515 // int foo
516 // ^ ^
517 //
518 // will be updated to
519 // int foo
520 // ^ ^
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000521 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
522 Ctx.getSourceManager(),
523 Ctx.getLangOptions());
524 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000525
Mike Stump1eb44332009-09-09 15:08:12 +0000526 SourceManager &SourceMgr = Ctx.getSourceManager();
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000527 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
528 return BeforeLoc;
Mike Stump1eb44332009-09-09 15:08:12 +0000529
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000530 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
531 return AfterLoc;
532
533 return ContainsLoc;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000534}
535
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000536#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000537void LocResolverBase::print(Decl *D) {
538 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000539 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
Argyrios Kyrtzidisf1d60ea2009-06-30 02:35:04 +0000540 D->print(OS);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000541 OS << " <";
542 D->getLocStart().print(OS, Ctx.getSourceManager());
543 OS << " > - <";
544 D->getLocEnd().print(OS, Ctx.getSourceManager());
545 OS << ">\n\n";
546 OS.flush();
547}
548
549void LocResolverBase::print(Stmt *Node) {
550 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000551 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
Chris Lattnere4f21422009-06-30 01:26:17 +0000552 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000553 OS << " <";
554 Node->getLocStart().print(OS, Ctx.getSourceManager());
555 OS << " > - <";
556 Node->getLocEnd().print(OS, Ctx.getSourceManager());
557 OS << ">\n\n";
558 OS.flush();
559}
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000560#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000561
562
563/// \brief Returns the AST node that a source location points to.
564///
Steve Naroff6a6de8b2009-10-21 13:56:23 +0000565ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
Steve Narofff96b5242009-10-28 20:44:47 +0000566 ASTLocation *LastLoc) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000567 if (Loc.isInvalid())
Argyrios Kyrtzidis874012b2009-07-06 21:34:20 +0000568 return ASTLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000569
Steve Narofff96b5242009-10-28 20:44:47 +0000570 if (LastLoc && LastLoc->isValid()) {
571 DeclContext *DC = 0;
572
573 if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
574 DC = Dcl->getDeclContext();
575 } else if (LastLoc->isStmt()) {
576 Decl *Parent = LastLoc->getParentDecl();
577 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
578 DC = FD;
579 else {
580 // This is needed to handle statements within an initializer.
581 // Example:
582 // void func() { long double fabsf = __builtin_fabsl(__x); }
583 // In this case, the 'parent' of __builtin_fabsl is fabsf.
584 DC = Parent->getDeclContext();
585 }
586 } else { // We have 'N_NamedRef' or 'N_Type'
587 DC = LastLoc->getParentDecl()->getDeclContext();
588 }
589 assert(DC && "Missing DeclContext");
590
591 FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
592 DeclLocResolver DLocResolver(Ctx, Loc);
593
594 if (FD && FD->isThisDeclarationADefinition() &&
595 DLocResolver.ContainsLocation(FD)) {
596 return DLocResolver.VisitFunctionDecl(FD);
597 }
598 // Fall through and try the slow path...
599 // FIXME: Optimize more cases.
600 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000601 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000602}