blob: ed905f364f0de9b42da55ed33fe9be390db3ba6c [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);
Ted Kremenek1d5fdf32009-11-18 02:02:52 +0000115 ASTLocation VisitObjCClassDecl(ObjCClassDecl *D);
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000116 ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
John McCallba6a9bd2009-10-24 08:00:42 +0000117 ASTLocation VisitTypedefDecl(TypedefDecl *D);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000118 ASTLocation VisitDecl(Decl *D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000119};
120
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000121class TypeLocResolver : public LocResolverBase,
122 public TypeLocVisitor<TypeLocResolver, ASTLocation> {
123 Decl * const ParentDecl;
124
125public:
126 TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
127 : LocResolverBase(ctx, loc), ParentDecl(pd) { }
128
John McCall54e14c42009-10-22 22:37:11 +0000129 ASTLocation VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
John McCall51bd8032009-10-18 01:05:36 +0000130 ASTLocation VisitTypedefTypeLoc(TypedefTypeLoc TL);
131 ASTLocation VisitFunctionTypeLoc(FunctionTypeLoc TL);
132 ASTLocation VisitArrayTypeLoc(ArrayTypeLoc TL);
133 ASTLocation VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
John McCall54e14c42009-10-22 22:37:11 +0000134 ASTLocation VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000135 ASTLocation VisitTypeLoc(TypeLoc TL);
136};
137
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000138} // anonymous namespace
139
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000140ASTLocation
John McCall5ab75172009-11-04 07:28:41 +0000141StmtLocResolver::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node) {
142 assert(ContainsLocation(Node) &&
143 "Should visit only after verifying that loc is in range");
144
145 if (Node->isArgumentType()) {
146 DeclaratorInfo *DInfo = Node->getArgumentTypeInfo();
147 if (ContainsLocation(DInfo))
148 return ResolveInDeclarator(Parent, Node, DInfo);
149 } else {
150 Expr *SubNode = Node->getArgumentExpr();
151 if (ContainsLocation(SubNode))
152 return Visit(SubNode);
153 }
154
155 return ASTLocation(Parent, Node);
156}
157
158
159ASTLocation
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000160StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
161 assert(ContainsLocation(Node) &&
162 "Should visit only after verifying that loc is in range");
163
164 if (Node->getNumArgs() == 1)
165 // Unary operator. Let normal child traversal handle it.
166 return VisitCallExpr(Node);
167
168 assert(Node->getNumArgs() == 2 &&
169 "Wrong args for the C++ operator call expr ?");
170
171 llvm::SmallVector<Expr *, 3> Nodes;
172 // Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
173 Nodes.push_back(Node->getArg(0));
174 Nodes.push_back(Node->getCallee());
175 Nodes.push_back(Node->getArg(1));
Mike Stump1eb44332009-09-09 15:08:12 +0000176
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000177 for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
178 RangePos RP = CheckRange(Nodes[i]);
179 if (RP == AfterLoc)
180 break;
181 if (RP == ContainsLoc)
182 return Visit(Nodes[i]);
183 }
184
185 return ASTLocation(Parent, Node);
186}
187
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000188ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000189 assert(ContainsLocation(Node) &&
190 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000191
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000192 // Search all declarations of this DeclStmt.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000193 for (DeclStmt::decl_iterator
194 I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000195 RangePos RP = CheckRange(*I);
196 if (RP == AfterLoc)
197 break;
198 if (RP == ContainsLoc)
199 return DeclLocResolver(Ctx, Loc).Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000200 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000201
202 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000203}
204
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000205ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000206 assert(ContainsLocation(Node) &&
207 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000208
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000209 // Search the child statements.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000210 for (Stmt::child_iterator
211 I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
Argyrios Kyrtzidis8c4dc1f2009-07-31 19:02:11 +0000212 if (*I == NULL)
213 continue;
214
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000215 RangePos RP = CheckRange(*I);
216 if (RP == AfterLoc)
217 break;
218 if (RP == ContainsLoc)
219 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000220 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000221
222 return ASTLocation(Parent, Node);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000223}
224
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000225ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000226 for (DeclContext::decl_iterator
Argyrios Kyrtzidis17945a02009-06-30 02:36:12 +0000227 I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000228 RangePos RP = CheckRange(*I);
229 if (RP == AfterLoc)
230 break;
231 if (RP == ContainsLoc)
232 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000233 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000234
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000235 return ASTLocation(cast<Decl>(DC));
236}
237
238ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
239 ASTLocation ASTLoc = VisitDeclContext(TU);
Argyrios Kyrtzidisf4526e32009-09-29 19:44:27 +0000240 if (ASTLoc.getParentDecl() == TU)
Argyrios Kyrtzidis2e46aee2009-07-14 03:18:17 +0000241 return ASTLocation();
242 return ASTLoc;
243}
244
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000245ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000246 assert(ContainsLocation(D) &&
247 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000248
Argyrios Kyrtzidis5a70ea62009-09-29 19:58:16 +0000249 if (ContainsLocation(D->getDeclaratorInfo()))
250 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
251
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000252 // First, search through the parameters of the function.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000253 for (FunctionDecl::param_iterator
254 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000255 RangePos RP = CheckRange(*I);
256 if (RP == AfterLoc)
257 return ASTLocation(D);
258 if (RP == ContainsLoc)
259 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000260 }
Mike Stump1eb44332009-09-09 15:08:12 +0000261
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000262 // We didn't find the location in the parameters and we didn't get passed it.
Mike Stump1eb44332009-09-09 15:08:12 +0000263
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000264 if (!D->isThisDeclarationADefinition())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000265 return ASTLocation(D);
Argyrios Kyrtzidis685477f2009-07-05 22:21:17 +0000266
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000267 // Second, search through the declarations that are part of the function.
268 // If we find he location there, we won't have to search through its body.
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000269
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000270 for (DeclContext::decl_iterator
271 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
272 if (isa<ParmVarDecl>(*I))
273 continue; // We already searched through the parameters.
Mike Stump1eb44332009-09-09 15:08:12 +0000274
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000275 RangePos RP = CheckRange(*I);
276 if (RP == AfterLoc)
277 break;
278 if (RP == ContainsLoc)
279 return Visit(*I);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000280 }
Argyrios Kyrtzidis07796e12009-07-05 22:21:46 +0000281
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000282 // We didn't find a declaration that corresponds to the source location.
Mike Stump1eb44332009-09-09 15:08:12 +0000283
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000284 // Finally, search through the body of the function.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000285 Stmt *Body = D->getBody();
286 assert(Body && "Expected definition");
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000287 assert(!isBeforeLocation(Body) &&
288 "This function is supposed to contain the loc");
289 if (isAfterLocation(Body))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000290 return ASTLocation(D);
291
292 // The body contains the location.
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000293 assert(ContainsLocation(Body));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000294 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000295}
296
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000297ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
298 assert(ContainsLocation(D) &&
299 "Should visit only after verifying that loc is in range");
300 if (ContainsLocation(D->getDeclaratorInfo()))
301 return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
302
303 return ASTLocation(D);
304}
305
John McCallba6a9bd2009-10-24 08:00:42 +0000306ASTLocation DeclLocResolver::VisitTypedefDecl(TypedefDecl *D) {
307 assert(ContainsLocation(D) &&
308 "Should visit only after verifying that loc is in range");
309
310 if (ContainsLocation(D->getTypeDeclaratorInfo()))
311 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeDeclaratorInfo());
312
313 return ASTLocation(D);
314}
315
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000316ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000317 assert(ContainsLocation(D) &&
318 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000319
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000320 // Check whether the location points to the init expression.
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000321 Expr *Init = D->getInit();
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000322 if (Init && ContainsLocation(Init))
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000323 return StmtLocResolver(Ctx, Loc, D).Visit(Init);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000324
325 if (ContainsLocation(D->getDeclaratorInfo()))
326 return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000327
328 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000329}
330
Ted Kremenek1d5fdf32009-11-18 02:02:52 +0000331ASTLocation DeclLocResolver::VisitObjCClassDecl(ObjCClassDecl *D) {
332 assert(ContainsLocation(D) &&
333 "Should visit only after verifying that loc is in range");
334
335 for (ObjCClassDecl::iterator I = D->begin(), E = D->end() ; I != E; ++I) {
336 if (CheckRange(I->getLocation()) == ContainsLoc)
337 return ASTLocation(D, I->getInterface(), I->getLocation());
338 }
339 return ASTLocation(D);
340}
341
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000342ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
343 assert(ContainsLocation(D) &&
344 "Should visit only after verifying that loc is in range");
345
346 // First, search through the parameters of the method.
347 for (ObjCMethodDecl::param_iterator
348 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
349 RangePos RP = CheckRange(*I);
350 if (RP == AfterLoc)
351 return ASTLocation(D);
352 if (RP == ContainsLoc)
353 return Visit(*I);
354 }
355
356 // We didn't find the location in the parameters and we didn't get passed it.
357
358 if (!D->getBody())
359 return ASTLocation(D);
360
361 // Second, search through the declarations that are part of the method.
362 // If we find he location there, we won't have to search through its body.
363
364 for (DeclContext::decl_iterator
365 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
366 if (isa<ParmVarDecl>(*I))
367 continue; // We already searched through the parameters.
368
369 RangePos RP = CheckRange(*I);
370 if (RP == AfterLoc)
371 break;
372 if (RP == ContainsLoc)
373 return Visit(*I);
374 }
375
376 // We didn't find a declaration that corresponds to the source location.
377
378 // Finally, search through the body of the method.
379 Stmt *Body = D->getBody();
380 assert(Body && "Expected definition");
381 assert(!isBeforeLocation(Body) &&
382 "This method is supposed to contain the loc");
383 if (isAfterLocation(Body))
384 return ASTLocation(D);
385
386 // The body contains the location.
387 assert(ContainsLocation(Body));
388 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
389}
390
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000391ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000392 assert(ContainsLocation(D) &&
393 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis7e4fe3b2009-07-18 00:33:40 +0000394 if (DeclContext *DC = dyn_cast<DeclContext>(D))
395 return VisitDeclContext(DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000396 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000397}
398
John McCall54e14c42009-10-22 22:37:11 +0000399ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
400 // Continue the 'id' magic by making the builtin type (which cannot
401 // actually be spelled) map to the typedef.
402 BuiltinType *T = TL.getTypePtr();
403 if (T->getKind() == BuiltinType::ObjCId) {
404 TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
405 return ASTLocation(ParentDecl, D, TL.getNameLoc());
406 }
407
408 // Same thing with 'Class'.
409 if (T->getKind() == BuiltinType::ObjCClass) {
410 TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
411 return ASTLocation(ParentDecl, D, TL.getNameLoc());
412 }
413
414 return ASTLocation(ParentDecl, TL);
415}
416
John McCall51bd8032009-10-18 01:05:36 +0000417ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000418 assert(ContainsLocation(TL) &&
419 "Should visit only after verifying that loc is in range");
420 if (ContainsLocation(TL.getNameLoc()))
421 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
422 return ASTLocation(ParentDecl, TL);
423}
424
John McCall51bd8032009-10-18 01:05:36 +0000425ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000426 assert(ContainsLocation(TL) &&
427 "Should visit only after verifying that loc is in range");
428
429 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
430 ParmVarDecl *Parm = TL.getArg(i);
431 RangePos RP = CheckRange(Parm);
432 if (RP == AfterLoc)
433 break;
434 if (RP == ContainsLoc)
435 return DeclLocResolver(Ctx, Loc).Visit(Parm);
436 }
437
438 return ASTLocation(ParentDecl, TL);
439}
440
John McCall51bd8032009-10-18 01:05:36 +0000441ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000442 assert(ContainsLocation(TL) &&
443 "Should visit only after verifying that loc is in range");
444
445 Expr *E = TL.getSizeExpr();
446 if (E && ContainsLocation(E))
447 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
448
449 return ASTLocation(ParentDecl, TL);
450}
451
John McCall51bd8032009-10-18 01:05:36 +0000452ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000453 assert(ContainsLocation(TL) &&
454 "Should visit only after verifying that loc is in range");
455 if (ContainsLocation(TL.getNameLoc()))
456 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000457
458 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
459 SourceLocation L = TL.getProtocolLoc(i);
460 RangePos RP = CheckRange(L);
461 if (RP == AfterLoc)
462 break;
463 if (RP == ContainsLoc)
464 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
465 }
466
467 return ASTLocation(ParentDecl, TL);
468}
469
John McCall54e14c42009-10-22 22:37:11 +0000470ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
471 assert(ContainsLocation(TL) &&
472 "Should visit only after verifying that loc is in range");
473
474 if (TL.hasProtocolsAsWritten()) {
475 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
476 SourceLocation L = TL.getProtocolLoc(i);
477 RangePos RP = CheckRange(L);
478 if (RP == AfterLoc)
479 break;
480 if (RP == ContainsLoc)
481 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
482 }
483 }
484
485 return ASTLocation(ParentDecl, TL);
486}
487
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000488ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
489 assert(ContainsLocation(TL) &&
490 "Should visit only after verifying that loc is in range");
491 return ASTLocation(ParentDecl, TL);
492}
493
494ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
495 DeclaratorInfo *DInfo) {
496 assert(ContainsLocation(DInfo) &&
497 "Should visit only after verifying that loc is in range");
498
Douglas Gregor6490ae52009-11-17 06:14:37 +0000499 (void)TypeLocResolver(Ctx, Loc, D);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000500 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
501 if (ContainsLocation(TL))
502 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
503
504 assert(0 && "Should have found the loc in a typeloc");
505 return ASTLocation(D, Stm);
506}
507
508LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
509 if (!DInfo)
510 return BeforeLoc; // Keep looking.
511
512 for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
513 if (ContainsLocation(TL))
514 return ContainsLoc;
515
516 return BeforeLoc; // Keep looking.
517}
518
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000519LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000520 if (!Range.isValid())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000521 return BeforeLoc; // Keep looking.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000522
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000523 // Update the end source range to cover the full length of the token
524 // positioned at the end of the source range.
525 //
526 // e.g.,
527 // int foo
528 // ^ ^
529 //
530 // will be updated to
531 // int foo
532 // ^ ^
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000533 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
534 Ctx.getSourceManager(),
535 Ctx.getLangOptions());
536 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000537
Mike Stump1eb44332009-09-09 15:08:12 +0000538 SourceManager &SourceMgr = Ctx.getSourceManager();
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000539 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
540 return BeforeLoc;
Mike Stump1eb44332009-09-09 15:08:12 +0000541
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000542 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
543 return AfterLoc;
544
545 return ContainsLoc;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000546}
547
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000548#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000549void LocResolverBase::print(Decl *D) {
550 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000551 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
Argyrios Kyrtzidisf1d60ea2009-06-30 02:35:04 +0000552 D->print(OS);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000553 OS << " <";
554 D->getLocStart().print(OS, Ctx.getSourceManager());
555 OS << " > - <";
556 D->getLocEnd().print(OS, Ctx.getSourceManager());
557 OS << ">\n\n";
558 OS.flush();
559}
560
561void LocResolverBase::print(Stmt *Node) {
562 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000563 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
Chris Lattnere4f21422009-06-30 01:26:17 +0000564 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000565 OS << " <";
566 Node->getLocStart().print(OS, Ctx.getSourceManager());
567 OS << " > - <";
568 Node->getLocEnd().print(OS, Ctx.getSourceManager());
569 OS << ">\n\n";
570 OS.flush();
571}
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000572#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000573
574
575/// \brief Returns the AST node that a source location points to.
576///
Steve Naroff6a6de8b2009-10-21 13:56:23 +0000577ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
Steve Narofff96b5242009-10-28 20:44:47 +0000578 ASTLocation *LastLoc) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000579 if (Loc.isInvalid())
Argyrios Kyrtzidis874012b2009-07-06 21:34:20 +0000580 return ASTLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000581
Steve Narofff96b5242009-10-28 20:44:47 +0000582 if (LastLoc && LastLoc->isValid()) {
583 DeclContext *DC = 0;
584
585 if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
586 DC = Dcl->getDeclContext();
587 } else if (LastLoc->isStmt()) {
588 Decl *Parent = LastLoc->getParentDecl();
589 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
590 DC = FD;
591 else {
592 // This is needed to handle statements within an initializer.
593 // Example:
594 // void func() { long double fabsf = __builtin_fabsl(__x); }
595 // In this case, the 'parent' of __builtin_fabsl is fabsf.
596 DC = Parent->getDeclContext();
597 }
598 } else { // We have 'N_NamedRef' or 'N_Type'
599 DC = LastLoc->getParentDecl()->getDeclContext();
600 }
601 assert(DC && "Missing DeclContext");
602
603 FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
604 DeclLocResolver DLocResolver(Ctx, Loc);
605
606 if (FD && FD->isThisDeclarationADefinition() &&
607 DLocResolver.ContainsLocation(FD)) {
608 return DLocResolver.VisitFunctionDecl(FD);
609 }
610 // Fall through and try the slow path...
611 // FIXME: Optimize more cases.
612 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000613 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000614}