summaryrefslogtreecommitdiffstats
path: root/tools/CIndex
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-01-23 11:10:26 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-01-23 11:10:26 +0000
commit2fce988e86bc01829142e4362d4eff1af0925147 (patch)
treec69d3f4f13d508570bb5257a6aea735f88bdf09c /tools/CIndex
parenta3fa5c7f1b5e2ba4d6ec033dc0e2376326b05824 (diff)
downloadFreeBSD-src-2fce988e86bc01829142e4362d4eff1af0925147.zip
FreeBSD-src-2fce988e86bc01829142e4362d4eff1af0925147.tar.gz
Update clang to r94309.
Diffstat (limited to 'tools/CIndex')
-rw-r--r--tools/CIndex/CIndex.cpp1920
-rw-r--r--tools/CIndex/CIndex.exports39
-rw-r--r--tools/CIndex/CIndexCodeCompletion.cpp31
-rw-r--r--tools/CIndex/CIndexUSRs.cpp134
-rw-r--r--tools/CIndex/CIndexer.cpp37
-rw-r--r--tools/CIndex/CIndexer.h30
-rw-r--r--tools/CIndex/CMakeLists.txt4
-rw-r--r--tools/CIndex/CXCursor.cpp305
-rw-r--r--tools/CIndex/CXCursor.h88
-rw-r--r--tools/CIndex/Makefile2
10 files changed, 1848 insertions, 742 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 86e0ddc..84f908d 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -13,10 +13,14 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
+#include "CXCursor.h"
+#include "clang/Basic/Version.h"
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLocVisitor.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Program.h"
@@ -24,6 +28,7 @@
#include <cstdio>
using namespace clang;
+using namespace clang::cxcursor;
using namespace idx;
//===----------------------------------------------------------------------===//
@@ -111,362 +116,744 @@ public:
#endif
#endif
-//===----------------------------------------------------------------------===//
-// Visitors.
-//===----------------------------------------------------------------------===//
+typedef llvm::PointerIntPair<ASTContext *, 1, bool> CXSourceLocationPtr;
-namespace {
-static enum CXCursorKind TranslateDeclRefExpr(DeclRefExpr *DRE) {
- NamedDecl *D = DRE->getDecl();
- if (isa<VarDecl>(D))
- return CXCursor_VarRef;
- else if (isa<FunctionDecl>(D))
- return CXCursor_FunctionRef;
- else if (isa<EnumConstantDecl>(D))
- return CXCursor_EnumConstantRef;
- else
- return CXCursor_NotImplemented;
+/// \brief Translate a Clang source location into a CIndex source location.
+static CXSourceLocation translateSourceLocation(ASTContext &Context,
+ SourceLocation Loc,
+ bool AtEnd = false) {
+ CXSourceLocationPtr Ptr(&Context, AtEnd);
+ CXSourceLocation Result = { Ptr.getOpaqueValue(), Loc.getRawEncoding() };
+ return Result;
}
-#if 0
-// Will be useful one day.
-class CRefVisitor : public StmtVisitor<CRefVisitor> {
- CXDecl CDecl;
- CXDeclIterator Callback;
- CXClientData CData;
-
- void Call(enum CXCursorKind CK, Stmt *SRef) {
- CXCursor C = { CK, CDecl, SRef };
- Callback(CDecl, C, CData);
- }
+/// \brief Translate a Clang source range into a CIndex source range.
+static CXSourceRange translateSourceRange(ASTContext &Context, SourceRange R) {
+ CXSourceRange Result = { &Context,
+ R.getBegin().getRawEncoding(),
+ R.getEnd().getRawEncoding() };
+ return Result;
+}
-public:
- CRefVisitor(CXDecl C, CXDeclIterator cback, CXClientData D) :
- CDecl(C), Callback(cback), CData(D) {}
+static SourceLocation translateSourceLocation(CXSourceLocation L) {
+ return SourceLocation::getFromRawEncoding(L.int_data);
+}
- void VisitStmt(Stmt *S) {
- for (Stmt::child_iterator C = S->child_begin(), CEnd = S->child_end();
- C != CEnd; ++C)
- Visit(*C);
- }
- void VisitDeclRefExpr(DeclRefExpr *Node) {
- Call(TranslateDeclRefExpr(Node), Node);
- }
- void VisitMemberExpr(MemberExpr *Node) {
- Call(CXCursor_MemberRef, Node);
- }
- void VisitObjCMessageExpr(ObjCMessageExpr *Node) {
- Call(CXCursor_ObjCSelectorRef, Node);
- }
- void VisitObjCIvarRefExpr(ObjCIvarRefExpr *Node) {
- Call(CXCursor_ObjCIvarRef, Node);
- }
+static SourceRange translateSourceRange(CXSourceRange R) {
+ return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data),
+ SourceLocation::getFromRawEncoding(R.end_int_data));
+}
+
+/// \brief The result of comparing two source ranges.
+enum RangeComparisonResult {
+ /// \brief Either the ranges overlap or one of the ranges is invalid.
+ RangeOverlap,
+
+ /// \brief The first range ends before the second range starts.
+ RangeBefore,
+
+ /// \brief The first range starts after the second range ends.
+ RangeAfter
};
-#endif
-// Translation Unit Visitor.
+/// \brief Compare two source ranges to determine their relative position in
+/// the translation unit.
+static RangeComparisonResult RangeCompare(SourceManager &SM,
+ SourceRange R1,
+ SourceRange R2) {
+ assert(R1.isValid() && "First range is invalid?");
+ assert(R2.isValid() && "Second range is invalid?");
+ if (SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
+ return RangeBefore;
+ if (SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
+ return RangeAfter;
+ return RangeOverlap;
+}
-class TUVisitor : public DeclVisitor<TUVisitor> {
-public:
- typedef void (*Iterator)(void *, CXCursor, CXClientData);
-private:
- void *Root; // CXDecl or CXTranslationUnit
- Iterator Callback; // CXTranslationUnitIterator or CXDeclIterator.
- CXClientData CData;
+//===----------------------------------------------------------------------===//
+// Cursor visitor.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+// Cursor visitor.
+class CursorVisitor : public DeclVisitor<CursorVisitor, bool>,
+ public TypeLocVisitor<CursorVisitor, bool>,
+ public StmtVisitor<CursorVisitor, bool>
+{
+ /// \brief The translation unit we are traversing.
+ ASTUnit *TU;
+
+ /// \brief The parent cursor whose children we are traversing.
+ CXCursor Parent;
+
+ /// \brief The declaration that serves at the parent of any statement or
+ /// expression nodes.
+ Decl *StmtParent;
+
+ /// \brief The visitor function.
+ CXCursorVisitor Visitor;
+
+ /// \brief The opaque client data, to be passed along to the visitor.
+ CXClientData ClientData;
+
// MaxPCHLevel - the maximum PCH level of declarations that we will pass on
// to the visitor. Declarations with a PCH level greater than this value will
// be suppressed.
unsigned MaxPCHLevel;
- void Call(enum CXCursorKind CK, NamedDecl *ND) {
- // Filter any declarations that have a PCH level greater than what we allow.
- if (ND->getPCHLevel() > MaxPCHLevel)
- return;
+ /// \brief When valid, a source range to which the cursor should restrict
+ /// its search.
+ SourceRange RegionOfInterest;
+
+ using DeclVisitor<CursorVisitor, bool>::Visit;
+ using TypeLocVisitor<CursorVisitor, bool>::Visit;
+ using StmtVisitor<CursorVisitor, bool>::Visit;
+
+ /// \brief Determine whether this particular source range comes before, comes
+ /// after, or overlaps the region of interest.
+ ///
+ /// \param R a source range retrieved from the abstract syntax tree.
+ RangeComparisonResult CompareRegionOfInterest(SourceRange R);
+
+ /// \brief Determine whether this particular source range comes before, comes
+ /// after, or overlaps the region of interest.
+ ///
+ /// \param CXR a source range retrieved from a cursor.
+ RangeComparisonResult CompareRegionOfInterest(CXSourceRange CXR);
+
+public:
+ CursorVisitor(ASTUnit *TU, CXCursorVisitor Visitor, CXClientData ClientData,
+ unsigned MaxPCHLevel,
+ SourceRange RegionOfInterest = SourceRange())
+ : TU(TU), Visitor(Visitor), ClientData(ClientData),
+ MaxPCHLevel(MaxPCHLevel), RegionOfInterest(RegionOfInterest)
+ {
+ Parent.kind = CXCursor_NoDeclFound;
+ Parent.data[0] = 0;
+ Parent.data[1] = 0;
+ Parent.data[2] = 0;
+ StmtParent = 0;
+ }
+
+ bool Visit(CXCursor Cursor, bool CheckedRegionOfInterest = false);
+ bool VisitChildren(CXCursor Parent);
+
+ // Declaration visitors
+ bool VisitDeclContext(DeclContext *DC);
+ bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
+ bool VisitTypedefDecl(TypedefDecl *D);
+ bool VisitTagDecl(TagDecl *D);
+ bool VisitEnumConstantDecl(EnumConstantDecl *D);
+ bool VisitDeclaratorDecl(DeclaratorDecl *DD);
+ bool VisitFunctionDecl(FunctionDecl *ND);
+ bool VisitFieldDecl(FieldDecl *D);
+ bool VisitVarDecl(VarDecl *);
+ bool VisitObjCMethodDecl(ObjCMethodDecl *ND);
+ bool VisitObjCContainerDecl(ObjCContainerDecl *D);
+ bool VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
+ bool VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
+ bool VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
+ bool VisitObjCImplDecl(ObjCImplDecl *D);
+ bool VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
+ bool VisitObjCImplementationDecl(ObjCImplementationDecl *D);
+ // FIXME: ObjCPropertyDecl requires TypeSourceInfo, getter/setter locations,
+ // etc.
+ // FIXME: ObjCCompatibleAliasDecl requires aliased-class locations.
+ bool VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D);
+ bool VisitObjCClassDecl(ObjCClassDecl *D);
+
+ // Type visitors
+ // FIXME: QualifiedTypeLoc doesn't provide any location information
+ bool VisitBuiltinTypeLoc(BuiltinTypeLoc TL);
+ bool VisitTypedefTypeLoc(TypedefTypeLoc TL);
+ bool VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL);
+ bool VisitTagTypeLoc(TagTypeLoc TL);
+ // FIXME: TemplateTypeParmTypeLoc doesn't provide any location information
+ bool VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL);
+ bool VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL);
+ bool VisitPointerTypeLoc(PointerTypeLoc TL);
+ bool VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL);
+ bool VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL);
+ bool VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL);
+ bool VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL);
+ bool VisitFunctionTypeLoc(FunctionTypeLoc TL);
+ bool VisitArrayTypeLoc(ArrayTypeLoc TL);
+ // FIXME: Implement for TemplateSpecializationTypeLoc
+ // FIXME: Implement visitors here when the unimplemented TypeLocs get
+ // implemented
+ bool VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL);
+ bool VisitTypeOfTypeLoc(TypeOfTypeLoc TL);
+
+ // Statement visitors
+ bool VisitStmt(Stmt *S);
+ bool VisitDeclStmt(DeclStmt *S);
+ // FIXME: LabelStmt label?
+ bool VisitIfStmt(IfStmt *S);
+ bool VisitSwitchStmt(SwitchStmt *S);
+
+ // Expression visitors
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+ bool VisitExplicitCastExpr(ExplicitCastExpr *E);
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+};
+
+} // end anonymous namespace
- // Filter any implicit declarations (since the source info will be bogus).
- if (ND->isImplicit())
- return;
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
+ assert(RegionOfInterest.isValid() && "RangeCompare called with invalid range");
+ if (R.isInvalid())
+ return RangeOverlap;
+
+ // Move the end of the input range to the end of the last token in that
+ // range.
+ R.setEnd(TU->getPreprocessor().getLocForEndOfToken(R.getEnd(), 1));
+ return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
+}
+
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(CXSourceRange CXR) {
+ return CompareRegionOfInterest(translateSourceRange(CXR));
+}
+
+/// \brief Visit the given cursor and, if requested by the visitor,
+/// its children.
+///
+/// \param Cursor the cursor to visit.
+///
+/// \param CheckRegionOfInterest if true, then the caller already checked that
+/// this cursor is within the region of interest.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::Visit(CXCursor Cursor, bool CheckedRegionOfInterest) {
+ if (clang_isInvalid(Cursor.kind))
+ return false;
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ assert(D && "Invalid declaration cursor");
+ if (D->getPCHLevel() > MaxPCHLevel)
+ return false;
+
+ if (D->isImplicit())
+ return false;
+ }
- CXCursor C = { CK, ND, 0, 0 };
- Callback(Root, C, CData);
+ // If we have a range of interest, and this cursor doesn't intersect with it,
+ // we're done.
+ if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
+ CXSourceRange Range = clang_getCursorExtent(Cursor);
+ if (translateSourceRange(Range).isInvalid() ||
+ CompareRegionOfInterest(Range))
+ return false;
}
+
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
-public:
- TUVisitor(void *root, Iterator cback, CXClientData D, unsigned MaxPCHLevel) :
- Root(root), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
-
- void VisitDeclContext(DeclContext *DC);
- void VisitFunctionDecl(FunctionDecl *ND);
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND);
- void VisitObjCImplementationDecl(ObjCImplementationDecl *ND);
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND);
- void VisitObjCProtocolDecl(ObjCProtocolDecl *ND);
- void VisitTagDecl(TagDecl *ND);
- void VisitTranslationUnitDecl(TranslationUnitDecl *D);
- void VisitTypedefDecl(TypedefDecl *ND);
- void VisitVarDecl(VarDecl *ND);
-};
+ case CXChildVisit_Continue:
+ return false;
-void TUVisitor::VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator I = DC->decls_begin(), E = DC->decls_end();
- I != E; ++I)
- Visit(*I);
+ case CXChildVisit_Recurse:
+ return VisitChildren(Cursor);
+ }
+
+ llvm_unreachable("Silly GCC, we can't get here");
}
+
+/// \brief Visit the children of the given cursor.
+///
+/// \returns true if the visitation should be aborted, false if it
+/// should continue.
+bool CursorVisitor::VisitChildren(CXCursor Cursor) {
+ if (clang_isReference(Cursor.kind)) {
+ // By definition, references have no children.
+ return false;
+ }
-void TUVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- Call(ND->isThisDeclarationADefinition() ? CXCursor_FunctionDefn
- : CXCursor_FunctionDecl, ND);
+ // Set the Parent field to Cursor, then back to its old value once we're
+ // done.
+ class SetParentRAII {
+ CXCursor &Parent;
+ Decl *&StmtParent;
+ CXCursor OldParent;
+
+ public:
+ SetParentRAII(CXCursor &Parent, Decl *&StmtParent, CXCursor NewParent)
+ : Parent(Parent), StmtParent(StmtParent), OldParent(Parent)
+ {
+ Parent = NewParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+
+ ~SetParentRAII() {
+ Parent = OldParent;
+ if (clang_isDeclaration(Parent.kind))
+ StmtParent = getCursorDecl(Parent);
+ }
+ } SetParent(Parent, StmtParent, Cursor);
+
+ if (clang_isDeclaration(Cursor.kind)) {
+ Decl *D = getCursorDecl(Cursor);
+ assert(D && "Invalid declaration cursor");
+ return Visit(D);
+ }
+
+ if (clang_isStatement(Cursor.kind))
+ return Visit(getCursorStmt(Cursor));
+ if (clang_isExpression(Cursor.kind))
+ return Visit(getCursorExpr(Cursor));
+
+ if (clang_isTranslationUnit(Cursor.kind)) {
+ ASTUnit *CXXUnit = getCursorASTUnit(Cursor);
+ if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls() &&
+ RegionOfInterest.isInvalid()) {
+ const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
+ for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
+ ie = TLDs.end(); it != ie; ++it) {
+ if (Visit(MakeCXCursor(*it, CXXUnit), true))
+ return true;
+ }
+ } else {
+ return VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl());
+ }
+
+ return false;
+ }
+
+ // Nothing to visit at the moment.
+ return false;
}
+
+bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
+ for (DeclContext::decl_iterator
+ I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
+ if (RegionOfInterest.isValid()) {
+ SourceRange R = (*I)->getSourceRange();
+ if (R.isInvalid())
+ continue;
+
+ switch (CompareRegionOfInterest(R)) {
+ case RangeBefore:
+ // This declaration comes before the region of interest; skip it.
+ continue;
+
+ case RangeAfter:
+ // This declaration comes after the region of interest; we're done.
+ return false;
+
+ case RangeOverlap:
+ // This declaration overlaps the region of interest; visit it.
+ break;
+ }
+ }
+
+ if (Visit(MakeCXCursor(*I, TU), true))
+ return true;
+ }
-void TUVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- Call(CXCursor_ObjCCategoryDecl, ND);
+ return false;
}
-void TUVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *ND) {
- Call(CXCursor_ObjCCategoryDefn, ND);
+bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ llvm_unreachable("Translation units are visited directly by Visit()");
+ return false;
}
-void TUVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *ND) {
- Call(CXCursor_ObjCClassDefn, ND);
+bool CursorVisitor::VisitTypedefDecl(TypedefDecl *D) {
+ if (TypeSourceInfo *TSInfo = D->getTypeSourceInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitTagDecl(TagDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitEnumConstantDecl(EnumConstantDecl *D) {
+ if (Expr *Init = D->getInitExpr())
+ return Visit(MakeCXCursor(Init, StmtParent, TU));
+ return false;
+}
+
+bool CursorVisitor::VisitDeclaratorDecl(DeclaratorDecl *DD) {
+ if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return false;
}
+
+bool CursorVisitor::VisitFunctionDecl(FunctionDecl *ND) {
+ if (VisitDeclaratorDecl(ND))
+ return true;
+
+ if (ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+ return true;
-void TUVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *ND) {
- Call(CXCursor_ObjCInterfaceDecl, ND);
-}
+ return false;
+}
-void TUVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *ND) {
- Call(CXCursor_ObjCProtocolDecl, ND);
+bool CursorVisitor::VisitFieldDecl(FieldDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
+
+ if (Expr *BitWidth = D->getBitWidth())
+ return Visit(MakeCXCursor(BitWidth, StmtParent, TU));
+
+ return false;
}
+
+bool CursorVisitor::VisitVarDecl(VarDecl *D) {
+ if (VisitDeclaratorDecl(D))
+ return true;
-void TUVisitor::VisitTagDecl(TagDecl *ND) {
- switch (ND->getTagKind()) {
- case TagDecl::TK_struct:
- Call(CXCursor_StructDecl, ND);
- break;
- case TagDecl::TK_class:
- Call(CXCursor_ClassDecl, ND);
- break;
- case TagDecl::TK_union:
- Call(CXCursor_UnionDecl, ND);
- break;
- case TagDecl::TK_enum:
- Call(CXCursor_EnumDecl, ND);
- break;
+ if (Expr *Init = D->getInit())
+ return Visit(MakeCXCursor(Init, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
+ // FIXME: We really need a TypeLoc covering Objective-C method declarations.
+ // At the moment, we don't have information about locations in the return
+ // type.
+ for (ObjCMethodDecl::param_iterator P = ND->param_begin(),
+ PEnd = ND->param_end();
+ P != PEnd; ++P) {
+ if (Visit(MakeCXCursor(*P, TU)))
+ return true;
}
+
+ if (ND->isThisDeclarationADefinition() &&
+ Visit(MakeCXCursor(ND->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
}
+
+bool CursorVisitor::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ return VisitDeclContext(D);
+}
+
+bool CursorVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
+ if (Visit(MakeCursorObjCClassRef(ND->getClassInterface(), ND->getLocation(),
+ TU)))
+ return true;
-void TUVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+ ObjCCategoryDecl::protocol_loc_iterator PL = ND->protocol_loc_begin();
+ for (ObjCCategoryDecl::protocol_iterator I = ND->protocol_begin(),
+ E = ND->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(ND);
}
+
+bool CursorVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
+ ObjCProtocolDecl::protocol_loc_iterator PL = PID->protocol_loc_begin();
+ for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
+ E = PID->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
-void TUVisitor::VisitTypedefDecl(TypedefDecl *ND) {
- Call(CXCursor_TypedefDecl, ND);
+ return VisitObjCContainerDecl(PID);
}
-void TUVisitor::VisitVarDecl(VarDecl *ND) {
- Call(CXCursor_VarDecl, ND);
+bool CursorVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
+ // Issue callbacks for super class.
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+
+ ObjCInterfaceDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCInterfaceDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end(); I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return VisitObjCContainerDecl(D);
}
-// Declaration visitor.
-class CDeclVisitor : public DeclVisitor<CDeclVisitor> {
- CXDecl CDecl;
- CXDeclIterator Callback;
- CXClientData CData;
+bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
+ return VisitObjCContainerDecl(D);
+}
- // MaxPCHLevel - the maximum PCH level of declarations that we will pass on
- // to the visitor. Declarations with a PCH level greater than this value will
- // be suppressed.
- unsigned MaxPCHLevel;
+bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ if (Visit(MakeCursorObjCClassRef(D->getCategoryDecl()->getClassInterface(),
+ D->getLocation(), TU)))
+ return true;
+
+ return VisitObjCImplDecl(D);
+}
- void Call(enum CXCursorKind CK, NamedDecl *ND) {
- // Disable the callback when the context is equal to the visiting decl.
- if (CDecl == ND && !clang_isReference(CK))
- return;
+bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
+#if 0
+ // Issue callbacks for super class.
+ // FIXME: No source location information!
+ if (D->getSuperClass() &&
+ Visit(MakeCursorObjCSuperClassRef(D->getSuperClass(),
+ D->getSuperClassLoc(),
+ TU)))
+ return true;
+#endif
+
+ return VisitObjCImplDecl(D);
+}
- // Filter any declarations that have a PCH level greater than what we allow.
- if (ND->getPCHLevel() > MaxPCHLevel)
- return;
+bool CursorVisitor::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ ObjCForwardProtocolDecl::protocol_loc_iterator PL = D->protocol_loc_begin();
+ for (ObjCForwardProtocolDecl::protocol_iterator I = D->protocol_begin(),
+ E = D->protocol_end();
+ I != E; ++I, ++PL)
+ if (Visit(MakeCursorObjCProtocolRef(*I, *PL, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCClassDecl(ObjCClassDecl *D) {
+ for (ObjCClassDecl::iterator C = D->begin(), CEnd = D->end(); C != CEnd; ++C)
+ if (Visit(MakeCursorObjCClassRef(C->getInterface(), C->getLocation(), TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitBuiltinTypeLoc(BuiltinTypeLoc TL) {
+ ASTContext &Context = TU->getASTContext();
+
+ // Some builtin types (such as Objective-C's "id", "sel", and
+ // "Class") have associated declarations. Create cursors for those.
+ QualType VisitType;
+ switch (TL.getType()->getAs<BuiltinType>()->getKind()) {
+ case BuiltinType::Void:
+ case BuiltinType::Bool:
+ case BuiltinType::Char_U:
+ case BuiltinType::UChar:
+ case BuiltinType::Char16:
+ case BuiltinType::Char32:
+ case BuiltinType::UShort:
+ case BuiltinType::UInt:
+ case BuiltinType::ULong:
+ case BuiltinType::ULongLong:
+ case BuiltinType::UInt128:
+ case BuiltinType::Char_S:
+ case BuiltinType::SChar:
+ case BuiltinType::WChar:
+ case BuiltinType::Short:
+ case BuiltinType::Int:
+ case BuiltinType::Long:
+ case BuiltinType::LongLong:
+ case BuiltinType::Int128:
+ case BuiltinType::Float:
+ case BuiltinType::Double:
+ case BuiltinType::LongDouble:
+ case BuiltinType::NullPtr:
+ case BuiltinType::Overload:
+ case BuiltinType::Dependent:
+ break;
+
+ case BuiltinType::UndeducedAuto: // FIXME: Deserves a cursor?
+ break;
+
+ case BuiltinType::ObjCId:
+ VisitType = Context.getObjCIdType();
+ break;
+
+ case BuiltinType::ObjCClass:
+ VisitType = Context.getObjCClassType();
+ break;
+
+ case BuiltinType::ObjCSel:
+ VisitType = Context.getObjCSelType();
+ break;
+ }
- CXCursor C = { CK, ND, 0, 0 };
- Callback(CDecl, C, CData);
+ if (!VisitType.isNull()) {
+ if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
+ TU));
}
-public:
- CDeclVisitor(CXDecl C, CXDeclIterator cback, CXClientData D,
- unsigned MaxPCHLevel) :
- CDecl(C), Callback(cback), CData(D), MaxPCHLevel(MaxPCHLevel) {}
-
- void VisitDeclContext(DeclContext *DC);
- void VisitEnumConstantDecl(EnumConstantDecl *ND);
- void VisitFieldDecl(FieldDecl *ND);
- void VisitFunctionDecl(FunctionDecl *ND);
- void VisitObjCCategoryDecl(ObjCCategoryDecl *ND);
- void VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D);
- void VisitObjCImplementationDecl(ObjCImplementationDecl *D);
- void VisitObjCInterfaceDecl(ObjCInterfaceDecl *D);
- void VisitObjCIvarDecl(ObjCIvarDecl *ND);
- void VisitObjCMethodDecl(ObjCMethodDecl *ND);
- void VisitObjCPropertyDecl(ObjCPropertyDecl *ND);
- void VisitObjCProtocolDecl(ObjCProtocolDecl *PID);
- void VisitParmVarDecl(ParmVarDecl *ND);
- void VisitTagDecl(TagDecl *D);
- void VisitVarDecl(VarDecl *ND);
-};
-} // end anonymous namespace
-void CDeclVisitor::VisitDeclContext(DeclContext *DC) {
- for (DeclContext::decl_iterator
- I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I)
- Visit(*I);
+ return false;
}
-void CDeclVisitor::VisitEnumConstantDecl(EnumConstantDecl *ND) {
- Call(CXCursor_EnumConstantDecl, ND);
+bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU));
}
-void CDeclVisitor::VisitFieldDecl(FieldDecl *ND) {
- Call(CXCursor_FieldDecl, ND);
+bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
}
-void CDeclVisitor::VisitFunctionDecl(FunctionDecl *ND) {
- if (ND->isThisDeclarationADefinition()) {
- VisitDeclContext(dyn_cast<DeclContext>(ND));
-#if 0
- // Not currently needed.
- CompoundStmt *Body = dyn_cast<CompoundStmt>(ND->getBody());
- CRefVisitor RVisit(CDecl, Callback, CData);
- RVisit.Visit(Body);
-#endif
+bool CursorVisitor::VisitTagTypeLoc(TagTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitObjCInterfaceTypeLoc(ObjCInterfaceTypeLoc TL) {
+ if (Visit(MakeCursorObjCClassRef(TL.getIFaceDecl(), TL.getNameLoc(), TU)))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I), TL.getProtocolLoc(I),
+ TU)))
+ return true;
}
-}
-void CDeclVisitor::VisitObjCCategoryDecl(ObjCCategoryDecl *ND) {
- // Issue callbacks for the containing class.
- Call(CXCursor_ObjCClassRef, ND);
- // FIXME: Issue callbacks for protocol refs.
- VisitDeclContext(dyn_cast<DeclContext>(ND));
+ return false;
}
-void CDeclVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitObjCObjectPointerTypeLoc(ObjCObjectPointerTypeLoc TL) {
+ if (TL.hasBaseTypeAsWritten() && Visit(TL.getBaseTypeLoc()))
+ return true;
+
+ if (TL.hasProtocolsAsWritten()) {
+ for (unsigned I = 0, N = TL.getNumProtocols(); I != N; ++I) {
+ if (Visit(MakeCursorObjCProtocolRef(TL.getProtocol(I),
+ TL.getProtocolLoc(I),
+ TU)))
+ return true;
+ }
+ }
+
+ return false;
}
-void CDeclVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCInterfaceDecl(ObjCInterfaceDecl *D) {
- // Issue callbacks for super class.
- if (D->getSuperClass())
- Call(CXCursor_ObjCSuperClassRef, D);
-
- for (ObjCProtocolDecl::protocol_iterator I = D->protocol_begin(),
- E = D->protocol_end(); I != E; ++I)
- Call(CXCursor_ObjCProtocolRef, *I);
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCIvarDecl(ObjCIvarDecl *ND) {
- Call(CXCursor_ObjCIvarDecl, ND);
+bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
- if (ND->getBody()) {
- Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDefn
- : CXCursor_ObjCClassMethodDefn, ND);
- VisitDeclContext(dyn_cast<DeclContext>(ND));
- } else
- Call(ND->isInstanceMethod() ? CXCursor_ObjCInstanceMethodDecl
- : CXCursor_ObjCClassMethodDecl, ND);
+bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCPropertyDecl(ObjCPropertyDecl *ND) {
- Call(CXCursor_ObjCPropertyDecl, ND);
+bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
}
-void CDeclVisitor::VisitObjCProtocolDecl(ObjCProtocolDecl *PID) {
- for (ObjCProtocolDecl::protocol_iterator I = PID->protocol_begin(),
- E = PID->protocol_end(); I != E; ++I)
- Call(CXCursor_ObjCProtocolRef, *I);
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ if (Visit(TL.getResultLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (Visit(MakeCXCursor(TL.getArg(I), TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitArrayTypeLoc(ArrayTypeLoc TL) {
+ if (Visit(TL.getElementLoc()))
+ return true;
+
+ if (Expr *Size = TL.getSizeExpr())
+ return Visit(MakeCXCursor(Size, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypeOfExprTypeLoc(TypeOfExprTypeLoc TL) {
+ return Visit(MakeCXCursor(TL.getUnderlyingExpr(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitTypeOfTypeLoc(TypeOfTypeLoc TL) {
+ if (TypeSourceInfo *TSInfo = TL.getUnderlyingTInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
+}
+
+bool CursorVisitor::VisitStmt(Stmt *S) {
+ for (Stmt::child_iterator Child = S->child_begin(), ChildEnd = S->child_end();
+ Child != ChildEnd; ++Child) {
+ if (Visit(MakeCXCursor(*Child, StmtParent, TU)))
+ return true;
+ }
- VisitDeclContext(dyn_cast<DeclContext>(PID));
+ return false;
}
-void CDeclVisitor::VisitParmVarDecl(ParmVarDecl *ND) {
- Call(CXCursor_ParmDecl, ND);
+bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ if (Visit(MakeCXCursor(*D, TU)))
+ return true;
+ }
+
+ return false;
}
-void CDeclVisitor::VisitTagDecl(TagDecl *D) {
- VisitDeclContext(dyn_cast<DeclContext>(D));
+bool CursorVisitor::VisitIfStmt(IfStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ } else if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+
+ if (S->getThen() && Visit(MakeCXCursor(S->getThen(), StmtParent, TU)))
+ return true;
+
+ if (S->getElse() && Visit(MakeCXCursor(S->getElse(), StmtParent, TU)))
+ return true;
+
+ return false;
}
-void CDeclVisitor::VisitVarDecl(VarDecl *ND) {
- Call(CXCursor_VarDecl, ND);
+bool CursorVisitor::VisitSwitchStmt(SwitchStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ } else if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+
+ if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
}
-static SourceLocation getLocationFromCursor(CXCursor C,
- SourceManager &SourceMgr,
- NamedDecl *ND) {
- if (clang_isReference(C.kind)) {
- switch (C.kind) {
- case CXCursor_ObjCClassRef: {
- if (isa<ObjCInterfaceDecl>(ND)) {
- // FIXME: This is a hack (storing the parent decl in the stmt slot).
- NamedDecl *parentDecl = static_cast<NamedDecl *>(C.stmt);
- return parentDecl->getLocation();
- }
- ObjCCategoryDecl *OID = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing category decl");
- return OID->getClassInterface()->getLocation();
- }
- case CXCursor_ObjCSuperClassRef: {
- ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing interface decl");
- return OID->getSuperClassLoc();
- }
- case CXCursor_ObjCProtocolRef: {
- ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing protocol decl");
- return OID->getLocation();
- }
- case CXCursor_ObjCSelectorRef: {
- ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(OME && "clang_getCursorLine(): Missing message expr");
- return OME->getLeftLoc(); /* FIXME: should be a range */
- }
- case CXCursor_VarRef:
- case CXCursor_FunctionRef:
- case CXCursor_EnumConstantRef: {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return DRE->getLocation();
- }
- default:
- return SourceLocation();
- }
- } else { // We have a declaration or a definition.
- SourceLocation SLoc;
- switch (ND->getKind()) {
- case Decl::ObjCInterface: {
- SLoc = dyn_cast<ObjCInterfaceDecl>(ND)->getClassLoc();
- break;
- }
- case Decl::ObjCProtocol: {
- SLoc = ND->getLocation(); /* FIXME: need to get the name location. */
- break;
- }
- default: {
- SLoc = ND->getLocation();
- break;
- }
- }
- if (SLoc.isInvalid())
- return SourceLocation();
- return SourceMgr.getSpellingLoc(SLoc); // handles macro instantiations.
+bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
+ if (E->isArgumentType()) {
+ if (TypeSourceInfo *TSInfo = E->getArgumentTypeInfo())
+ return Visit(TSInfo->getTypeLoc());
+
+ return false;
}
+
+ return VisitExpr(E);
+}
+
+bool CursorVisitor::VisitExplicitCastExpr(ExplicitCastExpr *E) {
+ if (TypeSourceInfo *TSInfo = E->getTypeInfoAsWritten())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return VisitCastExpr(E);
+}
+
+bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
+ if (TypeSourceInfo *TSInfo = E->getTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return VisitExpr(E);
}
CXString CIndexer::createCXString(const char *String, bool DupString){
@@ -484,7 +871,7 @@ CXString CIndexer::createCXString(const char *String, bool DupString){
extern "C" {
CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
int displayDiagnostics) {
- CIndexer *CIdxr = new CIndexer(new Program());
+ CIndexer *CIdxr = new CIndexer();
if (excludeDeclarationsFromPCH)
CIdxr->setOnlyLocalDecls();
if (displayDiagnostics)
@@ -518,10 +905,22 @@ CXTranslationUnit
clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
const char *source_filename,
int num_command_line_args,
- const char **command_line_args) {
+ const char **command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files) {
assert(CIdx && "Passed null CXIndex");
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
+ unsaved_files[I].Contents + unsaved_files[I].Length,
+ unsaved_files[I].Filename);
+ RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
if (!CXXIdx->getUseExternalASTGeneration()) {
llvm::SmallVector<const char *, 16> Args;
@@ -544,7 +943,9 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
CXXIdx->getDiags(),
CXXIdx->getClangResourcesPath(),
CXXIdx->getOnlyLocalDecls(),
- /* UseBumpAllocator = */ true));
+ /* UseBumpAllocator = */ true,
+ RemappedFiles.data(),
+ RemappedFiles.size()));
// FIXME: Until we have broader testing, just drop the entire AST if we
// encountered an error.
@@ -575,6 +976,17 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
char astTmpFile[L_tmpnam];
argv.push_back(tmpnam(astTmpFile));
+ // Remap any unsaved files to temporary files.
+ std::vector<llvm::sys::Path> TemporaryFiles;
+ std::vector<std::string> RemapArgs;
+ if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+ return 0;
+
+ // The pointers into the elements of RemapArgs are stable because we
+ // won't be adding anything to RemapArgs after this point.
+ for (unsigned i = 0, e = RemapArgs.size(); i != e; ++i)
+ argv.push_back(RemapArgs[i].c_str());
+
// Process the compiler options, stripping off '-o', '-c', '-fsyntax-only'.
for (int i = 0; i < num_command_line_args; ++i)
if (const char *arg = command_line_args[i]) {
@@ -615,11 +1027,17 @@ clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
llvm::errs() << '\n';
}
- // Finally, we create the translation unit from the ast file.
- ASTUnit *ATU = static_cast<ASTUnit *>(
- clang_createTranslationUnit(CIdx, astTmpFile));
+ ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, CXXIdx->getDiags(),
+ CXXIdx->getOnlyLocalDecls(),
+ /* UseBumpAllocator = */ true,
+ RemappedFiles.data(),
+ RemappedFiles.size());
if (ATU)
ATU->unlinkTemporaryFile();
+
+ for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+ TemporaryFiles[i].eraseFromDisk();
+
return ATU;
}
@@ -635,165 +1053,123 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
true);
}
-void clang_loadTranslationUnit(CXTranslationUnit CTUnit,
- CXTranslationUnitIterator callback,
- CXClientData CData) {
- assert(CTUnit && "Passed null CXTranslationUnit");
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
- ASTContext &Ctx = CXXUnit->getASTContext();
-
- unsigned PCHLevel = Decl::MaxPCHLevel;
-
- // Set the PCHLevel to filter out unwanted decls if requested.
- if (CXXUnit->getOnlyLocalDecls()) {
- PCHLevel = 0;
-
- // If the main input was an AST, bump the level.
- if (CXXUnit->isMainFileAST())
- ++PCHLevel;
- }
-
- TUVisitor DVisit(CTUnit, callback, CData, PCHLevel);
-
- // If using a non-AST based ASTUnit, iterate over the stored list of top-level
- // decls.
- if (!CXXUnit->isMainFileAST() && CXXUnit->getOnlyLocalDecls()) {
- const std::vector<Decl*> &TLDs = CXXUnit->getTopLevelDecls();
- for (std::vector<Decl*>::const_iterator it = TLDs.begin(),
- ie = TLDs.end(); it != ie; ++it) {
- DVisit.Visit(*it);
- }
- } else
- DVisit.Visit(Ctx.getTranslationUnitDecl());
+CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
+ CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
+ return Result;
}
-void clang_loadDeclaration(CXDecl Dcl,
- CXDeclIterator callback,
- CXClientData CData) {
- assert(Dcl && "Passed null CXDecl");
-
- CDeclVisitor DVisit(Dcl, callback, CData,
- static_cast<Decl *>(Dcl)->getPCHLevel());
- DVisit.Visit(static_cast<Decl *>(Dcl));
-}
} // end: extern "C"
//===----------------------------------------------------------------------===//
-// CXDecl Operations.
+// CXSourceLocation and CXSourceRange Operations.
//===----------------------------------------------------------------------===//
-static const FileEntry *getFileEntryFromSourceLocation(SourceManager &SMgr,
- SourceLocation SLoc) {
- FileID FID;
- if (SLoc.isFileID())
- FID = SMgr.getFileID(SLoc);
- else
- FID = SMgr.getDecomposedSpellingLoc(SLoc).first;
- return SMgr.getFileEntryForID(FID);
-}
-
extern "C" {
-CXString clang_getDeclSpelling(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
-
- if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
- return CIndexer::createCXString(OMD->getSelector().getAsString().c_str(),
- true);
-
- if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
- // No, this isn't the same as the code below. getIdentifier() is non-virtual
- // and returns different names. NamedDecl returns the class name and
- // ObjCCategoryImplDecl returns the category name.
- return CIndexer::createCXString(CIMP->getIdentifier()->getNameStart());
-
- if (ND->getIdentifier())
- return CIndexer::createCXString(ND->getIdentifier()->getNameStart());
-
- return CIndexer::createCXString("");
+CXSourceLocation clang_getNullLocation() {
+ CXSourceLocation Result = { 0, 0 };
+ return Result;
}
-unsigned clang_getDeclLine(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return SourceMgr.getSpellingLineNumber(ND->getLocation());
+unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
+ return loc1.ptr_data == loc2.ptr_data && loc1.int_data == loc2.int_data;
}
-unsigned clang_getDeclColumn(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return SourceMgr.getSpellingColumnNumber(ND->getLocation());
-}
+CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column) {
+ if (!tu)
+ return clang_getNullLocation();
-CXDeclExtent clang_getDeclExtent(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SM = ND->getASTContext().getSourceManager();
- SourceRange R = ND->getSourceRange();
-
- SourceLocation Begin = SM.getInstantiationLoc(R.getBegin());
- SourceLocation End = SM.getInstantiationLoc(R.getEnd());
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
+ SourceLocation SLoc
+ = CXXUnit->getSourceManager().getLocation(
+ static_cast<const FileEntry *>(file),
+ line, column);
+
+ return translateSourceLocation(CXXUnit->getASTContext(), SLoc, false);
+}
- if (!Begin.isValid()) {
- CXDeclExtent extent = { { 0, 0 }, { 0, 0 } };
- return extent;
+CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
+ if (begin.ptr_data != end.ptr_data) {
+ CXSourceRange Result = { 0, 0, 0 };
+ return Result;
}
+ CXSourceRange Result = { begin.ptr_data, begin.int_data, end.int_data };
+ return Result;
+}
+
+void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column) {
+ CXSourceLocationPtr Ptr
+ = CXSourceLocationPtr::getFromOpaqueValue(location.ptr_data);
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!Ptr.getPointer() || Loc.isInvalid()) {
+ if (file)
+ *file = 0;
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ return;
+ }
+
// FIXME: This is largely copy-paste from
///TextDiagnosticPrinter::HighlightRange. When it is clear that this is
- // what we want the two routines should be refactored.
-
- // If the End location and the start location are the same and are a macro
- // location, then the range was something that came from a macro expansion
- // or _Pragma. If this is an object-like macro, the best we can do is to
- // get the range. If this is a function-like macro, we'd also like to
- // get the arguments.
- if (Begin == End && R.getEnd().isMacroID())
- End = SM.getInstantiationRange(R.getEnd()).second;
-
- assert(SM.getFileID(Begin) == SM.getFileID(End));
- unsigned StartLineNo = SM.getInstantiationLineNumber(Begin);
- unsigned EndLineNo = SM.getInstantiationLineNumber(End);
-
- // Compute the column number of the start. Keep the column based at 1.
- unsigned StartColNo = SM.getInstantiationColumnNumber(Begin);
-
- // Compute the column number of the end.
- unsigned EndColNo = SM.getInstantiationColumnNumber(End);
- if (EndColNo) {
- // Offset the end column by 1 so that we point to the last character
- // in the last token.
- --EndColNo;
-
- // Add in the length of the token, so that we cover multi-char tokens.
- ASTContext &Ctx = ND->getTranslationUnitDecl()->getASTContext();
- const LangOptions &LOpts = Ctx.getLangOptions();
-
- EndColNo += Lexer::MeasureTokenLength(End, SM, LOpts);
+ // what we want the two routines should be refactored.
+ ASTContext &Context = *Ptr.getPointer();
+ SourceManager &SM = Context.getSourceManager();
+ SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
+
+ if (Ptr.getInt()) {
+ // We want the last character in this location, so we will adjust
+ // the instantiation location accordingly.
+
+ // If the location is from a macro instantiation, get the end of
+ // the instantiation range.
+ if (Loc.isMacroID())
+ InstLoc = SM.getInstantiationRange(Loc).second;
+
+ // Measure the length token we're pointing at, so we can adjust
+ // the physical location in the file to point at the last
+ // character.
+ // FIXME: This won't cope with trigraphs or escaped newlines
+ // well. For that, we actually need a preprocessor, which isn't
+ // currently available here. Eventually, we'll switch the pointer
+ // data of CXSourceLocation/CXSourceRange to a translation unit
+ // (CXXUnit), so that the preprocessor will be available here. At
+ // that point, we can use Preprocessor::getLocForEndOfToken().
+ unsigned Length = Lexer::MeasureTokenLength(InstLoc, SM,
+ Context.getLangOptions());
+ if (Length > 0)
+ InstLoc = InstLoc.getFileLocWithOffset(Length - 1);
}
- // Package up the line/column data and return to the caller.
- CXDeclExtent extent = { { StartLineNo, StartColNo },
- { EndLineNo, EndColNo } };
- return extent;
+ if (file)
+ *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
+ if (line)
+ *line = SM.getInstantiationLineNumber(InstLoc);
+ if (column)
+ *column = SM.getInstantiationColumnNumber(InstLoc);
}
-const char *clang_getDeclSource(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- FileEntry *FEnt = static_cast<FileEntry *>(clang_getDeclSourceFile(AnonDecl));
- assert(FEnt && "Cannot find FileEntry for Decl");
- return clang_getFileName(FEnt);
+CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+ CXSourceLocation Result = { range.ptr_data, range.begin_int_data };
+ return Result;
}
-
-CXFile clang_getDeclSourceFile(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
- return (void *)getFileEntryFromSourceLocation(SourceMgr, ND->getLocation());
+CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+ llvm::PointerIntPair<ASTContext *, 1, bool> Ptr;
+ Ptr.setPointer(static_cast<ASTContext *>(range.ptr_data));
+ Ptr.setInt(true);
+ CXSourceLocation Result = { Ptr.getOpaqueValue(), range.end_int_data };
+ return Result;
}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
@@ -802,58 +1178,40 @@ CXFile clang_getDeclSourceFile(CXDecl AnonDecl) {
extern "C" {
const char *clang_getFileName(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
assert(SFile && "Passed null CXFile");
FileEntry *FEnt = static_cast<FileEntry *>(SFile);
return FEnt->getName();
}
time_t clang_getFileTime(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
assert(SFile && "Passed null CXFile");
FileEntry *FEnt = static_cast<FileEntry *>(SFile);
return FEnt->getModificationTime();
}
+
+CXFile clang_getFile(CXTranslationUnit tu, const char *file_name) {
+ if (!tu)
+ return 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
+
+ FileManager &FMgr = CXXUnit->getFileManager();
+ const FileEntry *File = FMgr.getFile(file_name, file_name+strlen(file_name));
+ return const_cast<FileEntry *>(File);
+}
+
} // end: extern "C"
//===----------------------------------------------------------------------===//
// CXCursor Operations.
//===----------------------------------------------------------------------===//
-static enum CXCursorKind TranslateKind(Decl *D) {
- switch (D->getKind()) {
- case Decl::Function: return CXCursor_FunctionDecl;
- case Decl::Typedef: return CXCursor_TypedefDecl;
- case Decl::Enum: return CXCursor_EnumDecl;
- case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
- case Decl::Record: return CXCursor_StructDecl; // FIXME: union/class
- case Decl::Field: return CXCursor_FieldDecl;
- case Decl::Var: return CXCursor_VarDecl;
- case Decl::ParmVar: return CXCursor_ParmDecl;
- case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
- case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
- case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
- case Decl::ObjCMethod: {
- ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D);
- if (MD->isInstanceMethod())
- return CXCursor_ObjCInstanceMethodDecl;
- return CXCursor_ObjCClassMethodDecl;
- }
- default: break;
- }
- return CXCursor_NotImplemented;
-}
-
-
-static CXCursor MakeCXCursor(CXCursorKind K, Decl *D) {
- CXCursor C = { K, D, 0, 0 };
- return C;
-}
-
-static CXCursor MakeCXCursor(CXCursorKind K, Decl *D, Stmt *S) {
- assert(clang_isReference(K));
- CXCursor C = { K, D, S, 0 };
- return C;
-}
-
static Decl *getDeclFromExpr(Stmt *E) {
if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
return RefExpr->getDecl();
@@ -873,53 +1231,90 @@ static Decl *getDeclFromExpr(Stmt *E) {
}
extern "C" {
+
+unsigned clang_visitChildren(CXCursor parent,
+ CXCursorVisitor visitor,
+ CXClientData client_data) {
+ ASTUnit *CXXUnit = getCursorASTUnit(parent);
+
+ unsigned PCHLevel = Decl::MaxPCHLevel;
+
+ // Set the PCHLevel to filter out unwanted decls if requested.
+ if (CXXUnit->getOnlyLocalDecls()) {
+ PCHLevel = 0;
+
+ // If the main input was an AST, bump the level.
+ if (CXXUnit->isMainFileAST())
+ ++PCHLevel;
+ }
+
+ CursorVisitor CursorVis(CXXUnit, visitor, client_data, PCHLevel);
+ return CursorVis.VisitChildren(parent);
+}
+
+static CXString getDeclSpelling(Decl *D) {
+ NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D);
+ if (!ND)
+ return CIndexer::createCXString("");
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return CIndexer::createCXString(OMD->getSelector().getAsString().c_str(),
+ true);
+
+ if (ObjCCategoryImplDecl *CIMP = dyn_cast<ObjCCategoryImplDecl>(ND))
+ // No, this isn't the same as the code below. getIdentifier() is non-virtual
+ // and returns different names. NamedDecl returns the class name and
+ // ObjCCategoryImplDecl returns the category name.
+ return CIndexer::createCXString(CIMP->getIdentifier()->getNameStart());
+
+ if (ND->getIdentifier())
+ return CIndexer::createCXString(ND->getIdentifier()->getNameStart());
+
+ return CIndexer::createCXString("");
+}
+
CXString clang_getCursorSpelling(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ if (clang_isTranslationUnit(C.kind))
+ return clang_getTranslationUnitSpelling(C.data[2]);
if (clang_isReference(C.kind)) {
switch (C.kind) {
case CXCursor_ObjCSuperClassRef: {
- ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing interface decl");
- return CIndexer::createCXString(OID->getSuperClass()->getIdentifier()
- ->getNameStart());
+ ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
+ return CIndexer::createCXString(Super->getIdentifier()->getNameStart());
}
case CXCursor_ObjCClassRef: {
- if (ObjCInterfaceDecl *OID = dyn_cast<ObjCInterfaceDecl>(ND))
- return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
-
- ObjCCategoryDecl *OCD = dyn_cast<ObjCCategoryDecl>(ND);
- assert(OCD && "clang_getCursorLine(): Missing category decl");
- return CIndexer::createCXString(OCD->getClassInterface()->getIdentifier()
- ->getNameStart());
+ ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ return CIndexer::createCXString(Class->getIdentifier()->getNameStart());
}
case CXCursor_ObjCProtocolRef: {
- ObjCProtocolDecl *OID = dyn_cast<ObjCProtocolDecl>(ND);
- assert(OID && "clang_getCursorLine(): Missing protocol decl");
+ ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
+ assert(OID && "getCursorSpelling(): Missing protocol decl");
return CIndexer::createCXString(OID->getIdentifier()->getNameStart());
}
- case CXCursor_ObjCSelectorRef: {
- ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(OME && "clang_getCursorLine(): Missing message expr");
- return CIndexer::createCXString(OME->getSelector().getAsString().c_str(),
+ case CXCursor_TypeRef: {
+ TypeDecl *Type = getCursorTypeRef(C).first;
+ assert(Type && "Missing type decl");
+
+ return CIndexer::createCXString(
+ getCursorContext(C).getTypeDeclType(Type).getAsString().c_str(),
true);
}
- case CXCursor_VarRef:
- case CXCursor_FunctionRef:
- case CXCursor_EnumConstantRef: {
- DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(
- static_cast<Stmt *>(C.stmt));
- assert(DRE && "clang_getCursorLine(): Missing decl ref expr");
- return CIndexer::createCXString(DRE->getDecl()->getIdentifier()
- ->getNameStart());
- }
+
default:
return CIndexer::createCXString("<not implemented>");
}
}
- return clang_getDeclSpelling(C.decl);
+
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return getDeclSpelling(D);
+ return CIndexer::createCXString("");
+ }
+
+ return getDeclSpelling(getCursorDecl(C));
}
const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) {
@@ -941,90 +1336,66 @@ const char *clang_getCursorKindSpelling(enum CXCursorKind Kind) {
case CXCursor_ObjCIvarDecl: return "ObjCIvarDecl";
case CXCursor_ObjCInstanceMethodDecl: return "ObjCInstanceMethodDecl";
case CXCursor_ObjCClassMethodDecl: return "ObjCClassMethodDecl";
- case CXCursor_FunctionDefn: return "FunctionDefn";
- case CXCursor_ObjCInstanceMethodDefn: return "ObjCInstanceMethodDefn";
- case CXCursor_ObjCClassMethodDefn: return "ObjCClassMethodDefn";
- case CXCursor_ObjCClassDefn: return "ObjCClassDefn";
- case CXCursor_ObjCCategoryDefn: return "ObjCCategoryDefn";
+ case CXCursor_ObjCImplementationDecl: return "ObjCImplementationDecl";
+ case CXCursor_ObjCCategoryImplDecl: return "ObjCCategoryImplDecl";
+ case CXCursor_UnexposedDecl: return "UnexposedDecl";
case CXCursor_ObjCSuperClassRef: return "ObjCSuperClassRef";
case CXCursor_ObjCProtocolRef: return "ObjCProtocolRef";
case CXCursor_ObjCClassRef: return "ObjCClassRef";
- case CXCursor_ObjCSelectorRef: return "ObjCSelectorRef";
-
- case CXCursor_VarRef: return "VarRef";
- case CXCursor_FunctionRef: return "FunctionRef";
- case CXCursor_EnumConstantRef: return "EnumConstantRef";
- case CXCursor_MemberRef: return "MemberRef";
-
+ case CXCursor_TypeRef: return "TypeRef";
+ case CXCursor_UnexposedExpr: return "UnexposedExpr";
+ case CXCursor_DeclRefExpr: return "DeclRefExpr";
+ case CXCursor_MemberRefExpr: return "MemberRefExpr";
+ case CXCursor_CallExpr: return "CallExpr";
+ case CXCursor_ObjCMessageExpr: return "ObjCMessageExpr";
+ case CXCursor_UnexposedStmt: return "UnexposedStmt";
case CXCursor_InvalidFile: return "InvalidFile";
case CXCursor_NoDeclFound: return "NoDeclFound";
case CXCursor_NotImplemented: return "NotImplemented";
- default: return "<not implemented>";
+ case CXCursor_TranslationUnit: return "TranslationUnit";
}
+
+ llvm_unreachable("Unhandled CXCursorKind");
+ return NULL;
}
-CXCursor clang_getCursor(CXTranslationUnit CTUnit, const char *source_name,
- unsigned line, unsigned column) {
- assert(CTUnit && "Passed null CXTranslationUnit");
- ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
-
- FileManager &FMgr = CXXUnit->getFileManager();
- const FileEntry *File = FMgr.getFile(source_name,
- source_name+strlen(source_name));
- if (!File)
+enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ CXCursor *BestCursor = static_cast<CXCursor *>(client_data);
+ *BestCursor = cursor;
+ return CXChildVisit_Recurse;
+}
+
+CXCursor clang_getCursor(CXTranslationUnit TU, CXSourceLocation Loc) {
+ if (!TU)
return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
- SourceLocation SLoc =
- CXXUnit->getSourceManager().getLocation(File, line, column);
-
- ASTLocation LastLoc = CXXUnit->getLastASTLocation();
- ASTLocation ALoc = ResolveLocationInAST(CXXUnit->getASTContext(), SLoc,
- &LastLoc);
-
- // FIXME: This doesn't look thread-safe.
- if (ALoc.isValid())
- CXXUnit->setLastASTLocation(ALoc);
-
- Decl *Dcl = ALoc.getParentDecl();
- if (ALoc.isNamedRef())
- Dcl = ALoc.AsNamedRef().ND;
- Stmt *Stm = ALoc.dyn_AsStmt();
- if (Dcl) {
- if (Stm) {
- if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(Stm))
- return MakeCXCursor(TranslateDeclRefExpr(DRE), Dcl, Stm);
- else if (ObjCMessageExpr *MExp = dyn_cast<ObjCMessageExpr>(Stm))
- return MakeCXCursor(CXCursor_ObjCSelectorRef, Dcl, MExp);
- // Fall through...treat as a decl, not a ref.
- }
- if (ALoc.isNamedRef()) {
- if (isa<ObjCInterfaceDecl>(Dcl)) {
- CXCursor C = { CXCursor_ObjCClassRef, Dcl, ALoc.getParentDecl(), 0 };
- return C;
- }
- if (isa<ObjCProtocolDecl>(Dcl)) {
- CXCursor C = { CXCursor_ObjCProtocolRef, Dcl, ALoc.getParentDecl(), 0 };
- return C;
- }
- }
- return MakeCXCursor(TranslateKind(Dcl), Dcl);
+ SourceLocation SLoc = translateSourceLocation(Loc);
+ CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ if (SLoc.isValid()) {
+ SourceRange RegionOfInterest(SLoc,
+ CXXUnit->getPreprocessor().getLocForEndOfToken(SLoc, 1));
+
+ // FIXME: Would be great to have a "hint" cursor, then walk from that
+ // hint cursor upward until we find a cursor whose source range encloses
+ // the region of interest, rather than starting from the translation unit.
+ CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
+ CursorVisitor CursorVis(CXXUnit, GetCursorVisitor, &Result,
+ Decl::MaxPCHLevel, RegionOfInterest);
+ CursorVis.VisitChildren(Parent);
}
- return MakeCXCursor(CXCursor_NoDeclFound, 0);
+ return Result;
}
CXCursor clang_getNullCursor(void) {
- return MakeCXCursor(CXCursor_InvalidFile, 0);
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
}
unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
- return X.kind == Y.kind && X.decl == Y.decl && X.stmt == Y.stmt &&
- X.referringDecl == Y.referringDecl;
-}
-
-CXCursor clang_getCursorFromDecl(CXDecl AnonDecl) {
- assert(AnonDecl && "Passed null CXDecl");
- NamedDecl *ND = static_cast<NamedDecl *>(AnonDecl);
- return MakeCXCursor(TranslateKind(ND), ND);
+ return X == Y;
}
unsigned clang_isInvalid(enum CXCursorKind K) {
@@ -1039,80 +1410,413 @@ unsigned clang_isReference(enum CXCursorKind K) {
return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
}
-unsigned clang_isDefinition(enum CXCursorKind K) {
- return K >= CXCursor_FirstDefn && K <= CXCursor_LastDefn;
+unsigned clang_isExpression(enum CXCursorKind K) {
+ return K >= CXCursor_FirstExpr && K <= CXCursor_LastExpr;
+}
+
+unsigned clang_isStatement(enum CXCursorKind K) {
+ return K >= CXCursor_FirstStmt && K <= CXCursor_LastStmt;
+}
+
+unsigned clang_isTranslationUnit(enum CXCursorKind K) {
+ return K == CXCursor_TranslationUnit;
}
CXCursorKind clang_getCursorKind(CXCursor C) {
return C.kind;
}
-CXDecl clang_getCursorDecl(CXCursor C) {
- if (clang_isDeclaration(C.kind))
- return C.decl;
+static SourceLocation getLocationFromExpr(Expr *E) {
+ if (ObjCMessageExpr *Msg = dyn_cast<ObjCMessageExpr>(E))
+ return /*FIXME:*/Msg->getLeftLoc();
+ if (DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(E))
+ return DRE->getLocation();
+ if (MemberExpr *Member = dyn_cast<MemberExpr>(E))
+ return Member->getMemberLoc();
+ if (ObjCIvarRefExpr *Ivar = dyn_cast<ObjCIvarRefExpr>(E))
+ return Ivar->getLocation();
+ return E->getLocStart();
+}
+CXSourceLocation clang_getCursorLocation(CXCursor C) {
if (clang_isReference(C.kind)) {
- if (C.stmt) {
- if (C.kind == CXCursor_ObjCClassRef ||
- C.kind == CXCursor_ObjCProtocolRef)
- return static_cast<Stmt *>(C.stmt);
- else
- return getDeclFromExpr(static_cast<Stmt *>(C.stmt));
- } else
- return C.decl;
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
}
- return 0;
-}
-unsigned clang_getCursorLine(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+ if (clang_isExpression(C.kind))
+ return translateSourceLocation(getCursorContext(C),
+ getLocationFromExpr(getCursorExpr(C)));
+
+ if (!getCursorDecl(C)) {
+ CXSourceLocation empty = { 0, 0 };
+ return empty;
+ }
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- return SourceMgr.getSpellingLineNumber(SLoc);
+ Decl *D = getCursorDecl(C);
+ SourceLocation Loc = D->getLocation();
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
+ Loc = Class->getClassLoc();
+ return translateSourceLocation(D->getASTContext(), Loc);
}
+
+CXSourceRange clang_getCursorExtent(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ default:
+ // FIXME: Need a way to enumerate all non-reference cases.
+ llvm_unreachable("Missed a reference kind");
+ }
+ }
+
+ if (clang_isExpression(C.kind))
+ return translateSourceRange(getCursorContext(C),
+ getCursorExpr(C)->getSourceRange());
+
+ if (clang_isStatement(C.kind))
+ return translateSourceRange(getCursorContext(C),
+ getCursorStmt(C)->getSourceRange());
-unsigned clang_getCursorColumn(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+ if (!getCursorDecl(C)) {
+ CXSourceRange empty = { 0, 0, 0 };
+ return empty;
+ }
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
- return SourceMgr.getSpellingColumnNumber(SLoc);
+ Decl *D = getCursorDecl(C);
+ return translateSourceRange(D->getASTContext(), D->getSourceRange());
}
-const char *clang_getCursorSource(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+CXCursor clang_getCursorReferenced(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
- SourceLocation SLoc = getLocationFromCursor(C, SourceMgr, ND);
+ ASTUnit *CXXUnit = getCursorASTUnit(C);
+ if (clang_isDeclaration(C.kind))
+ return C;
- if (SLoc.isFileID()) {
- const char *bufferName = SourceMgr.getBufferName(SLoc);
- return bufferName[0] == '<' ? NULL : bufferName;
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return MakeCXCursor(D, CXXUnit);
+ return clang_getNullCursor();
}
+
+ if (!clang_isReference(C.kind))
+ return clang_getNullCursor();
- // Retrieve the file in which the macro was instantiated, then provide that
- // buffer name.
- // FIXME: Do we want to give specific macro-instantiation information?
- const llvm::MemoryBuffer *Buffer
- = SourceMgr.getBuffer(SourceMgr.getDecomposedSpellingLoc(SLoc).first);
- if (!Buffer)
- return 0;
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef:
+ return MakeCXCursor(getCursorObjCSuperClassRef(C).first, CXXUnit);
+
+ case CXCursor_ObjCProtocolRef: {
+ return MakeCXCursor(getCursorObjCProtocolRef(C).first, CXXUnit);
+
+ case CXCursor_ObjCClassRef:
+ return MakeCXCursor(getCursorObjCClassRef(C).first, CXXUnit);
+
+ case CXCursor_TypeRef:
+ return MakeCXCursor(getCursorTypeRef(C).first, CXXUnit);
+
+ default:
+ // We would prefer to enumerate all non-reference cursor kinds here.
+ llvm_unreachable("Unhandled reference cursor kind");
+ break;
+ }
+ }
- return Buffer->getBufferIdentifier();
+ return clang_getNullCursor();
}
-CXFile clang_getCursorSourceFile(CXCursor C) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
- SourceManager &SourceMgr = ND->getASTContext().getSourceManager();
+CXCursor clang_getCursorDefinition(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = getCursorASTUnit(C);
+
+ bool WasReference = false;
+ if (clang_isReference(C.kind) || clang_isExpression(C.kind)) {
+ C = clang_getCursorReferenced(C);
+ WasReference = true;
+ }
+
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullCursor();
+
+ Decl *D = getCursorDecl(C);
+ if (!D)
+ return clang_getNullCursor();
+
+ switch (D->getKind()) {
+ // Declaration kinds that don't really separate the notions of
+ // declaration and definition.
+ case Decl::Namespace:
+ case Decl::Typedef:
+ case Decl::TemplateTypeParm:
+ case Decl::EnumConstant:
+ case Decl::Field:
+ case Decl::ObjCIvar:
+ case Decl::ObjCAtDefsField:
+ case Decl::ImplicitParam:
+ case Decl::ParmVar:
+ case Decl::NonTypeTemplateParm:
+ case Decl::TemplateTemplateParm:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCImplementation:
+ case Decl::LinkageSpec:
+ case Decl::ObjCPropertyImpl:
+ case Decl::FileScopeAsm:
+ case Decl::StaticAssert:
+ case Decl::Block:
+ return C;
+
+ // Declaration kinds that don't make any sense here, but are
+ // nonetheless harmless.
+ case Decl::TranslationUnit:
+ case Decl::Template:
+ case Decl::ObjCContainer:
+ break;
+
+ // Declaration kinds for which the definition is not resolvable.
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ break;
+
+ case Decl::UsingDirective:
+ return MakeCXCursor(cast<UsingDirectiveDecl>(D)->getNominatedNamespace(),
+ CXXUnit);
+
+ case Decl::NamespaceAlias:
+ return MakeCXCursor(cast<NamespaceAliasDecl>(D)->getNamespace(), CXXUnit);
+
+ case Decl::Enum:
+ case Decl::Record:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::ClassTemplatePartialSpecialization:
+ if (TagDecl *Def = cast<TagDecl>(D)->getDefinition(D->getASTContext()))
+ return MakeCXCursor(Def, CXXUnit);
+ return clang_getNullCursor();
+
+ case Decl::Function:
+ case Decl::CXXMethod:
+ case Decl::CXXConstructor:
+ case Decl::CXXDestructor:
+ case Decl::CXXConversion: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionDecl>(D)->getBody(Def))
+ return MakeCXCursor(const_cast<FunctionDecl *>(Def), CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Var: {
+ VarDecl *Var = cast<VarDecl>(D);
+
+ // Variables with initializers have definitions.
+ const VarDecl *Def = 0;
+ if (Var->getDefinition(Def))
+ return MakeCXCursor(const_cast<VarDecl *>(Def), CXXUnit);
+
+ // extern and private_extern variables are not definitions.
+ if (Var->hasExternalStorage())
+ return clang_getNullCursor();
+
+ // In-line static data members do not have definitions.
+ if (Var->isStaticDataMember() && !Var->isOutOfLine())
+ return clang_getNullCursor();
+
+ // All other variables are themselves definitions.
+ return C;
+ }
+
+ case Decl::FunctionTemplate: {
+ const FunctionDecl *Def = 0;
+ if (cast<FunctionTemplateDecl>(D)->getTemplatedDecl()->getBody(Def))
+ return MakeCXCursor(Def->getDescribedFunctionTemplate(), CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::ClassTemplate: {
+ if (RecordDecl *Def = cast<ClassTemplateDecl>(D)->getTemplatedDecl()
+ ->getDefinition(D->getASTContext()))
+ return MakeCXCursor(
+ cast<CXXRecordDecl>(Def)->getDescribedClassTemplate(),
+ CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ case Decl::Using: {
+ UsingDecl *Using = cast<UsingDecl>(D);
+ CXCursor Def = clang_getNullCursor();
+ for (UsingDecl::shadow_iterator S = Using->shadow_begin(),
+ SEnd = Using->shadow_end();
+ S != SEnd; ++S) {
+ if (Def != clang_getNullCursor()) {
+ // FIXME: We have no way to return multiple results.
+ return clang_getNullCursor();
+ }
+
+ Def = clang_getCursorDefinition(MakeCXCursor((*S)->getTargetDecl(),
+ CXXUnit));
+ }
+
+ return Def;
+ }
+
+ case Decl::UsingShadow:
+ return clang_getCursorDefinition(
+ MakeCXCursor(cast<UsingShadowDecl>(D)->getTargetDecl(),
+ CXXUnit));
+
+ case Decl::ObjCMethod: {
+ ObjCMethodDecl *Method = cast<ObjCMethodDecl>(D);
+ if (Method->isThisDeclarationADefinition())
+ return C;
+
+ // Dig out the method definition in the associated
+ // @implementation, if we have it.
+ // FIXME: The ASTs should make finding the definition easier.
+ if (ObjCInterfaceDecl *Class
+ = dyn_cast<ObjCInterfaceDecl>(Method->getDeclContext()))
+ if (ObjCImplementationDecl *ClassImpl = Class->getImplementation())
+ if (ObjCMethodDecl *Def = ClassImpl->getMethod(Method->getSelector(),
+ Method->isInstanceMethod()))
+ if (Def->isThisDeclarationADefinition())
+ return MakeCXCursor(Def, CXXUnit);
+
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCCategory:
+ if (ObjCCategoryImplDecl *Impl
+ = cast<ObjCCategoryDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, CXXUnit);
+ return clang_getNullCursor();
+
+ case Decl::ObjCProtocol:
+ if (!cast<ObjCProtocolDecl>(D)->isForwardDecl())
+ return C;
+ return clang_getNullCursor();
+
+ case Decl::ObjCInterface:
+ // There are two notions of a "definition" for an Objective-C
+ // class: the interface and its implementation. When we resolved a
+ // reference to an Objective-C class, produce the @interface as
+ // the definition; when we were provided with the interface,
+ // produce the @implementation as the definition.
+ if (WasReference) {
+ if (!cast<ObjCInterfaceDecl>(D)->isForwardDecl())
+ return C;
+ } else if (ObjCImplementationDecl *Impl
+ = cast<ObjCInterfaceDecl>(D)->getImplementation())
+ return MakeCXCursor(Impl, CXXUnit);
+ return clang_getNullCursor();
- return (void *)
- getFileEntryFromSourceLocation(SourceMgr, getLocationFromCursor(C,SourceMgr,
- ND));
+ case Decl::ObjCProperty:
+ // FIXME: We don't really know where to find the
+ // ObjCPropertyImplDecls that implement this property.
+ return clang_getNullCursor();
+
+ case Decl::ObjCCompatibleAlias:
+ if (ObjCInterfaceDecl *Class
+ = cast<ObjCCompatibleAliasDecl>(D)->getClassInterface())
+ if (!Class->isForwardDecl())
+ return MakeCXCursor(Class, CXXUnit);
+
+ return clang_getNullCursor();
+
+ case Decl::ObjCForwardProtocol: {
+ ObjCForwardProtocolDecl *Forward = cast<ObjCForwardProtocolDecl>(D);
+ if (Forward->protocol_size() == 1)
+ return clang_getCursorDefinition(
+ MakeCXCursor(*Forward->protocol_begin(),
+ CXXUnit));
+
+ // FIXME: Cannot return multiple definitions.
+ return clang_getNullCursor();
+ }
+
+ case Decl::ObjCClass: {
+ ObjCClassDecl *Class = cast<ObjCClassDecl>(D);
+ if (Class->size() == 1) {
+ ObjCInterfaceDecl *IFace = Class->begin()->getInterface();
+ if (!IFace->isForwardDecl())
+ return MakeCXCursor(IFace, CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ // FIXME: Cannot return multiple definitions.
+ return clang_getNullCursor();
+ }
+
+ case Decl::Friend:
+ if (NamedDecl *Friend = cast<FriendDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
+ return clang_getNullCursor();
+
+ case Decl::FriendTemplate:
+ if (NamedDecl *Friend = cast<FriendTemplateDecl>(D)->getFriendDecl())
+ return clang_getCursorDefinition(MakeCXCursor(Friend, CXXUnit));
+ return clang_getNullCursor();
+ }
+
+ return clang_getNullCursor();
+}
+
+unsigned clang_isCursorDefinition(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return 0;
+
+ return clang_getCursorDefinition(C) == C;
}
void clang_getDefinitionSpellingAndExtent(CXCursor C,
@@ -1122,8 +1826,8 @@ void clang_getDefinitionSpellingAndExtent(CXCursor C,
unsigned *startColumn,
unsigned *endLine,
unsigned *endColumn) {
- assert(C.decl && "CXCursor has null decl");
- NamedDecl *ND = static_cast<NamedDecl *>(C.decl);
+ assert(getCursorDecl(C) && "CXCursor has null decl");
+ NamedDecl *ND = static_cast<NamedDecl *>(getCursorDecl(C));
FunctionDecl *FD = dyn_cast<FunctionDecl>(ND);
CompoundStmt *Body = dyn_cast<CompoundStmt>(FD->getBody());
@@ -1151,4 +1855,18 @@ void clang_disposeString(CXString string) {
if (string.MustFreeString && string.Spelling)
free((void*)string.Spelling);
}
+
} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Misc. utility functions.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+const char *clang_getClangVersion() {
+ return getClangFullVersion();
+}
+
+} // end: extern "C"
+
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index a695ba2..d349086 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -7,40 +7,41 @@ _clang_disposeIndex
_clang_disposeString
_clang_disposeTranslationUnit
_clang_equalCursors
+_clang_equalLocations
+_clang_getClangVersion
_clang_getCString
_clang_getCompletionChunkCompletionString
_clang_getCompletionChunkKind
_clang_getCompletionChunkText
_clang_getCursor
-_clang_getCursorColumn
-_clang_getCursorDecl
-_clang_getCursorFromDecl
+_clang_getCursorDefinition
+_clang_getCursorExtent
_clang_getCursorKind
_clang_getCursorKindSpelling
-_clang_getCursorLine
-_clang_getCursorSource
-_clang_getCursorSourceFile
+_clang_getCursorLocation
+_clang_getCursorReferenced
_clang_getCursorSpelling
-_clang_getDeclColumn
-_clang_getDeclExtent
-_clang_getDeclLine
-_clang_getDeclExtent
-_clang_getDeclSource
-_clang_getDeclSourceFile
-_clang_getDeclSpelling
-_clang_getDeclUSR
-_clang_getDeclaration
+_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
-_clang_getEntityFromDecl
+_clang_getFile
_clang_getFileName
_clang_getFileTime
+_clang_getInstantiationLocation
+_clang_getLocation
_clang_getNullCursor
+_clang_getNullLocation
_clang_getNumCompletionChunks
+_clang_getRange
+_clang_getRangeEnd
+_clang_getRangeStart
+_clang_getTranslationUnitCursor
_clang_getTranslationUnitSpelling
+_clang_isCursorDefinition
_clang_isDeclaration
-_clang_isDefinition
+_clang_isExpression
_clang_isInvalid
_clang_isReference
-_clang_loadDeclaration
-_clang_loadTranslationUnit
+_clang_isStatement
+_clang_isTranslationUnit
_clang_setUseExternalASTGeneration
+_clang_visitChildren
diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp
index f70479b..f3b60dc 100644
--- a/tools/CIndex/CIndexCodeCompletion.cpp
+++ b/tools/CIndex/CIndexCodeCompletion.cpp
@@ -221,35 +221,10 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
argv.push_back("-Xclang");
argv.push_back("-code-completion-macros");
+ // Remap any unsaved files to temporary files.
std::vector<std::string> RemapArgs;
- for (unsigned i = 0; i != num_unsaved_files; ++i) {
- char tmpFile[L_tmpnam];
- char *tmpFileName = tmpnam(tmpFile);
-
- // Write the contents of this unsaved file into the temporary file.
- llvm::sys::Path SavedFile(tmpFileName);
- std::string ErrorInfo;
- llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
- if (!ErrorInfo.empty())
- continue;
-
- OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
- OS.close();
- if (OS.has_error()) {
- SavedFile.eraseFromDisk();
- continue;
- }
-
- // Remap the file.
- std::string RemapArg = unsaved_files[i].Filename;
- RemapArg += ';';
- RemapArg += tmpFileName;
- RemapArgs.push_back("-Xclang");
- RemapArgs.push_back("-remap-file");
- RemapArgs.push_back("-Xclang");
- RemapArgs.push_back(RemapArg);
- TemporaryFiles.push_back(SavedFile);
- }
+ if (RemapFiles(num_unsaved_files, unsaved_files, RemapArgs, TemporaryFiles))
+ return 0;
// The pointers into the elements of RemapArgs are stable because we
// won't be adding anything to RemapArgs after this point.
diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp
index 549c650..fd605fb 100644
--- a/tools/CIndex/CIndexUSRs.cpp
+++ b/tools/CIndex/CIndexUSRs.cpp
@@ -12,56 +12,11 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
+#include "CXCursor.h"
#include "clang/AST/DeclVisitor.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
-// Some notes on CXEntity:
-//
-// - Since the 'ordinary' namespace includes functions, data, typedefs,
-// ObjC interfaces, thecurrent algorithm is a bit naive (resulting in one
-// entity for 2 different types). For example:
-//
-// module1.m: @interface Foo @end Foo *x;
-// module2.m: void Foo(int);
-//
-// - Since the unique name spans translation units, static data/functions
-// within a CXTranslationUnit are *not* currently represented by entities.
-// As a result, there will be no entity for the following:
-//
-// module.m: static void Foo() { }
-//
-
-static inline Entity GetEntity(const CXEntity &E) {
- return Entity::getFromOpaquePtr(E.data);
-}
-
-static inline ASTUnit *GetTranslationUnit(CXTranslationUnit TU) {
- return (ASTUnit*) TU;
-}
-
-static inline ASTContext &GetASTContext(CXTranslationUnit TU) {
- return GetTranslationUnit(TU)->getASTContext();
-}
-
-static inline CXEntity NullCXEntity() {
- CXEntity CE;
- CE.index = NULL;
- CE.data = NULL;
- return CE;
-}
-
-static inline CXEntity MakeEntity(CXIndex CIdx, const Entity &E) {
- CXEntity CE;
- CE.index = CIdx;
- CE.data = E.getAsOpaquePtr();
- return CE;
-}
-
-static inline Program &GetProgram(CXIndex CIdx) {
- return ((CIndexer*) CIdx)->getProgram();
-}
-
//===----------------------------------------------------------------------===//
// USR generation.
//===----------------------------------------------------------------------===//
@@ -69,18 +24,22 @@ static inline Program &GetProgram(CXIndex CIdx) {
namespace {
class USRGenerator : public DeclVisitor<USRGenerator> {
llvm::raw_ostream &Out;
+ bool IgnoreResults;
public:
- USRGenerator(llvm::raw_ostream &out) : Out(out) {}
+ USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {}
+
+ bool ignoreResults() const { return IgnoreResults; }
void VisitBlockDecl(BlockDecl *D);
void VisitDeclContext(DeclContext *D);
+ void VisitFieldDecl(FieldDecl *D);
void VisitFunctionDecl(FunctionDecl *D);
void VisitNamedDecl(NamedDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
void VisitObjCContainerDecl(ObjCContainerDecl *CD);
void VisitObjCMethodDecl(ObjCMethodDecl *MD);
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
- void VisitRecordDecl(RecordDecl *D);
+ void VisitTagDecl(TagDecl *D);
void VisitTypedefDecl(TypedefDecl *D);
};
} // end anonymous namespace
@@ -96,6 +55,17 @@ void USRGenerator::VisitDeclContext(DeclContext *DC) {
Visit(D);
}
+void USRGenerator::VisitFieldDecl(FieldDecl *D) {
+ const std::string &s = D->getNameAsString();
+ if (s.empty()) {
+ // Bit fields can be anonymous.
+ IgnoreResults = true;
+ return;
+ }
+ VisitDeclContext(D->getDeclContext());
+ Out << "@^FI^" << s;
+}
+
void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
VisitDeclContext(D->getDeclContext());
Out << "@F^" << D->getNameAsString();
@@ -113,17 +83,6 @@ void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
Out << "@N^" << D->getNameAsString();
}
-void USRGenerator::VisitRecordDecl(RecordDecl *D) {
- VisitDeclContext(D->getDeclContext());
- Out << "@S^";
- // FIXME: Better support for anonymous structures.
- const std::string &s = D->getNameAsString();
- if (s.empty())
- Out << "^anon";
- else
- Out << s;
-}
-
void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
Visit(cast<Decl>(D->getDeclContext()));
Out << (D->isInstanceMethod() ? "(im)" : "(cm)");
@@ -141,13 +100,13 @@ void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
case Decl::ObjCCategory: {
ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
Out << "objc(cy)" << CD->getClassInterface()->getName()
- << '_' << CD->getName();
+ << '^' << CD->getName();
break;
}
case Decl::ObjCCategoryImpl: {
ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
Out << "objc(cy)" << CD->getClassInterface()->getName()
- << '_' << CD->getName();
+ << '^' << CD->getName();
break;
}
case Decl::ObjCProtocol:
@@ -161,6 +120,27 @@ void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
Out << "(py)" << D->getName();
}
+void USRGenerator::VisitTagDecl(TagDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ switch (D->getTagKind()) {
+ case TagDecl::TK_struct: Out << "@S^"; break;
+ case TagDecl::TK_class: Out << "@C^"; break;
+ case TagDecl::TK_union: Out << "@U^"; break;
+ case TagDecl::TK_enum: Out << "@E^"; break;
+ }
+
+ // FIXME: Better support for anonymous structures and enums.
+ const std::string &s = D->getNameAsString();
+ if (s.empty()) {
+ if (TypedefDecl *TD = D->getTypedefForAnonDecl())
+ Out << "^anontd^" << TD->getNameAsString();
+ else
+ Out << "^anon";
+ }
+ else
+ Out << s;
+}
+
void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
DeclContext *DC = D->getDeclContext();
if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
@@ -168,36 +148,32 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
Out << "typedef@" << D->getName();
}
-extern "C" {
-
-/// clang_getDeclaration() maps from a CXEntity to the matching CXDecl (if any)
-/// in a specified translation unit.
-CXDecl clang_getDeclaration(CXEntity CE, CXTranslationUnit TU) {
- return (CXDecl) GetEntity(CE).getDecl(GetASTContext(TU));
-}
-
-
-CXEntity clang_getEntityFromDecl(CXIndex CIdx, CXDecl CE) {
- if (Decl *D = (Decl *) CE)
- return MakeEntity(CIdx, Entity::get(D, GetProgram(CIdx)));
- return NullCXEntity();
-}
-
// FIXME: This is a skeleton implementation. It will be overhauled.
-CXString clang_getDeclUSR(CXDecl D) {
- assert(D && "Null CXDecl passed to clang_getDeclUSR()");
+static CXString ConstructUSR(Decl *D) {
llvm::SmallString<1024> StrBuf;
{
llvm::raw_svector_ostream Out(StrBuf);
USRGenerator UG(Out);
UG.Visit(static_cast<Decl*>(D));
+ if (UG.ignoreResults())
+ return CIndexer::createCXString(NULL);
}
if (StrBuf.empty())
return CIndexer::createCXString(NULL);
-
+
// Return a copy of the string that must be disposed by the caller.
return CIndexer::createCXString(StrBuf.c_str(), true);
}
+
+extern "C" {
+
+CXString clang_getCursorUSR(CXCursor C) {
+ if (Decl *D = cxcursor::getCursorDecl(C))
+ return ConstructUSR(D);
+
+ return CIndexer::createCXString(NULL);
+}
+
} // end extern "C"
diff --git a/tools/CIndex/CIndexer.cpp b/tools/CIndex/CIndexer.cpp
index f26c8ce..53636a4 100644
--- a/tools/CIndex/CIndexer.cpp
+++ b/tools/CIndex/CIndexer.cpp
@@ -94,3 +94,40 @@ std::string CIndexer::getClangResourcesPath() {
return P.str();
}
+
+bool clang::RemapFiles(unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ std::vector<std::string> &RemapArgs,
+ std::vector<llvm::sys::Path> &TemporaryFiles) {
+ for (unsigned i = 0; i != num_unsaved_files; ++i) {
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+
+ // Write the contents of this unsaved file into the temporary file.
+ llvm::sys::Path SavedFile(tmpFileName);
+ std::string ErrorInfo;
+ llvm::raw_fd_ostream OS(SavedFile.c_str(), ErrorInfo);
+ if (!ErrorInfo.empty())
+ return true;
+
+ OS.write(unsaved_files[i].Contents, unsaved_files[i].Length);
+ OS.close();
+ if (OS.has_error()) {
+ SavedFile.eraseFromDisk();
+ return true;
+ }
+
+ // Remap the file.
+ std::string RemapArg = unsaved_files[i].Filename;
+ RemapArg += ';';
+ RemapArg += tmpFileName;
+ RemapArgs.push_back("-Xclang");
+ RemapArgs.push_back("-remap-file");
+ RemapArgs.push_back("-Xclang");
+ RemapArgs.push_back(RemapArg);
+ TemporaryFiles.push_back(SavedFile);
+ }
+
+ return false;
+}
+
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index 4f3cd8b..d01454f 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -16,13 +16,10 @@
#define LLVM_CLANG_CINDEXER_H
#include "clang-c/Index.h"
-#include "clang/Index/ASTLocation.h"
-#include "clang/Index/Indexer.h"
-#include "clang/Index/Program.h"
-#include "clang/Index/Utils.h"
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/ASTUnit.h"
#include "llvm/System/Path.h"
+#include <vector>
using namespace clang;
@@ -34,7 +31,7 @@ public:
virtual void HandleDiagnostic(Diagnostic::Level, const DiagnosticInfo &) {}
};
-class CIndexer : public Indexer {
+class CIndexer {
DiagnosticOptions DiagOpts;
IgnoreDiagnosticsClient IgnoreDiagClient;
llvm::OwningPtr<Diagnostic> TextDiags;
@@ -46,16 +43,12 @@ class CIndexer : public Indexer {
llvm::sys::Path ClangPath;
public:
- explicit CIndexer(Program *prog) : Indexer(*prog),
- IgnoreDiags(&IgnoreDiagClient),
- UseExternalASTGeneration(false),
- OnlyLocalDecls(false),
- DisplayDiagnostics(false) {
+ CIndexer() : IgnoreDiags(&IgnoreDiagClient), UseExternalASTGeneration(false),
+ OnlyLocalDecls(false), DisplayDiagnostics(false)
+ {
TextDiags.reset(CompilerInstance::createDiagnostics(DiagOpts, 0, 0));
}
- virtual ~CIndexer() { delete &getProgram(); }
-
/// \brief Whether we only want to see "local" declarations (that did not
/// come from a previous precompiled header). If false, we want to see all
/// declarations.
@@ -85,4 +78,17 @@ public:
static CXString createCXString(const char *String, bool DupString = false);
};
+namespace clang {
+ /**
+ * \brief Given a set of "unsaved" files, create temporary files and
+ * construct the clang -cc1 argument list needed to perform the remapping.
+ *
+ * \returns true if an error occurred.
+ */
+ bool RemapFiles(unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ std::vector<std::string> &RemapArgs,
+ std::vector<llvm::sys::Path> &TemporaryFiles);
+}
+
#endif
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index 52f847e..730eaaf 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -3,8 +3,7 @@ set(SHARED_LIBRARY TRUE)
set(LLVM_NO_RTTI 1)
set(LLVM_USED_LIBS
- clangIndex
- clangFrontend
+ clangFrontend
clangDriver
clangSema
clangAnalysis
@@ -24,6 +23,7 @@ add_clang_library(CIndex
CIndexCodeCompletion.cpp
CIndexUSRs.cpp
CIndexer.cpp
+ CXCursor.cpp
)
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp
new file mode 100644
index 0000000..63d9bc9
--- /dev/null
+++ b/tools/CIndex/CXCursor.cpp
@@ -0,0 +1,305 @@
+//===- CXCursor.cpp - Routines for manipulating CXCursors -----------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors. It should be the
+// only file that has internal knowledge of the encoding of the data in
+// CXCursor.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CXCursor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/Expr.h"
+#include "llvm/Support/ErrorHandling.h"
+
+using namespace clang;
+
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
+ assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
+ CXCursor C = { K, { 0, 0, 0 } };
+ return C;
+}
+
+static CXCursorKind GetCursorKind(Decl *D) {
+ switch (D->getKind()) {
+ case Decl::Enum: return CXCursor_EnumDecl;
+ case Decl::EnumConstant: return CXCursor_EnumConstantDecl;
+ case Decl::Field: return CXCursor_FieldDecl;
+ case Decl::Function:
+ return CXCursor_FunctionDecl;
+ case Decl::ObjCCategory: return CXCursor_ObjCCategoryDecl;
+ case Decl::ObjCCategoryImpl: return CXCursor_ObjCCategoryImplDecl;
+ case Decl::ObjCClass:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCForwardProtocol:
+ // FIXME
+ return CXCursor_UnexposedDecl;
+ case Decl::ObjCImplementation: return CXCursor_ObjCImplementationDecl;
+ case Decl::ObjCInterface: return CXCursor_ObjCInterfaceDecl;
+ case Decl::ObjCIvar: return CXCursor_ObjCIvarDecl;
+ case Decl::ObjCMethod:
+ return cast<ObjCMethodDecl>(D)->isInstanceMethod()
+ ? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+ case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
+ case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
+ case Decl::ParmVar: return CXCursor_ParmDecl;
+ case Decl::Typedef: return CXCursor_TypedefDecl;
+ case Decl::Var: return CXCursor_VarDecl;
+ default:
+ if (TagDecl *TD = dyn_cast<TagDecl>(D)) {
+ switch (TD->getTagKind()) {
+ case TagDecl::TK_struct: return CXCursor_StructDecl;
+ case TagDecl::TK_class: return CXCursor_ClassDecl;
+ case TagDecl::TK_union: return CXCursor_UnionDecl;
+ case TagDecl::TK_enum: return CXCursor_EnumDecl;
+ }
+ }
+
+ return CXCursor_UnexposedDecl;
+ }
+
+ llvm_unreachable("Invalid Decl");
+ return CXCursor_NotImplemented;
+}
+
+CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU) {
+ CXCursor C = { GetCursorKind(D), { D, 0, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) {
+ CXCursorKind K = CXCursor_NotImplemented;
+
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass:
+ break;
+
+ case Stmt::NullStmtClass:
+ case Stmt::CompoundStmtClass:
+ case Stmt::CaseStmtClass:
+ case Stmt::DefaultStmtClass:
+ case Stmt::LabelStmtClass:
+ case Stmt::IfStmtClass:
+ case Stmt::SwitchStmtClass:
+ case Stmt::WhileStmtClass:
+ case Stmt::DoStmtClass:
+ case Stmt::ForStmtClass:
+ case Stmt::GotoStmtClass:
+ case Stmt::IndirectGotoStmtClass:
+ case Stmt::ContinueStmtClass:
+ case Stmt::BreakStmtClass:
+ case Stmt::ReturnStmtClass:
+ case Stmt::DeclStmtClass:
+ case Stmt::SwitchCaseClass:
+ case Stmt::AsmStmtClass:
+ case Stmt::ObjCAtTryStmtClass:
+ case Stmt::ObjCAtCatchStmtClass:
+ case Stmt::ObjCAtFinallyStmtClass:
+ case Stmt::ObjCAtThrowStmtClass:
+ case Stmt::ObjCAtSynchronizedStmtClass:
+ case Stmt::ObjCForCollectionStmtClass:
+ case Stmt::CXXCatchStmtClass:
+ case Stmt::CXXTryStmtClass:
+ K = CXCursor_UnexposedStmt;
+ break;
+
+ case Stmt::ExprClass:
+ case Stmt::PredefinedExprClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::ParenExprClass:
+ case Stmt::UnaryOperatorClass:
+ case Stmt::SizeOfAlignOfExprClass:
+ case Stmt::ArraySubscriptExprClass:
+ case Stmt::CastExprClass:
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::ImplicitCastExprClass:
+ case Stmt::ExplicitCastExprClass:
+ case Stmt::CStyleCastExprClass:
+ case Stmt::CompoundLiteralExprClass:
+ case Stmt::ExtVectorElementExprClass:
+ case Stmt::InitListExprClass:
+ case Stmt::DesignatedInitExprClass:
+ case Stmt::ImplicitValueInitExprClass:
+ case Stmt::ParenListExprClass:
+ case Stmt::VAArgExprClass:
+ case Stmt::AddrLabelExprClass:
+ case Stmt::StmtExprClass:
+ case Stmt::TypesCompatibleExprClass:
+ case Stmt::ChooseExprClass:
+ case Stmt::GNUNullExprClass:
+ case Stmt::CXXNamedCastExprClass:
+ case Stmt::CXXStaticCastExprClass:
+ case Stmt::CXXDynamicCastExprClass:
+ case Stmt::CXXReinterpretCastExprClass:
+ case Stmt::CXXConstCastExprClass:
+ case Stmt::CXXFunctionalCastExprClass:
+ case Stmt::CXXTypeidExprClass:
+ case Stmt::CXXBoolLiteralExprClass:
+ case Stmt::CXXNullPtrLiteralExprClass:
+ case Stmt::CXXThisExprClass:
+ case Stmt::CXXThrowExprClass:
+ case Stmt::CXXDefaultArgExprClass:
+ case Stmt::CXXZeroInitValueExprClass:
+ case Stmt::CXXNewExprClass:
+ case Stmt::CXXDeleteExprClass:
+ case Stmt::CXXPseudoDestructorExprClass:
+ case Stmt::UnresolvedLookupExprClass:
+ case Stmt::UnaryTypeTraitExprClass:
+ case Stmt::DependentScopeDeclRefExprClass:
+ case Stmt::CXXBindTemporaryExprClass:
+ case Stmt::CXXExprWithTemporariesClass:
+ case Stmt::CXXUnresolvedConstructExprClass:
+ case Stmt::CXXDependentScopeMemberExprClass:
+ case Stmt::UnresolvedMemberExprClass:
+ case Stmt::ObjCStringLiteralClass:
+ case Stmt::ObjCEncodeExprClass:
+ case Stmt::ObjCSelectorExprClass:
+ case Stmt::ObjCProtocolExprClass:
+ case Stmt::ObjCImplicitSetterGetterRefExprClass:
+ case Stmt::ObjCSuperExprClass:
+ case Stmt::ObjCIsaExprClass:
+ case Stmt::ShuffleVectorExprClass:
+ case Stmt::BlockExprClass:
+ K = CXCursor_UnexposedExpr;
+ break;
+ case Stmt::DeclRefExprClass:
+ case Stmt::BlockDeclRefExprClass:
+ // FIXME: UnresolvedLookupExpr?
+ // FIXME: DependentScopeDeclRefExpr?
+ K = CXCursor_DeclRefExpr;
+ break;
+
+ case Stmt::MemberExprClass:
+ case Stmt::ObjCIvarRefExprClass:
+ case Stmt::ObjCPropertyRefExprClass:
+ // FIXME: UnresolvedMemberExpr?
+ // FIXME: CXXDependentScopeMemberExpr?
+ K = CXCursor_MemberRefExpr;
+ break;
+
+ case Stmt::CallExprClass:
+ case Stmt::CXXOperatorCallExprClass:
+ case Stmt::CXXMemberCallExprClass:
+ case Stmt::CXXConstructExprClass:
+ case Stmt::CXXTemporaryObjectExprClass:
+ // FIXME: CXXUnresolvedConstructExpr
+ // FIXME: ObjCImplicitSetterGetterRefExpr?
+ K = CXCursor_CallExpr;
+ break;
+
+ case Stmt::ObjCMessageExprClass:
+ K = CXCursor_ObjCMessageExpr;
+ break;
+ }
+
+ CXCursor C = { K, { Parent, S, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCSuperClassRef, { Super, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCSuperClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCSuperClassRef);
+ return std::make_pair(static_cast<ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorObjCProtocolRef(ObjCProtocolDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCProtocolRef, { Super, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCProtocolDecl *, SourceLocation>
+cxcursor::getCursorObjCProtocolRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCProtocolRef);
+ return std::make_pair(static_cast<ObjCProtocolDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorObjCClassRef(ObjCInterfaceDecl *Class,
+ SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_ObjCClassRef, { Class, RawLoc, TU } };
+ return C;
+}
+
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+cxcursor::getCursorObjCClassRef(CXCursor C) {
+ assert(C.kind == CXCursor_ObjCClassRef);
+ return std::make_pair(static_cast<ObjCInterfaceDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+CXCursor cxcursor::MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc,
+ ASTUnit *TU) {
+ void *RawLoc = reinterpret_cast<void *>(Loc.getRawEncoding());
+ CXCursor C = { CXCursor_TypeRef, { Type, RawLoc, TU } };
+ return C;
+}
+
+std::pair<TypeDecl *, SourceLocation>
+cxcursor::getCursorTypeRef(CXCursor C) {
+ assert(C.kind == CXCursor_TypeRef);
+ return std::make_pair(static_cast<TypeDecl *>(C.data[0]),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t>(C.data[1])));
+}
+
+Decl *cxcursor::getCursorDecl(CXCursor Cursor) {
+ return (Decl *)Cursor.data[0];
+}
+
+Expr *cxcursor::getCursorExpr(CXCursor Cursor) {
+ return dyn_cast_or_null<Expr>(getCursorStmt(Cursor));
+}
+
+Stmt *cxcursor::getCursorStmt(CXCursor Cursor) {
+ if (Cursor.kind == CXCursor_ObjCSuperClassRef ||
+ Cursor.kind == CXCursor_ObjCProtocolRef ||
+ Cursor.kind == CXCursor_ObjCClassRef)
+ return 0;
+
+ return (Stmt *)Cursor.data[1];
+}
+
+ASTContext &cxcursor::getCursorContext(CXCursor Cursor) {
+ return getCursorASTUnit(Cursor)->getASTContext();
+}
+
+ASTUnit *cxcursor::getCursorASTUnit(CXCursor Cursor) {
+ return static_cast<ASTUnit *>(Cursor.data[2]);
+}
+
+bool cxcursor::operator==(CXCursor X, CXCursor Y) {
+ return X.kind == Y.kind && X.data[0] == Y.data[0] && X.data[1] == Y.data[1] &&
+ X.data[2] == Y.data[2];
+}
diff --git a/tools/CIndex/CXCursor.h b/tools/CIndex/CXCursor.h
new file mode 100644
index 0000000..546dd7f
--- /dev/null
+++ b/tools/CIndex/CXCursor.h
@@ -0,0 +1,88 @@
+//===- CXCursor.h - Routines for manipulating CXCursors -------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines routines for manipulating CXCursors.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CXCURSOR_H
+#define LLVM_CLANG_CXCursor_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/SourceLocation.h"
+#include <utility>
+
+namespace clang {
+
+class ASTContext;
+class ASTUnit;
+class Decl;
+class Expr;
+class NamedDecl;
+class ObjCInterfaceDecl;
+class ObjCProtocolDecl;
+class Stmt;
+class TypeDecl;
+
+namespace cxcursor {
+
+CXCursor MakeCXCursorInvalid(CXCursorKind K);
+CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent, ASTUnit *TU);
+CXCursor MakeCXCursor(clang::Decl *D, ASTUnit *TU);
+
+/// \brief Create an Objective-C superclass reference at the given location.
+CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
+ SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCSuperClassRef cursor into the interface it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+ getCursorObjCSuperClassRef(CXCursor C);
+
+/// \brief Create an Objective-C protocol reference at the given location.
+CXCursor MakeCursorObjCProtocolRef(ObjCProtocolDecl *Proto, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCProtocolRef cursor into the protocol it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCProtocolDecl *, SourceLocation>
+ getCursorObjCProtocolRef(CXCursor C);
+
+/// \brief Create an Objective-C class reference at the given location.
+CXCursor MakeCursorObjCClassRef(ObjCInterfaceDecl *Class, SourceLocation Loc,
+ ASTUnit *TU);
+
+/// \brief Unpack an ObjCClassRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<ObjCInterfaceDecl *, SourceLocation>
+ getCursorObjCClassRef(CXCursor C);
+
+/// \brief Create a type reference at the given location.
+CXCursor MakeCursorTypeRef(TypeDecl *Type, SourceLocation Loc, ASTUnit *TU);
+
+/// \brief Unpack a TypeRef cursor into the class it references
+/// and optionally the location where the reference occurred.
+std::pair<TypeDecl *, SourceLocation> getCursorTypeRef(CXCursor C);
+
+Decl *getCursorDecl(CXCursor Cursor);
+Expr *getCursorExpr(CXCursor Cursor);
+Stmt *getCursorStmt(CXCursor Cursor);
+ASTContext &getCursorContext(CXCursor Cursor);
+ASTUnit *getCursorASTUnit(CXCursor Cursor);
+
+bool operator==(CXCursor X, CXCursor Y);
+
+inline bool operator!=(CXCursor X, CXCursor Y) {
+ return !(X == Y);
+}
+
+}} // end namespace: clang::cxcursor
+
+#endif
diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile
index 94f0467..7bdbba1 100644
--- a/tools/CIndex/Makefile
+++ b/tools/CIndex/Makefile
@@ -22,7 +22,7 @@ LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
LINK_COMPONENTS := bitreader mc core
-USEDLIBS = clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
+USEDLIBS = clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LEVEL)/Makefile.common
OpenPOWER on IntegriCloud