aboutsummaryrefslogtreecommitdiff
path: root/lib/Index/ResolveLocation.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Index/ResolveLocation.cpp')
-rw-r--r--lib/Index/ResolveLocation.cpp45
1 files changed, 37 insertions, 8 deletions
diff --git a/lib/Index/ResolveLocation.cpp b/lib/Index/ResolveLocation.cpp
index 4e992f752b..ec8c1dcb38 100644
--- a/lib/Index/ResolveLocation.cpp
+++ b/lib/Index/ResolveLocation.cpp
@@ -60,11 +60,6 @@ protected:
}
template <typename T>
- bool ContainsLocation(T Node) {
- return CheckRange(Node) == ContainsLoc;
- }
-
- template <typename T>
bool isAfterLocation(T Node) {
return CheckRange(Node) == AfterLoc;
}
@@ -72,6 +67,11 @@ protected:
public:
LocResolverBase(ASTContext &ctx, SourceLocation loc)
: Ctx(ctx), Loc(loc) {}
+
+ template <typename T>
+ bool ContainsLocation(T Node) {
+ return CheckRange(Node) == ContainsLoc;
+ }
#ifndef NDEBUG
/// \brief Debugging output.
@@ -543,11 +543,40 @@ void LocResolverBase::print(Stmt *Node) {
/// \brief Returns the AST node that a source location points to.
///
ASTLocation idx::ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl) {
+ ASTLocation *LastLoc) {
if (Loc.isInvalid())
return ASTLocation();
- if (RelativeToDecl)
- return DeclLocResolver(Ctx, Loc).Visit(RelativeToDecl);
+ if (LastLoc && LastLoc->isValid()) {
+ DeclContext *DC = 0;
+
+ if (Decl *Dcl = LastLoc->dyn_AsDecl()) {
+ DC = Dcl->getDeclContext();
+ } else if (LastLoc->isStmt()) {
+ Decl *Parent = LastLoc->getParentDecl();
+ if (FunctionDecl *FD = dyn_cast<FunctionDecl>(Parent))
+ DC = FD;
+ else {
+ // This is needed to handle statements within an initializer.
+ // Example:
+ // void func() { long double fabsf = __builtin_fabsl(__x); }
+ // In this case, the 'parent' of __builtin_fabsl is fabsf.
+ DC = Parent->getDeclContext();
+ }
+ } else { // We have 'N_NamedRef' or 'N_Type'
+ DC = LastLoc->getParentDecl()->getDeclContext();
+ }
+ assert(DC && "Missing DeclContext");
+
+ FunctionDecl *FD = dyn_cast<FunctionDecl>(DC);
+ DeclLocResolver DLocResolver(Ctx, Loc);
+
+ if (FD && FD->isThisDeclarationADefinition() &&
+ DLocResolver.ContainsLocation(FD)) {
+ return DLocResolver.VisitFunctionDecl(FD);
+ }
+ // Fall through and try the slow path...
+ // FIXME: Optimize more cases.
+ }
return DeclLocResolver(Ctx, Loc).Visit(Ctx.getTranslationUnitDecl());
}