CINDEX_LINKAGE CXCursor clang_getCursor(CXTranslationUnit, const char *source_name,
unsigned line, unsigned column);
-/**
- Usage: clang_getCursorWithHint() provides the same functionality as
- clang_getCursor() except that it takes an option 'hint' argument.
- The 'hint' is a temporary CXLookupHint object (whose lifetime is managed by
- the caller) that should be initialized with clang_initCXLookupHint().
-
- FIXME: Add a better comment once getCursorWithHint() has more functionality.
- */
-typedef CXCursor CXLookupHint;
-CINDEX_LINKAGE CXCursor clang_getCursorWithHint(CXTranslationUnit, const char *source_name,
- unsigned line, unsigned column,
- CXLookupHint *hint);
-
-CINDEX_LINKAGE void clang_initCXLookupHint(CXLookupHint *hint);
-
CINDEX_LINKAGE enum CXCursorKind clang_getCursorKind(CXCursor);
CINDEX_LINKAGE unsigned clang_isDeclaration(enum CXCursorKind);
CINDEX_LINKAGE unsigned clang_isReference(enum CXCursorKind);
#include "llvm/ADT/OwningPtr.h"
#include "clang/Frontend/TextDiagnosticBuffer.h"
#include "clang/Basic/FileManager.h"
+#include "clang/Index/ASTLocation.h"
#include <string>
namespace clang {
class ASTContext;
class Decl;
+using namespace idx;
+
/// \brief Utility class for loading a ASTContext from a PCH file.
///
class ASTUnit {
// FIXME: This is temporary; eventually, CIndex will always do this.
bool OnlyLocalDecls;
+ // Critical optimization when using clang_getCursor().
+ ASTLocation LastLoc;
+
ASTUnit(const ASTUnit&); // DO NOT IMPLEMENT
ASTUnit &operator=(const ASTUnit &); // DO NOT IMPLEMENT
bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ void setLastASTLocation(ASTLocation ALoc) { LastLoc = ALoc; }
+ ASTLocation getLastASTLocation() const { return LastLoc; }
+
/// \brief Create a ASTUnit from a PCH file.
///
/// \param Filename - The PCH file to load.
namespace clang {
class ASTContext;
class SourceLocation;
- class Decl;
namespace idx {
class ASTLocation;
/// \returns the resolved ASTLocation or an invalid ASTLocation if the source
/// location could not be resolved.
ASTLocation ResolveLocationInAST(ASTContext &Ctx, SourceLocation Loc,
- Decl *RelativeToDecl = 0);
+ ASTLocation *LastLoc = 0);
} // end namespace idx
return CheckRange(Node) == BeforeLoc;
}
- template <typename T>
- bool ContainsLocation(T Node) {
- return CheckRange(Node) == ContainsLoc;
- }
-
template <typename T>
bool isAfterLocation(T Node) {
return CheckRange(Node) == AfterLoc;
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.
/// \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());
}
if (ND->getPCHLevel() > MaxPCHLevel)
return;
+ // Filter any implicit declarations (since the source info will be bogus).
+ if (ND->isImplicit())
+ return;
+
CXCursor C = { CK, ND, 0 };
Callback(TUnit, C, CData);
}
//
// CXCursor Operations.
//
-void clang_initCXLookupHint(CXLookupHint *hint) {
- memset(hint, 0, sizeof(*hint));
-}
-
CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
- unsigned line, unsigned column) {
- return clang_getCursorWithHint(CTUnit, source_name, line, column, NULL);
-}
-
-CXCursor clang_getCursorWithHint(CXTranslationUnit CTUnit,
- const char *source_name,
- unsigned line, unsigned column,
- CXLookupHint *hint)
+ unsigned line, unsigned column)
{
assert(CTUnit && "Passed null CXTranslationUnit");
ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- // FIXME: Make this better.
- CXDecl RelativeToDecl = hint ? hint->decl : NULL;
-
FileManager &FMgr = CXXUnit->getFileManager();
const FileEntry *File = FMgr.getFile(source_name,
source_name+strlen(source_name));
SourceLocation SLoc =
CXXUnit->getSourceManager().getLocation(File, line, column);
- ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
- static_cast<NamedDecl *>(RelativeToDecl));
-
+ ASTLocation LastLoc = CXXUnit->getLastASTLocation();
+
+ ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
+ &LastLoc);
+ if (ALoc.isValid())
+ CXXUnit->setLastASTLocation(ALoc);
+
Decl *Dcl = ALoc.getParentDecl();
if (ALoc.isNamedRef())
Dcl = ALoc.AsNamedRef().ND;
_clang_getCursorKind
_clang_getCursorLine
_clang_getCursorSource
-_clang_getCursorWithHint
_clang_getDeclarationName
_clang_getDeclSpelling
_clang_getDeclLine
_clang_createTranslationUnit
_clang_createTranslationUnitFromSourceFile
_clang_disposeTranslationUnit
-_clang_initCXLookupHint
_clang_isDeclaration
_clang_isReference
_clang_isDefinition
CXCursor Ref;
while (startBuf < endBuf) {
- CXLookupHint hint;
if (*startBuf == '\n') {
startBuf++;
curLine++;
} else if (*startBuf != '\t')
curColumn++;
- clang_initCXLookupHint(&hint);
- hint.decl = Cursor.decl;
-
- Ref = clang_getCursorWithHint(Unit, clang_getCursorSource(Cursor),
- curLine, curColumn, &hint);
+ Ref = clang_getCursor(Unit, clang_getCursorSource(Cursor),
+ curLine, curColumn);
if (Ref.kind == CXCursor_NoDeclFound) {
/* Nothing found here; that's fine. */
} else if (Ref.kind != CXCursor_FunctionDecl) {