summaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorrdivacky <rdivacky@FreeBSD.org>2010-05-04 16:12:48 +0000
committerrdivacky <rdivacky@FreeBSD.org>2010-05-04 16:12:48 +0000
commit8aaf5818a64e9f7687798852af5945b053c68a54 (patch)
treed6a70c3518b8dea8be7062438d7e8676820ed17f /tools
parent71438373cd57f0d5d8c93bb5cf690844a0fbc9d0 (diff)
downloadFreeBSD-src-8aaf5818a64e9f7687798852af5945b053c68a54.zip
FreeBSD-src-8aaf5818a64e9f7687798852af5945b053c68a54.tar.gz
Update clang to r103004.
Diffstat (limited to 'tools')
-rw-r--r--tools/CIndex/CIndex.cpp108
-rw-r--r--tools/CIndex/CIndex.darwin.exports81
-rw-r--r--tools/CIndex/CIndex.exports161
-rw-r--r--tools/CIndex/CIndexCodeCompletion.cpp92
-rw-r--r--tools/CIndex/CIndexDiagnostic.cpp1
-rw-r--r--tools/CIndex/CIndexDiagnostic.h15
-rw-r--r--tools/CIndex/CIndexInclusionStack.cpp2
-rw-r--r--tools/CIndex/CIndexUSRs.cpp211
-rw-r--r--tools/CIndex/CIndexer.cpp1
-rw-r--r--tools/CIndex/CIndexer.h4
-rw-r--r--tools/CIndex/CMakeLists.txt6
-rw-r--r--tools/CIndex/CXCursor.cpp2
-rw-r--r--tools/CIndex/CXSourceLocation.h5
-rw-r--r--tools/CIndex/Makefile3
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/Makefile4
-rw-r--r--tools/c-index-test/CMakeLists.txt2
-rw-r--r--tools/c-index-test/Makefile3
-rw-r--r--tools/c-index-test/c-index-test.c9
-rw-r--r--tools/driver/CMakeLists.txt3
-rw-r--r--tools/driver/cc1_main.cpp18
-rw-r--r--tools/libclang/CIndex.cpp2598
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp512
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp285
-rw-r--r--tools/libclang/CIndexDiagnostic.h53
-rw-r--r--tools/libclang/CIndexInclusionStack.cpp67
-rw-r--r--tools/libclang/CIndexUSRs.cpp477
-rw-r--r--tools/libclang/CIndexer.cpp154
-rw-r--r--tools/libclang/CIndexer.h78
-rw-r--r--tools/libclang/CMakeLists.txt57
-rw-r--r--tools/libclang/CXCursor.cpp370
-rw-r--r--tools/libclang/CXCursor.h112
-rw-r--r--tools/libclang/CXSourceLocation.h75
-rw-r--r--tools/libclang/Makefile55
-rw-r--r--tools/libclang/libclang.darwin.exports81
-rw-r--r--tools/libclang/libclang.exports81
-rwxr-xr-xtools/scan-build/ccc-analyzer7
37 files changed, 5632 insertions, 163 deletions
diff --git a/tools/CIndex/CIndex.cpp b/tools/CIndex/CIndex.cpp
index 01130e2..9cdb965 100644
--- a/tools/CIndex/CIndex.cpp
+++ b/tools/CIndex/CIndex.cpp
@@ -22,8 +22,12 @@
#include "clang/AST/DeclVisitor.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "clang/Lex/Preprocessor.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Program.h"
@@ -35,7 +39,6 @@
using namespace clang;
using namespace clang::cxcursor;
using namespace clang::cxstring;
-using namespace idx;
//===----------------------------------------------------------------------===//
// Crash Reporting.
@@ -242,6 +245,7 @@ public:
// Declaration visitors
bool VisitAttributes(Decl *D);
+ bool VisitBlockDecl(BlockDecl *B);
bool VisitDeclContext(DeclContext *DC);
bool VisitTranslationUnitDecl(TranslationUnitDecl *D);
bool VisitTypedefDecl(TypedefDecl *D);
@@ -297,10 +301,12 @@ public:
bool VisitForStmt(ForStmt *S);
// Expression visitors
- bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
- bool VisitExplicitCastExpr(ExplicitCastExpr *E);
+ bool VisitBlockExpr(BlockExpr *B);
bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ bool VisitExplicitCastExpr(ExplicitCastExpr *E);
bool VisitObjCMessageExpr(ObjCMessageExpr *E);
+ bool VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
};
} // end anonymous namespace
@@ -484,6 +490,15 @@ bool CursorVisitor::VisitChildren(CXCursor Cursor) {
return false;
}
+bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
+ for (BlockDecl::param_iterator I=B->param_begin(), E=B->param_end(); I!=E;++I)
+ if (Decl *D = *I)
+ if (Visit(D))
+ return true;
+
+ return Visit(MakeCXCursor(B->getBody(), StmtParent, TU));
+}
+
bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
for (DeclContext::decl_iterator
I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
@@ -814,8 +829,9 @@ bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
return true;
for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
- if (Visit(MakeCXCursor(TL.getArg(I), TU)))
- return true;
+ if (Decl *D = TL.getArg(I))
+ if (Visit(MakeCXCursor(D, TU)))
+ return true;
return false;
}
@@ -923,6 +939,10 @@ bool CursorVisitor::VisitForStmt(ForStmt *S) {
return false;
}
+bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
+ return Visit(B->getBlockDecl());
+}
+
bool CursorVisitor::VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E) {
if (E->isArgumentType()) {
if (TypeSourceInfo *TSInfo = E->getArgumentTypeInfo())
@@ -951,13 +971,18 @@ bool CursorVisitor::VisitCompoundLiteralExpr(CompoundLiteralExpr *E) {
}
bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) {
- ObjCMessageExpr::ClassInfo CI = E->getClassInfo();
- if (CI.Decl && Visit(MakeCursorObjCClassRef(CI.Decl, CI.Loc, TU)))
- return true;
+ if (TypeSourceInfo *TSInfo = E->getClassReceiverTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
return VisitExpr(E);
}
+bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ return Visit(E->getEncodedTypeSourceInfo()->getTypeLoc());
+}
+
+
bool CursorVisitor::VisitAttributes(Decl *D) {
for (const Attr *A = D->getAttrs(); A; A = A->getNext())
if (Visit(MakeCXCursor(A, D, TU)))
@@ -1539,6 +1564,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("ObjCImplementationDecl");
case CXCursor_ObjCCategoryImplDecl:
return createCXString("ObjCCategoryImplDecl");
+ case CXCursor_CXXMethod:
+ return createCXString("CXXMethod");
case CXCursor_UnexposedDecl:
return createCXString("UnexposedDecl");
case CXCursor_ObjCSuperClassRef:
@@ -1551,6 +1578,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("TypeRef");
case CXCursor_UnexposedExpr:
return createCXString("UnexposedExpr");
+ case CXCursor_BlockExpr:
+ return createCXString("BlockExpr");
case CXCursor_DeclRefExpr:
return createCXString("DeclRefExpr");
case CXCursor_MemberRefExpr:
@@ -1892,8 +1921,6 @@ CXCursor clang_getCursorDefinition(CXCursor 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.
@@ -2444,6 +2471,67 @@ CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
} // end: extern "C"
//===----------------------------------------------------------------------===//
+// Operations for querying language of a cursor.
+//===----------------------------------------------------------------------===//
+
+static CXLanguageKind getDeclLanguage(const Decl *D) {
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::ImplicitParam:
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCClass:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::ObjCForwardProtocol:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCIvar:
+ case Decl::ObjCMethod:
+ case Decl::ObjCProperty:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCProtocol:
+ return CXLanguage_ObjC;
+ case Decl::CXXConstructor:
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXMethod:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplate:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::LinkageSpec:
+ case Decl::Namespace:
+ case Decl::NamespaceAlias:
+ case Decl::NonTypeTemplateParm:
+ case Decl::StaticAssert:
+ case Decl::TemplateTemplateParm:
+ case Decl::TemplateTypeParm:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ case Decl::Using:
+ case Decl::UsingDirective:
+ case Decl::UsingShadow:
+ return CXLanguage_CPlusPlus;
+ }
+
+ return CXLanguage_C;
+}
+
+extern "C" {
+CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ return getDeclLanguage(cxcursor::getCursorDecl(cursor));
+
+ return CXLanguage_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
// CXString Operations.
//===----------------------------------------------------------------------===//
diff --git a/tools/CIndex/CIndex.darwin.exports b/tools/CIndex/CIndex.darwin.exports
new file mode 100644
index 0000000..b361168
--- /dev/null
+++ b/tools/CIndex/CIndex.darwin.exports
@@ -0,0 +1,81 @@
+_clang_annotateTokens
+_clang_codeComplete
+_clang_codeCompleteGetDiagnostic
+_clang_codeCompleteGetNumDiagnostics
+_clang_constructUSR_ObjCCategory
+_clang_constructUSR_ObjCClass
+_clang_constructUSR_ObjCIvar
+_clang_constructUSR_ObjCMethod
+_clang_constructUSR_ObjCProperty
+_clang_constructUSR_ObjCProtocol
+_clang_createIndex
+_clang_createTranslationUnit
+_clang_createTranslationUnitFromSourceFile
+_clang_defaultDiagnosticDisplayOptions
+_clang_disposeCodeCompleteResults
+_clang_disposeDiagnostic
+_clang_disposeIndex
+_clang_disposeString
+_clang_disposeTokens
+_clang_disposeTranslationUnit
+_clang_enableStackTraces
+_clang_equalCursors
+_clang_equalLocations
+_clang_formatDiagnostic
+_clang_getCString
+_clang_getClangVersion
+_clang_getCompletionChunkCompletionString
+_clang_getCompletionChunkKind
+_clang_getCompletionChunkText
+_clang_getCursor
+_clang_getCursorDefinition
+_clang_getCursorExtent
+_clang_getCursorKind
+_clang_getCursorKindSpelling
+_clang_getCursorLanguage
+_clang_getCursorLinkage
+_clang_getCursorLocation
+_clang_getCursorReferenced
+_clang_getCursorSpelling
+_clang_getCursorUSR
+_clang_getDefinitionSpellingAndExtent
+_clang_getDiagnostic
+_clang_getDiagnosticFixIt
+_clang_getDiagnosticLocation
+_clang_getDiagnosticNumFixIts
+_clang_getDiagnosticNumRanges
+_clang_getDiagnosticRange
+_clang_getDiagnosticSeverity
+_clang_getDiagnosticSpelling
+_clang_getFile
+_clang_getFileName
+_clang_getFileTime
+_clang_getInclusions
+_clang_getInstantiationLocation
+_clang_getLocation
+_clang_getNullCursor
+_clang_getNullLocation
+_clang_getNullRange
+_clang_getNumCompletionChunks
+_clang_getNumDiagnostics
+_clang_getRange
+_clang_getRangeEnd
+_clang_getRangeStart
+_clang_getTokenExtent
+_clang_getTokenKind
+_clang_getTokenLocation
+_clang_getTokenSpelling
+_clang_getTranslationUnitCursor
+_clang_getTranslationUnitSpelling
+_clang_isCursorDefinition
+_clang_isDeclaration
+_clang_isExpression
+_clang_isInvalid
+_clang_isPreprocessing
+_clang_isReference
+_clang_isStatement
+_clang_isTranslationUnit
+_clang_isUnexposed
+_clang_setUseExternalASTGeneration
+_clang_tokenize
+_clang_visitChildren
diff --git a/tools/CIndex/CIndex.exports b/tools/CIndex/CIndex.exports
index d036e5c..991bb06 100644
--- a/tools/CIndex/CIndex.exports
+++ b/tools/CIndex/CIndex.exports
@@ -1,80 +1,81 @@
-_clang_annotateTokens
-_clang_codeComplete
-_clang_codeCompleteGetDiagnostic
-_clang_codeCompleteGetNumDiagnostics
-_clang_constructUSR_ObjCClass
-_clang_constructUSR_ObjCCategory
-_clang_constructUSR_ObjCIvar
-_clang_constructUSR_ObjCMethod
-_clang_constructUSR_ObjCProtocol
-_clang_constructUSR_ObjCProperty
-_clang_createIndex
-_clang_createTranslationUnit
-_clang_createTranslationUnitFromSourceFile
-_clang_defaultDiagnosticDisplayOptions
-_clang_disposeCodeCompleteResults
-_clang_disposeDiagnostic
-_clang_disposeIndex
-_clang_disposeString
-_clang_disposeTokens
-_clang_disposeTranslationUnit
-_clang_enableStackTraces
-_clang_equalCursors
-_clang_equalLocations
-_clang_formatDiagnostic
-_clang_getClangVersion
-_clang_getCString
-_clang_getCompletionChunkCompletionString
-_clang_getCompletionChunkKind
-_clang_getCompletionChunkText
-_clang_getCursor
-_clang_getCursorDefinition
-_clang_getCursorExtent
-_clang_getCursorKind
-_clang_getCursorKindSpelling
-_clang_getCursorLinkage
-_clang_getCursorLocation
-_clang_getCursorReferenced
-_clang_getCursorSpelling
-_clang_getCursorUSR
-_clang_getDefinitionSpellingAndExtent
-_clang_getDiagnostic
-_clang_getDiagnosticFixIt
-_clang_getDiagnosticLocation
-_clang_getDiagnosticNumFixIts
-_clang_getDiagnosticNumRanges
-_clang_getDiagnosticRange
-_clang_getDiagnosticSeverity
-_clang_getDiagnosticSpelling
-_clang_getFile
-_clang_getFileName
-_clang_getFileTime
-_clang_getInclusions
-_clang_getInstantiationLocation
-_clang_getLocation
-_clang_getNullCursor
-_clang_getNullLocation
-_clang_getNullRange
-_clang_getNumCompletionChunks
-_clang_getNumDiagnostics
-_clang_getRange
-_clang_getRangeEnd
-_clang_getRangeStart
-_clang_getTokenExtent
-_clang_getTokenKind
-_clang_getTokenLocation
-_clang_getTokenSpelling
-_clang_getTranslationUnitCursor
-_clang_getTranslationUnitSpelling
-_clang_isCursorDefinition
-_clang_isDeclaration
-_clang_isExpression
-_clang_isInvalid
-_clang_isPreprocessing
-_clang_isReference
-_clang_isStatement
-_clang_isTranslationUnit
-_clang_isUnexposed
-_clang_setUseExternalASTGeneration
-_clang_tokenize
-_clang_visitChildren
+clang_annotateTokens
+clang_codeComplete
+clang_codeCompleteGetDiagnostic
+clang_codeCompleteGetNumDiagnostics
+clang_constructUSR_ObjCCategory
+clang_constructUSR_ObjCClass
+clang_constructUSR_ObjCIvar
+clang_constructUSR_ObjCMethod
+clang_constructUSR_ObjCProperty
+clang_constructUSR_ObjCProtocol
+clang_createIndex
+clang_createTranslationUnit
+clang_createTranslationUnitFromSourceFile
+clang_defaultDiagnosticDisplayOptions
+clang_disposeCodeCompleteResults
+clang_disposeDiagnostic
+clang_disposeIndex
+clang_disposeString
+clang_disposeTokens
+clang_disposeTranslationUnit
+clang_enableStackTraces
+clang_equalCursors
+clang_equalLocations
+clang_formatDiagnostic
+clang_getCString
+clang_getClangVersion
+clang_getCompletionChunkCompletionString
+clang_getCompletionChunkKind
+clang_getCompletionChunkText
+clang_getCursor
+clang_getCursorDefinition
+clang_getCursorExtent
+clang_getCursorKind
+clang_getCursorKindSpelling
+clang_getCursorLanguage
+clang_getCursorLinkage
+clang_getCursorLocation
+clang_getCursorReferenced
+clang_getCursorSpelling
+clang_getCursorUSR
+clang_getDefinitionSpellingAndExtent
+clang_getDiagnostic
+clang_getDiagnosticFixIt
+clang_getDiagnosticLocation
+clang_getDiagnosticNumFixIts
+clang_getDiagnosticNumRanges
+clang_getDiagnosticRange
+clang_getDiagnosticSeverity
+clang_getDiagnosticSpelling
+clang_getFile
+clang_getFileName
+clang_getFileTime
+clang_getInclusions
+clang_getInstantiationLocation
+clang_getLocation
+clang_getNullCursor
+clang_getNullLocation
+clang_getNullRange
+clang_getNumCompletionChunks
+clang_getNumDiagnostics
+clang_getRange
+clang_getRangeEnd
+clang_getRangeStart
+clang_getTokenExtent
+clang_getTokenKind
+clang_getTokenLocation
+clang_getTokenSpelling
+clang_getTranslationUnitCursor
+clang_getTranslationUnitSpelling
+clang_isCursorDefinition
+clang_isDeclaration
+clang_isExpression
+clang_isInvalid
+clang_isPreprocessing
+clang_isReference
+clang_isStatement
+clang_isTranslationUnit
+clang_isUnexposed
+clang_setUseExternalASTGeneration
+clang_tokenize
+clang_visitChildren
diff --git a/tools/CIndex/CIndexCodeCompletion.cpp b/tools/CIndex/CIndexCodeCompletion.cpp
index d11b8df..a21614c 100644
--- a/tools/CIndex/CIndexCodeCompletion.cpp
+++ b/tools/CIndex/CIndexCodeCompletion.cpp
@@ -14,12 +14,26 @@
#include "CIndexer.h"
#include "CIndexDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/System/Program.h"
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
using namespace clang;
using namespace clang::cxstring;
@@ -226,6 +240,12 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
const char *complete_filename,
unsigned complete_line,
unsigned complete_column) {
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
+#endif
+#endif
+
// The indexer, which is mainly used to determine where diagnostics go.
CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
@@ -383,6 +403,78 @@ CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
// destroyed.
Results->TemporaryFiles.swap(TemporaryFiles);
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
+ llvm::SmallString<256> LogResult;
+ llvm::raw_svector_ostream os(LogResult);
+
+ // Figure out the language and whether or not it uses PCH.
+ const char *lang = 0;
+ bool usesPCH = false;
+
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ if (*I == 0)
+ continue;
+ if (strcmp(*I, "-x") == 0) {
+ if (I + 1 != E) {
+ lang = *(++I);
+ continue;
+ }
+ }
+ else if (strcmp(*I, "-include") == 0) {
+ if (I+1 != E) {
+ const char *arg = *(++I);
+ llvm::SmallString<512> pchName;
+ {
+ llvm::raw_svector_ostream os(pchName);
+ os << arg << ".pth";
+ }
+ pchName.push_back('\0');
+ struct stat stat_results;
+ if (stat(pchName.data(), &stat_results) == 0)
+ usesPCH = true;
+ continue;
+ }
+ }
+ }
+
+ os << "{ ";
+ os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
+ os << ", \"numRes\": " << Results->NumResults;
+ os << ", \"diags\": " << Results->Diagnostics.size();
+ os << ", \"pch\": " << (usesPCH ? "true" : "false");
+ os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
+ const char *name = getlogin();
+ os << ", \"user\": \"" << (name ? name : "unknown") << '"';
+ os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
+ os << " }";
+
+ llvm::StringRef res = os.str();
+ if (res.size() > 0) {
+ do {
+ // Setup the UDP socket.
+ struct sockaddr_in servaddr;
+ bzero(&servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
+ if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
+ &servaddr.sin_addr) <= 0)
+ break;
+
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ break;
+
+ sendto(sockfd, res.data(), res.size(), 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ close(sockfd);
+ }
+ while (false);
+ }
+#endif
+#endif
return Results;
}
diff --git a/tools/CIndex/CIndexDiagnostic.cpp b/tools/CIndex/CIndexDiagnostic.cpp
index bcf066d..3db37b9 100644
--- a/tools/CIndex/CIndexDiagnostic.cpp
+++ b/tools/CIndex/CIndexDiagnostic.cpp
@@ -14,6 +14,7 @@
#include "CIndexer.h"
#include "CXSourceLocation.h"
+#include "clang/Frontend/ASTUnit.h"
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/Twine.h"
diff --git a/tools/CIndex/CIndexDiagnostic.h b/tools/CIndex/CIndexDiagnostic.h
index 79a5df0..919c21c 100644
--- a/tools/CIndex/CIndexDiagnostic.h
+++ b/tools/CIndex/CIndexDiagnostic.h
@@ -13,20 +13,21 @@
#ifndef LLVM_CLANG_CINDEX_DIAGNOSTIC_H
#define LLVM_CLANG_CINDEX_DIAGNOSTIC_H
-#include "clang-c/Index.h"
-#include "clang/Basic/Diagnostic.h"
-#include "clang/Basic/LangOptions.h"
-#include "llvm/ADT/SmallVector.h"
+struct CXUnsavedFile;
-namespace llvm { namespace sys {
-class Path;
-} }
+namespace llvm {
+template<typename T> class SmallVectorImpl;
+namespace sys { class Path; }
+}
namespace clang {
class Diagnostic;
+class FileManager;
class LangOptions;
class Preprocessor;
+class StoredDiagnostic;
+class SourceManager;
/// \brief The storage behind a CXDiagnostic
struct CXStoredDiagnostic {
diff --git a/tools/CIndex/CIndexInclusionStack.cpp b/tools/CIndex/CIndexInclusionStack.cpp
index 4a884e5..e863239 100644
--- a/tools/CIndex/CIndexInclusionStack.cpp
+++ b/tools/CIndex/CIndexInclusionStack.cpp
@@ -15,8 +15,10 @@
#include "CIndexer.h"
#include "CXSourceLocation.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
+using namespace clang;
extern "C" {
void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
diff --git a/tools/CIndex/CIndexUSRs.cpp b/tools/CIndex/CIndexUSRs.cpp
index 379320c..58870b9 100644
--- a/tools/CIndex/CIndexUSRs.cpp
+++ b/tools/CIndex/CIndexUSRs.cpp
@@ -14,9 +14,12 @@
#include "CIndexer.h"
#include "CXCursor.h"
#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Lex/PreprocessingRecord.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/raw_ostream.h"
+using namespace clang;
using namespace clang::cxstring;
//===----------------------------------------------------------------------===//
@@ -27,8 +30,10 @@ namespace {
class USRGenerator : public DeclVisitor<USRGenerator> {
llvm::raw_ostream &Out;
bool IgnoreResults;
+ ASTUnit *AU;
public:
- USRGenerator(llvm::raw_ostream &out) : Out(out), IgnoreResults(false) {}
+ USRGenerator(ASTUnit *au, llvm::raw_ostream &out)
+ : Out(out), IgnoreResults(false), AU(au) {}
bool ignoreResults() const { return IgnoreResults; }
@@ -39,12 +44,19 @@ public:
void VisitFunctionDecl(FunctionDecl *D);
void VisitNamedDecl(NamedDecl *D);
void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitObjCClassDecl(ObjCClassDecl *CD);
void VisitObjCContainerDecl(ObjCContainerDecl *CD);
+ void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
void VisitObjCMethodDecl(ObjCMethodDecl *MD);
void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
void VisitTagDecl(TagDecl *D);
void VisitTypedefDecl(TypedefDecl *D);
+ void VisitVarDecl(VarDecl *D);
+ /// Generate the string component containing the location of the
+ /// declaration.
+ void GenLoc(const Decl *D);
/// String generation methods used both by the visitation methods
/// and from other clients that want to directly generate USRs. These
@@ -78,10 +90,10 @@ private:
llvm::raw_svector_ostream Out;
USRGenerator UG;
public:
- StringUSRGenerator()
- : Out(StrBuf), UG(Out) {
+ StringUSRGenerator(const CXCursor *C = 0)
+ : Out(StrBuf), UG(C ? cxcursor::getCursorASTUnit(*C) : 0, Out) {
// Add the USR space prefix.
- Out << "c:";
+ Out << "c:";
}
llvm::StringRef str() {
@@ -106,7 +118,7 @@ public:
void USRGenerator::VisitBlockDecl(BlockDecl *D) {
VisitDeclContext(D->getDeclContext());
// FIXME: Better support for anonymous blocks.
- Out << "@B^anon";
+ Out << "@B@anon";
}
void USRGenerator::VisitDeclContext(DeclContext *DC) {
@@ -122,24 +134,48 @@ void USRGenerator::VisitFieldDecl(FieldDecl *D) {
return;
}
VisitDeclContext(D->getDeclContext());
- Out << "@^FI^" << s;
+ Out << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@") << s;
}
void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
VisitDeclContext(D->getDeclContext());
- Out << "@F^" << D->getNameAsString();
+ Out << "@F@" << D;
}
void USRGenerator::VisitNamedDecl(NamedDecl *D) {
VisitDeclContext(D->getDeclContext());
const std::string &s = D->getNameAsString();
- // assert(!s.empty());
- GenNamedDecl(s);
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ GenNamedDecl(s);
+}
+
+void USRGenerator::VisitVarDecl(VarDecl *D) {
+ // VarDecls can be declared 'extern' within a function or method body,
+ // but their enclosing DeclContext is the function, not the TU. We need
+ // to check the storage class to correctly generate the USR.
+ if (!D->hasExternalStorage())
+ VisitDeclContext(D->getDeclContext());
+
+ const std::string &s = D->getNameAsString();
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ GenNamedDecl(s);
}
void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
VisitDeclContext(D->getDeclContext());
- Out << "@N^" << D->getNameAsString();
+ Out << "@N@" << D;
}
void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
@@ -148,6 +184,18 @@ void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
D->isInstanceMethod());
}
+void USRGenerator::VisitObjCClassDecl(ObjCClassDecl *D) {
+ // FIXME: @class declarations can refer to multiple classes. We need
+ // to be able to traverse these.
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ // FIXME: @protocol declarations can refer to multiple protocols. We need
+ // to be able to traverse these.
+ IgnoreResults = true;
+}
+
void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
switch (D->getKind()) {
default:
@@ -195,32 +243,85 @@ void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
GenObjCProperty(D->getName());
}
+void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
+ VisitObjCPropertyDecl(PD);
+ return;
+ }
+
+ IgnoreResults = true;
+}
+
void USRGenerator::VisitTagDecl(TagDecl *D) {
+ D = D->getCanonicalDecl();
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;
+ 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();
+ const TypedefDecl *TD = 0;
if (s.empty()) {
- if (TypedefDecl *TD = D->getTypedefForAnonDecl())
- Out << "^anontd^" << TD->getNameAsString();
- else
- Out << "^anon";
+ TD = D->getTypedefForAnonDecl();
+ Out << (TD ? 'A' : 'a');
+ }
+
+ // Add the location of the tag decl to handle resolution across
+ // translation units.
+ if (D->getLinkage() == NoLinkage) {
+ Out << '@';
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ }
+
+ if (s.empty()) {
+ if (TD)
+ Out << '@' << TD;
}
else
- Out << s;
+ Out << '@' << s;
}
void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
DeclContext *DC = D->getDeclContext();
if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
Visit(DCN);
- Out << "typedef@" << D->getName();
+ Out << "@T@";
+ if (D->getLinkage() == NoLinkage) {
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ Out << '@';
+ }
+ Out << D->getName();
+}
+
+void USRGenerator::GenLoc(const Decl *D) {
+ const SourceManager &SM = AU->getSourceManager();
+ SourceLocation L = D->getLocStart();
+ if (L.isInvalid()) {
+ IgnoreResults = true;
+ return;
+ }
+ L = SM.getInstantiationLoc(L);
+ const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
+ const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
+ if (FE) {
+ llvm::sys::Path P(FE->getName());
+ Out << P.getLast();
+ }
+ else {
+ // This case really isn't interesting.
+ IgnoreResults = true;
+ return;
+ }
+ Out << '@'
+ << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':'
+ << SM.getColumnNumber(Decomposed.first, Decomposed.second);
}
//===----------------------------------------------------------------------===//
@@ -228,7 +329,7 @@ void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
//===----------------------------------------------------------------------===//
void USRGenerator::GenNamedDecl(llvm::StringRef name) {
- Out << "@^" << name;
+ Out << "@" << name;
}
void USRGenerator::GenObjCClass(llvm::StringRef cls) {
@@ -236,7 +337,7 @@ void USRGenerator::GenObjCClass(llvm::StringRef cls) {
}
void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) {
- Out << "objc(cy)" << cls << '^' << cat;
+ Out << "objc(cy)" << cls << '@' << cat;
}
void USRGenerator::GenObjCIvar(llvm::StringRef ivar) {
@@ -259,29 +360,69 @@ void USRGenerator::GenObjCProtocol(llvm::StringRef prot) {
// API hooks.
//===----------------------------------------------------------------------===//
-extern "C" {
+static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) {
+ return s.startswith("c:") ? s.substr(2) : "";
+}
-CXString clang_getCursorUSR(CXCursor C) {
+static CXString getDeclCursorUSR(const CXCursor &C) {
Decl *D = cxcursor::getCursorDecl(C);
- if (!D)
- return createCXString(NULL);
- StringUSRGenerator SUG;
- SUG->Visit(static_cast<Decl*>(D));
+ // Don't generate USRs for things with invalid locations.
+ if (!D || D->getLocStart().isInvalid())
+ return createCXString("");
+
+ // Check if the cursor has 'NoLinkage'.
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ switch (ND->getLinkage()) {
+ case ExternalLinkage:
+ // Generate USRs for all entities with external linkage.
+ break;
+ case NoLinkage:
+ // We allow enums, typedefs, and structs that have no linkage to
+ // have USRs that are anchored to the file they were defined in
+ // (e.g., the header). This is a little gross, but in principal
+ // enums/anonymous structs/etc. defined in a common header file
+ // are referred to across multiple translation units.
+ if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
+ isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND))
+ break;
+ // Fall-through.
+ case InternalLinkage:
+ case UniqueExternalLinkage:
+ return createCXString("");
+ }
+
+ StringUSRGenerator SUG(&C);
+ SUG->Visit(D);
if (SUG->ignoreResults())
return createCXString("");
- // Return a copy of the string that must be disposed by the caller.
+ // For development testing.
+ // assert(SUG.str().size() > 2);
+
+ // Return a copy of the string that must be disposed by the caller.
return createCXString(SUG.str(), true);
}
-static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) {
- if (!(s.size() >= 2 && s[0] == 'c' && s[1] == ':'))
- return "";
- return s.substr(2);
+extern "C" {
+
+CXString clang_getCursorUSR(CXCursor C) {
+ const CXCursorKind &K = clang_getCursorKind(C);
+
+ if (clang_isDeclaration(K))
+ return getDeclCursorUSR(C);
+
+ if (K == CXCursor_MacroDefinition) {
+ StringUSRGenerator SUG(&C);
+ SUG << "macro@"
+ << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();
+ return createCXString(SUG.str(), true);
+ }
+
+ return createCXString("");
}
-
+
CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
StringUSRGenerator SUG;
SUG << extractUSRSuffix(clang_getCString(classUSR));
diff --git a/tools/CIndex/CIndexer.cpp b/tools/CIndex/CIndexer.cpp
index 0774ae2..d5131ff 100644
--- a/tools/CIndex/CIndexer.cpp
+++ b/tools/CIndex/CIndexer.cpp
@@ -38,7 +38,6 @@
#endif
using namespace clang;
-using namespace idx;
const llvm::sys::Path& CIndexer::getClangPath() {
// Did we already compute the path?
diff --git a/tools/CIndex/CIndexer.h b/tools/CIndex/CIndexer.h
index 1fa3ca9..31bf779 100644
--- a/tools/CIndex/CIndexer.h
+++ b/tools/CIndex/CIndexer.h
@@ -16,14 +16,10 @@
#define LLVM_CLANG_CINDEXER_H
#include "clang-c/Index.h"
-#include "clang/Frontend/CompilerInstance.h"
-#include "clang/Frontend/ASTUnit.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/System/Path.h"
#include <vector>
-using namespace clang;
-
namespace clang {
namespace cxstring {
CXString createCXString(const char *String, bool DupString = false);
diff --git a/tools/CIndex/CMakeLists.txt b/tools/CIndex/CMakeLists.txt
index 6aa7a57..609719e 100644
--- a/tools/CIndex/CMakeLists.txt
+++ b/tools/CIndex/CMakeLists.txt
@@ -32,9 +32,13 @@ add_clang_library(CIndex
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
# FIXME: Deal with LLVM_SUBMIT_VERSION?
+ # FIXME: This uses a special darwin-specific exports file in order to
+ # get underscore-prefixed names. It would be better to have build rules
+ # which know how to produce a darwin-suitable exports file from the
+ # regular exports file.
set_target_properties(CIndex
PROPERTIES
- LINK_FLAGS "-avoid-version -Wl,-exported_symbols_list -Wl,${CMAKE_CURRENT_SOURCE_DIR}/CIndex.exports -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000"
+ LINK_FLAGS "-avoid-version -Wl,-exported_symbols_list -Wl,${CMAKE_CURRENT_SOURCE_DIR}/CIndex.darwin.exports -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000"
INSTALL_NAME_DIR "@executable_path/../lib"
)
endif()
diff --git a/tools/CIndex/CXCursor.cpp b/tools/CIndex/CXCursor.cpp
index cbf9d7e..3bc5d01 100644
--- a/tools/CIndex/CXCursor.cpp
+++ b/tools/CIndex/CXCursor.cpp
@@ -50,6 +50,7 @@ static CXCursorKind GetCursorKind(Decl *D) {
case Decl::ObjCMethod:
return cast<ObjCMethodDecl>(D)->isInstanceMethod()
? CXCursor_ObjCInstanceMethodDecl : CXCursor_ObjCClassMethodDecl;
+ case Decl::CXXMethod: return CXCursor_CXXMethod;
case Decl::ObjCProperty: return CXCursor_ObjCPropertyDecl;
case Decl::ObjCProtocol: return CXCursor_ObjCProtocolDecl;
case Decl::ParmVar: return CXCursor_ParmDecl;
@@ -159,7 +160,6 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) {
case Stmt::TypesCompatibleExprClass:
case Stmt::ChooseExprClass:
case Stmt::GNUNullExprClass:
- case Stmt::CXXNamedCastExprClass:
case Stmt::CXXStaticCastExprClass:
case Stmt::CXXDynamicCastExprClass:
case Stmt::CXXReinterpretCastExprClass:
diff --git a/tools/CIndex/CXSourceLocation.h b/tools/CIndex/CXSourceLocation.h
index 8bfc6f9..66566c1 100644
--- a/tools/CIndex/CXSourceLocation.h
+++ b/tools/CIndex/CXSourceLocation.h
@@ -16,13 +16,12 @@
#include "clang-c/Index.h"
#include "clang/Basic/SourceLocation.h"
-#include "clang/Basic/SourceManager.h"
#include "clang/Basic/LangOptions.h"
#include "clang/AST/ASTContext.h"
namespace clang {
-
-class ASTContext;
+
+class SourceManager;
namespace cxloc {
diff --git a/tools/CIndex/Makefile b/tools/CIndex/Makefile
index 650bcd3..391746d 100644
--- a/tools/CIndex/Makefile
+++ b/tools/CIndex/Makefile
@@ -10,6 +10,8 @@
LEVEL = ../../../..
LIBRARYNAME = CIndex
+EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/CIndex.exports
+
CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
# Include this here so we can get the configuration of the targets
@@ -40,7 +42,6 @@ ifeq ($(HOST_OS),Darwin)
# extra options to override libtool defaults
LLVMLibsOptions := $(LLVMLibsOptions) \
-avoid-version \
- -Wl,-exported_symbols_list -Wl,$(PROJ_SRC_DIR)/CIndex.exports \
-Wl,-dead_strip \
-Wl,-seg1addr -Wl,0xE0000000
diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt
index 64c3a21..ae33b78 100644
--- a/tools/CMakeLists.txt
+++ b/tools/CMakeLists.txt
@@ -1,3 +1,3 @@
-add_subdirectory(CIndex)
+add_subdirectory(libclang)
add_subdirectory(c-index-test)
add_subdirectory(driver)
diff --git a/tools/Makefile b/tools/Makefile
index bfd5ad1..8407dfd 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -8,12 +8,12 @@
##===----------------------------------------------------------------------===##
LEVEL := ../../..
-DIRS := driver CIndex c-index-test
+DIRS := driver libclang c-index-test
include $(LEVEL)/Makefile.config
ifeq ($(OS), $(filter $(OS), Cygwin MingW))
-DIRS := $(filter-out CIndex c-index-test, $(DIRS))
+DIRS := $(filter-out libclang c-index-test, $(DIRS))
endif
include $(LEVEL)/Makefile.common
diff --git a/tools/c-index-test/CMakeLists.txt b/tools/c-index-test/CMakeLists.txt
index f0a34a5..d965fd2 100644
--- a/tools/c-index-test/CMakeLists.txt
+++ b/tools/c-index-test/CMakeLists.txt
@@ -1,7 +1,7 @@
set(LLVM_NO_RTTI 1)
set( LLVM_USED_LIBS
- CIndex
+ libclang
clangIndex
clangFrontend
clangDriver
diff --git a/tools/c-index-test/Makefile b/tools/c-index-test/Makefile
index e9ba174..24fed16 100644
--- a/tools/c-index-test/Makefile
+++ b/tools/c-index-test/Makefile
@@ -10,7 +10,6 @@ LEVEL = ../../../..
TOOLNAME = c-index-test
CPPFLAGS += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
-NO_INSTALL = 1
# No plugins, optimize startup time.
TOOL_NO_EXPORTS = 1
@@ -18,7 +17,7 @@ TOOL_NO_EXPORTS = 1
include $(LEVEL)/Makefile.config
LINK_COMPONENTS := bitreader mc core
-USEDLIBS = CIndex.a clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
+USEDLIBS = clang.a clangIndex.a clangFrontend.a clangDriver.a clangSema.a \
clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
include $(LLVM_SRC_ROOT)/Makefile.rules
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index d7f3483..4941816 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -372,12 +372,13 @@ enum CXChildVisitResult USRVisitor(CXCursor C, CXCursor parent,
VisitorData *Data = (VisitorData *)ClientData;
if (!Data->Filter || (C.kind == *(enum CXCursorKind *)Data->Filter)) {
CXString USR = clang_getCursorUSR(C);
- if (!clang_getCString(USR)) {
+ const char *cstr = clang_getCString(USR);
+ if (!cstr || cstr[0] == '\0') {
clang_disposeString(USR);
- return CXChildVisit_Continue;
+ return CXChildVisit_Recurse;
}
- printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C),
- clang_getCString(USR));
+ printf("// %s: %s %s", FileCheckPrefix, GetCursorSource(C), cstr);
+
PrintCursorExtent(C);
printf("\n");
clang_disposeString(USR);
diff --git a/tools/driver/CMakeLists.txt b/tools/driver/CMakeLists.txt
index c4320b0..ca2f408 100644
--- a/tools/driver/CMakeLists.txt
+++ b/tools/driver/CMakeLists.txt
@@ -30,6 +30,7 @@ add_clang_executable(clang
if(UNIX)
set(CLANGXX_LINK_OR_COPY create_symlink)
+ set(CLANGXX_DESTDIR $ENV{DESTDIR}/)
else()
set(CLANGXX_LINK_OR_COPY copy)
endif()
@@ -45,4 +46,4 @@ install(TARGETS clang
RUNTIME DESTINATION bin)
# Create the clang++ symlink at installation time.
-install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E ${CLANGXX_LINK_OR_COPY} \"${CMAKE_INSTALL_PREFIX}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}\" \"\$ENV{DESTDIR}/\${CMAKE_INSTALL_PREFIX}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}\")")
+install(CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E ${CLANGXX_LINK_OR_COPY} \"${CMAKE_INSTALL_PREFIX}/bin/clang${CMAKE_EXECUTABLE_SUFFIX}\" \"${CLANGXX_DESTDIR}${CMAKE_INSTALL_PREFIX}/bin/clang++${CMAKE_EXECUTABLE_SUFFIX}\")")
diff --git a/tools/driver/cc1_main.cpp b/tools/driver/cc1_main.cpp
index dd440f5..144a734 100644
--- a/tools/driver/cc1_main.cpp
+++ b/tools/driver/cc1_main.cpp
@@ -64,7 +64,6 @@ static FrontendAction *CreateFrontendBaseAction(CompilerInstance &CI) {
case ASTPrintXML: return new ASTPrintXMLAction();
case ASTView: return new ASTViewAction();
case DumpRawTokens: return new DumpRawTokensAction();
- case DumpRecordLayouts: return new DumpRecordAction();
case DumpTokens: return new DumpTokensAction();
case EmitAssembly: return new EmitAssemblyAction();
case EmitBC: return new EmitBCAction();
@@ -199,7 +198,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
const char *Argv0, void *MainAddr) {
llvm::OwningPtr<CompilerInstance> Clang(new CompilerInstance());
- Clang->setLLVMContext(new llvm::LLVMContext);
+ Clang->setLLVMContext(new llvm::LLVMContext());
// Run clang -cc1 test.
if (ArgBegin != ArgEnd && llvm::StringRef(ArgBegin[0]) == "-cc1test") {
@@ -242,6 +241,19 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
return 0;
}
+ // Honor -mllvm.
+ //
+ // FIXME: Remove this, one day.
+ if (!Clang->getFrontendOpts().LLVMArgs.empty()) {
+ unsigned NumArgs = Clang->getFrontendOpts().LLVMArgs.size();
+ const char **Args = new const char*[NumArgs + 2];
+ Args[0] = "clang (LLVM option parsing)";
+ for (unsigned i = 0; i != NumArgs; ++i)
+ Args[i + 1] = Clang->getFrontendOpts().LLVMArgs[i].c_str();
+ Args[NumArgs + 1] = 0;
+ llvm::cl::ParseCommandLineOptions(NumArgs + 1, const_cast<char **>(Args));
+ }
+
// Create the actual diagnostics engine.
Clang->createDiagnostics(ArgEnd - ArgBegin, const_cast<char**>(ArgBegin));
if (!Clang->hasDiagnostics())
@@ -249,7 +261,7 @@ int cc1_main(const char **ArgBegin, const char **ArgEnd,
// Set an error handler, so that any LLVM backend diagnostics go through our
// error handler.
- llvm::llvm_install_error_handler(LLVMErrorHandler,
+ llvm::install_fatal_error_handler(LLVMErrorHandler,
static_cast<void*>(&Clang->getDiagnostics()));
DiagsBuffer.FlushDiagnostics(Clang->getDiagnostics());
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
new file mode 100644
index 0000000..f9f7351
--- /dev/null
+++ b/tools/libclang/CIndex.cpp
@@ -0,0 +1,2598 @@
+//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the main API hooks in the Clang-C Source Indexing
+// library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "CXSourceLocation.h"
+#include "CIndexDiagnostic.h"
+
+#include "clang/Basic/Version.h"
+
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/AST/TypeLocVisitor.h"
+#include "clang/Basic/Diagnostic.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Lex/Lexer.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "clang/Lex/Preprocessor.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Program.h"
+#include "llvm/System/Signals.h"
+
+// Needed to define L_TMPNAM on some systems.
+#include <cstdio>
+
+using namespace clang;
+using namespace clang::cxcursor;
+using namespace clang::cxstring;
+
+//===----------------------------------------------------------------------===//
+// Crash Reporting.
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+#define USE_CRASHTRACER
+#include "clang/Analysis/Support/SaveAndRestore.h"
+// Integrate with crash reporter.
+extern "C" const char *__crashreporter_info__;
+#define NUM_CRASH_STRINGS 32
+static unsigned crashtracer_counter = 0;
+static unsigned crashtracer_counter_id[NUM_CRASH_STRINGS] = { 0 };
+static const char *crashtracer_strings[NUM_CRASH_STRINGS] = { 0 };
+static const char *agg_crashtracer_strings[NUM_CRASH_STRINGS] = { 0 };
+
+static unsigned SetCrashTracerInfo(const char *str,
+ llvm::SmallString<1024> &AggStr) {
+
+ unsigned slot = 0;
+ while (crashtracer_strings[slot]) {
+ if (++slot == NUM_CRASH_STRINGS)
+ slot = 0;
+ }
+ crashtracer_strings[slot] = str;
+ crashtracer_counter_id[slot] = ++crashtracer_counter;
+
+ // We need to create an aggregate string because multiple threads
+ // may be in this method at one time. The crash reporter string
+ // will attempt to overapproximate the set of in-flight invocations
+ // of this function. Race conditions can still cause this goal
+ // to not be achieved.
+ {
+ llvm::raw_svector_ostream Out(AggStr);
+ for (unsigned i = 0; i < NUM_CRASH_STRINGS; ++i)
+ if (crashtracer_strings[i]) Out << crashtracer_strings[i] << '\n';
+ }
+ __crashreporter_info__ = agg_crashtracer_strings[slot] = AggStr.c_str();
+ return slot;
+}
+
+static void ResetCrashTracerInfo(unsigned slot) {
+ unsigned max_slot = 0;
+ unsigned max_value = 0;
+
+ crashtracer_strings[slot] = agg_crashtracer_strings[slot] = 0;
+
+ for (unsigned i = 0 ; i < NUM_CRASH_STRINGS; ++i)
+ if (agg_crashtracer_strings[i] &&
+ crashtracer_counter_id[i] > max_value) {
+ max_slot = i;
+ max_value = crashtracer_counter_id[i];
+ }
+
+ __crashreporter_info__ = agg_crashtracer_strings[max_slot];
+}
+
+namespace {
+class ArgsCrashTracerInfo {
+ llvm::SmallString<1024> CrashString;
+ llvm::SmallString<1024> AggregateString;
+ unsigned crashtracerSlot;
+public:
+ ArgsCrashTracerInfo(llvm::SmallVectorImpl<const char*> &Args)
+ : crashtracerSlot(0)
+ {
+ {
+ llvm::raw_svector_ostream Out(CrashString);
+ Out << "ClangCIndex [" << getClangFullVersion() << "]"
+ << "[createTranslationUnitFromSourceFile]: clang";
+ for (llvm::SmallVectorImpl<const char*>::iterator I=Args.begin(),
+ E=Args.end(); I!=E; ++I)
+ Out << ' ' << *I;
+ }
+ crashtracerSlot = SetCrashTracerInfo(CrashString.c_str(),
+ AggregateString);
+ }
+
+ ~ArgsCrashTracerInfo() {
+ ResetCrashTracerInfo(crashtracerSlot);
+ }
+};
+}
+#endif
+
+/// \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
+};
+
+/// \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 (R1.getEnd() == R2.getBegin() ||
+ SM.isBeforeInTranslationUnit(R1.getEnd(), R2.getBegin()))
+ return RangeBefore;
+ if (R2.getEnd() == R1.getBegin() ||
+ SM.isBeforeInTranslationUnit(R2.getEnd(), R1.getBegin()))
+ return RangeAfter;
+ return RangeOverlap;
+}
+
+/// \brief Translate a Clang source range into a CIndex source range.
+///
+/// Clang internally represents ranges where the end location points to the
+/// start of the token at the end. However, for external clients it is more
+/// useful to have a CXSourceRange be a proper half-open interval. This routine
+/// does the appropriate translation.
+CXSourceRange cxloc::translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceRange R) {
+ // We want the last character in this location, so we will adjust the
+ // location accordingly.
+ // FIXME: How do do this with a macro instantiation location?
+ SourceLocation EndLoc = R.getEnd();
+ if (!EndLoc.isInvalid() && EndLoc.isFileID()) {
+ unsigned Length = Lexer::MeasureTokenLength(EndLoc, SM, LangOpts);
+ EndLoc = EndLoc.getFileLocWithOffset(Length);
+ }
+
+ CXSourceRange Result = { { (void *)&SM, (void *)&LangOpts },
+ R.getBegin().getRawEncoding(),
+ EndLoc.getRawEncoding() };
+ return Result;
+}
+
+//===----------------------------------------------------------------------===//
+// 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;
+
+ /// \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 half-open source range retrieved from the abstract syntax tree.
+ RangeComparisonResult CompareRegionOfInterest(SourceRange R);
+
+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);
+
+ std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+ getPreprocessedEntities();
+
+ bool VisitChildren(CXCursor Parent);
+
+ // Declaration visitors
+ bool VisitAttributes(Decl *D);
+ bool VisitBlockDecl(BlockDecl *B);
+ 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);
+ bool VisitWhileStmt(WhileStmt *S);
+ bool VisitForStmt(ForStmt *S);
+
+ // Expression visitors
+ bool VisitBlockExpr(BlockExpr *B);
+ bool VisitCompoundLiteralExpr(CompoundLiteralExpr *E);
+ bool VisitExplicitCastExpr(ExplicitCastExpr *E);
+ bool VisitObjCMessageExpr(ObjCMessageExpr *E);
+ bool VisitObjCEncodeExpr(ObjCEncodeExpr *E);
+ bool VisitOffsetOfExpr(OffsetOfExpr *E);
+ bool VisitSizeOfAlignOfExpr(SizeOfAlignOfExpr *E);
+};
+
+} // end anonymous namespace
+
+RangeComparisonResult CursorVisitor::CompareRegionOfInterest(SourceRange R) {
+ return RangeCompare(TU->getSourceManager(), R, RegionOfInterest);
+}
+
+/// \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;
+ }
+
+ // If we have a range of interest, and this cursor doesn't intersect with it,
+ // we're done.
+ if (RegionOfInterest.isValid() && !CheckedRegionOfInterest) {
+ SourceRange Range =
+ cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ if (Range.isInvalid() || CompareRegionOfInterest(Range))
+ return false;
+ }
+
+ switch (Visitor(Cursor, Parent, ClientData)) {
+ case CXChildVisit_Break:
+ return true;
+
+ case CXChildVisit_Continue:
+ return false;
+
+ case CXChildVisit_Recurse:
+ return VisitChildren(Cursor);
+ }
+
+ return false;
+}
+
+std::pair<PreprocessingRecord::iterator, PreprocessingRecord::iterator>
+CursorVisitor::getPreprocessedEntities() {
+ PreprocessingRecord &PPRec
+ = *TU->getPreprocessor().getPreprocessingRecord();
+
+ bool OnlyLocalDecls
+ = !TU->isMainFileAST() && TU->getOnlyLocalDecls();
+
+ // There is no region of interest; we have to walk everything.
+ if (RegionOfInterest.isInvalid())
+ return std::make_pair(PPRec.begin(OnlyLocalDecls),
+ PPRec.end(OnlyLocalDecls));
+
+ // Find the file in which the region of interest lands.
+ SourceManager &SM = TU->getSourceManager();
+ std::pair<FileID, unsigned> Begin
+ = SM.getDecomposedInstantiationLoc(RegionOfInterest.getBegin());
+ std::pair<FileID, unsigned> End
+ = SM.getDecomposedInstantiationLoc(RegionOfInterest.getEnd());
+
+ // The region of interest spans files; we have to walk everything.
+ if (Begin.first != End.first)
+ return std::make_pair(PPRec.begin(OnlyLocalDecls),
+ PPRec.end(OnlyLocalDecls));
+
+ ASTUnit::PreprocessedEntitiesByFileMap &ByFileMap
+ = TU->getPreprocessedEntitiesByFile();
+ if (ByFileMap.empty()) {
+ // Build the mapping from files to sets of preprocessed entities.
+ for (PreprocessingRecord::iterator E = PPRec.begin(OnlyLocalDecls),
+ EEnd = PPRec.end(OnlyLocalDecls);
+ E != EEnd; ++E) {
+ std::pair<FileID, unsigned> P
+ = SM.getDecomposedInstantiationLoc((*E)->getSourceRange().getBegin());
+ ByFileMap[P.first].push_back(*E);
+ }
+ }
+
+ return std::make_pair(ByFileMap[Begin.first].begin(),
+ ByFileMap[Begin.first].end());
+}
+
+/// \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;
+ }
+
+ // 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 VisitAttributes(D) || 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 if (VisitDeclContext(
+ CXXUnit->getASTContext().getTranslationUnitDecl()))
+ return true;
+
+ // Walk the preprocessing record.
+ if (CXXUnit->getPreprocessor().getPreprocessingRecord()) {
+ // FIXME: Once we have the ability to deserialize a preprocessing record,
+ // do so.
+ PreprocessingRecord::iterator E, EEnd;
+ for (llvm::tie(E, EEnd) = getPreprocessedEntities(); E != EEnd; ++E) {
+ if (MacroInstantiation *MI = dyn_cast<MacroInstantiation>(*E)) {
+ if (Visit(MakeMacroInstantiationCursor(MI, CXXUnit)))
+ return true;
+
+ continue;
+ }
+
+ if (MacroDefinition *MD = dyn_cast<MacroDefinition>(*E)) {
+ if (Visit(MakeMacroDefinitionCursor(MD, CXXUnit)))
+ return true;
+
+ continue;
+ }
+ }
+ }
+ return false;
+ }
+
+ // Nothing to visit at the moment.
+ return false;
+}
+
+bool CursorVisitor::VisitBlockDecl(BlockDecl *B) {
+ for (BlockDecl::param_iterator I=B->param_begin(), E=B->param_end(); I!=E;++I)
+ if (Decl *D = *I)
+ if (Visit(D))
+ return true;
+
+ return Visit(MakeCXCursor(B->getBody(), StmtParent, TU));
+}
+
+bool CursorVisitor::VisitDeclContext(DeclContext *DC) {
+ for (DeclContext::decl_iterator
+ I = DC->decls_begin(), E = DC->decls_end(); I != E; ++I) {
+
+ CXCursor Cursor = MakeCXCursor(*I, TU);
+
+ if (RegionOfInterest.isValid()) {
+ SourceRange Range =
+ cxloc::translateCXSourceRange(clang_getCursorExtent(Cursor));
+ if (Range.isInvalid())
+ continue;
+
+ switch (CompareRegionOfInterest(Range)) {
+ 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(Cursor, true))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTranslationUnitDecl(TranslationUnitDecl *D) {
+ llvm_unreachable("Translation units are visited directly by Visit()");
+ return false;
+}
+
+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;
+
+ return false;
+}
+
+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;
+
+ if (Expr *Init = D->getInit())
+ return Visit(MakeCXCursor(Init, StmtParent, TU));
+
+ return false;
+}
+
+bool CursorVisitor::VisitObjCMethodDecl(ObjCMethodDecl *ND) {
+ if (TypeSourceInfo *TSInfo = ND->getResultTypeSourceInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ 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;
+
+ 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;
+
+ return VisitObjCContainerDecl(PID);
+}
+
+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);
+}
+
+bool CursorVisitor::VisitObjCImplDecl(ObjCImplDecl *D) {
+ return VisitObjCContainerDecl(D);
+}
+
+bool CursorVisitor::VisitObjCCategoryImplDecl(ObjCCategoryImplDecl *D) {
+ // 'ID' could be null when dealing with invalid code.
+ if (ObjCInterfaceDecl *ID = D->getClassInterface())
+ if (Visit(MakeCursorObjCClassRef(ID, D->getLocation(), TU)))
+ return true;
+
+ return VisitObjCImplDecl(D);
+}
+
+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);
+}
+
+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;
+ }
+
+ if (!VisitType.isNull()) {
+ if (const TypedefType *Typedef = VisitType->getAs<TypedefType>())
+ return Visit(MakeCursorTypeRef(Typedef->getDecl(), TL.getBuiltinLoc(),
+ TU));
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitTypedefTypeLoc(TypedefTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getTypedefDecl(), TL.getNameLoc(), TU));
+}
+
+bool CursorVisitor::VisitUnresolvedUsingTypeLoc(UnresolvedUsingTypeLoc TL) {
+ return Visit(MakeCursorTypeRef(TL.getDecl(), TL.getNameLoc(), TU));
+}
+
+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;
+ }
+
+ return false;
+}
+
+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;
+}
+
+bool CursorVisitor::VisitPointerTypeLoc(PointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitBlockPointerTypeLoc(BlockPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitMemberPointerTypeLoc(MemberPointerTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitLValueReferenceTypeLoc(LValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitRValueReferenceTypeLoc(RValueReferenceTypeLoc TL) {
+ return Visit(TL.getPointeeLoc());
+}
+
+bool CursorVisitor::VisitFunctionTypeLoc(FunctionTypeLoc TL) {
+ if (Visit(TL.getResultLoc()))
+ return true;
+
+ for (unsigned I = 0, N = TL.getNumArgs(); I != N; ++I)
+ if (Decl *D = TL.getArg(I))
+ if (Visit(MakeCXCursor(D, 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 (*Child && Visit(MakeCXCursor(*Child, StmtParent, TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitDeclStmt(DeclStmt *S) {
+ for (DeclStmt::decl_iterator D = S->decl_begin(), DEnd = S->decl_end();
+ D != DEnd; ++D) {
+ if (*D && Visit(MakeCXCursor(*D, TU)))
+ return true;
+ }
+
+ return false;
+}
+
+bool CursorVisitor::VisitIfStmt(IfStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ }
+
+ 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;
+}
+
+bool CursorVisitor::VisitSwitchStmt(SwitchStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ }
+
+ if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+ if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitWhileStmt(WhileStmt *S) {
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ }
+
+ if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+ if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitForStmt(ForStmt *S) {
+ if (S->getInit() && Visit(MakeCXCursor(S->getInit(), StmtParent, TU)))
+ return true;
+ if (VarDecl *Var = S->getConditionVariable()) {
+ if (Visit(MakeCXCursor(Var, TU)))
+ return true;
+ }
+
+ if (S->getCond() && Visit(MakeCXCursor(S->getCond(), StmtParent, TU)))
+ return true;
+ if (S->getInc() && Visit(MakeCXCursor(S->getInc(), StmtParent, TU)))
+ return true;
+ if (S->getBody() && Visit(MakeCXCursor(S->getBody(), StmtParent, TU)))
+ return true;
+
+ return false;
+}
+
+bool CursorVisitor::VisitBlockExpr(BlockExpr *B) {
+ return Visit(B->getBlockDecl());
+}
+
+bool CursorVisitor::VisitOffsetOfExpr(OffsetOfExpr *E) {
+ // FIXME: Visit fields as well?
+ if (Visit(E->getTypeSourceInfo()->getTypeLoc()))
+ return true;
+
+ return VisitExpr(E);
+}
+
+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);
+}
+
+bool CursorVisitor::VisitObjCMessageExpr(ObjCMessageExpr *E) {
+ if (TypeSourceInfo *TSInfo = E->getClassReceiverTypeInfo())
+ if (Visit(TSInfo->getTypeLoc()))
+ return true;
+
+ return VisitExpr(E);
+}
+
+bool CursorVisitor::VisitObjCEncodeExpr(ObjCEncodeExpr *E) {
+ return Visit(E->getEncodedTypeSourceInfo()->getTypeLoc());
+}
+
+
+bool CursorVisitor::VisitAttributes(Decl *D) {
+ for (const Attr *A = D->getAttrs(); A; A = A->getNext())
+ if (Visit(MakeCXCursor(A, D, TU)))
+ return true;
+
+ return false;
+}
+
+extern "C" {
+CXIndex clang_createIndex(int excludeDeclarationsFromPCH,
+ int displayDiagnostics) {
+ CIndexer *CIdxr = new CIndexer();
+ if (excludeDeclarationsFromPCH)
+ CIdxr->setOnlyLocalDecls();
+ if (displayDiagnostics)
+ CIdxr->setDisplayDiagnostics();
+ return CIdxr;
+}
+
+void clang_disposeIndex(CXIndex CIdx) {
+ if (CIdx)
+ delete static_cast<CIndexer *>(CIdx);
+}
+
+void clang_setUseExternalASTGeneration(CXIndex CIdx, int value) {
+ if (CIdx) {
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+ CXXIdx->setUseExternalASTGeneration(value);
+ }
+}
+
+CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
+ const char *ast_filename) {
+ if (!CIdx)
+ return 0;
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
+ return ASTUnit::LoadFromPCHFile(ast_filename, Diags,
+ CXXIdx->getOnlyLocalDecls(),
+ 0, 0, true);
+}
+
+CXTranslationUnit
+clang_createTranslationUnitFromSourceFile(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char **command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files) {
+ if (!CIdx)
+ return 0;
+
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ // Configure the diagnostics.
+ DiagnosticOptions DiagOpts;
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
+
+ llvm::SmallVector<ASTUnit::RemappedFile, 4> RemappedFiles;
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ llvm::StringRef Data(unsaved_files[I].Contents, unsaved_files[I].Length);
+ const llvm::MemoryBuffer *Buffer
+ = llvm::MemoryBuffer::getMemBufferCopy(Data, unsaved_files[I].Filename);
+ RemappedFiles.push_back(std::make_pair(unsaved_files[I].Filename,
+ Buffer));
+ }
+
+ if (!CXXIdx->getUseExternalASTGeneration()) {
+ llvm::SmallVector<const char *, 16> Args;
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ if (source_filename)
+ Args.push_back(source_filename);
+ Args.insert(Args.end(), command_line_args,
+ command_line_args + num_command_line_args);
+ Args.push_back("-Xclang");
+ Args.push_back("-detailed-preprocessing-record");
+ unsigned NumErrors = Diags->getNumErrors();
+
+#ifdef USE_CRASHTRACER
+ ArgsCrashTracerInfo ACTI(Args);
+#endif
+
+ llvm::OwningPtr<ASTUnit> Unit(
+ ASTUnit::LoadFromCommandLine(Args.data(), Args.data() + Args.size(),
+ Diags,
+ CXXIdx->getClangResourcesPath(),
+ CXXIdx->getOnlyLocalDecls(),
+ RemappedFiles.data(),
+ RemappedFiles.size(),
+ /*CaptureDiagnostics=*/true));
+
+ // FIXME: Until we have broader testing, just drop the entire AST if we
+ // encountered an error.
+ if (NumErrors != Diags->getNumErrors()) {
+ // Make sure to check that 'Unit' is non-NULL.
+ if (CXXIdx->getDisplayDiagnostics() && Unit.get()) {
+ for (ASTUnit::stored_diag_iterator D = Unit->stored_diag_begin(),
+ DEnd = Unit->stored_diag_end();
+ D != DEnd; ++D) {
+ CXStoredDiagnostic Diag(*D, Unit->getASTContext().getLangOptions());
+ CXString Msg = clang_formatDiagnostic(&Diag,
+ clang_defaultDiagnosticDisplayOptions());
+ fprintf(stderr, "%s\n", clang_getCString(Msg));
+ clang_disposeString(Msg);
+ }
+#ifdef LLVM_ON_WIN32
+ // On Windows, force a flush, since there may be multiple copies of
+ // stderr and stdout in the file system, all with different buffers
+ // but writing to the same device.
+ fflush(stderr);
+#endif
+ }
+ }
+
+ return Unit.take();
+ }
+
+ // Build up the arguments for invoking 'clang'.
+ std::vector<const char *> argv;
+
+ // First add the complete path to the 'clang' executable.
+ llvm::sys::Path ClangPath = static_cast<CIndexer *>(CIdx)->getClangPath();
+ argv.push_back(ClangPath.c_str());
+
+ // Add the '-emit-ast' option as our execution mode for 'clang'.
+ argv.push_back("-emit-ast");
+
+ // The 'source_filename' argument is optional. If the caller does not
+ // specify it then it is assumed that the source file is specified
+ // in the actual argument list.
+ if (source_filename)
+ argv.push_back(source_filename);
+
+ // Generate a temporary name for the AST file.
+ argv.push_back("-o");
+ 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]) {
+ if (strcmp(arg, "-o") == 0) {
+ ++i; // Also skip the matching argument.
+ continue;
+ }
+ if (strcmp(arg, "-emit-ast") == 0 ||
+ strcmp(arg, "-c") == 0 ||
+ strcmp(arg, "-fsyntax-only") == 0) {
+ continue;
+ }
+
+ // Keep the argument.
+ argv.push_back(arg);
+ }
+
+ // Generate a temporary name for the diagnostics file.
+ char tmpFileResults[L_tmpnam];
+ char *tmpResultsFileName = tmpnam(tmpFileResults);
+ llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
+ TemporaryFiles.push_back(DiagnosticsFile);
+ argv.push_back("-fdiagnostics-binary");
+
+ argv.push_back("-Xclang");
+ argv.push_back("-detailed-preprocessing-record");
+
+ // Add the null terminator.
+ argv.push_back(NULL);
+
+ // Invoke 'clang'.
+ llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
+ // on Unix or NUL (Windows).
+ std::string ErrMsg;
+ const llvm::sys::Path *Redirects[] = { &DevNull, &DevNull, &DiagnosticsFile,
+ NULL };
+ llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
+ /* redirects */ &Redirects[0],
+ /* secondsToWait */ 0, /* memoryLimits */ 0, &ErrMsg);
+
+ if (!ErrMsg.empty()) {
+ std::string AllArgs;
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ AllArgs += ' ';
+ if (*I)
+ AllArgs += *I;
+ }
+
+ Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
+ }
+
+ ASTUnit *ATU = ASTUnit::LoadFromPCHFile(astTmpFile, Diags,
+ CXXIdx->getOnlyLocalDecls(),
+ RemappedFiles.data(),
+ RemappedFiles.size(),
+ /*CaptureDiagnostics=*/true);
+ if (ATU) {
+ LoadSerializedDiagnostics(DiagnosticsFile,
+ num_unsaved_files, unsaved_files,
+ ATU->getFileManager(),
+ ATU->getSourceManager(),
+ ATU->getStoredDiagnostics());
+ } else if (CXXIdx->getDisplayDiagnostics()) {
+ // We failed to load the ASTUnit, but we can still deserialize the
+ // diagnostics and emit them.
+ FileManager FileMgr;
+ Diagnostic Diag;
+ SourceManager SourceMgr(Diag);
+ // FIXME: Faked LangOpts!
+ LangOptions LangOpts;
+ llvm::SmallVector<StoredDiagnostic, 4> Diags;
+ LoadSerializedDiagnostics(DiagnosticsFile,
+ num_unsaved_files, unsaved_files,
+ FileMgr, SourceMgr, Diags);
+ for (llvm::SmallVector<StoredDiagnostic, 4>::iterator D = Diags.begin(),
+ DEnd = Diags.end();
+ D != DEnd; ++D) {
+ CXStoredDiagnostic Diag(*D, LangOpts);
+ CXString Msg = clang_formatDiagnostic(&Diag,
+ clang_defaultDiagnosticDisplayOptions());
+ fprintf(stderr, "%s\n", clang_getCString(Msg));
+ clang_disposeString(Msg);
+ }
+
+#ifdef LLVM_ON_WIN32
+ // On Windows, force a flush, since there may be multiple copies of
+ // stderr and stdout in the file system, all with different buffers
+ // but writing to the same device.
+ fflush(stderr);
+#endif
+ }
+
+ if (ATU) {
+ // Make the translation unit responsible for destroying all temporary files.
+ for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+ ATU->addTemporaryFile(TemporaryFiles[i]);
+ ATU->addTemporaryFile(llvm::sys::Path(ATU->getPCHFileName()));
+ } else {
+ // Destroy all of the temporary files now; they can't be referenced any
+ // longer.
+ llvm::sys::Path(astTmpFile).eraseFromDisk();
+ for (unsigned i = 0, e = TemporaryFiles.size(); i != e; ++i)
+ TemporaryFiles[i].eraseFromDisk();
+ }
+
+ return ATU;
+}
+
+void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
+ if (CTUnit)
+ delete static_cast<ASTUnit *>(CTUnit);
+}
+
+CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
+ if (!CTUnit)
+ return createCXString("");
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(CTUnit);
+ return createCXString(CXXUnit->getOriginalSourceFileName(), true);
+}
+
+CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
+ CXCursor Result = { CXCursor_TranslationUnit, { 0, 0, TU } };
+ return Result;
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// CXSourceLocation and CXSourceRange Operations.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXSourceLocation clang_getNullLocation() {
+ CXSourceLocation Result = { { 0, 0 }, 0 };
+ return Result;
+}
+
+unsigned clang_equalLocations(CXSourceLocation loc1, CXSourceLocation loc2) {
+ return (loc1.ptr_data[0] == loc2.ptr_data[0] &&
+ loc1.ptr_data[1] == loc2.ptr_data[1] &&
+ loc1.int_data == loc2.int_data);
+}
+
+CXSourceLocation clang_getLocation(CXTranslationUnit tu,
+ CXFile file,
+ unsigned line,
+ unsigned column) {
+ if (!tu || !file)
+ return clang_getNullLocation();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(tu);
+ SourceLocation SLoc
+ = CXXUnit->getSourceManager().getLocation(
+ static_cast<const FileEntry *>(file),
+ line, column);
+
+ return cxloc::translateSourceLocation(CXXUnit->getASTContext(), SLoc);
+}
+
+CXSourceRange clang_getNullRange() {
+ CXSourceRange Result = { { 0, 0 }, 0, 0 };
+ return Result;
+}
+
+CXSourceRange clang_getRange(CXSourceLocation begin, CXSourceLocation end) {
+ if (begin.ptr_data[0] != end.ptr_data[0] ||
+ begin.ptr_data[1] != end.ptr_data[1])
+ return clang_getNullRange();
+
+ CXSourceRange Result = { { begin.ptr_data[0], begin.ptr_data[1] },
+ begin.int_data, end.int_data };
+ return Result;
+}
+
+void clang_getInstantiationLocation(CXSourceLocation location,
+ CXFile *file,
+ unsigned *line,
+ unsigned *column,
+ unsigned *offset) {
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(location.int_data);
+
+ if (!location.ptr_data[0] || Loc.isInvalid()) {
+ if (file)
+ *file = 0;
+ if (line)
+ *line = 0;
+ if (column)
+ *column = 0;
+ if (offset)
+ *offset = 0;
+ return;
+ }
+
+ const SourceManager &SM =
+ *static_cast<const SourceManager*>(location.ptr_data[0]);
+ SourceLocation InstLoc = SM.getInstantiationLoc(Loc);
+
+ if (file)
+ *file = (void *)SM.getFileEntryForID(SM.getFileID(InstLoc));
+ if (line)
+ *line = SM.getInstantiationLineNumber(InstLoc);
+ if (column)
+ *column = SM.getInstantiationColumnNumber(InstLoc);
+ if (offset)
+ *offset = SM.getDecomposedLoc(InstLoc).second;
+}
+
+CXSourceLocation clang_getRangeStart(CXSourceRange range) {
+ CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
+ range.begin_int_data };
+ return Result;
+}
+
+CXSourceLocation clang_getRangeEnd(CXSourceRange range) {
+ CXSourceLocation Result = { { range.ptr_data[0], range.ptr_data[1] },
+ range.end_int_data };
+ return Result;
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// CXFile Operations.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXString clang_getFileName(CXFile SFile) {
+ if (!SFile)
+ return createCXString(NULL);
+
+ FileEntry *FEnt = static_cast<FileEntry *>(SFile);
+ return createCXString(FEnt->getName());
+}
+
+time_t clang_getFileTime(CXFile SFile) {
+ if (!SFile)
+ return 0;
+
+ 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 Decl *getDeclFromExpr(Stmt *E) {
+ if (DeclRefExpr *RefExpr = dyn_cast<DeclRefExpr>(E))
+ return RefExpr->getDecl();
+ if (MemberExpr *ME = dyn_cast<MemberExpr>(E))
+ return ME->getMemberDecl();
+ if (ObjCIvarRefExpr *RE = dyn_cast<ObjCIvarRefExpr>(E))
+ return RE->getDecl();
+
+ if (CallExpr *CE = dyn_cast<CallExpr>(E))
+ return getDeclFromExpr(CE->getCallee());
+ if (CastExpr *CE = dyn_cast<CastExpr>(E))
+ return getDeclFromExpr(CE->getSubExpr());
+ if (ObjCMessageExpr *OME = dyn_cast<ObjCMessageExpr>(E))
+ return OME->getMethodDecl();
+
+ return 0;
+}
+
+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();
+}
+
+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 createCXString("");
+
+ if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(ND))
+ return createCXString(OMD->getSelector().getAsString());
+
+ 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 createCXString(CIMP->getIdentifier()->getNameStart());
+
+ if (ND->getIdentifier())
+ return createCXString(ND->getIdentifier()->getNameStart());
+
+ return createCXString("");
+}
+
+CXString clang_getCursorSpelling(CXCursor C) {
+ if (clang_isTranslationUnit(C.kind))
+ return clang_getTranslationUnitSpelling(C.data[2]);
+
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ ObjCInterfaceDecl *Super = getCursorObjCSuperClassRef(C).first;
+ return createCXString(Super->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCClassRef: {
+ ObjCInterfaceDecl *Class = getCursorObjCClassRef(C).first;
+ return createCXString(Class->getIdentifier()->getNameStart());
+ }
+ case CXCursor_ObjCProtocolRef: {
+ ObjCProtocolDecl *OID = getCursorObjCProtocolRef(C).first;
+ assert(OID && "getCursorSpelling(): Missing protocol decl");
+ return createCXString(OID->getIdentifier()->getNameStart());
+ }
+ case CXCursor_TypeRef: {
+ TypeDecl *Type = getCursorTypeRef(C).first;
+ assert(Type && "Missing type decl");
+
+ return createCXString(getCursorContext(C).getTypeDeclType(Type).
+ getAsString());
+ }
+
+ default:
+ return createCXString("<not implemented>");
+ }
+ }
+
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return getDeclSpelling(D);
+ return createCXString("");
+ }
+
+ if (C.kind == CXCursor_MacroInstantiation)
+ return createCXString(getCursorMacroInstantiation(C)->getName()
+ ->getNameStart());
+
+ if (C.kind == CXCursor_MacroDefinition)
+ return createCXString(getCursorMacroDefinition(C)->getName()
+ ->getNameStart());
+
+ if (clang_isDeclaration(C.kind))
+ return getDeclSpelling(getCursorDecl(C));
+
+ return createCXString("");
+}
+
+CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
+ switch (Kind) {
+ case CXCursor_FunctionDecl:
+ return createCXString("FunctionDecl");
+ case CXCursor_TypedefDecl:
+ return createCXString("TypedefDecl");
+ case CXCursor_EnumDecl:
+ return createCXString("EnumDecl");
+ case CXCursor_EnumConstantDecl:
+ return createCXString("EnumConstantDecl");
+ case CXCursor_StructDecl:
+ return createCXString("StructDecl");
+ case CXCursor_UnionDecl:
+ return createCXString("UnionDecl");
+ case CXCursor_ClassDecl:
+ return createCXString("ClassDecl");
+ case CXCursor_FieldDecl:
+ return createCXString("FieldDecl");
+ case CXCursor_VarDecl:
+ return createCXString("VarDecl");
+ case CXCursor_ParmDecl:
+ return createCXString("ParmDecl");
+ case CXCursor_ObjCInterfaceDecl:
+ return createCXString("ObjCInterfaceDecl");
+ case CXCursor_ObjCCategoryDecl:
+ return createCXString("ObjCCategoryDecl");
+ case CXCursor_ObjCProtocolDecl:
+ return createCXString("ObjCProtocolDecl");
+ case CXCursor_ObjCPropertyDecl:
+ return createCXString("ObjCPropertyDecl");
+ case CXCursor_ObjCIvarDecl:
+ return createCXString("ObjCIvarDecl");
+ case CXCursor_ObjCInstanceMethodDecl:
+ return createCXString("ObjCInstanceMethodDecl");
+ case CXCursor_ObjCClassMethodDecl:
+ return createCXString("ObjCClassMethodDecl");
+ case CXCursor_ObjCImplementationDecl:
+ return createCXString("ObjCImplementationDecl");
+ case CXCursor_ObjCCategoryImplDecl:
+ return createCXString("ObjCCategoryImplDecl");
+ case CXCursor_CXXMethod:
+ return createCXString("CXXMethod");
+ case CXCursor_UnexposedDecl:
+ return createCXString("UnexposedDecl");
+ case CXCursor_ObjCSuperClassRef:
+ return createCXString("ObjCSuperClassRef");
+ case CXCursor_ObjCProtocolRef:
+ return createCXString("ObjCProtocolRef");
+ case CXCursor_ObjCClassRef:
+ return createCXString("ObjCClassRef");
+ case CXCursor_TypeRef:
+ return createCXString("TypeRef");
+ case CXCursor_UnexposedExpr:
+ return createCXString("UnexposedExpr");
+ case CXCursor_BlockExpr:
+ return createCXString("BlockExpr");
+ case CXCursor_DeclRefExpr:
+ return createCXString("DeclRefExpr");
+ case CXCursor_MemberRefExpr:
+ return createCXString("MemberRefExpr");
+ case CXCursor_CallExpr:
+ return createCXString("CallExpr");
+ case CXCursor_ObjCMessageExpr:
+ return createCXString("ObjCMessageExpr");
+ case CXCursor_UnexposedStmt:
+ return createCXString("UnexposedStmt");
+ case CXCursor_InvalidFile:
+ return createCXString("InvalidFile");
+ case CXCursor_InvalidCode:
+ return createCXString("InvalidCode");
+ case CXCursor_NoDeclFound:
+ return createCXString("NoDeclFound");
+ case CXCursor_NotImplemented:
+ return createCXString("NotImplemented");
+ case CXCursor_TranslationUnit:
+ return createCXString("TranslationUnit");
+ case CXCursor_UnexposedAttr:
+ return createCXString("UnexposedAttr");
+ case CXCursor_IBActionAttr:
+ return createCXString("attribute(ibaction)");
+ case CXCursor_IBOutletAttr:
+ return createCXString("attribute(iboutlet)");
+ case CXCursor_PreprocessingDirective:
+ return createCXString("preprocessing directive");
+ case CXCursor_MacroDefinition:
+ return createCXString("macro definition");
+ case CXCursor_MacroInstantiation:
+ return createCXString("macro instantiation");
+ }
+
+ llvm_unreachable("Unhandled CXCursorKind");
+ return createCXString(NULL);
+}
+
+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);
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceLocation SLoc = cxloc::translateSourceLocation(Loc);
+ CXCursor Result = MakeCXCursorInvalid(CXCursor_NoDeclFound);
+ if (SLoc.isValid()) {
+ SourceRange RegionOfInterest(SLoc, SLoc.getFileLocWithOffset(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 Result;
+}
+
+CXCursor clang_getNullCursor(void) {
+ return MakeCXCursorInvalid(CXCursor_InvalidFile);
+}
+
+unsigned clang_equalCursors(CXCursor X, CXCursor Y) {
+ return X == Y;
+}
+
+unsigned clang_isInvalid(enum CXCursorKind K) {
+ return K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid;
+}
+
+unsigned clang_isDeclaration(enum CXCursorKind K) {
+ return K >= CXCursor_FirstDecl && K <= CXCursor_LastDecl;
+}
+
+unsigned clang_isReference(enum CXCursorKind K) {
+ return K >= CXCursor_FirstRef && K <= CXCursor_LastRef;
+}
+
+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;
+}
+
+unsigned clang_isPreprocessing(enum CXCursorKind K) {
+ return K >= CXCursor_FirstPreprocessing && K <= CXCursor_LastPreprocessing;
+}
+
+unsigned clang_isUnexposed(enum CXCursorKind K) {
+ switch (K) {
+ case CXCursor_UnexposedDecl:
+ case CXCursor_UnexposedExpr:
+ case CXCursor_UnexposedStmt:
+ case CXCursor_UnexposedAttr:
+ return true;
+ default:
+ return false;
+ }
+}
+
+CXCursorKind clang_getCursorKind(CXCursor C) {
+ return C.kind;
+}
+
+CXSourceLocation clang_getCursorLocation(CXCursor C) {
+ if (clang_isReference(C.kind)) {
+ switch (C.kind) {
+ case CXCursor_ObjCSuperClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCSuperClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+ return cxloc::translateSourceLocation(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return cxloc::translateSourceLocation(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 cxloc::translateSourceLocation(getCursorContext(C),
+ getLocationFromExpr(getCursorExpr(C)));
+
+ if (C.kind == CXCursor_PreprocessingDirective) {
+ SourceLocation L = cxcursor::getCursorPreprocessingDirective(C).getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroInstantiation) {
+ SourceLocation L
+ = cxcursor::getCursorMacroInstantiation(C)->getSourceRange().getBegin();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ SourceLocation L = cxcursor::getCursorMacroDefinition(C)->getLocation();
+ return cxloc::translateSourceLocation(getCursorContext(C), L);
+ }
+
+ if (!getCursorDecl(C))
+ return clang_getNullLocation();
+
+ Decl *D = getCursorDecl(C);
+ SourceLocation Loc = D->getLocation();
+ if (ObjCInterfaceDecl *Class = dyn_cast<ObjCInterfaceDecl>(D))
+ Loc = Class->getClassLoc();
+ return cxloc::translateSourceLocation(getCursorContext(C), 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 cxloc::translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCProtocolRef: {
+ std::pair<ObjCProtocolDecl *, SourceLocation> P
+ = getCursorObjCProtocolRef(C);
+ return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_ObjCClassRef: {
+ std::pair<ObjCInterfaceDecl *, SourceLocation> P
+ = getCursorObjCClassRef(C);
+
+ return cxloc::translateSourceRange(P.first->getASTContext(), P.second);
+ }
+
+ case CXCursor_TypeRef: {
+ std::pair<TypeDecl *, SourceLocation> P = getCursorTypeRef(C);
+ return cxloc::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 cxloc::translateSourceRange(getCursorContext(C),
+ getCursorExpr(C)->getSourceRange());
+
+ if (clang_isStatement(C.kind))
+ return cxloc::translateSourceRange(getCursorContext(C),
+ getCursorStmt(C)->getSourceRange());
+
+ if (C.kind == CXCursor_PreprocessingDirective) {
+ SourceRange R = cxcursor::getCursorPreprocessingDirective(C);
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ if (C.kind == CXCursor_MacroInstantiation) {
+ SourceRange R = cxcursor::getCursorMacroInstantiation(C)->getSourceRange();
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ if (C.kind == CXCursor_MacroDefinition) {
+ SourceRange R = cxcursor::getCursorMacroDefinition(C)->getSourceRange();
+ return cxloc::translateSourceRange(getCursorContext(C), R);
+ }
+
+ if (!getCursorDecl(C))
+ return clang_getNullRange();
+
+ Decl *D = getCursorDecl(C);
+ return cxloc::translateSourceRange(getCursorContext(C), D->getSourceRange());
+}
+
+CXCursor clang_getCursorReferenced(CXCursor C) {
+ if (clang_isInvalid(C.kind))
+ return clang_getNullCursor();
+
+ ASTUnit *CXXUnit = getCursorASTUnit(C);
+ if (clang_isDeclaration(C.kind))
+ return C;
+
+ if (clang_isExpression(C.kind)) {
+ Decl *D = getDeclFromExpr(getCursorExpr(C));
+ if (D)
+ return MakeCXCursor(D, CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ if (C.kind == CXCursor_MacroInstantiation) {
+ if (MacroDefinition *Def = getCursorMacroInstantiation(C)->getDefinition())
+ return MakeMacroDefinitionCursor(Def, CXXUnit);
+ }
+
+ if (!clang_isReference(C.kind))
+ return clang_getNullCursor();
+
+ 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 clang_getNullCursor();
+}
+
+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 (C.kind == CXCursor_MacroInstantiation)
+ return clang_getCursorReferenced(C);
+
+ 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:
+ 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())
+ 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: {
+ // Ask the variable if it has a definition.
+ if (VarDecl *Def = cast<VarDecl>(D)->getDefinition())
+ return MakeCXCursor(Def, CXXUnit);
+ return clang_getNullCursor();
+ }
+
+ 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())
+ 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();
+
+ 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,
+ const char **startBuf,
+ const char **endBuf,
+ unsigned *startLine,
+ unsigned *startColumn,
+ unsigned *endLine,
+ unsigned *endColumn) {
+ 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());
+
+ SourceManager &SM = FD->getASTContext().getSourceManager();
+ *startBuf = SM.getCharacterData(Body->getLBracLoc());
+ *endBuf = SM.getCharacterData(Body->getRBracLoc());
+ *startLine = SM.getSpellingLineNumber(Body->getLBracLoc());
+ *startColumn = SM.getSpellingColumnNumber(Body->getLBracLoc());
+ *endLine = SM.getSpellingLineNumber(Body->getRBracLoc());
+ *endColumn = SM.getSpellingColumnNumber(Body->getRBracLoc());
+}
+
+void clang_enableStackTraces(void) {
+ llvm::sys::PrintStackTraceOnErrorSignal();
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Token-based Operations.
+//===----------------------------------------------------------------------===//
+
+/* CXToken layout:
+ * int_data[0]: a CXTokenKind
+ * int_data[1]: starting token location
+ * int_data[2]: token length
+ * int_data[3]: reserved
+ * ptr_data: for identifiers and keywords, an IdentifierInfo*.
+ * otherwise unused.
+ */
+extern "C" {
+
+CXTokenKind clang_getTokenKind(CXToken CXTok) {
+ return static_cast<CXTokenKind>(CXTok.int_data[0]);
+}
+
+CXString clang_getTokenSpelling(CXTranslationUnit TU, CXToken CXTok) {
+ switch (clang_getTokenKind(CXTok)) {
+ case CXToken_Identifier:
+ case CXToken_Keyword:
+ // We know we have an IdentifierInfo*, so use that.
+ return createCXString(static_cast<IdentifierInfo *>(CXTok.ptr_data)
+ ->getNameStart());
+
+ case CXToken_Literal: {
+ // We have stashed the starting pointer in the ptr_data field. Use it.
+ const char *Text = static_cast<const char *>(CXTok.ptr_data);
+ return createCXString(llvm::StringRef(Text, CXTok.int_data[2]));
+ }
+
+ case CXToken_Punctuation:
+ case CXToken_Comment:
+ break;
+ }
+
+ // We have to find the starting buffer pointer the hard way, by
+ // deconstructing the source location.
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ if (!CXXUnit)
+ return createCXString("");
+
+ SourceLocation Loc = SourceLocation::getFromRawEncoding(CXTok.int_data[1]);
+ std::pair<FileID, unsigned> LocInfo
+ = CXXUnit->getSourceManager().getDecomposedLoc(Loc);
+ bool Invalid = false;
+ llvm::StringRef Buffer
+ = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return createCXString("");
+
+ return createCXString(Buffer.substr(LocInfo.second, CXTok.int_data[2]));
+}
+
+CXSourceLocation clang_getTokenLocation(CXTranslationUnit TU, CXToken CXTok) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ if (!CXXUnit)
+ return clang_getNullLocation();
+
+ return cxloc::translateSourceLocation(CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+CXSourceRange clang_getTokenExtent(CXTranslationUnit TU, CXToken CXTok) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ if (!CXXUnit)
+ return clang_getNullRange();
+
+ return cxloc::translateSourceRange(CXXUnit->getASTContext(),
+ SourceLocation::getFromRawEncoding(CXTok.int_data[1]));
+}
+
+void clang_tokenize(CXTranslationUnit TU, CXSourceRange Range,
+ CXToken **Tokens, unsigned *NumTokens) {
+ if (Tokens)
+ *Tokens = 0;
+ if (NumTokens)
+ *NumTokens = 0;
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ if (!CXXUnit || !Tokens || !NumTokens)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ SourceRange R = cxloc::translateCXSourceRange(Range);
+ if (R.isInvalid())
+ return;
+
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo
+ = SourceMgr.getDecomposedLoc(R.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo
+ = SourceMgr.getDecomposedLoc(R.getEnd());
+
+ // Cannot tokenize across files.
+ if (BeginLocInfo.first != EndLocInfo.first)
+ return;
+
+ // Create a lexer
+ bool Invalid = false;
+ llvm::StringRef Buffer
+ = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid);
+ if (Invalid)
+ return;
+
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOptions(),
+ Buffer.begin(), Buffer.data() + BeginLocInfo.second, Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ // Lex tokens until we hit the end of the range.
+ const char *EffectiveBufferEnd = Buffer.data() + EndLocInfo.second;
+ llvm::SmallVector<CXToken, 32> CXTokens;
+ Token Tok;
+ do {
+ // Lex the next token
+ Lex.LexFromRawLexer(Tok);
+ if (Tok.is(tok::eof))
+ break;
+
+ // Initialize the CXToken.
+ CXToken CXTok;
+
+ // - Common fields
+ CXTok.int_data[1] = Tok.getLocation().getRawEncoding();
+ CXTok.int_data[2] = Tok.getLength();
+ CXTok.int_data[3] = 0;
+
+ // - Kind-specific fields
+ if (Tok.isLiteral()) {
+ CXTok.int_data[0] = CXToken_Literal;
+ CXTok.ptr_data = (void *)Tok.getLiteralData();
+ } else if (Tok.is(tok::identifier)) {
+ // Lookup the identifier to determine whether we have a keyword.
+ std::pair<FileID, unsigned> LocInfo
+ = SourceMgr.getDecomposedLoc(Tok.getLocation());
+ bool Invalid = false;
+ llvm::StringRef Buf
+ = CXXUnit->getSourceManager().getBufferData(LocInfo.first, &Invalid);
+ if (Invalid)
+ return;
+
+ const char *StartPos = Buf.data() + LocInfo.second;
+ IdentifierInfo *II
+ = CXXUnit->getPreprocessor().LookUpIdentifierInfo(Tok, StartPos);
+ CXTok.int_data[0] = II->getTokenID() == tok::identifier?
+ CXToken_Identifier
+ : CXToken_Keyword;
+ CXTok.ptr_data = II;
+ } else if (Tok.is(tok::comment)) {
+ CXTok.int_data[0] = CXToken_Comment;
+ CXTok.ptr_data = 0;
+ } else {
+ CXTok.int_data[0] = CXToken_Punctuation;
+ CXTok.ptr_data = 0;
+ }
+ CXTokens.push_back(CXTok);
+ } while (Lex.getBufferLocation() <= EffectiveBufferEnd);
+
+ if (CXTokens.empty())
+ return;
+
+ *Tokens = (CXToken *)malloc(sizeof(CXToken) * CXTokens.size());
+ memmove(*Tokens, CXTokens.data(), sizeof(CXToken) * CXTokens.size());
+ *NumTokens = CXTokens.size();
+}
+
+typedef llvm::DenseMap<unsigned, CXCursor> AnnotateTokensData;
+
+enum CXChildVisitResult AnnotateTokensVisitor(CXCursor cursor,
+ CXCursor parent,
+ CXClientData client_data) {
+ AnnotateTokensData *Data = static_cast<AnnotateTokensData *>(client_data);
+
+ // We only annotate the locations of declarations, simple
+ // references, and expressions which directly reference something.
+ CXCursorKind Kind = clang_getCursorKind(cursor);
+ if (clang_isDeclaration(Kind) || clang_isReference(Kind)) {
+ // Okay: We can annotate the location of this declaration with the
+ // declaration or reference
+ } else if (clang_isExpression(cursor.kind)) {
+ if (Kind != CXCursor_DeclRefExpr &&
+ Kind != CXCursor_MemberRefExpr &&
+ Kind != CXCursor_ObjCMessageExpr)
+ return CXChildVisit_Recurse;
+
+ CXCursor Referenced = clang_getCursorReferenced(cursor);
+ if (Referenced == cursor || Referenced == clang_getNullCursor())
+ return CXChildVisit_Recurse;
+
+ // Okay: we can annotate the location of this expression
+ } else if (clang_isPreprocessing(cursor.kind)) {
+ // We can always annotate a preprocessing directive/macro instantiation.
+ } else {
+ // Nothing to annotate
+ return CXChildVisit_Recurse;
+ }
+
+ CXSourceLocation Loc = clang_getCursorLocation(cursor);
+ (*Data)[Loc.int_data] = cursor;
+ return CXChildVisit_Recurse;
+}
+
+void clang_annotateTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens,
+ CXCursor *Cursors) {
+ if (NumTokens == 0)
+ return;
+
+ // Any token we don't specifically annotate will have a NULL cursor.
+ for (unsigned I = 0; I != NumTokens; ++I)
+ Cursors[I] = clang_getNullCursor();
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ if (!CXXUnit || !Tokens)
+ return;
+
+ ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+
+ // Determine the region of interest, which contains all of the tokens.
+ SourceRange RegionOfInterest;
+ RegionOfInterest.setBegin(
+ cxloc::translateSourceLocation(clang_getTokenLocation(TU, Tokens[0])));
+ SourceLocation End
+ = cxloc::translateSourceLocation(clang_getTokenLocation(TU,
+ Tokens[NumTokens - 1]));
+ RegionOfInterest.setEnd(CXXUnit->getPreprocessor().getLocForEndOfToken(End));
+
+ // A mapping from the source locations found when re-lexing or traversing the
+ // region of interest to the corresponding cursors.
+ AnnotateTokensData Annotated;
+
+ // Relex the tokens within the source range to look for preprocessing
+ // directives.
+ SourceManager &SourceMgr = CXXUnit->getSourceManager();
+ std::pair<FileID, unsigned> BeginLocInfo
+ = SourceMgr.getDecomposedLoc(RegionOfInterest.getBegin());
+ std::pair<FileID, unsigned> EndLocInfo
+ = SourceMgr.getDecomposedLoc(RegionOfInterest.getEnd());
+
+ llvm::StringRef Buffer;
+ bool Invalid = false;
+ if (BeginLocInfo.first == EndLocInfo.first &&
+ ((Buffer = SourceMgr.getBufferData(BeginLocInfo.first, &Invalid)),true) &&
+ !Invalid) {
+ Lexer Lex(SourceMgr.getLocForStartOfFile(BeginLocInfo.first),
+ CXXUnit->getASTContext().getLangOptions(),
+ Buffer.begin(), Buffer.data() + BeginLocInfo.second,
+ Buffer.end());
+ Lex.SetCommentRetentionState(true);
+
+ // Lex tokens in raw mode until we hit the end of the range, to avoid
+ // entering #includes or expanding macros.
+ while (true) {
+ Token Tok;
+ Lex.LexFromRawLexer(Tok);
+
+ reprocess:
+ if (Tok.is(tok::hash) && Tok.isAtStartOfLine()) {
+ // We have found a preprocessing directive. Gobble it up so that we
+ // don't see it while preprocessing these tokens later, but keep track of
+ // all of the token locations inside this preprocessing directive so that
+ // we can annotate them appropriately.
+ //
+ // FIXME: Some simple tests here could identify macro definitions and
+ // #undefs, to provide specific cursor kinds for those.
+ std::vector<SourceLocation> Locations;
+ do {
+ Locations.push_back(Tok.getLocation());
+ Lex.LexFromRawLexer(Tok);
+ } while (!Tok.isAtStartOfLine() && !Tok.is(tok::eof));
+
+ using namespace cxcursor;
+ CXCursor Cursor
+ = MakePreprocessingDirectiveCursor(SourceRange(Locations.front(),
+ Locations.back()),
+ CXXUnit);
+ for (unsigned I = 0, N = Locations.size(); I != N; ++I) {
+ Annotated[Locations[I].getRawEncoding()] = Cursor;
+ }
+
+ if (Tok.isAtStartOfLine())
+ goto reprocess;
+
+ continue;
+ }
+
+ if (Tok.is(tok::eof))
+ break;
+ }
+ }
+
+ // Annotate all of the source locations in the region of interest that map to
+ // a specific cursor.
+ CXCursor Parent = clang_getTranslationUnitCursor(CXXUnit);
+ CursorVisitor AnnotateVis(CXXUnit, AnnotateTokensVisitor, &Annotated,
+ Decl::MaxPCHLevel, RegionOfInterest);
+ AnnotateVis.VisitChildren(Parent);
+
+ for (unsigned I = 0; I != NumTokens; ++I) {
+ // Determine whether we saw a cursor at this token's location.
+ AnnotateTokensData::iterator Pos = Annotated.find(Tokens[I].int_data[1]);
+ if (Pos == Annotated.end())
+ continue;
+
+ Cursors[I] = Pos->second;
+ }
+}
+
+void clang_disposeTokens(CXTranslationUnit TU,
+ CXToken *Tokens, unsigned NumTokens) {
+ free(Tokens);
+}
+
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Operations for querying linkage of a cursor.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+CXLinkageKind clang_getCursorLinkage(CXCursor cursor) {
+ if (!clang_isDeclaration(cursor.kind))
+ return CXLinkage_Invalid;
+
+ Decl *D = cxcursor::getCursorDecl(cursor);
+ if (NamedDecl *ND = dyn_cast_or_null<NamedDecl>(D))
+ switch (ND->getLinkage()) {
+ case NoLinkage: return CXLinkage_NoLinkage;
+ case InternalLinkage: return CXLinkage_Internal;
+ case UniqueExternalLinkage: return CXLinkage_UniqueExternal;
+ case ExternalLinkage: return CXLinkage_External;
+ };
+
+ return CXLinkage_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// Operations for querying language of a cursor.
+//===----------------------------------------------------------------------===//
+
+static CXLanguageKind getDeclLanguage(const Decl *D) {
+ switch (D->getKind()) {
+ default:
+ break;
+ case Decl::ImplicitParam:
+ case Decl::ObjCAtDefsField:
+ case Decl::ObjCCategory:
+ case Decl::ObjCCategoryImpl:
+ case Decl::ObjCClass:
+ case Decl::ObjCCompatibleAlias:
+ case Decl::ObjCForwardProtocol:
+ case Decl::ObjCImplementation:
+ case Decl::ObjCInterface:
+ case Decl::ObjCIvar:
+ case Decl::ObjCMethod:
+ case Decl::ObjCProperty:
+ case Decl::ObjCPropertyImpl:
+ case Decl::ObjCProtocol:
+ return CXLanguage_ObjC;
+ case Decl::CXXConstructor:
+ case Decl::CXXConversion:
+ case Decl::CXXDestructor:
+ case Decl::CXXMethod:
+ case Decl::CXXRecord:
+ case Decl::ClassTemplate:
+ case Decl::ClassTemplatePartialSpecialization:
+ case Decl::ClassTemplateSpecialization:
+ case Decl::Friend:
+ case Decl::FriendTemplate:
+ case Decl::FunctionTemplate:
+ case Decl::LinkageSpec:
+ case Decl::Namespace:
+ case Decl::NamespaceAlias:
+ case Decl::NonTypeTemplateParm:
+ case Decl::StaticAssert:
+ case Decl::TemplateTemplateParm:
+ case Decl::TemplateTypeParm:
+ case Decl::UnresolvedUsingTypename:
+ case Decl::UnresolvedUsingValue:
+ case Decl::Using:
+ case Decl::UsingDirective:
+ case Decl::UsingShadow:
+ return CXLanguage_CPlusPlus;
+ }
+
+ return CXLanguage_C;
+}
+
+extern "C" {
+CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
+ if (clang_isDeclaration(cursor.kind))
+ return getDeclLanguage(cxcursor::getCursorDecl(cursor));
+
+ return CXLanguage_Invalid;
+}
+} // end: extern "C"
+
+//===----------------------------------------------------------------------===//
+// CXString Operations.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+const char *clang_getCString(CXString string) {
+ return string.Spelling;
+}
+
+void clang_disposeString(CXString string) {
+ if (string.MustFreeString && string.Spelling)
+ free((void*)string.Spelling);
+}
+
+} // end: extern "C"
+
+namespace clang { namespace cxstring {
+CXString createCXString(const char *String, bool DupString){
+ CXString Str;
+ if (DupString) {
+ Str.Spelling = strdup(String);
+ Str.MustFreeString = 1;
+ } else {
+ Str.Spelling = String;
+ Str.MustFreeString = 0;
+ }
+ return Str;
+}
+
+CXString createCXString(llvm::StringRef String, bool DupString) {
+ CXString Result;
+ if (DupString || (!String.empty() && String.data()[String.size()] != 0)) {
+ char *Spelling = (char *)malloc(String.size() + 1);
+ memmove(Spelling, String.data(), String.size());
+ Spelling[String.size()] = 0;
+ Result.Spelling = Spelling;
+ Result.MustFreeString = 1;
+ } else {
+ Result.Spelling = String.data();
+ Result.MustFreeString = 0;
+ }
+ return Result;
+}
+}}
+
+//===----------------------------------------------------------------------===//
+// Misc. utility functions.
+//===----------------------------------------------------------------------===//
+
+extern "C" {
+
+CXString clang_getClangVersion() {
+ return createCXString(getClangFullVersion());
+}
+
+} // end: extern "C"
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
new file mode 100644
index 0000000..a21614c
--- /dev/null
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -0,0 +1,512 @@
+//===- CIndexCodeCompletion.cpp - Code Completion API hooks ---------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Clang-C Source Indexing library hooks for
+// code completion.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CIndexDiagnostic.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Frontend/CompilerInstance.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/System/Program.h"
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#include "clang/Basic/Version.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/Timer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+using namespace clang;
+using namespace clang::cxstring;
+
+extern "C" {
+
+enum CXCompletionChunkKind
+clang_getCompletionChunkKind(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return CXCompletionChunk_Text;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ return CXCompletionChunk_TypedText;
+ case CodeCompletionString::CK_Text:
+ return CXCompletionChunk_Text;
+ case CodeCompletionString::CK_Optional:
+ return CXCompletionChunk_Optional;
+ case CodeCompletionString::CK_Placeholder:
+ return CXCompletionChunk_Placeholder;
+ case CodeCompletionString::CK_Informative:
+ return CXCompletionChunk_Informative;
+ case CodeCompletionString::CK_ResultType:
+ return CXCompletionChunk_ResultType;
+ case CodeCompletionString::CK_CurrentParameter:
+ return CXCompletionChunk_CurrentParameter;
+ case CodeCompletionString::CK_LeftParen:
+ return CXCompletionChunk_LeftParen;
+ case CodeCompletionString::CK_RightParen:
+ return CXCompletionChunk_RightParen;
+ case CodeCompletionString::CK_LeftBracket:
+ return CXCompletionChunk_LeftBracket;
+ case CodeCompletionString::CK_RightBracket:
+ return CXCompletionChunk_RightBracket;
+ case CodeCompletionString::CK_LeftBrace:
+ return CXCompletionChunk_LeftBrace;
+ case CodeCompletionString::CK_RightBrace:
+ return CXCompletionChunk_RightBrace;
+ case CodeCompletionString::CK_LeftAngle:
+ return CXCompletionChunk_LeftAngle;
+ case CodeCompletionString::CK_RightAngle:
+ return CXCompletionChunk_RightAngle;
+ case CodeCompletionString::CK_Comma:
+ return CXCompletionChunk_Comma;
+ case CodeCompletionString::CK_Colon:
+ return CXCompletionChunk_Colon;
+ case CodeCompletionString::CK_SemiColon:
+ return CXCompletionChunk_SemiColon;
+ case CodeCompletionString::CK_Equal:
+ return CXCompletionChunk_Equal;
+ case CodeCompletionString::CK_HorizontalSpace:
+ return CXCompletionChunk_HorizontalSpace;
+ case CodeCompletionString::CK_VerticalSpace:
+ return CXCompletionChunk_VerticalSpace;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return CXCompletionChunk_Text;
+}
+
+CXString clang_getCompletionChunkText(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return createCXString(0);
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ case CodeCompletionString::CK_ResultType:
+ case CodeCompletionString::CK_Colon:
+ case CodeCompletionString::CK_SemiColon:
+ case CodeCompletionString::CK_Equal:
+ case CodeCompletionString::CK_HorizontalSpace:
+ case CodeCompletionString::CK_VerticalSpace:
+ return createCXString((*CCStr)[chunk_number].Text, false);
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return createCXString("");
+ }
+
+ // Should be unreachable, but let's be careful.
+ return createCXString(0);
+}
+
+
+CXCompletionString
+clang_getCompletionChunkCompletionString(CXCompletionString completion_string,
+ unsigned chunk_number) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ if (!CCStr || chunk_number >= CCStr->size())
+ return 0;
+
+ switch ((*CCStr)[chunk_number].Kind) {
+ case CodeCompletionString::CK_TypedText:
+ case CodeCompletionString::CK_Text:
+ case CodeCompletionString::CK_Placeholder:
+ case CodeCompletionString::CK_CurrentParameter:
+ case CodeCompletionString::CK_Informative:
+ case CodeCompletionString::CK_LeftParen:
+ case CodeCompletionString::CK_RightParen:
+ case CodeCompletionString::CK_LeftBracket:
+ case CodeCompletionString::CK_RightBracket:
+ case CodeCompletionString::CK_LeftBrace:
+ case CodeCompletionString::CK_RightBrace:
+ case CodeCompletionString::CK_LeftAngle:
+ case CodeCompletionString::CK_RightAngle:
+ case CodeCompletionString::CK_Comma:
+ case CodeCompletionString::CK_ResultType:
+ case CodeCompletionString::CK_Colon:
+ case CodeCompletionString::CK_SemiColon:
+ case CodeCompletionString::CK_Equal:
+ case CodeCompletionString::CK_HorizontalSpace:
+ case CodeCompletionString::CK_VerticalSpace:
+ return 0;
+
+ case CodeCompletionString::CK_Optional:
+ // Note: treated as an empty text block.
+ return (*CCStr)[chunk_number].Optional;
+ }
+
+ // Should be unreachable, but let's be careful.
+ return 0;
+}
+
+unsigned clang_getNumCompletionChunks(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+ return CCStr? CCStr->size() : 0;
+}
+
+static bool ReadUnsigned(const char *&Memory, const char *MemoryEnd,
+ unsigned &Value) {
+ if (Memory + sizeof(unsigned) > MemoryEnd)
+ return true;
+
+ memmove(&Value, Memory, sizeof(unsigned));
+ Memory += sizeof(unsigned);
+ return false;
+}
+
+/// \brief The CXCodeCompleteResults structure we allocate internally;
+/// the client only sees the initial CXCodeCompleteResults structure.
+struct AllocatedCXCodeCompleteResults : public CXCodeCompleteResults {
+ AllocatedCXCodeCompleteResults();
+ ~AllocatedCXCodeCompleteResults();
+
+ /// \brief The memory buffer from which we parsed the results. We
+ /// retain this buffer because the completion strings point into it.
+ llvm::MemoryBuffer *Buffer;
+
+ /// \brief Diagnostics produced while performing code completion.
+ llvm::SmallVector<StoredDiagnostic, 8> Diagnostics;
+
+ /// \brief Diag object
+ Diagnostic Diag;
+
+ /// \brief Language options used to adjust source locations.
+ LangOptions LangOpts;
+
+ /// \brief Source manager, used for diagnostics.
+ SourceManager SourceMgr;
+
+ /// \brief File manager, used for diagnostics.
+ FileManager FileMgr;
+
+ /// \brief Temporary files that should be removed once we have finished
+ /// with the code-completion results.
+ std::vector<llvm::sys::Path> TemporaryFiles;
+};
+
+AllocatedCXCodeCompleteResults::AllocatedCXCodeCompleteResults()
+ : CXCodeCompleteResults(), Buffer(0), SourceMgr(Diag) { }
+
+AllocatedCXCodeCompleteResults::~AllocatedCXCodeCompleteResults() {
+ for (unsigned I = 0, N = NumResults; I != N; ++I)
+ delete (CodeCompletionString *)Results[I].CompletionString;
+ delete [] Results;
+ delete Buffer;
+
+ for (unsigned I = 0, N = TemporaryFiles.size(); I != N; ++I)
+ TemporaryFiles[I].eraseFromDisk();
+}
+
+CXCodeCompleteResults *clang_codeComplete(CXIndex CIdx,
+ const char *source_filename,
+ int num_command_line_args,
+ const char **command_line_args,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ const char *complete_filename,
+ unsigned complete_line,
+ unsigned complete_column) {
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &StartTime = llvm::TimeRecord::getCurrentTime();
+#endif
+#endif
+
+ // The indexer, which is mainly used to determine where diagnostics go.
+ CIndexer *CXXIdx = static_cast<CIndexer *>(CIdx);
+
+ // Configure the diagnostics.
+ DiagnosticOptions DiagOpts;
+ llvm::IntrusiveRefCntPtr<Diagnostic> Diags;
+ Diags = CompilerInstance::createDiagnostics(DiagOpts, 0, 0);
+
+ // The set of temporary files that we've built.
+ std::vector<llvm::sys::Path> TemporaryFiles;
+
+ // Build up the arguments for invoking 'clang'.
+ std::vector<const char *> argv;
+
+ // First add the complete path to the 'clang' executable.
+ llvm::sys::Path ClangPath = CXXIdx->getClangPath();
+ argv.push_back(ClangPath.c_str());
+
+ // Add the '-fsyntax-only' argument so that we only perform a basic
+ // syntax check of the code.
+ argv.push_back("-fsyntax-only");
+
+ // Add the appropriate '-code-completion-at=file:line:column' argument
+ // to perform code completion, with an "-Xclang" preceding it.
+ std::string code_complete_at;
+ code_complete_at += complete_filename;
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_line);
+ code_complete_at += ":";
+ code_complete_at += llvm::utostr(complete_column);
+ argv.push_back("-Xclang");
+ argv.push_back("-code-completion-at");
+ argv.push_back("-Xclang");
+ argv.push_back(code_complete_at.c_str());
+ argv.push_back("-Xclang");
+ argv.push_back("-no-code-completion-debug-printer");
+ argv.push_back("-Xclang");
+ argv.push_back("-code-completion-macros");
+ argv.push_back("-fdiagnostics-binary");
+
+ // Remap any unsaved files to temporary files.
+ 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());
+
+ // Add the source file name (FIXME: later, we'll want to build temporary
+ // file from the buffer, or just feed the source text via standard input).
+ if (source_filename)
+ argv.push_back(source_filename);
+
+ // 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]) {
+ if (strcmp(arg, "-o") == 0) {
+ ++i; // Also skip the matching argument.
+ continue;
+ }
+ if (strcmp(arg, "-emit-ast") == 0 ||
+ strcmp(arg, "-c") == 0 ||
+ strcmp(arg, "-fsyntax-only") == 0) {
+ continue;
+ }
+
+ // Keep the argument.
+ argv.push_back(arg);
+ }
+
+ // Add the null terminator.
+ argv.push_back(NULL);
+
+ // Generate a temporary name for the code-completion results file.
+ char tmpFile[L_tmpnam];
+ char *tmpFileName = tmpnam(tmpFile);
+ llvm::sys::Path ResultsFile(tmpFileName);
+ TemporaryFiles.push_back(ResultsFile);
+
+ // Generate a temporary name for the diagnostics file.
+ char tmpFileResults[L_tmpnam];
+ char *tmpResultsFileName = tmpnam(tmpFileResults);
+ llvm::sys::Path DiagnosticsFile(tmpResultsFileName);
+ TemporaryFiles.push_back(DiagnosticsFile);
+
+ // Invoke 'clang'.
+ llvm::sys::Path DevNull; // leave empty, causes redirection to /dev/null
+ // on Unix or NUL (Windows).
+ std::string ErrMsg;
+ const llvm::sys::Path *Redirects[] = { &DevNull, &ResultsFile,
+ &DiagnosticsFile, 0 };
+ llvm::sys::Program::ExecuteAndWait(ClangPath, &argv[0], /* env */ NULL,
+ /* redirects */ &Redirects[0],
+ /* secondsToWait */ 0,
+ /* memoryLimits */ 0, &ErrMsg);
+
+ if (!ErrMsg.empty()) {
+ std::string AllArgs;
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ AllArgs += ' ';
+ if (*I)
+ AllArgs += *I;
+ }
+
+ Diags->Report(diag::err_fe_invoking) << AllArgs << ErrMsg;
+ }
+
+ // Parse the resulting source file to find code-completion results.
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+ AllocatedCXCodeCompleteResults *Results = new AllocatedCXCodeCompleteResults;
+ Results->Results = 0;
+ Results->NumResults = 0;
+ Results->Buffer = 0;
+ // FIXME: Set Results->LangOpts!
+ if (MemoryBuffer *F = MemoryBuffer::getFile(ResultsFile.c_str())) {
+ llvm::SmallVector<CXCompletionResult, 4> CompletionResults;
+ StringRef Buffer = F->getBuffer();
+ for (const char *Str = Buffer.data(), *StrEnd = Str + Buffer.size();
+ Str < StrEnd;) {
+ unsigned KindValue;
+ if (ReadUnsigned(Str, StrEnd, KindValue))
+ break;
+
+ CodeCompletionString *CCStr
+ = CodeCompletionString::Deserialize(Str, StrEnd);
+ if (!CCStr)
+ continue;
+
+ if (!CCStr->empty()) {
+ // Vend the code-completion result to the caller.
+ CXCompletionResult Result;
+ Result.CursorKind = (CXCursorKind)KindValue;
+ Result.CompletionString = CCStr;
+ CompletionResults.push_back(Result);
+ }
+ };
+
+ // Allocate the results.
+ Results->Results = new CXCompletionResult [CompletionResults.size()];
+ Results->NumResults = CompletionResults.size();
+ memcpy(Results->Results, CompletionResults.data(),
+ CompletionResults.size() * sizeof(CXCompletionResult));
+ Results->Buffer = F;
+ }
+
+ LoadSerializedDiagnostics(DiagnosticsFile, num_unsaved_files, unsaved_files,
+ Results->FileMgr, Results->SourceMgr,
+ Results->Diagnostics);
+
+ // Make sure we delete temporary files when the code-completion results are
+ // destroyed.
+ Results->TemporaryFiles.swap(TemporaryFiles);
+
+#ifdef UDP_CODE_COMPLETION_LOGGER
+#ifdef UDP_CODE_COMPLETION_LOGGER_PORT
+ const llvm::TimeRecord &EndTime = llvm::TimeRecord::getCurrentTime();
+ llvm::SmallString<256> LogResult;
+ llvm::raw_svector_ostream os(LogResult);
+
+ // Figure out the language and whether or not it uses PCH.
+ const char *lang = 0;
+ bool usesPCH = false;
+
+ for (std::vector<const char*>::iterator I = argv.begin(), E = argv.end();
+ I != E; ++I) {
+ if (*I == 0)
+ continue;
+ if (strcmp(*I, "-x") == 0) {
+ if (I + 1 != E) {
+ lang = *(++I);
+ continue;
+ }
+ }
+ else if (strcmp(*I, "-include") == 0) {
+ if (I+1 != E) {
+ const char *arg = *(++I);
+ llvm::SmallString<512> pchName;
+ {
+ llvm::raw_svector_ostream os(pchName);
+ os << arg << ".pth";
+ }
+ pchName.push_back('\0');
+ struct stat stat_results;
+ if (stat(pchName.data(), &stat_results) == 0)
+ usesPCH = true;
+ continue;
+ }
+ }
+ }
+
+ os << "{ ";
+ os << "\"wall\": " << (EndTime.getWallTime() - StartTime.getWallTime());
+ os << ", \"numRes\": " << Results->NumResults;
+ os << ", \"diags\": " << Results->Diagnostics.size();
+ os << ", \"pch\": " << (usesPCH ? "true" : "false");
+ os << ", \"lang\": \"" << (lang ? lang : "<unknown>") << '"';
+ const char *name = getlogin();
+ os << ", \"user\": \"" << (name ? name : "unknown") << '"';
+ os << ", \"clangVer\": \"" << getClangFullVersion() << '"';
+ os << " }";
+
+ llvm::StringRef res = os.str();
+ if (res.size() > 0) {
+ do {
+ // Setup the UDP socket.
+ struct sockaddr_in servaddr;
+ bzero(&servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(UDP_CODE_COMPLETION_LOGGER_PORT);
+ if (inet_pton(AF_INET, UDP_CODE_COMPLETION_LOGGER,
+ &servaddr.sin_addr) <= 0)
+ break;
+
+ int sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sockfd < 0)
+ break;
+
+ sendto(sockfd, res.data(), res.size(), 0,
+ (struct sockaddr *)&servaddr, sizeof(servaddr));
+ close(sockfd);
+ }
+ while (false);
+ }
+#endif
+#endif
+ return Results;
+}
+
+void clang_disposeCodeCompleteResults(CXCodeCompleteResults *ResultsIn) {
+ if (!ResultsIn)
+ return;
+
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ delete Results;
+}
+
+unsigned
+clang_codeCompleteGetNumDiagnostics(CXCodeCompleteResults *ResultsIn) {
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ if (!Results)
+ return 0;
+
+ return Results->Diagnostics.size();
+}
+
+CXDiagnostic
+clang_codeCompleteGetDiagnostic(CXCodeCompleteResults *ResultsIn,
+ unsigned Index) {
+ AllocatedCXCodeCompleteResults *Results
+ = static_cast<AllocatedCXCodeCompleteResults*>(ResultsIn);
+ if (!Results || Index >= Results->Diagnostics.size())
+ return 0;
+
+ return new CXStoredDiagnostic(Results->Diagnostics[Index], Results->LangOpts);
+}
+
+
+} // end extern "C"
diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp
new file mode 100644
index 0000000..3db37b9
--- /dev/null
+++ b/tools/libclang/CIndexDiagnostic.cpp
@@ -0,0 +1,285 @@
+/*===-- CIndexDiagnostics.cpp - Diagnostics C Interface ---------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements the diagnostic functions of the Clang C interface. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+#include "CIndexDiagnostic.h"
+#include "CIndexer.h"
+#include "CXSourceLocation.h"
+
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Frontend/FrontendDiagnostic.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::cxloc;
+using namespace clang::cxstring;
+using namespace llvm;
+
+//-----------------------------------------------------------------------------
+// C Interface Routines
+//-----------------------------------------------------------------------------
+extern "C" {
+
+unsigned clang_getNumDiagnostics(CXTranslationUnit Unit) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
+ return CXXUnit? CXXUnit->stored_diag_size() : 0;
+}
+
+CXDiagnostic clang_getDiagnostic(CXTranslationUnit Unit, unsigned Index) {
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(Unit);
+ if (!CXXUnit || Index >= CXXUnit->stored_diag_size())
+ return 0;
+
+ return new CXStoredDiagnostic(CXXUnit->stored_diag_begin()[Index],
+ CXXUnit->getASTContext().getLangOptions());
+}
+
+void clang_disposeDiagnostic(CXDiagnostic Diagnostic) {
+ CXStoredDiagnostic *Stored = static_cast<CXStoredDiagnostic *>(Diagnostic);
+ delete Stored;
+}
+
+CXString clang_formatDiagnostic(CXDiagnostic Diagnostic, unsigned Options) {
+ if (!Diagnostic)
+ return createCXString("");
+
+ CXDiagnosticSeverity Severity = clang_getDiagnosticSeverity(Diagnostic);
+
+ // Ignore diagnostics that should be ignored.
+ if (Severity == CXDiagnostic_Ignored)
+ return createCXString("");
+
+ llvm::SmallString<256> Str;
+ llvm::raw_svector_ostream Out(Str);
+
+ if (Options & CXDiagnostic_DisplaySourceLocation) {
+ // Print source location (file:line), along with optional column
+ // and source ranges.
+ CXFile File;
+ unsigned Line, Column;
+ clang_getInstantiationLocation(clang_getDiagnosticLocation(Diagnostic),
+ &File, &Line, &Column, 0);
+ if (File) {
+ CXString FName = clang_getFileName(File);
+ Out << clang_getCString(FName) << ":" << Line << ":";
+ clang_disposeString(FName);
+ if (Options & CXDiagnostic_DisplayColumn)
+ Out << Column << ":";
+
+ if (Options & CXDiagnostic_DisplaySourceRanges) {
+ unsigned N = clang_getDiagnosticNumRanges(Diagnostic);
+ bool PrintedRange = false;
+ for (unsigned I = 0; I != N; ++I) {
+ CXFile StartFile, EndFile;
+ CXSourceRange Range = clang_getDiagnosticRange(Diagnostic, I);
+
+ unsigned StartLine, StartColumn, EndLine, EndColumn;
+ clang_getInstantiationLocation(clang_getRangeStart(Range),
+ &StartFile, &StartLine, &StartColumn,
+ 0);
+ clang_getInstantiationLocation(clang_getRangeEnd(Range),
+ &EndFile, &EndLine, &EndColumn, 0);
+
+ if (StartFile != EndFile || StartFile != File)
+ continue;
+
+ Out << "{" << StartLine << ":" << StartColumn << "-"
+ << EndLine << ":" << EndColumn << "}";
+ PrintedRange = true;
+ }
+ if (PrintedRange)
+ Out << ":";
+ }
+ }
+
+ Out << " ";
+ }
+
+ /* Print warning/error/etc. */
+ switch (Severity) {
+ case CXDiagnostic_Ignored: assert(0 && "impossible"); break;
+ case CXDiagnostic_Note: Out << "note: "; break;
+ case CXDiagnostic_Warning: Out << "warning: "; break;
+ case CXDiagnostic_Error: Out << "error: "; break;
+ case CXDiagnostic_Fatal: Out << "fatal error: "; break;
+ }
+
+ CXString Text = clang_getDiagnosticSpelling(Diagnostic);
+ if (clang_getCString(Text))
+ Out << clang_getCString(Text);
+ else
+ Out << "<no diagnostic text>";
+ clang_disposeString(Text);
+ return createCXString(Out.str(), true);
+}
+
+unsigned clang_defaultDiagnosticDisplayOptions() {
+ return CXDiagnostic_DisplaySourceLocation | CXDiagnostic_DisplayColumn;
+}
+
+enum CXDiagnosticSeverity clang_getDiagnosticSeverity(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return CXDiagnostic_Ignored;
+
+ switch (StoredDiag->Diag.getLevel()) {
+ case Diagnostic::Ignored: return CXDiagnostic_Ignored;
+ case Diagnostic::Note: return CXDiagnostic_Note;
+ case Diagnostic::Warning: return CXDiagnostic_Warning;
+ case Diagnostic::Error: return CXDiagnostic_Error;
+ case Diagnostic::Fatal: return CXDiagnostic_Fatal;
+ }
+
+ llvm_unreachable("Invalid diagnostic level");
+ return CXDiagnostic_Ignored;
+}
+
+CXSourceLocation clang_getDiagnosticLocation(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
+ return clang_getNullLocation();
+
+ return translateSourceLocation(StoredDiag->Diag.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ StoredDiag->Diag.getLocation());
+}
+
+CXString clang_getDiagnosticSpelling(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return createCXString("");
+
+ return createCXString(StoredDiag->Diag.getMessage(), false);
+}
+
+unsigned clang_getDiagnosticNumRanges(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || StoredDiag->Diag.getLocation().isInvalid())
+ return 0;
+
+ return StoredDiag->Diag.range_size();
+}
+
+CXSourceRange clang_getDiagnosticRange(CXDiagnostic Diag, unsigned Range) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag || Range >= StoredDiag->Diag.range_size() ||
+ StoredDiag->Diag.getLocation().isInvalid())
+ return clang_getNullRange();
+
+ return translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ StoredDiag->Diag.range_begin()[Range]);
+}
+
+unsigned clang_getDiagnosticNumFixIts(CXDiagnostic Diag) {
+ CXStoredDiagnostic *StoredDiag = static_cast<CXStoredDiagnostic *>(Diag);
+ if (!StoredDiag)
+ return 0;
+
+ return StoredDiag->Diag.fixit_size();
+}
+
+CXString clang_getDiagnosticFixIt(CXDiagnostic Diagnostic, unsigned FixIt,
+ CXSourceRange *ReplacementRange) {
+ CXStoredDiagnostic *StoredDiag
+ = static_cast<CXStoredDiagnostic *>(Diagnostic);
+ if (!StoredDiag || FixIt >= StoredDiag->Diag.fixit_size() ||
+ StoredDiag->Diag.getLocation().isInvalid()) {
+ if (ReplacementRange)
+ *ReplacementRange = clang_getNullRange();
+
+ return createCXString("");
+ }
+
+ const FixItHint &Hint = StoredDiag->Diag.fixit_begin()[FixIt];
+ if (ReplacementRange) {
+ if (Hint.RemoveRange.isInvalid()) {
+ // Create an empty range that refers to a single source
+ // location (which is the insertion point).
+ CXSourceRange Range = {
+ { (void *)&StoredDiag->Diag.getLocation().getManager(),
+ (void *)&StoredDiag->LangOpts },
+ Hint.InsertionLoc.getRawEncoding(),
+ Hint.InsertionLoc.getRawEncoding()
+ };
+
+ *ReplacementRange = Range;
+ } else {
+ // Create a range that covers the entire replacement (or
+ // removal) range, adjusting the end of the range to point to
+ // the end of the token.
+ *ReplacementRange
+ = translateSourceRange(StoredDiag->Diag.getLocation().getManager(),
+ StoredDiag->LangOpts,
+ Hint.RemoveRange);
+ }
+ }
+
+ return createCXString(Hint.CodeToInsert);
+}
+
+} // end extern "C"
+
+void clang::LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ SmallVectorImpl<StoredDiagnostic> &Diags) {
+ using llvm::MemoryBuffer;
+ using llvm::StringRef;
+ MemoryBuffer *F = MemoryBuffer::getFile(DiagnosticsPath.c_str());
+ if (!F)
+ return;
+
+ // Enter the unsaved files into the file manager.
+ for (unsigned I = 0; I != num_unsaved_files; ++I) {
+ const FileEntry *File = FileMgr.getVirtualFile(unsaved_files[I].Filename,
+ unsaved_files[I].Length,
+ 0);
+ if (!File) {
+ // FIXME: Hard to localize when we have no diagnostics engine!
+ Diags.push_back(StoredDiagnostic(Diagnostic::Fatal,
+ (Twine("could not remap from missing file ") +
+ unsaved_files[I].Filename).str()));
+ delete F;
+ return;
+ }
+
+ MemoryBuffer *Buffer
+ = MemoryBuffer::getMemBuffer(unsaved_files[I].Contents,
+ unsaved_files[I].Contents + unsaved_files[I].Length);
+ if (!Buffer) {
+ delete F;
+ return;
+ }
+
+ SourceMgr.overrideFileContents(File, Buffer);
+ SourceMgr.createFileID(File, SourceLocation(), SrcMgr::C_User);
+ }
+
+ // Parse the diagnostics, emitting them one by one until we've
+ // exhausted the data.
+ StringRef Buffer = F->getBuffer();
+ const char *Memory = Buffer.data(), *MemoryEnd = Memory + Buffer.size();
+ while (Memory != MemoryEnd) {
+ StoredDiagnostic Stored = StoredDiagnostic::Deserialize(FileMgr, SourceMgr,
+ Memory, MemoryEnd);
+ if (!Stored)
+ break;
+
+ Diags.push_back(Stored);
+ }
+ delete F;
+}
diff --git a/tools/libclang/CIndexDiagnostic.h b/tools/libclang/CIndexDiagnostic.h
new file mode 100644
index 0000000..919c21c
--- /dev/null
+++ b/tools/libclang/CIndexDiagnostic.h
@@ -0,0 +1,53 @@
+/*===-- CIndexDiagnostic.h - Diagnostics C Interface ------------*- C++ -*-===*\
+|* *|
+|* The LLVM Compiler Infrastructure *|
+|* *|
+|* This file is distributed under the University of Illinois Open Source *|
+|* License. See LICENSE.TXT for details. *|
+|* *|
+|*===----------------------------------------------------------------------===*|
+|* *|
+|* Implements the diagnostic functions of the Clang C interface. *|
+|* *|
+\*===----------------------------------------------------------------------===*/
+#ifndef LLVM_CLANG_CINDEX_DIAGNOSTIC_H
+#define LLVM_CLANG_CINDEX_DIAGNOSTIC_H
+
+struct CXUnsavedFile;
+
+namespace llvm {
+template<typename T> class SmallVectorImpl;
+namespace sys { class Path; }
+}
+
+namespace clang {
+
+class Diagnostic;
+class FileManager;
+class LangOptions;
+class Preprocessor;
+class StoredDiagnostic;
+class SourceManager;
+
+/// \brief The storage behind a CXDiagnostic
+struct CXStoredDiagnostic {
+ const StoredDiagnostic &Diag;
+ const LangOptions &LangOpts;
+
+ CXStoredDiagnostic(const StoredDiagnostic &Diag,
+ const LangOptions &LangOpts)
+ : Diag(Diag), LangOpts(LangOpts) { }
+};
+
+/// \brief Given the path to a file that contains binary, serialized
+/// diagnostics produced by Clang, load those diagnostics.
+void LoadSerializedDiagnostics(const llvm::sys::Path &DiagnosticsPath,
+ unsigned num_unsaved_files,
+ struct CXUnsavedFile *unsaved_files,
+ FileManager &FileMgr,
+ SourceManager &SourceMgr,
+ llvm::SmallVectorImpl<StoredDiagnostic> &Diags);
+
+} // end namespace clang
+
+#endif // LLVM_CLANG_CINDEX_DIAGNOSTIC_H
diff --git a/tools/libclang/CIndexInclusionStack.cpp b/tools/libclang/CIndexInclusionStack.cpp
new file mode 100644
index 0000000..e863239
--- /dev/null
+++ b/tools/libclang/CIndexInclusionStack.cpp
@@ -0,0 +1,67 @@
+//===- CIndexInclusionStack.cpp - Clang-C Source Indexing Library ---------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines a callback mechanism for clients to get the inclusion
+// stack from a translation unit.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXSourceLocation.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+using namespace clang;
+
+extern "C" {
+void clang_getInclusions(CXTranslationUnit TU, CXInclusionVisitor CB,
+ CXClientData clientData) {
+
+ ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU);
+ SourceManager &SM = CXXUnit->getSourceManager();
+ ASTContext &Ctx = CXXUnit->getASTContext();
+
+ llvm::SmallVector<CXSourceLocation, 10> InclusionStack;
+ unsigned i = SM.sloc_loaded_entry_size();
+ unsigned n = SM.sloc_entry_size();
+
+ // In the case where all the SLocEntries are in an external source, traverse
+ // those SLocEntries as well. This is the case where we are looking
+ // at the inclusion stack of an AST/PCH file.
+ if (i >= n)
+ i = 0;
+
+ for ( ; i < n ; ++i) {
+
+ const SrcMgr::SLocEntry &SL = SM.getSLocEntry(i);
+
+ if (!SL.isFile())
+ continue;
+
+ const SrcMgr::FileInfo &FI = SL.getFile();
+ if (!FI.getContentCache()->Entry)
+ continue;
+
+ // Build the inclusion stack.
+ SourceLocation L = FI.getIncludeLoc();
+ InclusionStack.clear();
+ while (L.isValid()) {
+ PresumedLoc PLoc = SM.getPresumedLoc(L);
+ InclusionStack.push_back(cxloc::translateSourceLocation(Ctx, L));
+ L = PLoc.getIncludeLoc();
+ }
+
+ // Callback to the client.
+ // FIXME: We should have a function to construct CXFiles.
+ CB((CXFile) FI.getContentCache()->Entry,
+ InclusionStack.data(), InclusionStack.size(), clientData);
+ }
+}
+} // end extern C
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
new file mode 100644
index 0000000..f3c74e8
--- /dev/null
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -0,0 +1,477 @@
+//===- CIndexUSR.cpp - Clang-C Source Indexing Library --------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the generation and use of USRs from CXEntities.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+#include "CXCursor.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/Frontend/ASTUnit.h"
+#include "clang/Lex/PreprocessingRecord.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang;
+using namespace clang::cxstring;
+
+//===----------------------------------------------------------------------===//
+// USR generation.
+//===----------------------------------------------------------------------===//
+
+namespace {
+class USRGenerator : public DeclVisitor<USRGenerator> {
+ llvm::raw_ostream &Out;
+ bool IgnoreResults;
+ ASTUnit *AU;
+public:
+ USRGenerator(ASTUnit *au, llvm::raw_ostream &out)
+ : Out(out), IgnoreResults(false), AU(au) {}
+
+ bool ignoreResults() const { return IgnoreResults; }
+
+ // Visitation methods from generating USRs from AST elements.
+ void VisitDeclContext(DeclContext *D);
+ void VisitFieldDecl(FieldDecl *D);
+ void VisitFunctionDecl(FunctionDecl *D);
+ void VisitNamedDecl(NamedDecl *D);
+ void VisitNamespaceDecl(NamespaceDecl *D);
+ void VisitObjCClassDecl(ObjCClassDecl *CD);
+ void VisitObjCContainerDecl(ObjCContainerDecl *CD);
+ void VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *P);
+ void VisitObjCMethodDecl(ObjCMethodDecl *MD);
+ void VisitObjCPropertyDecl(ObjCPropertyDecl *D);
+ void VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D);
+ void VisitTagDecl(TagDecl *D);
+ void VisitTypedefDecl(TypedefDecl *D);
+ void VisitVarDecl(VarDecl *D);
+
+ /// Generate the string component containing the location of the
+ /// declaration.
+ void GenLoc(const Decl *D);
+
+ /// String generation methods used both by the visitation methods
+ /// and from other clients that want to directly generate USRs. These
+ /// methods do not construct complete USRs (which incorporate the parents
+ /// of an AST element), but only the fragments concerning the AST element
+ /// itself.
+
+ /// Generate a USR fragment for a named declaration. This does
+ /// not include the USR component for the parent.
+ void GenNamedDecl(llvm::StringRef name);
+
+ /// Generate a USR for an Objective-C class.
+ void GenObjCClass(llvm::StringRef cls);
+ /// Generate a USR for an Objective-C class category.
+ void GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat);
+ /// Generate a USR fragment for an Objective-C instance variable. The
+ /// complete USR can be created by concatenating the USR for the
+ /// encompassing class with this USR fragment.
+ void GenObjCIvar(llvm::StringRef ivar);
+ /// Generate a USR fragment for an Objective-C method.
+ void GenObjCMethod(llvm::StringRef sel, bool isInstanceMethod);
+ /// Generate a USR fragment for an Objective-C property.
+ void GenObjCProperty(llvm::StringRef prop);
+ /// Generate a USR for an Objective-C protocol.
+ void GenObjCProtocol(llvm::StringRef prot);
+};
+
+class StringUSRGenerator {
+private:
+ llvm::SmallString<1024> StrBuf;
+ llvm::raw_svector_ostream Out;
+ USRGenerator UG;
+public:
+ StringUSRGenerator(const CXCursor *C = 0)
+ : Out(StrBuf), UG(C ? cxcursor::getCursorASTUnit(*C) : 0, Out) {
+ // Add the USR space prefix.
+ Out << "c:";
+ }
+
+ llvm::StringRef str() {
+ return Out.str();
+ }
+
+ USRGenerator* operator->() { return &UG; }
+
+ template <typename T>
+ llvm::raw_svector_ostream &operator<<(const T &x) {
+ Out << x;
+ return Out;
+ }
+};
+
+} // end anonymous namespace
+
+//===----------------------------------------------------------------------===//
+// Generating USRs from ASTS.
+//===----------------------------------------------------------------------===//
+
+void USRGenerator::VisitDeclContext(DeclContext *DC) {
+ if (NamedDecl *D = dyn_cast<NamedDecl>(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 << (isa<ObjCIvarDecl>(D) ? "@" : "@FI@") << s;
+}
+
+void USRGenerator::VisitFunctionDecl(FunctionDecl *D) {
+ if (D->getLinkage() != ExternalLinkage) {
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ }
+ else
+ VisitDeclContext(D->getDeclContext());
+
+ Out << "@F@" << D;
+}
+
+void USRGenerator::VisitNamedDecl(NamedDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ const std::string &s = D->getNameAsString();
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ GenNamedDecl(s);
+}
+
+void USRGenerator::VisitVarDecl(VarDecl *D) {
+ // VarDecls can be declared 'extern' within a function or method body,
+ // but their enclosing DeclContext is the function, not the TU. We need
+ // to check the storage class to correctly generate the USR.
+ if (D->getLinkage() != ExternalLinkage) {
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ }
+
+ // Variables always have simple names.
+ llvm::StringRef s = D->getName();
+
+ // The string can be empty if the declaration has no name; e.g., it is
+ // the ParmDecl with no name for declaration of a function pointer type, e.g.:
+ // void (*f)(void *);
+ // In this case, don't generate a USR.
+ if (s.empty())
+ IgnoreResults = true;
+ else
+ GenNamedDecl(s);
+}
+
+void USRGenerator::VisitNamespaceDecl(NamespaceDecl *D) {
+ VisitDeclContext(D->getDeclContext());
+ Out << "@N@" << D;
+}
+
+void USRGenerator::VisitObjCMethodDecl(ObjCMethodDecl *D) {
+ Visit(cast<Decl>(D->getDeclContext()));
+ GenObjCMethod(DeclarationName(D->getSelector()).getAsString(),
+ D->isInstanceMethod());
+}
+
+void USRGenerator::VisitObjCClassDecl(ObjCClassDecl *D) {
+ // FIXME: @class declarations can refer to multiple classes. We need
+ // to be able to traverse these.
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitObjCForwardProtocolDecl(ObjCForwardProtocolDecl *D) {
+ // FIXME: @protocol declarations can refer to multiple protocols. We need
+ // to be able to traverse these.
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitObjCContainerDecl(ObjCContainerDecl *D) {
+ switch (D->getKind()) {
+ default:
+ assert(false && "Invalid ObjC container.");
+ case Decl::ObjCInterface:
+ case Decl::ObjCImplementation:
+ GenObjCClass(D->getName());
+ break;
+ case Decl::ObjCCategory: {
+ ObjCCategoryDecl *CD = cast<ObjCCategoryDecl>(D);
+ ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ GenObjCCategory(ID->getName(), CD->getName());
+ break;
+ }
+ case Decl::ObjCCategoryImpl: {
+ ObjCCategoryImplDecl *CD = cast<ObjCCategoryImplDecl>(D);
+ ObjCInterfaceDecl *ID = CD->getClassInterface();
+ if (!ID) {
+ // Handle invalid code where the @interface might not
+ // have been specified.
+ // FIXME: We should be able to generate this USR even if the
+ // @interface isn't available.
+ IgnoreResults = true;
+ return;
+ }
+ GenObjCCategory(ID->getName(), CD->getName());
+ break;
+ }
+ case Decl::ObjCProtocol:
+ GenObjCProtocol(cast<ObjCProtocolDecl>(D)->getName());
+ break;
+ }
+}
+
+void USRGenerator::VisitObjCPropertyDecl(ObjCPropertyDecl *D) {
+ Visit(cast<Decl>(D->getDeclContext()));
+ GenObjCProperty(D->getName());
+}
+
+void USRGenerator::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *D) {
+ if (ObjCPropertyDecl *PD = D->getPropertyDecl()) {
+ VisitObjCPropertyDecl(PD);
+ return;
+ }
+
+ IgnoreResults = true;
+}
+
+void USRGenerator::VisitTagDecl(TagDecl *D) {
+ D = D->getCanonicalDecl();
+ 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;
+ }
+
+ const std::string &s = D->getNameAsString();
+ const TypedefDecl *TD = 0;
+ if (s.empty()) {
+ TD = D->getTypedefForAnonDecl();
+ Out << (TD ? 'A' : 'a');
+ }
+
+ // Add the location of the tag decl to handle resolution across
+ // translation units.
+ if (D->getLinkage() == NoLinkage) {
+ Out << '@';
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ }
+
+ if (s.empty()) {
+ if (TD)
+ Out << '@' << TD;
+ }
+ else
+ Out << '@' << s;
+}
+
+void USRGenerator::VisitTypedefDecl(TypedefDecl *D) {
+ DeclContext *DC = D->getDeclContext();
+ if (NamedDecl *DCN = dyn_cast<NamedDecl>(DC))
+ Visit(DCN);
+ Out << "@T@";
+ if (D->getLinkage() == NoLinkage) {
+ GenLoc(D);
+ if (IgnoreResults)
+ return;
+ Out << '@';
+ }
+ Out << D->getName();
+}
+
+void USRGenerator::GenLoc(const Decl *D) {
+ const SourceManager &SM = AU->getSourceManager();
+ SourceLocation L = D->getLocStart();
+ if (L.isInvalid()) {
+ IgnoreResults = true;
+ return;
+ }
+ L = SM.getInstantiationLoc(L);
+ const std::pair<FileID, unsigned> &Decomposed = SM.getDecomposedLoc(L);
+ const FileEntry *FE = SM.getFileEntryForID(Decomposed.first);
+ if (FE) {
+ llvm::sys::Path P(FE->getName());
+ Out << P.getLast();
+ }
+ else {
+ // This case really isn't interesting.
+ IgnoreResults = true;
+ return;
+ }
+ Out << '@'
+ << SM.getLineNumber(Decomposed.first, Decomposed.second) << ':'
+ << SM.getColumnNumber(Decomposed.first, Decomposed.second);
+}
+
+//===----------------------------------------------------------------------===//
+// General purpose USR generation methods.
+//===----------------------------------------------------------------------===//
+
+void USRGenerator::GenNamedDecl(llvm::StringRef name) {
+ Out << "@" << name;
+}
+
+void USRGenerator::GenObjCClass(llvm::StringRef cls) {
+ Out << "objc(cs)" << cls;
+}
+
+void USRGenerator::GenObjCCategory(llvm::StringRef cls, llvm::StringRef cat) {
+ Out << "objc(cy)" << cls << '@' << cat;
+}
+
+void USRGenerator::GenObjCIvar(llvm::StringRef ivar) {
+ GenNamedDecl(ivar);
+}
+
+void USRGenerator::GenObjCMethod(llvm::StringRef meth, bool isInstanceMethod) {
+ Out << (isInstanceMethod ? "(im)" : "(cm)") << meth;
+}
+
+void USRGenerator::GenObjCProperty(llvm::StringRef prop) {
+ Out << "(py)" << prop;
+}
+
+void USRGenerator::GenObjCProtocol(llvm::StringRef prot) {
+ Out << "objc(pl)" << prot;
+}
+
+//===----------------------------------------------------------------------===//
+// API hooks.
+//===----------------------------------------------------------------------===//
+
+static inline llvm::StringRef extractUSRSuffix(llvm::StringRef s) {
+ return s.startswith("c:") ? s.substr(2) : "";
+}
+
+static CXString getDeclCursorUSR(const CXCursor &C) {
+ Decl *D = cxcursor::getCursorDecl(C);
+
+ // Don't generate USRs for things with invalid locations.
+ if (!D || D->getLocStart().isInvalid())
+ return createCXString("");
+
+ // Check if the cursor has 'NoLinkage'.
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(D))
+ switch (ND->getLinkage()) {
+ case ExternalLinkage:
+ // Generate USRs for all entities with external linkage.
+ break;
+ case NoLinkage:
+ // We allow enums, typedefs, and structs that have no linkage to
+ // have USRs that are anchored to the file they were defined in
+ // (e.g., the header). This is a little gross, but in principal
+ // enums/anonymous structs/etc. defined in a common header file
+ // are referred to across multiple translation units.
+ if (isa<TagDecl>(ND) || isa<TypedefDecl>(ND) ||
+ isa<EnumConstantDecl>(ND) || isa<FieldDecl>(ND) ||
+ isa<VarDecl>(ND))
+ break;
+ // Fall-through.
+ case InternalLinkage:
+ if (isa<FunctionDecl>(ND))
+ break;
+ case UniqueExternalLinkage:
+ return createCXString("");
+ }
+
+ StringUSRGenerator SUG(&C);
+ SUG->Visit(D);
+
+ if (SUG->ignoreResults())
+ return createCXString("");
+
+ // For development testing.
+ // assert(SUG.str().size() > 2);
+
+ // Return a copy of the string that must be disposed by the caller.
+ return createCXString(SUG.str(), true);
+}
+
+extern "C" {
+
+CXString clang_getCursorUSR(CXCursor C) {
+ const CXCursorKind &K = clang_getCursorKind(C);
+
+ if (clang_isDeclaration(K))
+ return getDeclCursorUSR(C);
+
+ if (K == CXCursor_MacroDefinition) {
+ StringUSRGenerator SUG(&C);
+ SUG << "macro@"
+ << cxcursor::getCursorMacroDefinition(C)->getName()->getNameStart();
+ return createCXString(SUG.str(), true);
+ }
+
+ return createCXString("");
+}
+
+CXString clang_constructUSR_ObjCIvar(const char *name, CXString classUSR) {
+ StringUSRGenerator SUG;
+ SUG << extractUSRSuffix(clang_getCString(classUSR));
+ SUG->GenObjCIvar(name);
+ return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCMethod(const char *name,
+ unsigned isInstanceMethod,
+ CXString classUSR) {
+ StringUSRGenerator SUG;
+ SUG << extractUSRSuffix(clang_getCString(classUSR));
+ SUG->GenObjCMethod(name, isInstanceMethod);
+ return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCClass(const char *name) {
+ StringUSRGenerator SUG;
+ SUG->GenObjCClass(name);
+ return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProtocol(const char *name) {
+ StringUSRGenerator SUG;
+ SUG->GenObjCProtocol(name);
+ return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCCategory(const char *class_name,
+ const char *category_name) {
+ StringUSRGenerator SUG;
+ SUG->GenObjCCategory(class_name, category_name);
+ return createCXString(SUG.str(), true);
+}
+
+CXString clang_constructUSR_ObjCProperty(const char *property,
+ CXString classUSR) {
+ StringUSRGenerator SUG;
+ SUG << extractUSRSuffix(clang_getCString(classUSR));
+ SUG->GenObjCProperty(property);
+ return createCXString(SUG.str(), true);
+}
+
+} // end extern "C"
diff --git a/tools/libclang/CIndexer.cpp b/tools/libclang/CIndexer.cpp
new file mode 100644
index 0000000..d5131ff
--- /dev/null
+++ b/tools/libclang/CIndexer.cpp
@@ -0,0 +1,154 @@
+//===- CIndex.cpp - Clang-C Source Indexing Library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements the Clang-C Source Indexing library.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CIndexer.h"
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclVisitor.h"
+#include "clang/AST/StmtVisitor.h"
+#include "clang/Basic/FileManager.h"
+#include "clang/Basic/SourceManager.h"
+#include "clang/Basic/Version.h"
+#include "clang/Sema/CodeCompleteConsumer.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Config/config.h"
+#include "llvm/Support/Compiler.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/System/Program.h"
+
+#include <cstdio>
+#include <vector>
+#include <sstream>
+
+#ifdef LLVM_ON_WIN32
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+
+using namespace clang;
+
+const llvm::sys::Path& CIndexer::getClangPath() {
+ // Did we already compute the path?
+ if (!ClangPath.empty())
+ return ClangPath;
+
+ // Find the location where this library lives (libCIndex.dylib).
+#ifdef LLVM_ON_WIN32
+ MEMORY_BASIC_INFORMATION mbi;
+ char path[MAX_PATH];
+ VirtualQuery((void *)(uintptr_t)clang_createTranslationUnit, &mbi,
+ sizeof(mbi));
+ GetModuleFileNameA((HINSTANCE)mbi.AllocationBase, path, MAX_PATH);
+
+ llvm::sys::Path CIndexPath(path);
+
+ CIndexPath.eraseComponent();
+ CIndexPath.appendComponent("clang");
+ CIndexPath.appendSuffix("exe");
+ CIndexPath.makeAbsolute();
+#else
+ // This silly cast below avoids a C++ warning.
+ Dl_info info;
+ if (dladdr((void *)(uintptr_t)clang_createTranslationUnit, &info) == 0)
+ assert(0 && "Call to dladdr() failed");
+
+ llvm::sys::Path CIndexPath(info.dli_fname);
+
+ // We now have the CIndex directory, locate clang relative to it.
+ CIndexPath.eraseComponent();
+ CIndexPath.appendComponent("..");
+ CIndexPath.appendComponent("bin");
+ CIndexPath.appendComponent("clang");
+#endif
+
+ // Cache our result.
+ ClangPath = CIndexPath;
+ return ClangPath;
+}
+
+std::string CIndexer::getClangResourcesPath() {
+ llvm::sys::Path P = getClangPath();
+
+ if (!P.empty()) {
+ P.eraseComponent(); // Remove /clang from foo/bin/clang
+ P.eraseComponent(); // Remove /bin from foo/bin
+
+ // Get foo/lib/clang/<version>/include
+ P.appendComponent("lib");
+ P.appendComponent("clang");
+ P.appendComponent(CLANG_VERSION_STRING);
+ }
+
+ return P.str();
+}
+
+static llvm::sys::Path GetTemporaryPath() {
+ // FIXME: This is lame; sys::Path should provide this function (in particular,
+ // it should know how to find the temporary files dir).
+ std::string Error;
+ const char *TmpDir = ::getenv("TMPDIR");
+ if (!TmpDir)
+ TmpDir = ::getenv("TEMP");
+ if (!TmpDir)
+ TmpDir = ::getenv("TMP");
+ if (!TmpDir)
+ TmpDir = "/tmp";
+ llvm::sys::Path P(TmpDir);
+ P.appendComponent("remap");
+ if (P.makeUnique(false, &Error))
+ return llvm::sys::Path("");
+
+ // FIXME: Grumble, makeUnique sometimes leaves the file around!? PR3837.
+ P.eraseFromDisk(false, 0);
+
+ return P;
+}
+
+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) {
+ // Write the contents of this unsaved file into the temporary file.
+ llvm::sys::Path SavedFile(GetTemporaryPath());
+ if (SavedFile.empty())
+ return true;
+
+ 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 += SavedFile.str();
+ 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/libclang/CIndexer.h b/tools/libclang/CIndexer.h
new file mode 100644
index 0000000..31bf779
--- /dev/null
+++ b/tools/libclang/CIndexer.h
@@ -0,0 +1,78 @@
+//===- CIndexer.h - Clang-C Source Indexing Library -----------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines CIndexer, a subclass of Indexer that provides extra
+// functionality needed by the CIndex library.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CINDEXER_H
+#define LLVM_CLANG_CINDEXER_H
+
+#include "clang-c/Index.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/System/Path.h"
+#include <vector>
+
+namespace clang {
+namespace cxstring {
+ CXString createCXString(const char *String, bool DupString = false);
+ CXString createCXString(llvm::StringRef String, bool DupString = true);
+}
+}
+
+class CIndexer {
+ bool UseExternalASTGeneration;
+ bool OnlyLocalDecls;
+ bool DisplayDiagnostics;
+
+ llvm::sys::Path ClangPath;
+
+public:
+ CIndexer()
+ : UseExternalASTGeneration(false), OnlyLocalDecls(false),
+ DisplayDiagnostics(false) { }
+
+ /// \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.
+ bool getOnlyLocalDecls() const { return OnlyLocalDecls; }
+ void setOnlyLocalDecls(bool Local = true) { OnlyLocalDecls = Local; }
+
+ bool getDisplayDiagnostics() const { return DisplayDiagnostics; }
+ void setDisplayDiagnostics(bool Display = true) {
+ DisplayDiagnostics = Display;
+ }
+
+ bool getUseExternalASTGeneration() const { return UseExternalASTGeneration; }
+ void setUseExternalASTGeneration(bool Value) {
+ UseExternalASTGeneration = Value;
+ }
+
+ /// \brief Get the path of the clang binary.
+ const llvm::sys::Path& getClangPath();
+
+ /// \brief Get the path of the clang resource files.
+ std::string getClangResourcesPath();
+};
+
+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/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
new file mode 100644
index 0000000..d3de94a
--- /dev/null
+++ b/tools/libclang/CMakeLists.txt
@@ -0,0 +1,57 @@
+set(SHARED_LIBRARY TRUE)
+
+set(LLVM_NO_RTTI 1)
+
+set(LLVM_USED_LIBS
+ clangFrontend
+ clangDriver
+ clangSema
+ clangAnalysis
+ clangAST
+ clangParse
+ clangLex
+ clangBasic)
+
+set( LLVM_LINK_COMPONENTS
+ bitreader
+ mc
+ core
+ )
+
+add_clang_library(libclang
+ CIndex.cpp
+ CIndexCodeCompletion.cpp
+ CIndexDiagnostic.cpp
+ CIndexInclusionStack.cpp
+ CIndexUSRs.cpp
+ CIndexer.cpp
+ CXCursor.cpp
+ ../../include/clang-c/Index.h
+)
+set_target_properties(libclang PROPERTIES OUTPUT_NAME clang)
+
+if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
+ # FIXME: Deal with LLVM_SUBMIT_VERSION?
+
+ # FIXME: This uses a special darwin-specific exports file in order to
+ # get underscore-prefixed names. It would be better to have build rules
+ # which know how to produce a darwin-suitable exports file from the
+ # regular exports file.
+ set_target_properties(libclang
+ PROPERTIES
+ LINK_FLAGS "-avoid-version -Wl,-exported_symbols_list -Wl,${CMAKE_CURRENT_SOURCE_DIR}/libclang.darwin.exports -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000"
+ INSTALL_NAME_DIR "@executable_path/../lib"
+ )
+endif()
+
+if(MSVC)
+ # windows.h doesn't compile with /Za
+ get_target_property(NON_ANSI_COMPILE_FLAGS libclang COMPILE_FLAGS)
+ string(REPLACE /Za "" NON_ANSI_COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+ set_target_properties(libclang PROPERTIES COMPILE_FLAGS ${NON_ANSI_COMPILE_FLAGS})
+endif(MSVC)
+
+set_target_properties(libclang
+ PROPERTIES
+ LINKER_LANGUAGE CXX
+ DEFINE_SYMBOL _CINDEX_LIB_)
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
new file mode 100644
index 0000000..c8eb482
--- /dev/null
+++ b/tools/libclang/CXCursor.cpp
@@ -0,0 +1,370 @@
+//===- 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) {
+ assert(D && "Invalid arguments!");
+ 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::CXXMethod: return CXCursor_CXXMethod;
+ 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;
+}
+
+static CXCursorKind GetCursorKind(const Attr *A) {
+ assert(A && "Invalid arguments!");
+ switch (A->getKind()) {
+ default: break;
+ case Attr::IBActionKind: return CXCursor_IBActionAttr;
+ case Attr::IBOutletKind: return CXCursor_IBOutletAttr;
+ }
+
+ return CXCursor_UnexposedAttr;
+}
+
+CXCursor cxcursor::MakeCXCursor(const Attr *A, Decl *Parent, ASTUnit *TU) {
+ assert(A && Parent && TU && "Invalid arguments!");
+ CXCursor C = { GetCursorKind(A), { Parent, (void*)A, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(Decl *D, ASTUnit *TU) {
+ assert(D && TU && "Invalid arguments!");
+ CXCursor C = { GetCursorKind(D), { D, 0, TU } };
+ return C;
+}
+
+CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, ASTUnit *TU) {
+ assert(S && TU && "Invalid arguments!");
+ 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::PredefinedExprClass:
+ case Stmt::IntegerLiteralClass:
+ case Stmt::FloatingLiteralClass:
+ case Stmt::ImaginaryLiteralClass:
+ case Stmt::StringLiteralClass:
+ case Stmt::CharacterLiteralClass:
+ case Stmt::ParenExprClass:
+ case Stmt::UnaryOperatorClass:
+ case Stmt::OffsetOfExprClass:
+ case Stmt::SizeOfAlignOfExprClass:
+ case Stmt::ArraySubscriptExprClass:
+ case Stmt::BinaryOperatorClass:
+ case Stmt::CompoundAssignOperatorClass:
+ case Stmt::ConditionalOperatorClass:
+ case Stmt::ImplicitCastExprClass:
+ 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::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::CXXBindReferenceExprClass:
+ 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) {
+ assert(Super && TU && "Invalid arguments!");
+ 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) {
+ assert(Super && TU && "Invalid arguments!");
+ 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) {
+ // 'Class' can be null for invalid code.
+ if (!Class)
+ return MakeCXCursorInvalid(CXCursor_InvalidCode);
+ assert(TU && "Invalid arguments!");
+ 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) {
+ assert(Type && TU && "Invalid arguments!");
+ 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])));
+}
+
+CXCursor cxcursor::MakePreprocessingDirectiveCursor(SourceRange Range,
+ ASTUnit *TU) {
+ CXCursor C = { CXCursor_PreprocessingDirective,
+ { reinterpret_cast<void *>(Range.getBegin().getRawEncoding()),
+ reinterpret_cast<void *>(Range.getEnd().getRawEncoding()),
+ TU }
+ };
+ return C;
+}
+
+SourceRange cxcursor::getCursorPreprocessingDirective(CXCursor C) {
+ assert(C.kind == CXCursor_PreprocessingDirective);
+ return SourceRange(SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t> (C.data[0])),
+ SourceLocation::getFromRawEncoding(
+ reinterpret_cast<uintptr_t> (C.data[1])));
+}
+
+CXCursor cxcursor::MakeMacroDefinitionCursor(MacroDefinition *MI, ASTUnit *TU) {
+ CXCursor C = { CXCursor_MacroDefinition, { MI, 0, TU } };
+ return C;
+}
+
+MacroDefinition *cxcursor::getCursorMacroDefinition(CXCursor C) {
+ assert(C.kind == CXCursor_MacroDefinition);
+ return static_cast<MacroDefinition *>(C.data[0]);
+}
+
+CXCursor cxcursor::MakeMacroInstantiationCursor(MacroInstantiation *MI,
+ ASTUnit *TU) {
+ CXCursor C = { CXCursor_MacroInstantiation, { MI, 0, TU } };
+ return C;
+}
+
+MacroInstantiation *cxcursor::getCursorMacroInstantiation(CXCursor C) {
+ assert(C.kind == CXCursor_MacroInstantiation);
+ return static_cast<MacroInstantiation *>(C.data[0]);
+}
+
+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/libclang/CXCursor.h b/tools/libclang/CXCursor.h
new file mode 100644
index 0000000..1664f5a
--- /dev/null
+++ b/tools/libclang/CXCursor.h
@@ -0,0 +1,112 @@
+//===- 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 Attr;
+class Decl;
+class Expr;
+class MacroDefinition;
+class MacroInstantiation;
+class NamedDecl;
+class ObjCInterfaceDecl;
+class ObjCProtocolDecl;
+class Stmt;
+class TypeDecl;
+
+namespace cxcursor {
+
+CXCursor MakeCXCursor(const clang::Attr *A, clang::Decl *Parent, ASTUnit *TU);
+CXCursor MakeCXCursor(clang::Decl *D, ASTUnit *TU);
+CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent, ASTUnit *TU);
+CXCursor MakeCXCursorInvalid(CXCursorKind K);
+
+/// \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);
+
+/// \brief Create a preprocessing directive cursor.
+CXCursor MakePreprocessingDirectiveCursor(SourceRange Range, ASTUnit *TU);
+
+/// \brief Unpack a given preprocessing directive to retrieve its source range.
+SourceRange getCursorPreprocessingDirective(CXCursor C);
+
+/// \brief Create a macro definition cursor.
+CXCursor MakeMacroDefinitionCursor(MacroDefinition *, ASTUnit *TU);
+
+/// \brief Unpack a given macro definition cursor to retrieve its
+/// source range.
+MacroDefinition *getCursorMacroDefinition(CXCursor C);
+
+/// \brief Create a macro instantiation cursor.
+CXCursor MakeMacroInstantiationCursor(MacroInstantiation *, ASTUnit *TU);
+
+/// \brief Unpack a given macro instantiation cursor to retrieve its
+/// source range.
+MacroInstantiation *getCursorMacroInstantiation(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/libclang/CXSourceLocation.h b/tools/libclang/CXSourceLocation.h
new file mode 100644
index 0000000..66566c1
--- /dev/null
+++ b/tools/libclang/CXSourceLocation.h
@@ -0,0 +1,75 @@
+//===- CXSourceLocation.h - CXSourceLocations Utilities ---------*- C++ -*-===//
+//
+// 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 CXSourceLocations.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CXSOURCELOCATION_H
+#define LLVM_CLANG_CXSOURCELOCATION_H
+
+#include "clang-c/Index.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/LangOptions.h"
+#include "clang/AST/ASTContext.h"
+
+namespace clang {
+
+class SourceManager;
+
+namespace cxloc {
+
+/// \brief Translate a Clang source location into a CIndex source location.
+static inline CXSourceLocation
+translateSourceLocation(const SourceManager &SM, const LangOptions &LangOpts,
+ SourceLocation Loc) {
+ CXSourceLocation Result = { { (void*) &SM, (void*) &LangOpts, },
+ Loc.getRawEncoding() };
+ return Result;
+}
+
+/// \brief Translate a Clang source location into a CIndex source location.
+static inline CXSourceLocation translateSourceLocation(ASTContext &Context,
+ SourceLocation Loc) {
+ return translateSourceLocation(Context.getSourceManager(),
+ Context.getLangOptions(),
+ Loc);
+}
+
+/// \brief Translate a Clang source range into a CIndex source range.
+///
+/// Clang internally represents ranges where the end location points to the
+/// start of the token at the end. However, for external clients it is more
+/// useful to have a CXSourceRange be a proper half-open interval. This routine
+/// does the appropriate translation.
+CXSourceRange translateSourceRange(const SourceManager &SM,
+ const LangOptions &LangOpts,
+ SourceRange R);
+
+/// \brief Translate a Clang source range into a CIndex source range.
+static inline CXSourceRange translateSourceRange(ASTContext &Context,
+ SourceRange R) {
+ return translateSourceRange(Context.getSourceManager(),
+ Context.getLangOptions(),
+ R);
+}
+
+static inline SourceLocation translateSourceLocation(CXSourceLocation L) {
+ return SourceLocation::getFromRawEncoding(L.int_data);
+}
+
+static inline SourceRange translateCXSourceRange(CXSourceRange R) {
+ return SourceRange(SourceLocation::getFromRawEncoding(R.begin_int_data),
+ SourceLocation::getFromRawEncoding(R.end_int_data));
+}
+
+
+}} // end namespace: clang::cxloc
+
+#endif
diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile
new file mode 100644
index 0000000..a7877bf
--- /dev/null
+++ b/tools/libclang/Makefile
@@ -0,0 +1,55 @@
+##===- tools/libclang/Makefile -----------------------------*- Makefile -*-===##
+#
+# The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+##===----------------------------------------------------------------------===##
+
+LEVEL = ../../../..
+LIBRARYNAME = clang
+
+EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/libclang.exports
+
+CPP.Flags += -I$(PROJ_SRC_DIR)/../../include -I$(PROJ_OBJ_DIR)/../../include
+
+# Include this here so we can get the configuration of the targets
+# that have been configured for construction. We have to do this
+# early so we can set up LINK_COMPONENTS before including Makefile.rules
+include $(LEVEL)/Makefile.config
+
+LINK_LIBS_IN_SHARED = 1
+SHARED_LIBRARY = 1
+
+LINK_COMPONENTS := bitreader mc core
+USEDLIBS = clangFrontend.a clangDriver.a clangSema.a \
+ clangAnalysis.a clangAST.a clangParse.a clangLex.a clangBasic.a
+
+include $(LEVEL)/Makefile.common
+
+##===----------------------------------------------------------------------===##
+# FIXME: This is copied from the 'lto' makefile. Should we share this?
+##===----------------------------------------------------------------------===##
+
+ifeq ($(HOST_OS),Darwin)
+ # set dylib internal version number to llvmCore submission number
+ ifdef LLVM_SUBMIT_VERSION
+ LLVMLibsOptions := $(LLVMLibsOptions) -Wl,-current_version \
+ -Wl,$(LLVM_SUBMIT_VERSION).$(LLVM_SUBMIT_SUBVERSION) \
+ -Wl,-compatibility_version -Wl,1
+ endif
+ # extra options to override libtool defaults
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -avoid-version \
+ -Wl,-dead_strip \
+ -Wl,-seg1addr -Wl,0xE0000000
+
+ # Mac OS X 10.4 and earlier tools do not allow a second -install_name on command line
+ DARWIN_VERS := $(shell echo $(TARGET_TRIPLE) | sed 's/.*darwin\([0-9]*\).*/\1/')
+ ifneq ($(DARWIN_VERS),8)
+ LLVMLibsOptions := $(LLVMLibsOptions) \
+ -no-undefined -Wl,-install_name \
+ -Wl,"@executable_path/../lib/lib$(LIBRARYNAME)$(SHLIBEXT)"
+ endif
+endif
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
new file mode 100644
index 0000000..b361168
--- /dev/null
+++ b/tools/libclang/libclang.darwin.exports
@@ -0,0 +1,81 @@
+_clang_annotateTokens
+_clang_codeComplete
+_clang_codeCompleteGetDiagnostic
+_clang_codeCompleteGetNumDiagnostics
+_clang_constructUSR_ObjCCategory
+_clang_constructUSR_ObjCClass
+_clang_constructUSR_ObjCIvar
+_clang_constructUSR_ObjCMethod
+_clang_constructUSR_ObjCProperty
+_clang_constructUSR_ObjCProtocol
+_clang_createIndex
+_clang_createTranslationUnit
+_clang_createTranslationUnitFromSourceFile
+_clang_defaultDiagnosticDisplayOptions
+_clang_disposeCodeCompleteResults
+_clang_disposeDiagnostic
+_clang_disposeIndex
+_clang_disposeString
+_clang_disposeTokens
+_clang_disposeTranslationUnit
+_clang_enableStackTraces
+_clang_equalCursors
+_clang_equalLocations
+_clang_formatDiagnostic
+_clang_getCString
+_clang_getClangVersion
+_clang_getCompletionChunkCompletionString
+_clang_getCompletionChunkKind
+_clang_getCompletionChunkText
+_clang_getCursor
+_clang_getCursorDefinition
+_clang_getCursorExtent
+_clang_getCursorKind
+_clang_getCursorKindSpelling
+_clang_getCursorLanguage
+_clang_getCursorLinkage
+_clang_getCursorLocation
+_clang_getCursorReferenced
+_clang_getCursorSpelling
+_clang_getCursorUSR
+_clang_getDefinitionSpellingAndExtent
+_clang_getDiagnostic
+_clang_getDiagnosticFixIt
+_clang_getDiagnosticLocation
+_clang_getDiagnosticNumFixIts
+_clang_getDiagnosticNumRanges
+_clang_getDiagnosticRange
+_clang_getDiagnosticSeverity
+_clang_getDiagnosticSpelling
+_clang_getFile
+_clang_getFileName
+_clang_getFileTime
+_clang_getInclusions
+_clang_getInstantiationLocation
+_clang_getLocation
+_clang_getNullCursor
+_clang_getNullLocation
+_clang_getNullRange
+_clang_getNumCompletionChunks
+_clang_getNumDiagnostics
+_clang_getRange
+_clang_getRangeEnd
+_clang_getRangeStart
+_clang_getTokenExtent
+_clang_getTokenKind
+_clang_getTokenLocation
+_clang_getTokenSpelling
+_clang_getTranslationUnitCursor
+_clang_getTranslationUnitSpelling
+_clang_isCursorDefinition
+_clang_isDeclaration
+_clang_isExpression
+_clang_isInvalid
+_clang_isPreprocessing
+_clang_isReference
+_clang_isStatement
+_clang_isTranslationUnit
+_clang_isUnexposed
+_clang_setUseExternalASTGeneration
+_clang_tokenize
+_clang_visitChildren
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
new file mode 100644
index 0000000..991bb06
--- /dev/null
+++ b/tools/libclang/libclang.exports
@@ -0,0 +1,81 @@
+clang_annotateTokens
+clang_codeComplete
+clang_codeCompleteGetDiagnostic
+clang_codeCompleteGetNumDiagnostics
+clang_constructUSR_ObjCCategory
+clang_constructUSR_ObjCClass
+clang_constructUSR_ObjCIvar
+clang_constructUSR_ObjCMethod
+clang_constructUSR_ObjCProperty
+clang_constructUSR_ObjCProtocol
+clang_createIndex
+clang_createTranslationUnit
+clang_createTranslationUnitFromSourceFile
+clang_defaultDiagnosticDisplayOptions
+clang_disposeCodeCompleteResults
+clang_disposeDiagnostic
+clang_disposeIndex
+clang_disposeString
+clang_disposeTokens
+clang_disposeTranslationUnit
+clang_enableStackTraces
+clang_equalCursors
+clang_equalLocations
+clang_formatDiagnostic
+clang_getCString
+clang_getClangVersion
+clang_getCompletionChunkCompletionString
+clang_getCompletionChunkKind
+clang_getCompletionChunkText
+clang_getCursor
+clang_getCursorDefinition
+clang_getCursorExtent
+clang_getCursorKind
+clang_getCursorKindSpelling
+clang_getCursorLanguage
+clang_getCursorLinkage
+clang_getCursorLocation
+clang_getCursorReferenced
+clang_getCursorSpelling
+clang_getCursorUSR
+clang_getDefinitionSpellingAndExtent
+clang_getDiagnostic
+clang_getDiagnosticFixIt
+clang_getDiagnosticLocation
+clang_getDiagnosticNumFixIts
+clang_getDiagnosticNumRanges
+clang_getDiagnosticRange
+clang_getDiagnosticSeverity
+clang_getDiagnosticSpelling
+clang_getFile
+clang_getFileName
+clang_getFileTime
+clang_getInclusions
+clang_getInstantiationLocation
+clang_getLocation
+clang_getNullCursor
+clang_getNullLocation
+clang_getNullRange
+clang_getNumCompletionChunks
+clang_getNumDiagnostics
+clang_getRange
+clang_getRangeEnd
+clang_getRangeStart
+clang_getTokenExtent
+clang_getTokenKind
+clang_getTokenLocation
+clang_getTokenSpelling
+clang_getTranslationUnitCursor
+clang_getTranslationUnitSpelling
+clang_isCursorDefinition
+clang_isDeclaration
+clang_isExpression
+clang_isInvalid
+clang_isPreprocessing
+clang_isReference
+clang_isStatement
+clang_isTranslationUnit
+clang_isUnexposed
+clang_setUseExternalASTGeneration
+clang_tokenize
+clang_visitChildren
diff --git a/tools/scan-build/ccc-analyzer b/tools/scan-build/ccc-analyzer
index daf5f7f..391ea57 100755
--- a/tools/scan-build/ccc-analyzer
+++ b/tools/scan-build/ccc-analyzer
@@ -139,12 +139,7 @@ sub GetCCArgs {
# Strip the newline and initial whitspace
chomp $line;
$line =~ s/^\s+//;
-
- my @items = quotewords('\s+', 1, $line);
- for (my $i = 0 ; $ i < scalar(@items); ++$i) {
- $items[$i] =~ s/^\"//;
- $items[$i] =~ s/\"$//;
- }
+ my @items = quotewords('\s+', 0, $line);
my $cmd = shift @items;
die "cannot find 'clang' in 'clang' command\n" if (!($cmd =~ /clang/));
return \@items;
OpenPOWER on IntegriCloud