2009-06-26 02:22:41 +08:00
|
|
|
//===--- ResolveLocation.cpp - Source location resolver ---------*- C++ -*-===//
|
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This defines the ResolveLocationInAST function, which resolves a
|
2009-07-07 05:35:02 +08:00
|
|
|
// source location into a ASTLocation.
|
2009-06-26 02:22:41 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2009-07-07 05:35:02 +08:00
|
|
|
#include "clang/Index/Utils.h"
|
2009-07-07 05:34:47 +08:00
|
|
|
#include "clang/Index/ASTLocation.h"
|
2009-09-30 05:27:32 +08:00
|
|
|
#include "clang/AST/TypeLocVisitor.h"
|
2009-06-26 02:22:41 +08:00
|
|
|
#include "clang/AST/DeclVisitor.h"
|
|
|
|
#include "clang/AST/StmtVisitor.h"
|
|
|
|
#include "clang/Lex/Lexer.h"
|
|
|
|
#include "clang/Basic/SourceManager.h"
|
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
using namespace clang;
|
2009-07-07 05:34:47 +08:00
|
|
|
using namespace idx;
|
2009-06-26 02:22:41 +08:00
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
/// \brief Base for the LocResolver classes. Mostly does source range checking.
|
|
|
|
class VISIBILITY_HIDDEN LocResolverBase {
|
|
|
|
protected:
|
|
|
|
ASTContext &Ctx;
|
|
|
|
SourceLocation Loc;
|
2009-09-30 03:45:41 +08:00
|
|
|
|
|
|
|
ASTLocation ResolveInDeclarator(Decl *D, Stmt *Stm, DeclaratorInfo *DInfo);
|
2009-07-07 08:53:31 +08:00
|
|
|
|
|
|
|
enum RangePos {
|
|
|
|
BeforeLoc,
|
|
|
|
ContainsLoc,
|
|
|
|
AfterLoc
|
|
|
|
};
|
|
|
|
|
|
|
|
RangePos CheckRange(SourceRange Range);
|
2009-09-30 03:45:41 +08:00
|
|
|
RangePos CheckRange(DeclaratorInfo *DInfo);
|
|
|
|
RangePos CheckRange(Decl *D) {
|
|
|
|
if (DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D))
|
|
|
|
if (ContainsLocation(DD->getDeclaratorInfo()))
|
|
|
|
return ContainsLoc;
|
|
|
|
|
|
|
|
return CheckRange(D->getSourceRange());
|
|
|
|
}
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos CheckRange(Stmt *Node) { return CheckRange(Node->getSourceRange()); }
|
2009-09-30 03:45:41 +08:00
|
|
|
RangePos CheckRange(TypeLoc TL) { return CheckRange(TL.getSourceRange()); }
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-07-10 11:41:26 +08:00
|
|
|
template <typename T>
|
2009-09-30 03:45:41 +08:00
|
|
|
bool isBeforeLocation(T Node) {
|
2009-07-10 11:41:26 +08:00
|
|
|
return CheckRange(Node) == BeforeLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2009-09-30 03:45:41 +08:00
|
|
|
bool ContainsLocation(T Node) {
|
2009-07-10 11:41:26 +08:00
|
|
|
return CheckRange(Node) == ContainsLoc;
|
|
|
|
}
|
|
|
|
|
|
|
|
template <typename T>
|
2009-09-30 03:45:41 +08:00
|
|
|
bool isAfterLocation(T Node) {
|
2009-07-10 11:41:26 +08:00
|
|
|
return CheckRange(Node) == AfterLoc;
|
|
|
|
}
|
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
public:
|
|
|
|
LocResolverBase(ASTContext &ctx, SourceLocation loc)
|
2009-07-07 08:53:31 +08:00
|
|
|
: Ctx(ctx), Loc(loc) {}
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-07-17 09:20:03 +08:00
|
|
|
#ifndef NDEBUG
|
2009-06-26 02:22:41 +08:00
|
|
|
/// \brief Debugging output.
|
|
|
|
void print(Decl *D);
|
|
|
|
/// \brief Debugging output.
|
|
|
|
void print(Stmt *Node);
|
2009-07-17 09:20:03 +08:00
|
|
|
#endif
|
2009-06-26 02:22:41 +08:00
|
|
|
};
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
/// \brief Searches a statement for the ASTLocation that corresponds to a source
|
2009-06-26 02:22:41 +08:00
|
|
|
/// location.
|
|
|
|
class VISIBILITY_HIDDEN StmtLocResolver : public LocResolverBase,
|
2009-07-07 08:53:31 +08:00
|
|
|
public StmtVisitor<StmtLocResolver,
|
|
|
|
ASTLocation > {
|
2009-07-18 08:33:52 +08:00
|
|
|
Decl * const Parent;
|
2009-07-07 08:53:31 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
public:
|
2009-07-07 08:53:31 +08:00
|
|
|
StmtLocResolver(ASTContext &ctx, SourceLocation loc, Decl *parent)
|
|
|
|
: LocResolverBase(ctx, loc), Parent(parent) {}
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-08-01 03:02:11 +08:00
|
|
|
ASTLocation VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node);
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation VisitDeclStmt(DeclStmt *Node);
|
|
|
|
ASTLocation VisitStmt(Stmt *Node);
|
2009-06-26 02:22:41 +08:00
|
|
|
};
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
/// \brief Searches a declaration for the ASTLocation that corresponds to a
|
|
|
|
/// source location.
|
2009-06-26 02:22:41 +08:00
|
|
|
class VISIBILITY_HIDDEN DeclLocResolver : public LocResolverBase,
|
2009-07-07 08:53:31 +08:00
|
|
|
public DeclVisitor<DeclLocResolver,
|
|
|
|
ASTLocation > {
|
2009-06-26 02:22:41 +08:00
|
|
|
public:
|
|
|
|
DeclLocResolver(ASTContext &ctx, SourceLocation loc)
|
|
|
|
: LocResolverBase(ctx, loc) {}
|
|
|
|
|
2009-07-14 11:18:17 +08:00
|
|
|
ASTLocation VisitDeclContext(DeclContext *DC);
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation VisitTranslationUnitDecl(TranslationUnitDecl *TU);
|
2009-09-30 03:45:41 +08:00
|
|
|
ASTLocation VisitDeclaratorDecl(DeclaratorDecl *D);
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation VisitVarDecl(VarDecl *D);
|
|
|
|
ASTLocation VisitFunctionDecl(FunctionDecl *D);
|
2009-07-18 08:33:52 +08:00
|
|
|
ASTLocation VisitObjCMethodDecl(ObjCMethodDecl *D);
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation VisitDecl(Decl *D);
|
2009-06-26 02:22:41 +08:00
|
|
|
};
|
|
|
|
|
2009-09-30 03:45:41 +08:00
|
|
|
class TypeLocResolver : public LocResolverBase,
|
|
|
|
public TypeLocVisitor<TypeLocResolver, ASTLocation> {
|
|
|
|
Decl * const ParentDecl;
|
|
|
|
|
|
|
|
public:
|
|
|
|
TypeLocResolver(ASTContext &ctx, SourceLocation loc, Decl *pd)
|
|
|
|
: LocResolverBase(ctx, loc), ParentDecl(pd) { }
|
|
|
|
|
|
|
|
ASTLocation VisitTypedefLoc(TypedefLoc TL);
|
|
|
|
ASTLocation VisitFunctionLoc(FunctionLoc TL);
|
|
|
|
ASTLocation VisitArrayLoc(ArrayLoc TL);
|
|
|
|
ASTLocation VisitObjCInterfaceLoc(ObjCInterfaceLoc TL);
|
|
|
|
ASTLocation VisitObjCProtocolListLoc(ObjCProtocolListLoc TL);
|
|
|
|
ASTLocation VisitTypeLoc(TypeLoc TL);
|
|
|
|
};
|
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
} // anonymous namespace
|
|
|
|
|
2009-08-01 03:02:11 +08:00
|
|
|
ASTLocation
|
|
|
|
StmtLocResolver::VisitCXXOperatorCallExpr(CXXOperatorCallExpr *Node) {
|
|
|
|
assert(ContainsLocation(Node) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
if (Node->getNumArgs() == 1)
|
|
|
|
// Unary operator. Let normal child traversal handle it.
|
|
|
|
return VisitCallExpr(Node);
|
|
|
|
|
|
|
|
assert(Node->getNumArgs() == 2 &&
|
|
|
|
"Wrong args for the C++ operator call expr ?");
|
|
|
|
|
|
|
|
llvm::SmallVector<Expr *, 3> Nodes;
|
|
|
|
// Binary operator. Check in order of 1-left arg, 2-callee, 3-right arg.
|
|
|
|
Nodes.push_back(Node->getArg(0));
|
|
|
|
Nodes.push_back(Node->getCallee());
|
|
|
|
Nodes.push_back(Node->getArg(1));
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-08-01 03:02:11 +08:00
|
|
|
for (unsigned i = 0, e = Nodes.size(); i != e; ++i) {
|
|
|
|
RangePos RP = CheckRange(Nodes[i]);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(Nodes[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ASTLocation(Parent, Node);
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation StmtLocResolver::VisitDeclStmt(DeclStmt *Node) {
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(Node) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
// Search all declarations of this DeclStmt.
|
2009-06-26 02:22:41 +08:00
|
|
|
for (DeclStmt::decl_iterator
|
|
|
|
I = Node->decl_begin(), E = Node->decl_end(); I != E; ++I) {
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return DeclLocResolver(Ctx, Loc).Visit(*I);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
2009-07-07 08:53:31 +08:00
|
|
|
|
|
|
|
return ASTLocation(Parent, Node);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation StmtLocResolver::VisitStmt(Stmt *Node) {
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(Node) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
2009-07-07 08:53:31 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// Search the child statements.
|
|
|
|
for (Stmt::child_iterator
|
|
|
|
I = Node->child_begin(), E = Node->child_end(); I != E; ++I) {
|
2009-08-01 03:02:11 +08:00
|
|
|
if (*I == NULL)
|
|
|
|
continue;
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
2009-07-07 08:53:31 +08:00
|
|
|
|
|
|
|
return ASTLocation(Parent, Node);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-07-14 11:18:17 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitDeclContext(DeclContext *DC) {
|
2009-06-26 02:22:41 +08:00
|
|
|
for (DeclContext::decl_iterator
|
2009-06-30 10:36:12 +08:00
|
|
|
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-07-14 11:18:17 +08:00
|
|
|
return ASTLocation(cast<Decl>(DC));
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation DeclLocResolver::VisitTranslationUnitDecl(TranslationUnitDecl *TU) {
|
|
|
|
ASTLocation ASTLoc = VisitDeclContext(TU);
|
2009-09-30 03:44:27 +08:00
|
|
|
if (ASTLoc.getParentDecl() == TU)
|
2009-07-14 11:18:17 +08:00
|
|
|
return ASTLocation();
|
|
|
|
return ASTLoc;
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitFunctionDecl(FunctionDecl *D) {
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(D) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-09-30 03:58:16 +08:00
|
|
|
if (ContainsLocation(D->getDeclaratorInfo()))
|
|
|
|
return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
|
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// First, search through the parameters of the function.
|
|
|
|
for (FunctionDecl::param_iterator
|
|
|
|
I = D->param_begin(), E = D->param_end(); I != E; ++I) {
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
return ASTLocation(D);
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
// We didn't find the location in the parameters and we didn't get passed it.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-06 06:21:17 +08:00
|
|
|
if (!D->isThisDeclarationADefinition())
|
2009-07-07 08:53:31 +08:00
|
|
|
return ASTLocation(D);
|
2009-07-06 06:21:17 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// Second, search through the declarations that are part of the function.
|
|
|
|
// If we find he location there, we won't have to search through its body.
|
2009-07-06 06:21:46 +08:00
|
|
|
|
|
|
|
for (DeclContext::decl_iterator
|
|
|
|
I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
|
|
|
|
if (isa<ParmVarDecl>(*I))
|
|
|
|
continue; // We already searched through the parameters.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
2009-07-06 06:21:46 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// We didn't find a declaration that corresponds to the source location.
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// Finally, search through the body of the function.
|
2009-07-07 08:53:31 +08:00
|
|
|
Stmt *Body = D->getBody();
|
|
|
|
assert(Body && "Expected definition");
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(!isBeforeLocation(Body) &&
|
|
|
|
"This function is supposed to contain the loc");
|
|
|
|
if (isAfterLocation(Body))
|
2009-07-07 08:53:31 +08:00
|
|
|
return ASTLocation(D);
|
|
|
|
|
|
|
|
// The body contains the location.
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(Body));
|
2009-07-07 08:53:31 +08:00
|
|
|
return StmtLocResolver(Ctx, Loc, D).Visit(Body);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-09-30 03:45:41 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitDeclaratorDecl(DeclaratorDecl *D) {
|
|
|
|
assert(ContainsLocation(D) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
if (ContainsLocation(D->getDeclaratorInfo()))
|
|
|
|
return ResolveInDeclarator(D, /*Stmt=*/0, D->getDeclaratorInfo());
|
|
|
|
|
|
|
|
return ASTLocation(D);
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitVarDecl(VarDecl *D) {
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(D) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
2009-07-07 08:53:31 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
// Check whether the location points to the init expression.
|
2009-07-07 08:53:31 +08:00
|
|
|
Expr *Init = D->getInit();
|
2009-07-10 11:41:26 +08:00
|
|
|
if (Init && ContainsLocation(Init))
|
2009-07-07 08:53:31 +08:00
|
|
|
return StmtLocResolver(Ctx, Loc, D).Visit(Init);
|
2009-09-30 03:45:41 +08:00
|
|
|
|
|
|
|
if (ContainsLocation(D->getDeclaratorInfo()))
|
|
|
|
return ResolveInDeclarator(D, 0, D->getDeclaratorInfo());
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
return ASTLocation(D);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-07-18 08:33:52 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitObjCMethodDecl(ObjCMethodDecl *D) {
|
|
|
|
assert(ContainsLocation(D) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
// First, search through the parameters of the method.
|
|
|
|
for (ObjCMethodDecl::param_iterator
|
|
|
|
I = D->param_begin(), E = D->param_end(); I != E; ++I) {
|
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
return ASTLocation(D);
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We didn't find the location in the parameters and we didn't get passed it.
|
|
|
|
|
|
|
|
if (!D->getBody())
|
|
|
|
return ASTLocation(D);
|
|
|
|
|
|
|
|
// Second, search through the declarations that are part of the method.
|
|
|
|
// If we find he location there, we won't have to search through its body.
|
|
|
|
|
|
|
|
for (DeclContext::decl_iterator
|
|
|
|
I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
|
|
|
|
if (isa<ParmVarDecl>(*I))
|
|
|
|
continue; // We already searched through the parameters.
|
|
|
|
|
|
|
|
RangePos RP = CheckRange(*I);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return Visit(*I);
|
|
|
|
}
|
|
|
|
|
|
|
|
// We didn't find a declaration that corresponds to the source location.
|
|
|
|
|
|
|
|
// Finally, search through the body of the method.
|
|
|
|
Stmt *Body = D->getBody();
|
|
|
|
assert(Body && "Expected definition");
|
|
|
|
assert(!isBeforeLocation(Body) &&
|
|
|
|
"This method is supposed to contain the loc");
|
|
|
|
if (isAfterLocation(Body))
|
|
|
|
return ASTLocation(D);
|
|
|
|
|
|
|
|
// The body contains the location.
|
|
|
|
assert(ContainsLocation(Body));
|
|
|
|
return StmtLocResolver(Ctx, Loc, D).Visit(Body);
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
ASTLocation DeclLocResolver::VisitDecl(Decl *D) {
|
2009-07-10 11:41:26 +08:00
|
|
|
assert(ContainsLocation(D) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
2009-07-18 08:33:40 +08:00
|
|
|
if (DeclContext *DC = dyn_cast<DeclContext>(D))
|
|
|
|
return VisitDeclContext(DC);
|
2009-07-07 08:53:31 +08:00
|
|
|
return ASTLocation(D);
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-09-30 03:45:41 +08:00
|
|
|
ASTLocation TypeLocResolver::VisitTypedefLoc(TypedefLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
if (ContainsLocation(TL.getNameLoc()))
|
|
|
|
return ASTLocation(ParentDecl, TL.getTypedefDecl(), TL.getNameLoc());
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation TypeLocResolver::VisitFunctionLoc(FunctionLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
for (unsigned i = 0; i != TL.getNumArgs(); ++i) {
|
|
|
|
ParmVarDecl *Parm = TL.getArg(i);
|
|
|
|
RangePos RP = CheckRange(Parm);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return DeclLocResolver(Ctx, Loc).Visit(Parm);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation TypeLocResolver::VisitArrayLoc(ArrayLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
Expr *E = TL.getSizeExpr();
|
|
|
|
if (E && ContainsLocation(E))
|
|
|
|
return StmtLocResolver(Ctx, Loc, ParentDecl).Visit(E);
|
|
|
|
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation TypeLocResolver::VisitObjCInterfaceLoc(ObjCInterfaceLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
if (ContainsLocation(TL.getNameLoc()))
|
|
|
|
return ASTLocation(ParentDecl, TL.getIFaceDecl(), TL.getNameLoc());
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation TypeLocResolver::VisitObjCProtocolListLoc(ObjCProtocolListLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
for (unsigned i = 0; i != TL.getNumProtocols(); ++i) {
|
|
|
|
SourceLocation L = TL.getProtocolLoc(i);
|
|
|
|
RangePos RP = CheckRange(L);
|
|
|
|
if (RP == AfterLoc)
|
|
|
|
break;
|
|
|
|
if (RP == ContainsLoc)
|
|
|
|
return ASTLocation(ParentDecl, TL.getProtocol(i), L);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation TypeLocResolver::VisitTypeLoc(TypeLoc TL) {
|
|
|
|
assert(ContainsLocation(TL) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
return ASTLocation(ParentDecl, TL);
|
|
|
|
}
|
|
|
|
|
|
|
|
ASTLocation LocResolverBase::ResolveInDeclarator(Decl *D, Stmt *Stm,
|
|
|
|
DeclaratorInfo *DInfo) {
|
|
|
|
assert(ContainsLocation(DInfo) &&
|
|
|
|
"Should visit only after verifying that loc is in range");
|
|
|
|
|
|
|
|
TypeLocResolver(Ctx, Loc, D);
|
|
|
|
for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
|
|
|
|
if (ContainsLocation(TL))
|
|
|
|
return TypeLocResolver(Ctx, Loc, D).Visit(TL);
|
|
|
|
|
|
|
|
assert(0 && "Should have found the loc in a typeloc");
|
|
|
|
return ASTLocation(D, Stm);
|
|
|
|
}
|
|
|
|
|
|
|
|
LocResolverBase::RangePos LocResolverBase::CheckRange(DeclaratorInfo *DInfo) {
|
|
|
|
if (!DInfo)
|
|
|
|
return BeforeLoc; // Keep looking.
|
|
|
|
|
|
|
|
for (TypeLoc TL = DInfo->getTypeLoc(); TL; TL = TL.getNextTypeLoc())
|
|
|
|
if (ContainsLocation(TL))
|
|
|
|
return ContainsLoc;
|
|
|
|
|
|
|
|
return BeforeLoc; // Keep looking.
|
|
|
|
}
|
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
LocResolverBase::RangePos LocResolverBase::CheckRange(SourceRange Range) {
|
2009-06-26 02:22:41 +08:00
|
|
|
if (!Range.isValid())
|
2009-07-07 08:53:31 +08:00
|
|
|
return BeforeLoc; // Keep looking.
|
|
|
|
|
|
|
|
// Update the end source range to cover the full length of the token
|
|
|
|
// positioned at the end of the source range.
|
|
|
|
//
|
|
|
|
// e.g.,
|
|
|
|
// int foo
|
|
|
|
// ^ ^
|
|
|
|
//
|
|
|
|
// will be updated to
|
|
|
|
// int foo
|
|
|
|
// ^ ^
|
|
|
|
unsigned TokSize = Lexer::MeasureTokenLength(Range.getEnd(),
|
|
|
|
Ctx.getSourceManager(),
|
|
|
|
Ctx.getLangOptions());
|
|
|
|
Range.setEnd(Range.getEnd().getFileLocWithOffset(TokSize-1));
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-09-09 23:08:12 +08:00
|
|
|
SourceManager &SourceMgr = Ctx.getSourceManager();
|
2009-06-26 02:22:41 +08:00
|
|
|
if (SourceMgr.isBeforeInTranslationUnit(Range.getEnd(), Loc))
|
2009-07-07 08:53:31 +08:00
|
|
|
return BeforeLoc;
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-06-26 02:22:41 +08:00
|
|
|
if (SourceMgr.isBeforeInTranslationUnit(Loc, Range.getBegin()))
|
2009-07-07 08:53:31 +08:00
|
|
|
return AfterLoc;
|
2009-06-26 02:22:41 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
return ContainsLoc;
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|
|
|
|
|
2009-07-17 09:20:03 +08:00
|
|
|
#ifndef NDEBUG
|
2009-06-26 02:22:41 +08:00
|
|
|
void LocResolverBase::print(Decl *D) {
|
|
|
|
llvm::raw_ostream &OS = llvm::outs();
|
2009-07-17 09:20:03 +08:00
|
|
|
OS << "#### DECL " << D->getDeclKindName() << " ####\n";
|
2009-06-30 10:35:04 +08:00
|
|
|
D->print(OS);
|
2009-06-26 02:22:41 +08:00
|
|
|
OS << " <";
|
|
|
|
D->getLocStart().print(OS, Ctx.getSourceManager());
|
|
|
|
OS << " > - <";
|
|
|
|
D->getLocEnd().print(OS, Ctx.getSourceManager());
|
|
|
|
OS << ">\n\n";
|
|
|
|
OS.flush();
|
|
|
|
}
|
|
|
|
|
|
|
|
void LocResolverBase::print(Stmt *Node) {
|
|
|
|
llvm::raw_ostream &OS = llvm::outs();
|
2009-07-17 09:20:03 +08:00
|
|
|
OS << "#### STMT " << Node->getStmtClassName() << " ####\n";
|
2009-06-30 09:26:17 +08:00
|
|
|
Node->printPretty(OS, Ctx, 0, PrintingPolicy(Ctx.getLangOptions()));
|
2009-06-26 02:22:41 +08:00
|
|
|
OS << " <";
|
|
|
|
Node->getLocStart().print(OS, Ctx.getSourceManager());
|
|
|
|
OS << " > - <";
|
|
|
|
Node->getLocEnd().print(OS, Ctx.getSourceManager());
|
|
|
|
OS << ">\n\n";
|
|
|
|
OS.flush();
|
|
|
|
}
|
2009-07-17 09:20:03 +08:00
|
|
|
#endif
|
2009-06-26 02:22:41 +08:00
|
|
|
|
|
|
|
|
|
|
|
/// \brief Returns the AST node that a source location points to.
|
|
|
|
///
|
2009-07-07 05:35:02 +08:00
|
|
|
ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc) {
|
2009-06-26 02:22:41 +08:00
|
|
|
if (Loc.isInvalid())
|
2009-07-07 05:34:20 +08:00
|
|
|
return ASTLocation();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-07-07 08:53:31 +08:00
|
|
|
return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
|
2009-06-26 02:22:41 +08:00
|
|
|
}
|