blob: 4bb15943bb4d1de1b58c953b6f6f6013291a9797 [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"
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000022using namespace clang;
Argyrios Kyrtzidisccbcb702009-07-06 21:34:47 +000023using namespace idx;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000024
25namespace {
26
27/// \brief Base for the LocResolver classes. Mostly does source range checking.
Benjamin Kramer85b45212009-11-28 19:45:26 +000028class LocResolverBase {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000029protected:
30 ASTContext &Ctx;
31 SourceLocation Loc;
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000032
John McCalla93c9342009-12-07 02:54:59 +000033 ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, TypeSourceInfo *TInfo);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000034
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000035 enum RangePos {
36 BeforeLoc,
37 ContainsLoc,
38 AfterLoc
39 };
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000040
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000041 RangePos CheckRange(SourceRange Range);
John McCalla93c9342009-12-07 02:54:59 +000042 RangePos CheckRange(TypeSourceInfo *TInfo);
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000043 RangePos CheckRange(Decl *D) {
44 if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
John McCalla93c9342009-12-07 02:54:59 +000045 if (ContainsLocation(DD->getTypeSourceInfo()))
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000046 return ContainsLoc;
John McCallba6a9bd2009-10-24 08:00:42 +000047 if (TypedefDecl *TD = dyn_cast<TypedefDecl>(D))
John McCalla93c9342009-12-07 02:54:59 +000048 if (ContainsLocation(TD->getTypeSourceInfo()))
John McCallba6a9bd2009-10-24 08:00:42 +000049 return ContainsLoc;
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000050
51 return CheckRange(D->getSourceRange());
52 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000053 RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000054 RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000055
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000056 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000057 bool isBeforeLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000058 return CheckRange(Node) == BeforeLoc;
59 }
60
61 template <typename T>
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +000062 bool isAfterLocation(T Node) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +000063 return CheckRange(Node) == AfterLoc;
64 }
65
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000066public:
67 LocResolverBase(ASTContext &ctx, SourceLocation loc)
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000068 : Ctx(ctx), Loc(loc) {}
Steve Narofff96b5242009-10-28 20:44:47 +000069
70 template <typename T>
71 bool ContainsLocation(T Node) {
72 return CheckRange(Node) == ContainsLoc;
73 }
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000074
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000075#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000076 /// \brief Debugging output.
77 void print(Decl *D);
78 /// \brief Debugging output.
79 void print(Stmt *Node);
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +000080#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000081};
82
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000083/// \brief Searches a statement for the ASTLocation that corresponds to a source
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000084/// location.
Benjamin Kramer85b45212009-11-28 19:45:26 +000085class StmtLocResolver : public LocResolverBase,
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000086 public StmtVisitor<StmtLocResolver,
87 ASTLocation > {
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +000088 Decl * const Parent;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +000089
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +000090public:
91 StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
92 : LocResolverBase(ctx, loc), Parent(parent) {}
93
John McCall5ab75172009-11-04 07:28:41 +000094 ASTLocation VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *Node);
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.
Benjamin Kramer85b45212009-11-28 19:45:26 +0000102class 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);
Ted Kremenek1d5fdf32009-11-18 02:02:52 +0000114 ASTLocation VisitObjCClassDecl(ObjCClassDecl *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()) {
John McCalla93c9342009-12-07 02:54:59 +0000145 TypeSourceInfo *TInfo = Node->getArgumentTypeInfo();
146 if (ContainsLocation(TInfo))
147 return ResolveInDeclarator(Parent, Node, TInfo);
John McCall5ab75172009-11-04 07:28:41 +0000148 } 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
John McCalla93c9342009-12-07 02:54:59 +0000248 if (ContainsLocation(D->getTypeSourceInfo()))
249 return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
Argyrios Kyrtzidis5a70ea62009-09-29 19:58:16 +0000250
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.
Douglas Gregorf2c87bd2010-01-15 19:40:17 +0000267 // If we find the 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");
John McCalla93c9342009-12-07 02:54:59 +0000299 if (ContainsLocation(D->getTypeSourceInfo()))
300 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000301
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
John McCalla93c9342009-12-07 02:54:59 +0000309 if (ContainsLocation(D->getTypeSourceInfo()))
310 return ResolveInDeclarator(D, /*Stmt=*/0, D->getTypeSourceInfo());
John McCallba6a9bd2009-10-24 08:00:42 +0000311
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
John McCalla93c9342009-12-07 02:54:59 +0000324 if (ContainsLocation(D->getTypeSourceInfo()))
325 return ResolveInDeclarator(D, 0, D->getTypeSourceInfo());
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000326
327 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000328}
329
Ted Kremenek1d5fdf32009-11-18 02:02:52 +0000330ASTLocation DeclLocResolver::VisitObjCClassDecl(ObjCClassDecl *D) {
331 assert(ContainsLocation(D) &&
332 "Should visit only after verifying that loc is in range");
333
334 for (ObjCClassDecl::iterator I = D->begin(), E = D->end() ; I != E; ++I) {
335 if (CheckRange(I->getLocation()) == ContainsLoc)
336 return ASTLocation(D, I->getInterface(), I->getLocation());
337 }
338 return ASTLocation(D);
339}
340
Argyrios Kyrtzidis0df13472009-07-18 00:33:52 +0000341ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
342 assert(ContainsLocation(D) &&
343 "Should visit only after verifying that loc is in range");
344
345 // First, search through the parameters of the method.
346 for (ObjCMethodDecl::param_iterator
347 I = D->param_begin(), E = D->param_end(); I != E; ++I) {
348 RangePos RP = CheckRange(*I);
349 if (RP == AfterLoc)
350 return ASTLocation(D);
351 if (RP == ContainsLoc)
352 return Visit(*I);
353 }
354
355 // We didn't find the location in the parameters and we didn't get passed it.
356
357 if (!D->getBody())
358 return ASTLocation(D);
359
360 // Second, search through the declarations that are part of the method.
361 // If we find he location there, we won't have to search through its body.
362
363 for (DeclContext::decl_iterator
364 I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
365 if (isa<ParmVarDecl>(*I))
366 continue; // We already searched through the parameters.
367
368 RangePos RP = CheckRange(*I);
369 if (RP == AfterLoc)
370 break;
371 if (RP == ContainsLoc)
372 return Visit(*I);
373 }
374
375 // We didn't find a declaration that corresponds to the source location.
376
377 // Finally, search through the body of the method.
378 Stmt *Body = D->getBody();
379 assert(Body && "Expected definition");
380 assert(!isBeforeLocation(Body) &&
381 "This method is supposed to contain the loc");
382 if (isAfterLocation(Body))
383 return ASTLocation(D);
384
385 // The body contains the location.
386 assert(ContainsLocation(Body));
387 return StmtLocResolver(Ctx, Loc, D).Visit(Body);
388}
389
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000390ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
Argyrios Kyrtzidisa6488a12009-07-10 03:41:26 +0000391 assert(ContainsLocation(D) &&
392 "Should visit only after verifying that loc is in range");
Argyrios Kyrtzidis7e4fe3b2009-07-18 00:33:40 +0000393 if (DeclContext *DC = dyn_cast<DeclContext>(D))
394 return VisitDeclContext(DC);
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000395 return ASTLocation(D);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000396}
397
John McCall54e14c42009-10-22 22:37:11 +0000398ASTLocation TypeLocResolver::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
399 // Continue the 'id' magic by making the builtin type (which cannot
400 // actually be spelled) map to the typedef.
401 BuiltinType *T = TL.getTypePtr();
402 if (T->getKind() == BuiltinType::ObjCId) {
403 TypedefDecl *D = Ctx.getObjCIdType()->getAs<TypedefType>()->getDecl();
404 return ASTLocation(ParentDecl, D, TL.getNameLoc());
405 }
406
407 // Same thing with 'Class'.
408 if (T->getKind() == BuiltinType::ObjCClass) {
409 TypedefDecl *D = Ctx.getObjCClassType()->getAs<TypedefType>()->getDecl();
410 return ASTLocation(ParentDecl, D, TL.getNameLoc());
411 }
412
413 return ASTLocation(ParentDecl, TL);
414}
415
John McCall51bd8032009-10-18 01:05:36 +0000416ASTLocation TypeLocResolver::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000417 assert(ContainsLocation(TL) &&
418 "Should visit only after verifying that loc is in range");
419 if (ContainsLocation(TL.getNameLoc()))
420 return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
421 return ASTLocation(ParentDecl, TL);
422}
423
John McCall51bd8032009-10-18 01:05:36 +0000424ASTLocation TypeLocResolver::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000425 assert(ContainsLocation(TL) &&
426 "Should visit only after verifying that loc is in range");
427
428 for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
429 ParmVarDecl *Parm = TL.getArg(i);
430 RangePos RP = CheckRange(Parm);
431 if (RP == AfterLoc)
432 break;
433 if (RP == ContainsLoc)
434 return DeclLocResolver(Ctx, Loc).Visit(Parm);
435 }
436
437 return ASTLocation(ParentDecl, TL);
438}
439
John McCall51bd8032009-10-18 01:05:36 +0000440ASTLocation TypeLocResolver::VisitArrayTypeLoc(ArrayTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000441 assert(ContainsLocation(TL) &&
442 "Should visit only after verifying that loc is in range");
443
444 Expr *E = TL.getSizeExpr();
445 if (E && ContainsLocation(E))
446 return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
447
448 return ASTLocation(ParentDecl, TL);
449}
450
John McCall51bd8032009-10-18 01:05:36 +0000451ASTLocation TypeLocResolver::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000452 assert(ContainsLocation(TL) &&
453 "Should visit only after verifying that loc is in range");
454 if (ContainsLocation(TL.getNameLoc()))
455 return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000456
457 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
458 SourceLocation L = TL.getProtocolLoc(i);
459 RangePos RP = CheckRange(L);
460 if (RP == AfterLoc)
461 break;
462 if (RP == ContainsLoc)
463 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
464 }
465
466 return ASTLocation(ParentDecl, TL);
467}
468
John McCall54e14c42009-10-22 22:37:11 +0000469ASTLocation TypeLocResolver::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
470 assert(ContainsLocation(TL) &&
471 "Should visit only after verifying that loc is in range");
472
473 if (TL.hasProtocolsAsWritten()) {
474 for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
475 SourceLocation L = TL.getProtocolLoc(i);
476 RangePos RP = CheckRange(L);
477 if (RP == AfterLoc)
478 break;
479 if (RP == ContainsLoc)
480 return ASTLocation(ParentDecl, TL.getProtocol(i), L);
481 }
482 }
483
484 return ASTLocation(ParentDecl, TL);
485}
486
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000487ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
488 assert(ContainsLocation(TL) &&
489 "Should visit only after verifying that loc is in range");
490 return ASTLocation(ParentDecl, TL);
491}
492
493ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
John McCalla93c9342009-12-07 02:54:59 +0000494 TypeSourceInfo *TInfo) {
495 assert(ContainsLocation(TInfo) &&
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000496 "Should visit only after verifying that loc is in range");
497
Douglas Gregor6490ae52009-11-17 06:14:37 +0000498 (void)TypeLocResolver(Ctx, Loc, D);
John McCalla93c9342009-12-07 02:54:59 +0000499 for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000500 if (ContainsLocation(TL))
501 return TypeLocResolver(Ctx, Loc, D).Visit(TL);
502
503 assert(0 && "Should have found the loc in a typeloc");
504 return ASTLocation(D, Stm);
505}
506
John McCalla93c9342009-12-07 02:54:59 +0000507LocResolverBase::RangePos LocResolverBase::CheckRange(TypeSourceInfo *TInfo) {
508 if (!TInfo)
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000509 return BeforeLoc; // Keep looking.
510
John McCalla93c9342009-12-07 02:54:59 +0000511 for (TypeLoc TL = TInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
Argyrios Kyrtzidisef6cd672009-09-29 19:45:41 +0000512 if (ContainsLocation(TL))
513 return ContainsLoc;
514
515 return BeforeLoc; // Keep looking.
516}
517
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000518LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000519 if (!Range.isValid())
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000520 return BeforeLoc; // Keep looking.
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000521
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000522 // Update the end source range to cover the full length of the token
523 // positioned at the end of the source range.
524 //
525 // e.g.,
526 // int foo
527 // ^ ^
528 //
529 // will be updated to
530 // int foo
531 // ^ ^
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000532 unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
533 Ctx.getSourceManager(),
534 Ctx.getLangOptions());
535 Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000536
Mike Stump1eb44332009-09-09 15:08:12 +0000537 SourceManager &SourceMgr = Ctx.getSourceManager();
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000538 if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
539 return BeforeLoc;
Mike Stump1eb44332009-09-09 15:08:12 +0000540
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000541 if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
542 return AfterLoc;
543
544 return ContainsLoc;
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000545}
546
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000547#ifndef NDEBUG
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000548void LocResolverBase::print(Decl *D) {
549 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000550 OS << "#### DECL " << D->getDeclKindName() << " ####\n";
Argyrios Kyrtzidisf1d60ea2009-06-30 02:35:04 +0000551 D->print(OS);
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000552 OS << " <";
553 D->getLocStart().print(OS, Ctx.getSourceManager());
554 OS << " > - <";
555 D->getLocEnd().print(OS, Ctx.getSourceManager());
556 OS << ">\n\n";
557 OS.flush();
558}
559
560void LocResolverBase::print(Stmt *Node) {
561 llvm::raw_ostream &OS = llvm::outs();
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000562 OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
Chris Lattnere4f21422009-06-30 01:26:17 +0000563 Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000564 OS << " <";
565 Node->getLocStart().print(OS, Ctx.getSourceManager());
566 OS << " > - <";
567 Node->getLocEnd().print(OS, Ctx.getSourceManager());
568 OS << ">\n\n";
569 OS.flush();
570}
Argyrios Kyrtzidisada45422009-07-17 01:20:03 +0000571#endif
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000572
573
574/// \brief Returns the AST node that a source location points to.
575///
Steve Naroff6a6de8b2009-10-21 13:56:23 +0000576ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
Steve Narofff96b5242009-10-28 20:44:47 +0000577 ASTLocation *LastLoc) {
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000578 if (Loc.isInvalid())
Argyrios Kyrtzidis874012b2009-07-06 21:34:20 +0000579 return ASTLocation();
Mike Stump1eb44332009-09-09 15:08:12 +0000580
Steve Narofff96b5242009-10-28 20:44:47 +0000581 if (LastLoc && LastLoc->isValid()) {
582 DeclContext *DC = 0;
583
584 if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
585 DC = Dcl->getDeclContext();
586 } else if (LastLoc->isStmt()) {
587 Decl *Parent = LastLoc->getParentDecl();
588 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
589 DC = FD;
590 else {
591 // This is needed to handle statements within an initializer.
592 // Example:
593 // void func() { long double fabsf = __builtin_fabsl(__x); }
594 // In this case, the 'parent' of __builtin_fabsl is fabsf.
595 DC = Parent->getDeclContext();
596 }
597 } else { // We have 'N_NamedRef' or 'N_Type'
598 DC = LastLoc->getParentDecl()->getDeclContext();
599 }
600 assert(DC && "Missing DeclContext");
601
602 FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
603 DeclLocResolver DLocResolver(Ctx, Loc);
604
605 if (FD && FD->isThisDeclarationADefinition() &&
606 DLocResolver.ContainsLocation(FD)) {
607 return DLocResolver.VisitFunctionDecl(FD);
608 }
609 // Fall through and try the slow path...
610 // FIXME: Optimize more cases.
611 }
Argyrios Kyrtzidisbd2ab6e2009-07-07 00:53:31 +0000612 return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
Argyrios Kyrtzidis53d4c142009-06-25 18:22:41 +0000613}