summaryrefslogtreecommitdiffstats
path: root/tools/libclang
diff options
context:
space:
mode:
Diffstat (limited to 'tools/libclang')
-rw-r--r--tools/libclang/CIndex.cpp221
-rw-r--r--tools/libclang/CIndexCodeCompletion.cpp25
-rw-r--r--tools/libclang/CIndexDiagnostic.cpp30
-rw-r--r--tools/libclang/CIndexUSRs.cpp2
-rw-r--r--tools/libclang/CMakeLists.txt76
-rw-r--r--tools/libclang/CXComment.cpp1230
-rw-r--r--tools/libclang/CXComment.h47
-rw-r--r--tools/libclang/CXCompilationDatabase.cpp129
-rw-r--r--tools/libclang/CXCursor.cpp244
-rw-r--r--tools/libclang/CXCursor.h11
-rw-r--r--tools/libclang/CXStoredDiagnostic.cpp7
-rw-r--r--tools/libclang/CXTranslationUnit.h1
-rw-r--r--tools/libclang/CXType.cpp18
-rw-r--r--tools/libclang/IndexBody.cpp16
-rw-r--r--tools/libclang/IndexDecl.cpp15
-rw-r--r--tools/libclang/IndexTypeSourceInfo.cpp4
-rw-r--r--tools/libclang/Indexing.cpp10
-rw-r--r--tools/libclang/IndexingContext.h6
-rw-r--r--tools/libclang/Makefile7
-rw-r--r--tools/libclang/RecursiveASTVisitor.h2185
-rw-r--r--tools/libclang/libclang.exports50
21 files changed, 4205 insertions, 129 deletions
diff --git a/tools/libclang/CIndex.cpp b/tools/libclang/CIndex.cpp
index 605cc8b..bd27b4c 100644
--- a/tools/libclang/CIndex.cpp
+++ b/tools/libclang/CIndex.cpp
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "CIndexer.h"
+#include "CXComment.h"
#include "CXCursor.h"
#include "CXTranslationUnit.h"
#include "CXString.h"
@@ -61,6 +62,7 @@ CXTranslationUnit cxtu::MakeCXTranslationUnit(CIndexer *CIdx, ASTUnit *TU) {
D->TUData = TU;
D->StringPool = createCXStringPool();
D->Diagnostics = 0;
+ D->OverridenCursorsPool = createOverridenCXCursorsPool();
return D;
}
@@ -1067,7 +1069,8 @@ bool CursorVisitor::VisitObjCImplementationDecl(ObjCImplementationDecl *D) {
bool CursorVisitor::VisitObjCPropertyImplDecl(ObjCPropertyImplDecl *PD) {
if (ObjCIvarDecl *Ivar = PD->getPropertyIvarDecl())
- return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
+ if (PD->isIvarNameSpecified())
+ return Visit(MakeCursorMemberRef(Ivar, PD->getPropertyIvarDeclLoc(), TU));
return false;
}
@@ -2462,7 +2465,8 @@ CXTranslationUnit clang_createTranslationUnit(CXIndex CIdx,
CXXIdx->getOnlyLocalDecls(),
0, 0,
/*CaptureDiagnostics=*/true,
- /*AllowPCHWithCompilerErrors=*/true);
+ /*AllowPCHWithCompilerErrors=*/true,
+ /*UserFilesAreVolatile=*/true);
return MakeCXTranslationUnit(CXXIdx, TU);
}
@@ -2521,6 +2525,8 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
= (options & CXTranslationUnit_Incomplete)? TU_Prefix : TU_Complete;
bool CacheCodeCompetionResults
= options & CXTranslationUnit_CacheCompletionResults;
+ bool IncludeBriefCommentsInCodeCompletion
+ = options & CXTranslationUnit_IncludeBriefCommentsInCodeCompletion;
bool SkipFunctionBodies = options & CXTranslationUnit_SkipFunctionBodies;
// Configure the diagnostics.
@@ -2605,8 +2611,10 @@ static void clang_parseTranslationUnit_Impl(void *UserData) {
PrecompilePreamble,
TUKind,
CacheCodeCompetionResults,
+ IncludeBriefCommentsInCodeCompletion,
/*AllowPCHWithCompilerErrors=*/true,
SkipFunctionBodies,
+ /*UserFilesAreVolatile=*/true,
&ErrUnit));
if (NumErrors != Diags->getClient()->getNumErrors()) {
@@ -2691,6 +2699,8 @@ int clang_saveTranslationUnit(CXTranslationUnit TU, const char *FileName,
ASTUnit *CXXUnit = static_cast<ASTUnit *>(TU->TUData);
ASTUnit::ConcurrencyCheck Check(*CXXUnit);
+ if (!CXXUnit->hasSema())
+ return CXSaveError_InvalidTU;
SaveTranslationUnitInfo STUI = { TU, FileName, options, CXSaveError_None };
@@ -2734,6 +2744,7 @@ void clang_disposeTranslationUnit(CXTranslationUnit CTUnit) {
delete static_cast<ASTUnit *>(CTUnit->TUData);
disposeCXStringPool(CTUnit->StringPool);
delete static_cast<CXDiagnosticSetImpl *>(CTUnit->Diagnostics);
+ disposeOverridenCXCursorsPool(CTUnit->OverridenCursorsPool);
delete CTUnit;
}
}
@@ -2829,8 +2840,8 @@ CXString clang_getTranslationUnitSpelling(CXTranslationUnit CTUnit) {
}
CXCursor clang_getTranslationUnitCursor(CXTranslationUnit TU) {
- CXCursor Result = { CXCursor_TranslationUnit, 0, { 0, 0, TU } };
- return Result;
+ ASTUnit *CXXUnit = static_cast<ASTUnit*>(TU->TUData);
+ return MakeCXCursor(CXXUnit->getASTContext().getTranslationUnitDecl(), TU);
}
} // end: extern "C"
@@ -3501,6 +3512,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return createCXString("ReturnStmt");
case CXCursor_AsmStmt:
return createCXString("AsmStmt");
+ case CXCursor_MSAsmStmt:
+ return createCXString("MSAsmStmt");
case CXCursor_ObjCAtTryStmt:
return createCXString("ObjCAtTryStmt");
case CXCursor_ObjCAtCatchStmt:
@@ -3609,12 +3622,15 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
struct GetCursorData {
SourceLocation TokenBeginLoc;
bool PointsAtMacroArgExpansion;
+ bool VisitedObjCPropertyImplDecl;
+ SourceLocation VisitedDeclaratorDeclStartLoc;
CXCursor &BestCursor;
GetCursorData(SourceManager &SM,
SourceLocation tokenBegin, CXCursor &outputCursor)
: TokenBeginLoc(tokenBegin), BestCursor(outputCursor) {
PointsAtMacroArgExpansion = SM.isMacroArgExpansion(tokenBegin);
+ VisitedObjCPropertyImplDecl = false;
}
};
@@ -3654,6 +3670,32 @@ static enum CXChildVisitResult GetCursorVisitor(CXCursor cursor,
!ID->isThisDeclarationADefinition())
return CXChildVisit_Break;
}
+
+ } else if (DeclaratorDecl *DD
+ = dyn_cast_or_null<DeclaratorDecl>(getCursorDecl(cursor))) {
+ SourceLocation StartLoc = DD->getSourceRange().getBegin();
+ // Check that when we have multiple declarators in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // int Foo, Bar;
+ // source ranges for both start at 'int', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedDeclaratorDeclStartLoc == StartLoc)
+ return CXChildVisit_Break;
+ Data->VisitedDeclaratorDeclStartLoc = StartLoc;
+
+ } else if (ObjCPropertyImplDecl *PropImp
+ = dyn_cast_or_null<ObjCPropertyImplDecl>(getCursorDecl(cursor))) {
+ (void)PropImp;
+ // Check that when we have multiple @synthesize in the same line,
+ // that later ones do not override the previous ones.
+ // If we have:
+ // @synthesize Foo, Bar;
+ // source ranges for both start at '@', so 'Bar' will end up overriding
+ // 'Foo' even though the cursor location was at 'Foo'.
+ if (Data->VisitedObjCPropertyImplDecl)
+ return CXChildVisit_Break;
+ Data->VisitedObjCPropertyImplDecl = true;
}
}
@@ -5487,6 +5529,90 @@ enum CXAvailabilityKind clang_getCursorAvailability(CXCursor cursor) {
return CXAvailability_Available;
}
+static CXVersion convertVersion(VersionTuple In) {
+ CXVersion Out = { -1, -1, -1 };
+ if (In.empty())
+ return Out;
+
+ Out.Major = In.getMajor();
+
+ if (llvm::Optional<unsigned> Minor = In.getMinor())
+ Out.Minor = *Minor;
+ else
+ return Out;
+
+ if (llvm::Optional<unsigned> Subminor = In.getSubminor())
+ Out.Subminor = *Subminor;
+
+ return Out;
+}
+
+int clang_getCursorPlatformAvailability(CXCursor cursor,
+ int *always_deprecated,
+ CXString *deprecated_message,
+ int *always_unavailable,
+ CXString *unavailable_message,
+ CXPlatformAvailability *availability,
+ int availability_size) {
+ if (always_deprecated)
+ *always_deprecated = 0;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createCXString("", /*DupString=*/false);
+ if (always_unavailable)
+ *always_unavailable = 0;
+ if (unavailable_message)
+ *unavailable_message = cxstring::createCXString("", /*DupString=*/false);
+
+ if (!clang_isDeclaration(cursor.kind))
+ return 0;
+
+ Decl *D = cxcursor::getCursorDecl(cursor);
+ if (!D)
+ return 0;
+
+ int N = 0;
+ for (Decl::attr_iterator A = D->attr_begin(), AEnd = D->attr_end(); A != AEnd;
+ ++A) {
+ if (DeprecatedAttr *Deprecated = dyn_cast<DeprecatedAttr>(*A)) {
+ if (always_deprecated)
+ *always_deprecated = 1;
+ if (deprecated_message)
+ *deprecated_message = cxstring::createCXString(Deprecated->getMessage());
+ continue;
+ }
+
+ if (UnavailableAttr *Unavailable = dyn_cast<UnavailableAttr>(*A)) {
+ if (always_unavailable)
+ *always_unavailable = 1;
+ if (unavailable_message) {
+ *unavailable_message
+ = cxstring::createCXString(Unavailable->getMessage());
+ }
+ continue;
+ }
+
+ if (AvailabilityAttr *Avail = dyn_cast<AvailabilityAttr>(*A)) {
+ if (N < availability_size) {
+ availability[N].Platform
+ = cxstring::createCXString(Avail->getPlatform()->getName());
+ availability[N].Introduced = convertVersion(Avail->getIntroduced());
+ availability[N].Deprecated = convertVersion(Avail->getDeprecated());
+ availability[N].Obsoleted = convertVersion(Avail->getObsoleted());
+ availability[N].Unavailable = Avail->getUnavailable();
+ availability[N].Message = cxstring::createCXString(Avail->getMessage());
+ }
+ ++N;
+ }
+ }
+
+ return N;
+}
+
+void clang_disposeCXPlatformAvailability(CXPlatformAvailability *availability) {
+ clang_disposeString(availability->Platform);
+ clang_disposeString(availability->Message);
+}
+
CXLanguageKind clang_getCursorLanguage(CXCursor cursor) {
if (clang_isDeclaration(cursor.kind))
return getDeclLanguage(cxcursor::getCursorDecl(cursor));
@@ -5549,44 +5675,73 @@ CXCursor clang_getCursorLexicalParent(CXCursor cursor) {
return clang_getNullCursor();
}
-void clang_getOverriddenCursors(CXCursor cursor,
- CXCursor **overridden,
- unsigned *num_overridden) {
- if (overridden)
- *overridden = 0;
- if (num_overridden)
- *num_overridden = 0;
- if (!overridden || !num_overridden)
- return;
- if (!clang_isDeclaration(cursor.kind))
- return;
+CXFile clang_getIncludedFile(CXCursor cursor) {
+ if (cursor.kind != CXCursor_InclusionDirective)
+ return 0;
+
+ InclusionDirective *ID = getCursorInclusionDirective(cursor);
+ return (void *)ID->getFile();
+}
- SmallVector<CXCursor, 8> Overridden;
- cxcursor::getOverriddenCursors(cursor, Overridden);
+CXSourceRange clang_Cursor_getCommentRange(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return clang_getNullRange();
- // Don't allocate memory if we have no overriden cursors.
- if (Overridden.size() == 0)
- return;
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ if (!RC)
+ return clang_getNullRange();
- *num_overridden = Overridden.size();
- *overridden = new CXCursor [Overridden.size()];
- std::copy(Overridden.begin(), Overridden.end(), *overridden);
+ return cxloc::translateSourceRange(Context, RC->getSourceRange());
}
-void clang_disposeOverriddenCursors(CXCursor *overridden) {
- delete [] overridden;
+CXString clang_Cursor_getRawCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return createCXString((const char *) NULL);
+
+ const Decl *D = getCursorDecl(C);
+ ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+ StringRef RawText = RC ? RC->getRawText(Context.getSourceManager()) :
+ StringRef();
+
+ // Don't duplicate the string because RawText points directly into source
+ // code.
+ return createCXString(RawText, false);
}
-CXFile clang_getIncludedFile(CXCursor cursor) {
- if (cursor.kind != CXCursor_InclusionDirective)
- return 0;
-
- InclusionDirective *ID = getCursorInclusionDirective(cursor);
- return (void *)ID->getFile();
+CXString clang_Cursor_getBriefCommentText(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return createCXString((const char *) NULL);
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const RawComment *RC = Context.getRawCommentForAnyRedecl(D);
+
+ if (RC) {
+ StringRef BriefText = RC->getBriefText(Context);
+
+ // Don't duplicate the string because RawComment ensures that this memory
+ // will not go away.
+ return createCXString(BriefText, false);
+ }
+
+ return createCXString((const char *) NULL);
}
-
-} // end: extern "C"
+CXComment clang_Cursor_getParsedComment(CXCursor C) {
+ if (!clang_isDeclaration(C.kind))
+ return cxcomment::createCXComment(NULL);
+
+ const Decl *D = getCursorDecl(C);
+ const ASTContext &Context = getCursorContext(C);
+ const comments::FullComment *FC = Context.getCommentForDecl(D);
+
+ return cxcomment::createCXComment(FC);
+}
+
+} // end: extern "C"
//===----------------------------------------------------------------------===//
// C++ AST instrospection.
diff --git a/tools/libclang/CIndexCodeCompletion.cpp b/tools/libclang/CIndexCodeCompletion.cpp
index 303fb1f..0073b50 100644
--- a/tools/libclang/CIndexCodeCompletion.cpp
+++ b/tools/libclang/CIndexCodeCompletion.cpp
@@ -227,6 +227,17 @@ clang_getCompletionParent(CXCompletionString completion_string,
*kind = CCStr->getParentContextKind();
return createCXString(CCStr->getParentContextName(), /*DupString=*/false);
}
+
+CXString
+clang_getCompletionBriefComment(CXCompletionString completion_string) {
+ CodeCompletionString *CCStr = (CodeCompletionString *)completion_string;
+
+ if (!CCStr)
+ return createCXString((const char *) NULL);
+
+ return createCXString(CCStr->getBriefComment(), /*DupString=*/false);
+}
+
/// \brief The CXCodeCompleteResults structure we allocate internally;
/// the client only sees the initial CXCodeCompleteResults structure.
@@ -509,9 +520,10 @@ namespace {
SmallVector<CXCompletionResult, 16> StoredResults;
CXTranslationUnit *TU;
public:
- CaptureCompletionResults(AllocatedCXCodeCompleteResults &Results,
+ CaptureCompletionResults(const CodeCompleteOptions &Opts,
+ AllocatedCXCodeCompleteResults &Results,
CXTranslationUnit *TranslationUnit)
- : CodeCompleteConsumer(true, false, true, false),
+ : CodeCompleteConsumer(Opts, false),
AllocatedResults(Results), CCTUInfo(Results.CodeCompletionAllocator),
TU(TranslationUnit) { }
~CaptureCompletionResults() { Finish(); }
@@ -524,7 +536,8 @@ namespace {
for (unsigned I = 0; I != NumResults; ++I) {
CodeCompletionString *StoredCompletion
= Results[I].CreateCodeCompletionString(S, getAllocator(),
- getCodeCompletionTUInfo());
+ getCodeCompletionTUInfo(),
+ includeBriefComments());
CXCompletionResult R;
R.CursorKind = Results[I].CursorKind;
@@ -658,6 +671,7 @@ void clang_codeCompleteAt_Impl(void *UserData) {
struct CXUnsavedFile *unsaved_files = CCAI->unsaved_files;
unsigned num_unsaved_files = CCAI->num_unsaved_files;
unsigned options = CCAI->options;
+ bool IncludeBriefComments = options & CXCodeComplete_IncludeBriefComments;
CCAI->result = 0;
#ifdef UDP_CODE_COMPLETION_LOGGER
@@ -699,13 +713,16 @@ void clang_codeCompleteAt_Impl(void *UserData) {
Results->NumResults = 0;
// Create a code-completion consumer to capture the results.
- CaptureCompletionResults Capture(*Results, &TU);
+ CodeCompleteOptions Opts;
+ Opts.IncludeBriefComments = IncludeBriefComments;
+ CaptureCompletionResults Capture(Opts, *Results, &TU);
// Perform completion.
AST->CodeComplete(complete_filename, complete_line, complete_column,
RemappedFiles.data(), RemappedFiles.size(),
(options & CXCodeComplete_IncludeMacros),
(options & CXCodeComplete_IncludeCodePatterns),
+ IncludeBriefComments,
Capture,
*Results->Diag, Results->LangOpts, *Results->SourceMgr,
*Results->FileMgr, Results->Diagnostics,
diff --git a/tools/libclang/CIndexDiagnostic.cpp b/tools/libclang/CIndexDiagnostic.cpp
index 8fbe3d8..14722e0 100644
--- a/tools/libclang/CIndexDiagnostic.cpp
+++ b/tools/libclang/CIndexDiagnostic.cpp
@@ -86,11 +86,10 @@ public:
class CXDiagnosticRenderer : public DiagnosticNoteRenderer {
public:
- CXDiagnosticRenderer(const SourceManager &SM,
- const LangOptions &LangOpts,
+ CXDiagnosticRenderer(const LangOptions &LangOpts,
const DiagnosticOptions &DiagOpts,
CXDiagnosticSetImpl *mainSet)
- : DiagnosticNoteRenderer(SM, LangOpts, DiagOpts),
+ : DiagnosticNoteRenderer(LangOpts, DiagOpts),
CurrentSet(mainSet), MainSet(mainSet) {}
virtual ~CXDiagnosticRenderer() {}
@@ -116,26 +115,38 @@ public:
DiagnosticsEngine::Level Level,
StringRef Message,
ArrayRef<CharSourceRange> Ranges,
+ const SourceManager *SM,
DiagOrStoredDiag D) {
if (!D.isNull())
return;
- CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
+ CXSourceLocation L;
+ if (SM)
+ L = translateSourceLocation(*SM, LangOpts, Loc);
+ else
+ L = clang_getNullLocation();
CXDiagnosticImpl *CD = new CXDiagnosticCustomNoteImpl(Message, L);
CurrentSet->appendDiagnostic(CD);
}
virtual void emitDiagnosticLoc(SourceLocation Loc, PresumedLoc PLoc,
DiagnosticsEngine::Level Level,
- ArrayRef<CharSourceRange> Ranges) {}
+ ArrayRef<CharSourceRange> Ranges,
+ const SourceManager &SM) {}
virtual void emitCodeContext(SourceLocation Loc,
DiagnosticsEngine::Level Level,
SmallVectorImpl<CharSourceRange>& Ranges,
- ArrayRef<FixItHint> Hints) {}
+ ArrayRef<FixItHint> Hints,
+ const SourceManager &SM) {}
- virtual void emitNote(SourceLocation Loc, StringRef Message) {
- CXSourceLocation L = translateSourceLocation(SM, LangOpts, Loc);
+ virtual void emitNote(SourceLocation Loc, StringRef Message,
+ const SourceManager *SM) {
+ CXSourceLocation L;
+ if (SM)
+ L = translateSourceLocation(*SM, LangOpts, Loc);
+ else
+ L = clang_getNullLocation();
CurrentSet->appendDiagnostic(new CXDiagnosticCustomNoteImpl(Message,
L));
}
@@ -181,8 +192,7 @@ CXDiagnosticSetImpl *cxdiag::lazyCreateDiags(CXTranslationUnit TU,
CXDiagnosticSetImpl *Set = new CXDiagnosticSetImpl();
TU->Diagnostics = Set;
DiagnosticOptions DOpts;
- CXDiagnosticRenderer Renderer(AU->getSourceManager(),
- AU->getASTContext().getLangOpts(),
+ CXDiagnosticRenderer Renderer(AU->getASTContext().getLangOpts(),
DOpts, Set);
for (ASTUnit::stored_diag_iterator it = AU->stored_diag_begin(),
diff --git a/tools/libclang/CIndexUSRs.cpp b/tools/libclang/CIndexUSRs.cpp
index 7c79b69..c885dd5 100644
--- a/tools/libclang/CIndexUSRs.cpp
+++ b/tools/libclang/CIndexUSRs.cpp
@@ -754,7 +754,7 @@ void USRGenerator::VisitTemplateArgument(const TemplateArgument &Arg) {
case TemplateArgument::Integral:
Out << 'V';
VisitType(Arg.getIntegralType());
- Out << *Arg.getAsIntegral();
+ Out << Arg.getAsIntegral();
break;
}
}
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index fb0b91f..283276f 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -1,16 +1,6 @@
-set(LLVM_USED_LIBS
- clangARCMigrate
- clangRewrite
- clangFrontend
- clangDriver
- clangSerialization
- clangSema
- clangEdit
- clangAST
- clangLex
- clangBasic)
-
-set( LLVM_LINK_COMPONENTS
+set(LLVM_LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ asmparser
support
mc
)
@@ -27,8 +17,10 @@ set(SOURCES
CIndexUSRs.cpp
CIndexer.cpp
CIndexer.h
+ CXComment.cpp
CXCursor.cpp
CXCursor.h
+ CXCompilationDatabase.cpp
CXLoadedDiagnostic.cpp
CXLoadedDiagnostic.h
CXSourceLocation.cpp
@@ -49,32 +41,60 @@ set(SOURCES
../../include/clang-c/Index.h
)
+set(LIBRARIES
+ clangARCMigrate
+ clangRewrite
+ clangFrontend
+ clangDriver
+ clangSerialization
+ clangSema
+ clangEdit
+ clangAST
+ clangLex
+ clangTooling
+ clangBasic
+ )
+
+set(GENERATED_HEADERS
+ ClangAttrClasses
+ ClangAttrList
+ ClangAttrParsedAttrList
+ ClangCommentNodes
+ ClangDiagnosticCommon
+ ClangDiagnosticFrontend
+ ClangDeclNodes
+ ClangStmtNodes
+ )
+
if( LLVM_ENABLE_PIC )
set(SHARED_LIBRARY TRUE)
add_clang_library(libclang ${SOURCES})
+ target_link_libraries(libclang ${LIBRARIES})
+ add_dependencies(libclang ${GENERATED_HEADERS})
- set_target_properties(libclang
- PROPERTIES
- OUTPUT_NAME "libclang"
- VERSION ${LIBCLANG_LIBRARY_VERSION}
- DEFINE_SYMBOL _CINDEX_LIB_)
+ if(WIN32)
+ set_target_properties(libclang
+ PROPERTIES
+ OUTPUT_NAME "libclang"
+ VERSION ${LIBCLANG_LIBRARY_VERSION}
+ DEFINE_SYMBOL _CINDEX_LIB_)
+ else()
+ set_target_properties(libclang
+ PROPERTIES
+ OUTPUT_NAME "clang"
+ VERSION ${LIBCLANG_LIBRARY_VERSION}
+ DEFINE_SYMBOL _CINDEX_LIB_)
+ endif()
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
set(LIBCLANG_LINK_FLAGS
- "-Wl,-compatibility_version -Wl,1 -Wl,-dead_strip -Wl,-seg1addr -Wl,0xE0000000")
+ "-Wl,-compatibility_version -Wl,1 -Wl,-dead_strip")
set_target_properties(libclang
PROPERTIES
LINK_FLAGS "${LIBCLANG_LINK_FLAGS}"
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()
set(LIBCLANG_STATIC_TARGET_NAME libclang_static)
else()
@@ -83,8 +103,10 @@ endif()
if( NOT BUILD_SHARED_LIBS AND NOT WIN32 )
add_clang_library(${LIBCLANG_STATIC_TARGET_NAME} STATIC ${SOURCES})
+ target_link_libraries(${LIBCLANG_STATIC_TARGET_NAME} ${LIBRARIES})
+ add_dependencies(${LIBCLANG_STATIC_TARGET_NAME} ${GENERATED_HEADERS})
set_target_properties(${LIBCLANG_STATIC_TARGET_NAME}
PROPERTIES
- OUTPUT_NAME "libclang")
+ OUTPUT_NAME "clang")
endif()
diff --git a/tools/libclang/CXComment.cpp b/tools/libclang/CXComment.cpp
new file mode 100644
index 0000000..c5c9ca8
--- /dev/null
+++ b/tools/libclang/CXComment.cpp
@@ -0,0 +1,1230 @@
+//===- CXComment.cpp - libclang APIs for manipulating CXComments ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines all libclang APIs related to walking comment AST.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang-c/Index.h"
+#include "CXString.h"
+#include "CXComment.h"
+#include "CXCursor.h"
+#include "CXTranslationUnit.h"
+
+#include "clang/AST/CommentVisitor.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/Decl.h"
+#include "clang/Frontend/ASTUnit.h"
+
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+
+#include <climits>
+
+using namespace clang;
+using namespace clang::cxstring;
+using namespace clang::comments;
+using namespace clang::cxcomment;
+
+extern "C" {
+
+enum CXCommentKind clang_Comment_getKind(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return CXComment_Null;
+
+ switch (C->getCommentKind()) {
+ case Comment::NoCommentKind:
+ return CXComment_Null;
+
+ case Comment::TextCommentKind:
+ return CXComment_Text;
+
+ case Comment::InlineCommandCommentKind:
+ return CXComment_InlineCommand;
+
+ case Comment::HTMLStartTagCommentKind:
+ return CXComment_HTMLStartTag;
+
+ case Comment::HTMLEndTagCommentKind:
+ return CXComment_HTMLEndTag;
+
+ case Comment::ParagraphCommentKind:
+ return CXComment_Paragraph;
+
+ case Comment::BlockCommandCommentKind:
+ return CXComment_BlockCommand;
+
+ case Comment::ParamCommandCommentKind:
+ return CXComment_ParamCommand;
+
+ case Comment::TParamCommandCommentKind:
+ return CXComment_TParamCommand;
+
+ case Comment::VerbatimBlockCommentKind:
+ return CXComment_VerbatimBlockCommand;
+
+ case Comment::VerbatimBlockLineCommentKind:
+ return CXComment_VerbatimBlockLine;
+
+ case Comment::VerbatimLineCommentKind:
+ return CXComment_VerbatimLine;
+
+ case Comment::FullCommentKind:
+ return CXComment_FullComment;
+ }
+ llvm_unreachable("unknown CommentKind");
+}
+
+unsigned clang_Comment_getNumChildren(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return 0;
+
+ return C->child_count();
+}
+
+CXComment clang_Comment_getChild(CXComment CXC, unsigned ChildIdx) {
+ const Comment *C = getASTNode(CXC);
+ if (!C || ChildIdx >= C->child_count())
+ return createCXComment(NULL);
+
+ return createCXComment(*(C->child_begin() + ChildIdx));
+}
+
+unsigned clang_Comment_isWhitespace(CXComment CXC) {
+ const Comment *C = getASTNode(CXC);
+ if (!C)
+ return false;
+
+ if (const TextComment *TC = dyn_cast<TextComment>(C))
+ return TC->isWhitespace();
+
+ if (const ParagraphComment *PC = dyn_cast<ParagraphComment>(C))
+ return PC->isWhitespace();
+
+ return false;
+}
+
+unsigned clang_InlineContentComment_hasTrailingNewline(CXComment CXC) {
+ const InlineContentComment *ICC = getASTNodeAs<InlineContentComment>(CXC);
+ if (!ICC)
+ return false;
+
+ return ICC->hasTrailingNewline();
+}
+
+CXString clang_TextComment_getText(CXComment CXC) {
+ const TextComment *TC = getASTNodeAs<TextComment>(CXC);
+ if (!TC)
+ return createCXString((const char *) 0);
+
+ return createCXString(TC->getText(), /*DupString=*/ false);
+}
+
+CXString clang_InlineCommandComment_getCommandName(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return createCXString((const char *) 0);
+
+ return createCXString(ICC->getCommandName(), /*DupString=*/ false);
+}
+
+enum CXCommentInlineCommandRenderKind
+clang_InlineCommandComment_getRenderKind(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return CXCommentInlineCommandRenderKind_Normal;
+
+ switch (ICC->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ return CXCommentInlineCommandRenderKind_Normal;
+
+ case InlineCommandComment::RenderBold:
+ return CXCommentInlineCommandRenderKind_Bold;
+
+ case InlineCommandComment::RenderMonospaced:
+ return CXCommentInlineCommandRenderKind_Monospaced;
+
+ case InlineCommandComment::RenderEmphasized:
+ return CXCommentInlineCommandRenderKind_Emphasized;
+ }
+ llvm_unreachable("unknown InlineCommandComment::RenderKind");
+}
+
+unsigned clang_InlineCommandComment_getNumArgs(CXComment CXC) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC)
+ return 0;
+
+ return ICC->getNumArgs();
+}
+
+CXString clang_InlineCommandComment_getArgText(CXComment CXC,
+ unsigned ArgIdx) {
+ const InlineCommandComment *ICC = getASTNodeAs<InlineCommandComment>(CXC);
+ if (!ICC || ArgIdx >= ICC->getNumArgs())
+ return createCXString((const char *) 0);
+
+ return createCXString(ICC->getArgText(ArgIdx), /*DupString=*/ false);
+}
+
+CXString clang_HTMLTagComment_getTagName(CXComment CXC) {
+ const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
+ if (!HTC)
+ return createCXString((const char *) 0);
+
+ return createCXString(HTC->getTagName(), /*DupString=*/ false);
+}
+
+unsigned clang_HTMLStartTagComment_isSelfClosing(CXComment CXC) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST)
+ return false;
+
+ return HST->isSelfClosing();
+}
+
+unsigned clang_HTMLStartTag_getNumAttrs(CXComment CXC) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST)
+ return 0;
+
+ return HST->getNumAttrs();
+}
+
+CXString clang_HTMLStartTag_getAttrName(CXComment CXC, unsigned AttrIdx) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST || AttrIdx >= HST->getNumAttrs())
+ return createCXString((const char *) 0);
+
+ return createCXString(HST->getAttr(AttrIdx).Name, /*DupString=*/ false);
+}
+
+CXString clang_HTMLStartTag_getAttrValue(CXComment CXC, unsigned AttrIdx) {
+ const HTMLStartTagComment *HST = getASTNodeAs<HTMLStartTagComment>(CXC);
+ if (!HST || AttrIdx >= HST->getNumAttrs())
+ return createCXString((const char *) 0);
+
+ return createCXString(HST->getAttr(AttrIdx).Value, /*DupString=*/ false);
+}
+
+CXString clang_BlockCommandComment_getCommandName(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return createCXString((const char *) 0);
+
+ return createCXString(BCC->getCommandName(), /*DupString=*/ false);
+}
+
+unsigned clang_BlockCommandComment_getNumArgs(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return 0;
+
+ return BCC->getNumArgs();
+}
+
+CXString clang_BlockCommandComment_getArgText(CXComment CXC,
+ unsigned ArgIdx) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC || ArgIdx >= BCC->getNumArgs())
+ return createCXString((const char *) 0);
+
+ return createCXString(BCC->getArgText(ArgIdx), /*DupString=*/ false);
+}
+
+CXComment clang_BlockCommandComment_getParagraph(CXComment CXC) {
+ const BlockCommandComment *BCC = getASTNodeAs<BlockCommandComment>(CXC);
+ if (!BCC)
+ return createCXComment(NULL);
+
+ return createCXComment(BCC->getParagraph());
+}
+
+CXString clang_ParamCommandComment_getParamName(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC || !PCC->hasParamName())
+ return createCXString((const char *) 0);
+
+ return createCXString(PCC->getParamName(), /*DupString=*/ false);
+}
+
+unsigned clang_ParamCommandComment_isParamIndexValid(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return false;
+
+ return PCC->isParamIndexValid();
+}
+
+unsigned clang_ParamCommandComment_getParamIndex(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC || !PCC->isParamIndexValid())
+ return ParamCommandComment::InvalidParamIndex;
+
+ return PCC->getParamIndex();
+}
+
+unsigned clang_ParamCommandComment_isDirectionExplicit(CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return false;
+
+ return PCC->isDirectionExplicit();
+}
+
+enum CXCommentParamPassDirection clang_ParamCommandComment_getDirection(
+ CXComment CXC) {
+ const ParamCommandComment *PCC = getASTNodeAs<ParamCommandComment>(CXC);
+ if (!PCC)
+ return CXCommentParamPassDirection_In;
+
+ switch (PCC->getDirection()) {
+ case ParamCommandComment::In:
+ return CXCommentParamPassDirection_In;
+
+ case ParamCommandComment::Out:
+ return CXCommentParamPassDirection_Out;
+
+ case ParamCommandComment::InOut:
+ return CXCommentParamPassDirection_InOut;
+ }
+ llvm_unreachable("unknown ParamCommandComment::PassDirection");
+}
+
+CXString clang_TParamCommandComment_getParamName(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->hasParamName())
+ return createCXString((const char *) 0);
+
+ return createCXString(TPCC->getParamName(), /*DupString=*/ false);
+}
+
+unsigned clang_TParamCommandComment_isParamPositionValid(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC)
+ return false;
+
+ return TPCC->isPositionValid();
+}
+
+unsigned clang_TParamCommandComment_getDepth(CXComment CXC) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid())
+ return 0;
+
+ return TPCC->getDepth();
+}
+
+unsigned clang_TParamCommandComment_getIndex(CXComment CXC, unsigned Depth) {
+ const TParamCommandComment *TPCC = getASTNodeAs<TParamCommandComment>(CXC);
+ if (!TPCC || !TPCC->isPositionValid() || Depth >= TPCC->getDepth())
+ return 0;
+
+ return TPCC->getIndex(Depth);
+}
+
+CXString clang_VerbatimBlockLineComment_getText(CXComment CXC) {
+ const VerbatimBlockLineComment *VBL =
+ getASTNodeAs<VerbatimBlockLineComment>(CXC);
+ if (!VBL)
+ return createCXString((const char *) 0);
+
+ return createCXString(VBL->getText(), /*DupString=*/ false);
+}
+
+CXString clang_VerbatimLineComment_getText(CXComment CXC) {
+ const VerbatimLineComment *VLC = getASTNodeAs<VerbatimLineComment>(CXC);
+ if (!VLC)
+ return createCXString((const char *) 0);
+
+ return createCXString(VLC->getText(), /*DupString=*/ false);
+}
+
+} // end extern "C"
+
+//===----------------------------------------------------------------------===//
+// Helpers for converting comment AST to HTML.
+//===----------------------------------------------------------------------===//
+
+namespace {
+
+/// This comparison will sort parameters with valid index by index and
+/// invalid (unresolved) parameters last.
+class ParamCommandCommentCompareIndex {
+public:
+ bool operator()(const ParamCommandComment *LHS,
+ const ParamCommandComment *RHS) const {
+ unsigned LHSIndex = UINT_MAX;
+ unsigned RHSIndex = UINT_MAX;
+ if (LHS->isParamIndexValid())
+ LHSIndex = LHS->getParamIndex();
+ if (RHS->isParamIndexValid())
+ RHSIndex = RHS->getParamIndex();
+
+ return LHSIndex < RHSIndex;
+ }
+};
+
+/// This comparison will sort template parameters in the following order:
+/// \li real template parameters (depth = 1) in index order;
+/// \li all other names (depth > 1);
+/// \li unresolved names.
+class TParamCommandCommentComparePosition {
+public:
+ bool operator()(const TParamCommandComment *LHS,
+ const TParamCommandComment *RHS) const {
+ // Sort unresolved names last.
+ if (!LHS->isPositionValid())
+ return false;
+ if (!RHS->isPositionValid())
+ return true;
+
+ if (LHS->getDepth() > 1)
+ return false;
+ if (RHS->getDepth() > 1)
+ return true;
+
+ // Sort template parameters in index order.
+ if (LHS->getDepth() == 1 && RHS->getDepth() == 1)
+ return LHS->getIndex(0) < RHS->getIndex(0);
+
+ // Leave all other names in source order.
+ return true;
+ }
+};
+
+/// Separate parts of a FullComment.
+struct FullCommentParts {
+ /// Take a full comment apart and initialize members accordingly.
+ FullCommentParts(const FullComment *C);
+
+ const BlockContentComment *Brief;
+ const ParagraphComment *FirstParagraph;
+ const BlockCommandComment *Returns;
+ SmallVector<const ParamCommandComment *, 8> Params;
+ SmallVector<const TParamCommandComment *, 4> TParams;
+ SmallVector<const BlockContentComment *, 8> MiscBlocks;
+};
+
+FullCommentParts::FullCommentParts(const FullComment *C) :
+ Brief(NULL), FirstParagraph(NULL), Returns(NULL) {
+ const CommandTraits Traits;
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ const Comment *Child = *I;
+ if (!Child)
+ continue;
+ switch (Child->getCommentKind()) {
+ case Comment::NoCommentKind:
+ continue;
+
+ case Comment::ParagraphCommentKind: {
+ const ParagraphComment *PC = cast<ParagraphComment>(Child);
+ if (PC->isWhitespace())
+ break;
+ if (!FirstParagraph)
+ FirstParagraph = PC;
+
+ MiscBlocks.push_back(PC);
+ break;
+ }
+
+ case Comment::BlockCommandCommentKind: {
+ const BlockCommandComment *BCC = cast<BlockCommandComment>(Child);
+ StringRef CommandName = BCC->getCommandName();
+ if (!Brief && Traits.isBriefCommand(CommandName)) {
+ Brief = BCC;
+ break;
+ }
+ if (!Returns && Traits.isReturnsCommand(CommandName)) {
+ Returns = BCC;
+ break;
+ }
+ MiscBlocks.push_back(BCC);
+ break;
+ }
+
+ case Comment::ParamCommandCommentKind: {
+ const ParamCommandComment *PCC = cast<ParamCommandComment>(Child);
+ if (!PCC->hasParamName())
+ break;
+
+ if (!PCC->isDirectionExplicit() && !PCC->hasNonWhitespaceParagraph())
+ break;
+
+ Params.push_back(PCC);
+ break;
+ }
+
+ case Comment::TParamCommandCommentKind: {
+ const TParamCommandComment *TPCC = cast<TParamCommandComment>(Child);
+ if (!TPCC->hasParamName())
+ break;
+
+ if (!TPCC->hasNonWhitespaceParagraph())
+ break;
+
+ TParams.push_back(TPCC);
+ break;
+ }
+
+ case Comment::VerbatimBlockCommentKind:
+ MiscBlocks.push_back(cast<BlockCommandComment>(Child));
+ break;
+
+ case Comment::VerbatimLineCommentKind: {
+ const VerbatimLineComment *VLC = cast<VerbatimLineComment>(Child);
+ if (!Traits.isDeclarationCommand(VLC->getCommandName()))
+ MiscBlocks.push_back(VLC);
+ break;
+ }
+
+ case Comment::TextCommentKind:
+ case Comment::InlineCommandCommentKind:
+ case Comment::HTMLStartTagCommentKind:
+ case Comment::HTMLEndTagCommentKind:
+ case Comment::VerbatimBlockLineCommentKind:
+ case Comment::FullCommentKind:
+ llvm_unreachable("AST node of this kind can't be a child of "
+ "a FullComment");
+ }
+ }
+
+ // Sort params in order they are declared in the function prototype.
+ // Unresolved parameters are put at the end of the list in the same order
+ // they were seen in the comment.
+ std::stable_sort(Params.begin(), Params.end(),
+ ParamCommandCommentCompareIndex());
+
+ std::stable_sort(TParams.begin(), TParams.end(),
+ TParamCommandCommentComparePosition());
+}
+
+void PrintHTMLStartTagComment(const HTMLStartTagComment *C,
+ llvm::raw_svector_ostream &Result) {
+ Result << "<" << C->getTagName();
+
+ if (C->getNumAttrs() != 0) {
+ for (unsigned i = 0, e = C->getNumAttrs(); i != e; i++) {
+ Result << " ";
+ const HTMLStartTagComment::Attribute &Attr = C->getAttr(i);
+ Result << Attr.Name;
+ if (!Attr.Value.empty())
+ Result << "=\"" << Attr.Value << "\"";
+ }
+ }
+
+ if (!C->isSelfClosing())
+ Result << ">";
+ else
+ Result << "/>";
+}
+
+class CommentASTToHTMLConverter :
+ public ConstCommentVisitor<CommentASTToHTMLConverter> {
+public:
+ /// \param Str accumulator for HTML.
+ CommentASTToHTMLConverter(SmallVectorImpl<char> &Str) : Result(Str) { }
+
+ // Inline content.
+ void visitTextComment(const TextComment *C);
+ void visitInlineCommandComment(const InlineCommandComment *C);
+ void visitHTMLStartTagComment(const HTMLStartTagComment *C);
+ void visitHTMLEndTagComment(const HTMLEndTagComment *C);
+
+ // Block content.
+ void visitParagraphComment(const ParagraphComment *C);
+ void visitBlockCommandComment(const BlockCommandComment *C);
+ void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
+ void visitVerbatimBlockComment(const VerbatimBlockComment *C);
+ void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
+ void visitVerbatimLineComment(const VerbatimLineComment *C);
+
+ void visitFullComment(const FullComment *C);
+
+ // Helpers.
+
+ /// Convert a paragraph that is not a block by itself (an argument to some
+ /// command).
+ void visitNonStandaloneParagraphComment(const ParagraphComment *C);
+
+ void appendToResultWithHTMLEscaping(StringRef S);
+
+private:
+ const CommandTraits Traits;
+
+ /// Output stream for HTML.
+ llvm::raw_svector_ostream Result;
+};
+} // end unnamed namespace
+
+void CommentASTToHTMLConverter::visitTextComment(const TextComment *C) {
+ appendToResultWithHTMLEscaping(C->getText());
+}
+
+void CommentASTToHTMLConverter::visitInlineCommandComment(
+ const InlineCommandComment *C) {
+ // Nothing to render if no arguments supplied.
+ if (C->getNumArgs() == 0)
+ return;
+
+ // Nothing to render if argument is empty.
+ StringRef Arg0 = C->getArgText(0);
+ if (Arg0.empty())
+ return;
+
+ switch (C->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
+ appendToResultWithHTMLEscaping(C->getArgText(i));
+ Result << " ";
+ }
+ return;
+
+ case InlineCommandComment::RenderBold:
+ assert(C->getNumArgs() == 1);
+ Result << "<b>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result << "</b>";
+ return;
+ case InlineCommandComment::RenderMonospaced:
+ assert(C->getNumArgs() == 1);
+ Result << "<tt>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result<< "</tt>";
+ return;
+ case InlineCommandComment::RenderEmphasized:
+ assert(C->getNumArgs() == 1);
+ Result << "<em>";
+ appendToResultWithHTMLEscaping(Arg0);
+ Result << "</em>";
+ return;
+ }
+}
+
+void CommentASTToHTMLConverter::visitHTMLStartTagComment(
+ const HTMLStartTagComment *C) {
+ PrintHTMLStartTagComment(C, Result);
+}
+
+void CommentASTToHTMLConverter::visitHTMLEndTagComment(
+ const HTMLEndTagComment *C) {
+ Result << "</" << C->getTagName() << ">";
+}
+
+void CommentASTToHTMLConverter::visitParagraphComment(
+ const ParagraphComment *C) {
+ if (C->isWhitespace())
+ return;
+
+ Result << "<p>";
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+ Result << "</p>";
+}
+
+void CommentASTToHTMLConverter::visitBlockCommandComment(
+ const BlockCommandComment *C) {
+ StringRef CommandName = C->getCommandName();
+ if (Traits.isBriefCommand(CommandName)) {
+ Result << "<p class=\"para-brief\">";
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</p>";
+ return;
+ }
+ if (Traits.isReturnsCommand(CommandName)) {
+ Result << "<p class=\"para-returns\">"
+ "<span class=\"word-returns\">Returns</span> ";
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</p>";
+ return;
+ }
+ // We don't know anything about this command. Just render the paragraph.
+ visit(C->getParagraph());
+}
+
+void CommentASTToHTMLConverter::visitParamCommandComment(
+ const ParamCommandComment *C) {
+ if (C->isParamIndexValid()) {
+ Result << "<dt class=\"param-name-index-"
+ << C->getParamIndex()
+ << "\">";
+ } else
+ Result << "<dt class=\"param-name-index-invalid\">";
+
+ appendToResultWithHTMLEscaping(C->getParamName());
+ Result << "</dt>";
+
+ if (C->isParamIndexValid()) {
+ Result << "<dd class=\"param-descr-index-"
+ << C->getParamIndex()
+ << "\">";
+ } else
+ Result << "<dd class=\"param-descr-index-invalid\">";
+
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</dd>";
+}
+
+void CommentASTToHTMLConverter::visitTParamCommandComment(
+ const TParamCommandComment *C) {
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dt class=\"tparam-name-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dt class=\"tparam-name-index-other\">";
+ } else
+ Result << "<dt class=\"tparam-name-index-invalid\">";
+
+ appendToResultWithHTMLEscaping(C->getParamName());
+ Result << "</dt>";
+
+ if (C->isPositionValid()) {
+ if (C->getDepth() == 1)
+ Result << "<dd class=\"tparam-descr-index-"
+ << C->getIndex(0)
+ << "\">";
+ else
+ Result << "<dd class=\"tparam-descr-index-other\">";
+ } else
+ Result << "<dd class=\"tparam-descr-index-invalid\">";
+
+ visitNonStandaloneParagraphComment(C->getParagraph());
+ Result << "</dd>";
+}
+
+void CommentASTToHTMLConverter::visitVerbatimBlockComment(
+ const VerbatimBlockComment *C) {
+ unsigned NumLines = C->getNumLines();
+ if (NumLines == 0)
+ return;
+
+ Result << "<pre>";
+ for (unsigned i = 0; i != NumLines; ++i) {
+ appendToResultWithHTMLEscaping(C->getText(i));
+ if (i + 1 != NumLines)
+ Result << '\n';
+ }
+ Result << "</pre>";
+}
+
+void CommentASTToHTMLConverter::visitVerbatimBlockLineComment(
+ const VerbatimBlockLineComment *C) {
+ llvm_unreachable("should not see this AST node");
+}
+
+void CommentASTToHTMLConverter::visitVerbatimLineComment(
+ const VerbatimLineComment *C) {
+ Result << "<pre>";
+ appendToResultWithHTMLEscaping(C->getText());
+ Result << "</pre>";
+}
+
+void CommentASTToHTMLConverter::visitFullComment(const FullComment *C) {
+ FullCommentParts Parts(C);
+
+ bool FirstParagraphIsBrief = false;
+ if (Parts.Brief)
+ visit(Parts.Brief);
+ else if (Parts.FirstParagraph) {
+ Result << "<p class=\"para-brief\">";
+ visitNonStandaloneParagraphComment(Parts.FirstParagraph);
+ Result << "</p>";
+ FirstParagraphIsBrief = true;
+ }
+
+ for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
+ const Comment *C = Parts.MiscBlocks[i];
+ if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
+ continue;
+ visit(C);
+ }
+
+ if (Parts.TParams.size() != 0) {
+ Result << "<dl>";
+ for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
+ visit(Parts.TParams[i]);
+ Result << "</dl>";
+ }
+
+ if (Parts.Params.size() != 0) {
+ Result << "<dl>";
+ for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
+ visit(Parts.Params[i]);
+ Result << "</dl>";
+ }
+
+ if (Parts.Returns)
+ visit(Parts.Returns);
+
+ Result.flush();
+}
+
+void CommentASTToHTMLConverter::visitNonStandaloneParagraphComment(
+ const ParagraphComment *C) {
+ if (!C)
+ return;
+
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+}
+
+void CommentASTToHTMLConverter::appendToResultWithHTMLEscaping(StringRef S) {
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ const char C = *I;
+ switch (C) {
+ case '&':
+ Result << "&amp;";
+ break;
+ case '<':
+ Result << "&lt;";
+ break;
+ case '>':
+ Result << "&gt;";
+ break;
+ case '"':
+ Result << "&quot;";
+ break;
+ case '\'':
+ Result << "&#39;";
+ break;
+ case '/':
+ Result << "&#47;";
+ break;
+ default:
+ Result << C;
+ break;
+ }
+ }
+}
+
+extern "C" {
+
+CXString clang_HTMLTagComment_getAsString(CXComment CXC) {
+ const HTMLTagComment *HTC = getASTNodeAs<HTMLTagComment>(CXC);
+ if (!HTC)
+ return createCXString((const char *) 0);
+
+ SmallString<128> HTML;
+ CommentASTToHTMLConverter Converter(HTML);
+ Converter.visit(HTC);
+ return createCXString(HTML.str(), /* DupString = */ true);
+}
+
+CXString clang_FullComment_getAsHTML(CXComment CXC) {
+ const FullComment *FC = getASTNodeAs<FullComment>(CXC);
+ if (!FC)
+ return createCXString((const char *) 0);
+
+ SmallString<1024> HTML;
+ CommentASTToHTMLConverter Converter(HTML);
+ Converter.visit(FC);
+ return createCXString(HTML.str(), /* DupString = */ true);
+}
+
+} // end extern "C"
+
+namespace {
+class CommentASTToXMLConverter :
+ public ConstCommentVisitor<CommentASTToXMLConverter> {
+public:
+ /// \param Str accumulator for XML.
+ CommentASTToXMLConverter(const SourceManager &SM,
+ SmallVectorImpl<char> &Str) :
+ SM(SM), Result(Str) { }
+
+ // Inline content.
+ void visitTextComment(const TextComment *C);
+ void visitInlineCommandComment(const InlineCommandComment *C);
+ void visitHTMLStartTagComment(const HTMLStartTagComment *C);
+ void visitHTMLEndTagComment(const HTMLEndTagComment *C);
+
+ // Block content.
+ void visitParagraphComment(const ParagraphComment *C);
+ void visitBlockCommandComment(const BlockCommandComment *C);
+ void visitParamCommandComment(const ParamCommandComment *C);
+ void visitTParamCommandComment(const TParamCommandComment *C);
+ void visitVerbatimBlockComment(const VerbatimBlockComment *C);
+ void visitVerbatimBlockLineComment(const VerbatimBlockLineComment *C);
+ void visitVerbatimLineComment(const VerbatimLineComment *C);
+
+ void visitFullComment(const FullComment *C);
+
+ // Helpers.
+ void appendToResultWithXMLEscaping(StringRef S);
+
+private:
+ const SourceManager &SM;
+
+ /// Output stream for XML.
+ llvm::raw_svector_ostream Result;
+};
+} // end unnamed namespace
+
+void CommentASTToXMLConverter::visitTextComment(const TextComment *C) {
+ appendToResultWithXMLEscaping(C->getText());
+}
+
+void CommentASTToXMLConverter::visitInlineCommandComment(const InlineCommandComment *C) {
+ // Nothing to render if no arguments supplied.
+ if (C->getNumArgs() == 0)
+ return;
+
+ // Nothing to render if argument is empty.
+ StringRef Arg0 = C->getArgText(0);
+ if (Arg0.empty())
+ return;
+
+ switch (C->getRenderKind()) {
+ case InlineCommandComment::RenderNormal:
+ for (unsigned i = 0, e = C->getNumArgs(); i != e; ++i) {
+ appendToResultWithXMLEscaping(C->getArgText(i));
+ Result << " ";
+ }
+ return;
+ case InlineCommandComment::RenderBold:
+ assert(C->getNumArgs() == 1);
+ Result << "<bold>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</bold>";
+ return;
+ case InlineCommandComment::RenderMonospaced:
+ assert(C->getNumArgs() == 1);
+ Result << "<monospaced>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</monospaced>";
+ return;
+ case InlineCommandComment::RenderEmphasized:
+ assert(C->getNumArgs() == 1);
+ Result << "<emphasized>";
+ appendToResultWithXMLEscaping(Arg0);
+ Result << "</emphasized>";
+ return;
+ }
+}
+
+void CommentASTToXMLConverter::visitHTMLStartTagComment(const HTMLStartTagComment *C) {
+ Result << "<rawHTML><![CDATA[";
+ PrintHTMLStartTagComment(C, Result);
+ Result << "]]></rawHTML>";
+}
+
+void CommentASTToXMLConverter::visitHTMLEndTagComment(const HTMLEndTagComment *C) {
+ Result << "<rawHTML>&lt;/" << C->getTagName() << "&gt;</rawHTML>";
+}
+
+void CommentASTToXMLConverter::visitParagraphComment(const ParagraphComment *C) {
+ if (C->isWhitespace())
+ return;
+
+ Result << "<Para>";
+ for (Comment::child_iterator I = C->child_begin(), E = C->child_end();
+ I != E; ++I) {
+ visit(*I);
+ }
+ Result << "</Para>";
+}
+
+void CommentASTToXMLConverter::visitBlockCommandComment(const BlockCommandComment *C) {
+ visit(C->getParagraph());
+}
+
+void CommentASTToXMLConverter::visitParamCommandComment(const ParamCommandComment *C) {
+ Result << "<Parameter><Name>";
+ appendToResultWithXMLEscaping(C->getParamName());
+ Result << "</Name>";
+
+ if (C->isParamIndexValid())
+ Result << "<Index>" << C->getParamIndex() << "</Index>";
+
+ Result << "<Direction isExplicit=\"" << C->isDirectionExplicit() << "\">";
+ switch (C->getDirection()) {
+ case ParamCommandComment::In:
+ Result << "in";
+ break;
+ case ParamCommandComment::Out:
+ Result << "out";
+ break;
+ case ParamCommandComment::InOut:
+ Result << "in,out";
+ break;
+ }
+ Result << "</Direction><Discussion>";
+ visit(C->getParagraph());
+ Result << "</Discussion></Parameter>";
+}
+
+void CommentASTToXMLConverter::visitTParamCommandComment(
+ const TParamCommandComment *C) {
+ Result << "<Parameter><Name>";
+ appendToResultWithXMLEscaping(C->getParamName());
+ Result << "</Name>";
+
+ if (C->isPositionValid() && C->getDepth() == 1) {
+ Result << "<Index>" << C->getIndex(0) << "</Index>";
+ }
+
+ Result << "<Discussion>";
+ visit(C->getParagraph());
+ Result << "</Discussion></Parameter>";
+}
+
+void CommentASTToXMLConverter::visitVerbatimBlockComment(
+ const VerbatimBlockComment *C) {
+ unsigned NumLines = C->getNumLines();
+ if (NumLines == 0)
+ return;
+
+ Result << llvm::StringSwitch<const char *>(C->getCommandName())
+ .Case("code", "<Verbatim xml:space=\"preserve\" kind=\"code\">")
+ .Default("<Verbatim xml:space=\"preserve\" kind=\"verbatim\">");
+ for (unsigned i = 0; i != NumLines; ++i) {
+ appendToResultWithXMLEscaping(C->getText(i));
+ if (i + 1 != NumLines)
+ Result << '\n';
+ }
+ Result << "</Verbatim>";
+}
+
+void CommentASTToXMLConverter::visitVerbatimBlockLineComment(
+ const VerbatimBlockLineComment *C) {
+ llvm_unreachable("should not see this AST node");
+}
+
+void CommentASTToXMLConverter::visitVerbatimLineComment(
+ const VerbatimLineComment *C) {
+ Result << "<Verbatim xml:space=\"preserve\" kind=\"verbatim\">";
+ appendToResultWithXMLEscaping(C->getText());
+ Result << "</Verbatim>";
+}
+
+void CommentASTToXMLConverter::visitFullComment(const FullComment *C) {
+ FullCommentParts Parts(C);
+
+ const DeclInfo *DI = C->getDeclInfo();
+ StringRef RootEndTag;
+ if (DI) {
+ switch (DI->getKind()) {
+ case DeclInfo::OtherKind:
+ RootEndTag = "</Other>";
+ Result << "<Other";
+ break;
+ case DeclInfo::FunctionKind:
+ RootEndTag = "</Function>";
+ Result << "<Function";
+ switch (DI->TemplateKind) {
+ case DeclInfo::NotTemplate:
+ break;
+ case DeclInfo::Template:
+ Result << " templateKind=\"template\"";
+ break;
+ case DeclInfo::TemplateSpecialization:
+ Result << " templateKind=\"specialization\"";
+ break;
+ case DeclInfo::TemplatePartialSpecialization:
+ llvm_unreachable("partial specializations of functions "
+ "are not allowed in C++");
+ }
+ if (DI->IsInstanceMethod)
+ Result << " isInstanceMethod=\"1\"";
+ if (DI->IsClassMethod)
+ Result << " isClassMethod=\"1\"";
+ break;
+ case DeclInfo::ClassKind:
+ RootEndTag = "</Class>";
+ Result << "<Class";
+ switch (DI->TemplateKind) {
+ case DeclInfo::NotTemplate:
+ break;
+ case DeclInfo::Template:
+ Result << " templateKind=\"template\"";
+ break;
+ case DeclInfo::TemplateSpecialization:
+ Result << " templateKind=\"specialization\"";
+ break;
+ case DeclInfo::TemplatePartialSpecialization:
+ Result << " templateKind=\"partialSpecialization\"";
+ break;
+ }
+ break;
+ case DeclInfo::VariableKind:
+ RootEndTag = "</Variable>";
+ Result << "<Variable";
+ break;
+ case DeclInfo::NamespaceKind:
+ RootEndTag = "</Namespace>";
+ Result << "<Namespace";
+ break;
+ case DeclInfo::TypedefKind:
+ RootEndTag = "</Typedef>";
+ Result << "<Typedef";
+ break;
+ case DeclInfo::EnumKind:
+ RootEndTag = "</Enum>";
+ Result << "<Enum";
+ break;
+ }
+
+ {
+ // Print line and column number.
+ SourceLocation Loc = DI->ThisDecl->getLocation();
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+ FileID FID = LocInfo.first;
+ unsigned FileOffset = LocInfo.second;
+
+ if (!FID.isInvalid()) {
+ if (const FileEntry *FE = SM.getFileEntryForID(FID)) {
+ Result << " file=\"";
+ appendToResultWithXMLEscaping(FE->getName());
+ Result << "\"";
+ }
+ Result << " line=\"" << SM.getLineNumber(FID, FileOffset)
+ << "\" column=\"" << SM.getColumnNumber(FID, FileOffset)
+ << "\"";
+ }
+ }
+
+ // Finish the root tag.
+ Result << ">";
+
+ bool FoundName = false;
+ if (const NamedDecl *ND = dyn_cast<NamedDecl>(DI->ThisDecl)) {
+ if (DeclarationName DeclName = ND->getDeclName()) {
+ Result << "<Name>";
+ std::string Name = DeclName.getAsString();
+ appendToResultWithXMLEscaping(Name);
+ FoundName = true;
+ Result << "</Name>";
+ }
+ }
+ if (!FoundName)
+ Result << "<Name>&lt;anonymous&gt;</Name>";
+
+ {
+ // Print USR.
+ SmallString<128> USR;
+ cxcursor::getDeclCursorUSR(DI->ThisDecl, USR);
+ if (!USR.empty()) {
+ Result << "<USR>";
+ appendToResultWithXMLEscaping(USR);
+ Result << "</USR>";
+ }
+ }
+ } else {
+ // No DeclInfo -- just emit some root tag and name tag.
+ RootEndTag = "</Other>";
+ Result << "<Other><Name>unknown</Name>";
+ }
+
+ bool FirstParagraphIsBrief = false;
+ if (Parts.Brief) {
+ Result << "<Abstract>";
+ visit(Parts.Brief);
+ Result << "</Abstract>";
+ } else if (Parts.FirstParagraph) {
+ Result << "<Abstract>";
+ visit(Parts.FirstParagraph);
+ Result << "</Abstract>";
+ FirstParagraphIsBrief = true;
+ }
+
+ if (Parts.TParams.size() != 0) {
+ Result << "<TemplateParameters>";
+ for (unsigned i = 0, e = Parts.TParams.size(); i != e; ++i)
+ visit(Parts.TParams[i]);
+ Result << "</TemplateParameters>";
+ }
+
+ if (Parts.Params.size() != 0) {
+ Result << "<Parameters>";
+ for (unsigned i = 0, e = Parts.Params.size(); i != e; ++i)
+ visit(Parts.Params[i]);
+ Result << "</Parameters>";
+ }
+
+ if (Parts.Returns) {
+ Result << "<ResultDiscussion>";
+ visit(Parts.Returns);
+ Result << "</ResultDiscussion>";
+ }
+
+ {
+ bool StartTagEmitted = false;
+ for (unsigned i = 0, e = Parts.MiscBlocks.size(); i != e; ++i) {
+ const Comment *C = Parts.MiscBlocks[i];
+ if (FirstParagraphIsBrief && C == Parts.FirstParagraph)
+ continue;
+ if (!StartTagEmitted) {
+ Result << "<Discussion>";
+ StartTagEmitted = true;
+ }
+ visit(C);
+ }
+ if (StartTagEmitted)
+ Result << "</Discussion>";
+ }
+
+ Result << RootEndTag;
+
+ Result.flush();
+}
+
+void CommentASTToXMLConverter::appendToResultWithXMLEscaping(StringRef S) {
+ for (StringRef::iterator I = S.begin(), E = S.end(); I != E; ++I) {
+ const char C = *I;
+ switch (C) {
+ case '&':
+ Result << "&amp;";
+ break;
+ case '<':
+ Result << "&lt;";
+ break;
+ case '>':
+ Result << "&gt;";
+ break;
+ case '"':
+ Result << "&quot;";
+ break;
+ case '\'':
+ Result << "&apos;";
+ break;
+ default:
+ Result << C;
+ break;
+ }
+ }
+}
+
+extern "C" {
+
+CXString clang_FullComment_getAsXML(CXTranslationUnit TU, CXComment CXC) {
+ const FullComment *FC = getASTNodeAs<FullComment>(CXC);
+ if (!FC)
+ return createCXString((const char *) 0);
+
+ SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager();
+
+ SmallString<1024> XML;
+ CommentASTToXMLConverter Converter(SM, XML);
+ Converter.visit(FC);
+ return createCXString(XML.str(), /* DupString = */ true);
+}
+
+} // end extern "C"
+
diff --git a/tools/libclang/CXComment.h b/tools/libclang/CXComment.h
new file mode 100644
index 0000000..753877e
--- /dev/null
+++ b/tools/libclang/CXComment.h
@@ -0,0 +1,47 @@
+//===- CXComment.h - Routines for manipulating CXComments -----------------===//
+//
+// 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 CXComments.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_CXCOMMENT_H
+#define LLVM_CLANG_CXCOMMENT_H
+
+#include "clang-c/Index.h"
+
+#include "clang/AST/Comment.h"
+
+namespace clang {
+namespace cxcomment {
+
+inline CXComment createCXComment(const comments::Comment *C) {
+ CXComment Result;
+ Result.Data = C;
+ return Result;
+}
+
+inline const comments::Comment *getASTNode(CXComment CXC) {
+ return static_cast<const comments::Comment *>(CXC.Data);
+}
+
+template<typename T>
+inline const T *getASTNodeAs(CXComment CXC) {
+ const comments::Comment *C = getASTNode(CXC);
+ if (!C)
+ return NULL;
+
+ return dyn_cast<T>(C);
+}
+
+} // end namespace cxcomment
+} // end namespace clang
+
+#endif
+
diff --git a/tools/libclang/CXCompilationDatabase.cpp b/tools/libclang/CXCompilationDatabase.cpp
new file mode 100644
index 0000000..7bd319a
--- /dev/null
+++ b/tools/libclang/CXCompilationDatabase.cpp
@@ -0,0 +1,129 @@
+#include "clang-c/CXCompilationDatabase.h"
+#include "clang/Tooling/CompilationDatabase.h"
+#include "CXString.h"
+
+using namespace clang;
+using namespace clang::tooling;
+using namespace clang::cxstring;
+
+extern "C" {
+
+// FIXME: do something more usefull with the error message
+CXCompilationDatabase
+clang_CompilationDatabase_fromDirectory(const char *BuildDir,
+ CXCompilationDatabase_Error *ErrorCode)
+{
+ std::string ErrorMsg;
+ CXCompilationDatabase_Error Err = CXCompilationDatabase_NoError;
+
+ CompilationDatabase *db = CompilationDatabase::loadFromDirectory(BuildDir,
+ ErrorMsg);
+
+ if (!db) {
+ fprintf(stderr, "LIBCLANG TOOLING ERROR: %s\n", ErrorMsg.c_str());
+ Err = CXCompilationDatabase_CanNotLoadDatabase;
+ }
+
+ if (ErrorCode)
+ *ErrorCode = Err;
+
+ return db;
+}
+
+void
+clang_CompilationDatabase_dispose(CXCompilationDatabase CDb)
+{
+ delete static_cast<CompilationDatabase *>(CDb);
+}
+
+struct AllocatedCXCompileCommands
+{
+ std::vector<CompileCommand> CCmd;
+
+ AllocatedCXCompileCommands(const std::vector<CompileCommand>& Cmd)
+ : CCmd(Cmd)
+ { }
+};
+
+CXCompileCommands
+clang_CompilationDatabase_getCompileCommands(CXCompilationDatabase CDb,
+ const char *CompleteFileName)
+{
+ if (CompilationDatabase *db = static_cast<CompilationDatabase *>(CDb)) {
+ const std::vector<CompileCommand>
+ CCmd(db->getCompileCommands(CompleteFileName));
+ if (!CCmd.empty())
+ return new AllocatedCXCompileCommands( CCmd );
+ }
+
+ return 0;
+}
+
+void
+clang_CompileCommands_dispose(CXCompileCommands Cmds)
+{
+ delete static_cast<AllocatedCXCompileCommands *>(Cmds);
+}
+
+unsigned
+clang_CompileCommands_getSize(CXCompileCommands Cmds)
+{
+ if (!Cmds)
+ return 0;
+
+ AllocatedCXCompileCommands *ACC =
+ static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+ return ACC->CCmd.size();
+}
+
+CXCompileCommand
+clang_CompileCommands_getCommand(CXCompileCommands Cmds, unsigned I)
+{
+ if (!Cmds)
+ return 0;
+
+ AllocatedCXCompileCommands *ACC =
+ static_cast<AllocatedCXCompileCommands *>(Cmds);
+
+ if (I >= ACC->CCmd.size())
+ return 0;
+
+ return &ACC->CCmd[I];
+}
+
+CXString
+clang_CompileCommand_getDirectory(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return createCXString((const char*)NULL);
+
+ CompileCommand *cmd = static_cast<CompileCommand *>(CCmd);
+ return createCXString(cmd->Directory);
+}
+
+unsigned
+clang_CompileCommand_getNumArgs(CXCompileCommand CCmd)
+{
+ if (!CCmd)
+ return 0;
+
+ return static_cast<CompileCommand *>(CCmd)->CommandLine.size();
+}
+
+CXString
+clang_CompileCommand_getArg(CXCompileCommand CCmd, unsigned Arg)
+{
+ if (!CCmd)
+ return createCXString((const char*)NULL);
+
+ CompileCommand *Cmd = static_cast<CompileCommand *>(CCmd);
+
+ if (Arg >= Cmd->CommandLine.size())
+ return createCXString((const char*)NULL);
+
+ return createCXString(Cmd->CommandLine[Arg]);
+}
+
+
+} // end: extern "C"
diff --git a/tools/libclang/CXCursor.cpp b/tools/libclang/CXCursor.cpp
index a298759..2757af4 100644
--- a/tools/libclang/CXCursor.cpp
+++ b/tools/libclang/CXCursor.cpp
@@ -30,9 +30,9 @@
using namespace clang;
using namespace cxcursor;
-CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K) {
+CXCursor cxcursor::MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU) {
assert(K >= CXCursor_FirstInvalid && K <= CXCursor_LastInvalid);
- CXCursor C = { K, 0, { 0, 0, 0 } };
+ CXCursor C = { K, 0, { 0, 0, TU } };
return C;
}
@@ -148,6 +148,10 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
case Stmt::AsmStmtClass:
K = CXCursor_AsmStmt;
break;
+
+ case Stmt::MSAsmStmtClass:
+ K = CXCursor_MSAsmStmt;
+ break;
case Stmt::ObjCAtTryStmtClass:
K = CXCursor_ObjCAtTryStmt;
@@ -229,7 +233,7 @@ CXCursor cxcursor::MakeCXCursor(Stmt *S, Decl *Parent, CXTranslationUnit TU,
case Stmt::VAArgExprClass:
case Stmt::ObjCArrayLiteralClass:
case Stmt::ObjCDictionaryLiteralClass:
- case Stmt::ObjCNumericLiteralClass:
+ case Stmt::ObjCBoxedExprClass:
case Stmt::ObjCSubscriptRefExprClass:
K = CXCursor_UnexposedExpr;
break;
@@ -864,27 +868,10 @@ static inline void CollectOverriddenMethods(CXTranslationUnit TU,
/*MovedToSuper=*/false);
}
-void cxcursor::getOverriddenCursors(CXCursor cursor,
- SmallVectorImpl<CXCursor> &overridden) {
- assert(clang_isDeclaration(cursor.kind));
- Decl *D = getCursorDecl(cursor);
- if (!D)
- return;
-
- // Handle C++ member functions.
- CXTranslationUnit TU = getCursorTU(cursor);
- if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
- for (CXXMethodDecl::method_iterator
- M = CXXMethod->begin_overridden_methods(),
- MEnd = CXXMethod->end_overridden_methods();
- M != MEnd; ++M)
- overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU));
- return;
- }
-
- ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
- if (!Method)
- return;
+static void collectOverriddenMethodsSlow(CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &overridden) {
+ assert(Method->isOverriding());
if (ObjCProtocolDecl *
ProtD = dyn_cast<ObjCProtocolDecl>(Method->getDeclContext())) {
@@ -921,6 +908,83 @@ void cxcursor::getOverriddenCursors(CXCursor cursor,
}
}
+static void collectOnCategoriesAfterLocation(SourceLocation Loc,
+ ObjCInterfaceDecl *Class,
+ CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &Methods) {
+ if (!Class)
+ return;
+
+ SourceManager &SM = static_cast<ASTUnit *>(TU->TUData)->getSourceManager();
+ for (ObjCCategoryDecl *Category = Class->getCategoryList();
+ Category; Category = Category->getNextClassCategory())
+ if (SM.isBeforeInTranslationUnit(Loc, Category->getLocation()))
+ CollectOverriddenMethodsRecurse(TU, Category, Method, Methods, true);
+
+ collectOnCategoriesAfterLocation(Loc, Class->getSuperClass(), TU,
+ Method, Methods);
+}
+
+/// \brief Faster collection that is enabled when ObjCMethodDecl::isOverriding()
+/// returns false.
+/// You'd think that in that case there are no overrides but categories can
+/// "introduce" new overridden methods that are missed by Sema because the
+/// overrides lookup that it does for methods, inside implementations, will
+/// stop at the interface level (if there is a method there) and not look
+/// further in super classes.
+static void collectOverriddenMethodsFast(CXTranslationUnit TU,
+ ObjCMethodDecl *Method,
+ SmallVectorImpl<CXCursor> &Methods) {
+ assert(!Method->isOverriding());
+
+ ObjCContainerDecl *ContD = cast<ObjCContainerDecl>(Method->getDeclContext());
+ if (isa<ObjCInterfaceDecl>(ContD) || isa<ObjCProtocolDecl>(ContD))
+ return;
+ ObjCInterfaceDecl *Class = Method->getClassInterface();
+ if (!Class)
+ return;
+
+ collectOnCategoriesAfterLocation(Class->getLocation(), Class->getSuperClass(),
+ TU, Method, Methods);
+}
+
+void cxcursor::getOverriddenCursors(CXCursor cursor,
+ SmallVectorImpl<CXCursor> &overridden) {
+ assert(clang_isDeclaration(cursor.kind));
+ Decl *D = getCursorDecl(cursor);
+ if (!D)
+ return;
+
+ // Handle C++ member functions.
+ CXTranslationUnit TU = getCursorTU(cursor);
+ if (CXXMethodDecl *CXXMethod = dyn_cast<CXXMethodDecl>(D)) {
+ for (CXXMethodDecl::method_iterator
+ M = CXXMethod->begin_overridden_methods(),
+ MEnd = CXXMethod->end_overridden_methods();
+ M != MEnd; ++M)
+ overridden.push_back(MakeCXCursor(const_cast<CXXMethodDecl*>(*M), TU));
+ return;
+ }
+
+ ObjCMethodDecl *Method = dyn_cast<ObjCMethodDecl>(D);
+ if (!Method)
+ return;
+
+ if (Method->isRedeclaration()) {
+ Method = cast<ObjCContainerDecl>(Method->getDeclContext())->
+ getMethod(Method->getSelector(), Method->isInstanceMethod());
+ }
+
+ if (!Method->isOverriding()) {
+ collectOverriddenMethodsFast(TU, Method, overridden);
+ } else {
+ collectOverriddenMethodsSlow(TU, Method, overridden);
+ assert(!overridden.empty() &&
+ "ObjCMethodDecl's overriding bit is not as expected");
+ }
+}
+
std::pair<int, SourceLocation>
cxcursor::getSelectorIdentifierIndexAndLoc(CXCursor cursor) {
if (cursor.kind == CXCursor_ObjCMessageExpr) {
@@ -1134,7 +1198,8 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
= Result.CreateCodeCompletionString(unit->getASTContext(),
unit->getPreprocessor(),
unit->getCodeCompletionTUInfo().getAllocator(),
- unit->getCodeCompletionTUInfo());
+ unit->getCodeCompletionTUInfo(),
+ true);
return String;
}
}
@@ -1147,10 +1212,137 @@ CXCompletionString clang_getCursorCompletionString(CXCursor cursor) {
= Result.CreateCodeCompletionString(unit->getASTContext(),
unit->getPreprocessor(),
unit->getCodeCompletionTUInfo().getAllocator(),
- unit->getCodeCompletionTUInfo());
+ unit->getCodeCompletionTUInfo(),
+ false);
return String;
}
return NULL;
}
+} // end: extern C.
+
+namespace {
+ struct OverridenCursorsPool {
+ typedef llvm::SmallVector<CXCursor, 2> CursorVec;
+ std::vector<CursorVec*> AllCursors;
+ std::vector<CursorVec*> AvailableCursors;
+
+ ~OverridenCursorsPool() {
+ for (std::vector<CursorVec*>::iterator I = AllCursors.begin(),
+ E = AllCursors.end(); I != E; ++I) {
+ delete *I;
+ }
+ }
+ };
+}
+
+void *cxcursor::createOverridenCXCursorsPool() {
+ return new OverridenCursorsPool();
+}
+
+void cxcursor::disposeOverridenCXCursorsPool(void *pool) {
+ delete static_cast<OverridenCursorsPool*>(pool);
+}
+
+extern "C" {
+void clang_getOverriddenCursors(CXCursor cursor,
+ CXCursor **overridden,
+ unsigned *num_overridden) {
+ if (overridden)
+ *overridden = 0;
+ if (num_overridden)
+ *num_overridden = 0;
+
+ CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
+
+ if (!overridden || !num_overridden || !TU)
+ return;
+
+ if (!clang_isDeclaration(cursor.kind))
+ return;
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+
+ OverridenCursorsPool::CursorVec *Vec = 0;
+ if (!pool.AvailableCursors.empty()) {
+ Vec = pool.AvailableCursors.back();
+ pool.AvailableCursors.pop_back();
+ }
+ else {
+ Vec = new OverridenCursorsPool::CursorVec();
+ pool.AllCursors.push_back(Vec);
+ }
+
+ // Clear out the vector, but don't free the memory contents. This
+ // reduces malloc() traffic.
+ Vec->clear();
+
+ // Use the first entry to contain a back reference to the vector.
+ // This is a complete hack.
+ CXCursor backRefCursor = MakeCXCursorInvalid(CXCursor_InvalidFile, TU);
+ backRefCursor.data[0] = Vec;
+ assert(cxcursor::getCursorTU(backRefCursor) == TU);
+ Vec->push_back(backRefCursor);
+
+ // Get the overriden cursors.
+ cxcursor::getOverriddenCursors(cursor, *Vec);
+
+ // Did we get any overriden cursors? If not, return Vec to the pool
+ // of available cursor vectors.
+ if (Vec->size() == 1) {
+ pool.AvailableCursors.push_back(Vec);
+ return;
+ }
+
+ // Now tell the caller about the overriden cursors.
+ assert(Vec->size() > 1);
+ *overridden = &((*Vec)[1]);
+ *num_overridden = Vec->size() - 1;
+}
+
+void clang_disposeOverriddenCursors(CXCursor *overridden) {
+ if (!overridden)
+ return;
+
+ // Use pointer arithmetic to get back the first faux entry
+ // which has a back-reference to the TU and the vector.
+ --overridden;
+ OverridenCursorsPool::CursorVec *Vec =
+ static_cast<OverridenCursorsPool::CursorVec*>(overridden->data[0]);
+ CXTranslationUnit TU = getCursorTU(*overridden);
+
+ assert(Vec && TU);
+
+ OverridenCursorsPool &pool =
+ *static_cast<OverridenCursorsPool*>(TU->OverridenCursorsPool);
+
+ pool.AvailableCursors.push_back(Vec);
+}
+
+int clang_Cursor_isDynamicCall(CXCursor C) {
+ const Expr *E = 0;
+ if (clang_isExpression(C.kind))
+ E = getCursorExpr(C);
+ if (!E)
+ return 0;
+
+ if (const ObjCMessageExpr *MsgE = dyn_cast<ObjCMessageExpr>(E))
+ return MsgE->getReceiverKind() == ObjCMessageExpr::Instance;
+
+ const MemberExpr *ME = 0;
+ if (isa<MemberExpr>(E))
+ ME = cast<MemberExpr>(E);
+ else if (const CallExpr *CE = dyn_cast<CallExpr>(E))
+ ME = dyn_cast_or_null<MemberExpr>(CE->getCallee());
+
+ if (ME) {
+ if (const CXXMethodDecl *
+ MD = dyn_cast_or_null<CXXMethodDecl>(ME->getMemberDecl()))
+ return MD->isVirtual() && !ME->hasQualifier();
+ }
+
+ return 0;
+}
+
} // end: extern "C"
diff --git a/tools/libclang/CXCursor.h b/tools/libclang/CXCursor.h
index 947b0a3..120b881 100644
--- a/tools/libclang/CXCursor.h
+++ b/tools/libclang/CXCursor.h
@@ -55,7 +55,7 @@ CXCursor MakeCXCursor(clang::Decl *D, CXTranslationUnit TU,
CXCursor MakeCXCursor(clang::Stmt *S, clang::Decl *Parent,
CXTranslationUnit TU,
SourceRange RegionOfInterest = SourceRange());
-CXCursor MakeCXCursorInvalid(CXCursorKind K);
+CXCursor MakeCXCursorInvalid(CXCursorKind K, CXTranslationUnit TU = 0);
/// \brief Create an Objective-C superclass reference at the given location.
CXCursor MakeCursorObjCSuperClassRef(ObjCInterfaceDecl *Super,
@@ -206,8 +206,15 @@ ASTUnit *getCursorASTUnit(CXCursor Cursor);
CXTranslationUnit getCursorTU(CXCursor Cursor);
void getOverriddenCursors(CXCursor cursor,
- SmallVectorImpl<CXCursor> &overridden);
+ SmallVectorImpl<CXCursor> &overridden);
+
+/// \brief Create an opaque pool used for fast generation of overriden
+/// CXCursor arrays.
+void *createOverridenCXCursorsPool();
+/// \brief Dispose of the overriden CXCursors pool.
+void disposeOverridenCXCursorsPool(void *pool);
+
/// \brief Returns a index/location pair for a selector identifier if the cursor
/// points to one.
std::pair<int, SourceLocation> getSelectorIdentifierIndexAndLoc(CXCursor);
diff --git a/tools/libclang/CXStoredDiagnostic.cpp b/tools/libclang/CXStoredDiagnostic.cpp
index 8284dc9..fa331de 100644
--- a/tools/libclang/CXStoredDiagnostic.cpp
+++ b/tools/libclang/CXStoredDiagnostic.cpp
@@ -66,13 +66,8 @@ CXString CXStoredDiagnostic::getDiagnosticOption(CXString *Disable) const {
*Disable = createCXString("-ferror-limit=0");
return createCXString("-ferror-limit=");
}
-
- bool EnabledByDefault;
- if (DiagnosticIDs::isBuiltinExtensionDiag(ID, EnabledByDefault) &&
- !EnabledByDefault)
- return createCXString("-pedantic");
- return createCXString("");
+ return createCXString("");
}
unsigned CXStoredDiagnostic::getCategory() const {
diff --git a/tools/libclang/CXTranslationUnit.h b/tools/libclang/CXTranslationUnit.h
index 3ad867c..37789aa 100644
--- a/tools/libclang/CXTranslationUnit.h
+++ b/tools/libclang/CXTranslationUnit.h
@@ -20,6 +20,7 @@ struct CXTranslationUnitImpl {
void *TUData;
void *StringPool;
void *Diagnostics;
+ void *OverridenCursorsPool;
};
}
diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp
index 850fac1..15f818a 100644
--- a/tools/libclang/CXType.cpp
+++ b/tools/libclang/CXType.cpp
@@ -94,7 +94,23 @@ static CXTypeKind GetTypeKind(QualType T) {
CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
- CXTypeKind TK = GetTypeKind(T);
+ CXTypeKind TK = CXType_Invalid;
+
+ if (TU && !T.isNull()) {
+ ASTContext &Ctx = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
+ if (Ctx.getLangOpts().ObjC1) {
+ QualType UnqualT = T.getUnqualifiedType();
+ if (Ctx.isObjCIdType(UnqualT))
+ TK = CXType_ObjCId;
+ else if (Ctx.isObjCClassType(UnqualT))
+ TK = CXType_ObjCClass;
+ else if (Ctx.isObjCSelType(UnqualT))
+ TK = CXType_ObjCSel;
+ }
+ }
+ if (TK == CXType_Invalid)
+ TK = GetTypeKind(T);
+
CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
return CT;
}
diff --git a/tools/libclang/IndexBody.cpp b/tools/libclang/IndexBody.cpp
index 74a8d37..acf8838 100644
--- a/tools/libclang/IndexBody.cpp
+++ b/tools/libclang/IndexBody.cpp
@@ -9,14 +9,14 @@
#include "IndexingContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "RecursiveASTVisitor.h"
using namespace clang;
using namespace cxindex;
namespace {
-class BodyIndexer : public RecursiveASTVisitor<BodyIndexer> {
+class BodyIndexer : public cxindex::RecursiveASTVisitor<BodyIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
@@ -90,13 +90,19 @@ public:
return true;
}
- bool VisitObjCNumericLiteral(ObjCNumericLiteral *E) {
- if (ObjCMethodDecl *MD = E->getObjCNumericLiteralMethod())
+ bool VisitObjCProtocolExpr(ObjCProtocolExpr *E) {
+ IndexCtx.handleReference(E->getProtocol(), E->getProtocolIdLoc(),
+ Parent, ParentDC, E, CXIdxEntityRef_Direct);
+ return true;
+ }
+
+ bool VisitObjCBoxedExpr(ObjCBoxedExpr *E) {
+ if (ObjCMethodDecl *MD = E->getBoxingMethod())
IndexCtx.handleReference(MD, E->getLocStart(),
Parent, ParentDC, E, CXIdxEntityRef_Implicit);
return true;
}
-
+
bool VisitObjCDictionaryLiteral(ObjCDictionaryLiteral *E) {
if (ObjCMethodDecl *MD = E->getDictWithObjectsMethod())
IndexCtx.handleReference(MD, E->getLocStart(),
diff --git a/tools/libclang/IndexDecl.cpp b/tools/libclang/IndexDecl.cpp
index c257c34..7560398 100644
--- a/tools/libclang/IndexDecl.cpp
+++ b/tools/libclang/IndexDecl.cpp
@@ -154,7 +154,20 @@ public:
IndexCtx.handleObjCImplementation(D);
IndexCtx.indexTUDeclsInObjCContainer();
- IndexCtx.indexDeclContext(D);
+
+ // Index the ivars first to make sure the synthesized ivars are indexed
+ // before indexing the methods that can reference them.
+ for (ObjCImplementationDecl::ivar_iterator
+ IvarI = D->ivar_begin(),
+ IvarE = D->ivar_end(); IvarI != IvarE; ++IvarI) {
+ IndexCtx.indexDecl(*IvarI);
+ }
+ for (DeclContext::decl_iterator
+ I = D->decls_begin(), E = D->decls_end(); I != E; ++I) {
+ if (!isa<ObjCIvarDecl>(*I))
+ IndexCtx.indexDecl(*I);
+ }
+
return true;
}
diff --git a/tools/libclang/IndexTypeSourceInfo.cpp b/tools/libclang/IndexTypeSourceInfo.cpp
index b62d521..67a06f2 100644
--- a/tools/libclang/IndexTypeSourceInfo.cpp
+++ b/tools/libclang/IndexTypeSourceInfo.cpp
@@ -9,14 +9,14 @@
#include "IndexingContext.h"
-#include "clang/AST/RecursiveASTVisitor.h"
+#include "RecursiveASTVisitor.h"
using namespace clang;
using namespace cxindex;
namespace {
-class TypeIndexer : public RecursiveASTVisitor<TypeIndexer> {
+class TypeIndexer : public cxindex::RecursiveASTVisitor<TypeIndexer> {
IndexingContext &IndexCtx;
const NamedDecl *Parent;
const DeclContext *ParentDC;
diff --git a/tools/libclang/Indexing.cpp b/tools/libclang/Indexing.cpp
index e660c4d..8fe9c36 100644
--- a/tools/libclang/Indexing.cpp
+++ b/tools/libclang/Indexing.cpp
@@ -353,7 +353,8 @@ static void clang_indexSourceFile_Impl(void *UserData) {
CInvok->getDiagnosticOpts().IgnoreWarnings = true;
ASTUnit *Unit = ASTUnit::create(CInvok.getPtr(), Diags,
- /*CaptureDiagnostics=*/true);
+ /*CaptureDiagnostics=*/true,
+ /*UserFilesAreVolatile=*/true);
OwningPtr<CXTUOwner> CXTU(new CXTUOwner(MakeCXTranslationUnit(CXXIdx, Unit)));
// Recover resources if we crash before exiting this method.
@@ -369,7 +370,6 @@ static void clang_indexSourceFile_Impl(void *UserData) {
IndexActionCleanup(IndexAction.get());
bool Persistent = requestedToGetTU;
- StringRef ResourceFilesPath = CXXIdx->getClangResourcesPath();
bool OnlyLocalDecls = false;
bool PrecompilePreamble = false;
bool CacheCodeCompletionResults = false;
@@ -393,11 +393,13 @@ static void clang_indexSourceFile_Impl(void *UserData) {
IndexAction.get(),
Unit,
Persistent,
- ResourceFilesPath,
+ CXXIdx->getClangResourcesPath(),
OnlyLocalDecls,
/*CaptureDiagnostics=*/true,
PrecompilePreamble,
- CacheCodeCompletionResults);
+ CacheCodeCompletionResults,
+ /*IncludeBriefCommentsInCodeCompletion=*/false,
+ /*UserFilesAreVolatile=*/true);
if (DiagTrap.hasErrorOccurred() && CXXIdx->getDisplayDiagnostics())
printDiagsToStderr(Unit);
diff --git a/tools/libclang/IndexingContext.h b/tools/libclang/IndexingContext.h
index 6271660..00e1096 100644
--- a/tools/libclang/IndexingContext.h
+++ b/tools/libclang/IndexingContext.h
@@ -542,10 +542,8 @@ namespace llvm {
}
static unsigned getHashValue(clang::cxindex::RefFileOccurence S) {
- llvm::FoldingSetNodeID ID;
- ID.AddPointer(S.File);
- ID.AddPointer(S.Dcl);
- return ID.ComputeHash();
+ typedef std::pair<const clang::FileEntry *, const clang::Decl *> PairTy;
+ return DenseMapInfo<PairTy>::getHashValue(PairTy(S.File, S.Dcl));
}
static bool isEqual(clang::cxindex::RefFileOccurence LHS,
diff --git a/tools/libclang/Makefile b/tools/libclang/Makefile
index 08bf3c6..975d381 100644
--- a/tools/libclang/Makefile
+++ b/tools/libclang/Makefile
@@ -15,11 +15,12 @@ EXPORTED_SYMBOL_FILE = $(PROJ_SRC_DIR)/libclang.exports
LINK_LIBS_IN_SHARED = 1
SHARED_LIBRARY = 1
-LINK_COMPONENTS := support mc
+include $(CLANG_LEVEL)/../../Makefile.config
+LINK_COMPONENTS := $(TARGETS_TO_BUILD) asmparser support mc
USEDLIBS = clangARCMigrate.a clangRewrite.a clangFrontend.a clangDriver.a \
clangSerialization.a \
clangParse.a clangSema.a clangEdit.a clangAnalysis.a \
- clangAST.a clangLex.a clangBasic.a
+ clangAST.a clangLex.a clangTooling.a clangBasic.a
include $(CLANG_LEVEL)/Makefile
@@ -42,7 +43,7 @@ ifeq ($(HOST_OS),Darwin)
endif
# Extra options to override libtool defaults.
- LLVMLibsOptions += -Wl,-dead_strip -Wl,-seg1addr,0xE0000000
+ LLVMLibsOptions += -Wl,-dead_strip
# 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/')
diff --git a/tools/libclang/RecursiveASTVisitor.h b/tools/libclang/RecursiveASTVisitor.h
new file mode 100644
index 0000000..7131025
--- /dev/null
+++ b/tools/libclang/RecursiveASTVisitor.h
@@ -0,0 +1,2185 @@
+//===--- RecursiveASTVisitor.h - Recursive AST Visitor ----------*- 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 the RecursiveASTVisitor interface, which recursively
+// traverses the entire AST.
+//
+//===----------------------------------------------------------------------===//
+#ifndef LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
+#define LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
+
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclCXX.h"
+#include "clang/AST/DeclFriend.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclTemplate.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprCXX.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/NestedNameSpecifier.h"
+#include "clang/AST/Stmt.h"
+#include "clang/AST/StmtCXX.h"
+#include "clang/AST/StmtObjC.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
+
+// The following three macros are used for meta programming. The code
+// using them is responsible for defining macro OPERATOR().
+
+// All unary operators.
+#define UNARYOP_LIST() \
+ OPERATOR(PostInc) OPERATOR(PostDec) \
+ OPERATOR(PreInc) OPERATOR(PreDec) \
+ OPERATOR(AddrOf) OPERATOR(Deref) \
+ OPERATOR(Plus) OPERATOR(Minus) \
+ OPERATOR(Not) OPERATOR(LNot) \
+ OPERATOR(Real) OPERATOR(Imag) \
+ OPERATOR(Extension)
+
+// All binary operators (excluding compound assign operators).
+#define BINOP_LIST() \
+ OPERATOR(PtrMemD) OPERATOR(PtrMemI) \
+ OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) \
+ OPERATOR(Add) OPERATOR(Sub) OPERATOR(Shl) \
+ OPERATOR(Shr) \
+ \
+ OPERATOR(LT) OPERATOR(GT) OPERATOR(LE) \
+ OPERATOR(GE) OPERATOR(EQ) OPERATOR(NE) \
+ OPERATOR(And) OPERATOR(Xor) OPERATOR(Or) \
+ OPERATOR(LAnd) OPERATOR(LOr) \
+ \
+ OPERATOR(Assign) \
+ OPERATOR(Comma)
+
+// All compound assign operators.
+#define CAO_LIST() \
+ OPERATOR(Mul) OPERATOR(Div) OPERATOR(Rem) OPERATOR(Add) OPERATOR(Sub) \
+ OPERATOR(Shl) OPERATOR(Shr) OPERATOR(And) OPERATOR(Or) OPERATOR(Xor)
+
+namespace clang {
+namespace cxindex {
+
+// A helper macro to implement short-circuiting when recursing. It
+// invokes CALL_EXPR, which must be a method call, on the derived
+// object (s.t. a user of RecursiveASTVisitor can override the method
+// in CALL_EXPR).
+#define TRY_TO(CALL_EXPR) \
+ do { if (!getDerived().CALL_EXPR) return false; } while (0)
+
+/// \brief A class that does preorder depth-first traversal on the
+/// entire Clang AST and visits each node.
+///
+/// This class performs three distinct tasks:
+/// 1. traverse the AST (i.e. go to each node);
+/// 2. at a given node, walk up the class hierarchy, starting from
+/// the node's dynamic type, until the top-most class (e.g. Stmt,
+/// Decl, or Type) is reached.
+/// 3. given a (node, class) combination, where 'class' is some base
+/// class of the dynamic type of 'node', call a user-overridable
+/// function to actually visit the node.
+///
+/// These tasks are done by three groups of methods, respectively:
+/// 1. TraverseDecl(Decl *x) does task #1. It is the entry point
+/// for traversing an AST rooted at x. This method simply
+/// dispatches (i.e. forwards) to TraverseFoo(Foo *x) where Foo
+/// is the dynamic type of *x, which calls WalkUpFromFoo(x) and
+/// then recursively visits the child nodes of x.
+/// TraverseStmt(Stmt *x) and TraverseType(QualType x) work
+/// similarly.
+/// 2. WalkUpFromFoo(Foo *x) does task #2. It does not try to visit
+/// any child node of x. Instead, it first calls WalkUpFromBar(x)
+/// where Bar is the direct parent class of Foo (unless Foo has
+/// no parent), and then calls VisitFoo(x) (see the next list item).
+/// 3. VisitFoo(Foo *x) does task #3.
+///
+/// These three method groups are tiered (Traverse* > WalkUpFrom* >
+/// Visit*). A method (e.g. Traverse*) may call methods from the same
+/// tier (e.g. other Traverse*) or one tier lower (e.g. WalkUpFrom*).
+/// It may not call methods from a higher tier.
+///
+/// Note that since WalkUpFromFoo() calls WalkUpFromBar() (where Bar
+/// is Foo's super class) before calling VisitFoo(), the result is
+/// that the Visit*() methods for a given node are called in the
+/// top-down order (e.g. for a node of type NamedDecl, the order will
+/// be VisitDecl(), VisitNamedDecl(), and then VisitNamespaceDecl()).
+///
+/// This scheme guarantees that all Visit*() calls for the same AST
+/// node are grouped together. In other words, Visit*() methods for
+/// different nodes are never interleaved.
+///
+/// Stmts are traversed internally using a data queue to avoid a stack overflow
+/// with hugely nested ASTs.
+///
+/// Clients of this visitor should subclass the visitor (providing
+/// themselves as the template argument, using the curiously recurring
+/// template pattern) and override any of the Traverse*, WalkUpFrom*,
+/// and Visit* methods for declarations, types, statements,
+/// expressions, or other AST nodes where the visitor should customize
+/// behavior. Most users only need to override Visit*. Advanced
+/// users may override Traverse* and WalkUpFrom* to implement custom
+/// traversal strategies. Returning false from one of these overridden
+/// functions will abort the entire traversal.
+///
+/// By default, this visitor tries to visit every part of the explicit
+/// source code exactly once. The default policy towards templates
+/// is to descend into the 'pattern' class or function body, not any
+/// explicit or implicit instantiations. Explicit specializations
+/// are still visited, and the patterns of partial specializations
+/// are visited separately. This behavior can be changed by
+/// overriding shouldVisitTemplateInstantiations() in the derived class
+/// to return true, in which case all known implicit and explicit
+/// instantiations will be visited at the same time as the pattern
+/// from which they were produced.
+template<typename Derived>
+class RecursiveASTVisitor {
+public:
+ /// \brief Return a reference to the derived class.
+ Derived &getDerived() { return *static_cast<Derived*>(this); }
+
+ /// \brief Return whether this visitor should recurse into
+ /// template instantiations.
+ bool shouldVisitTemplateInstantiations() const { return false; }
+
+ /// \brief Return whether this visitor should recurse into the types of
+ /// TypeLocs.
+ bool shouldWalkTypesOfTypeLocs() const { return true; }
+
+ /// \brief Recursively visit a statement or expression, by
+ /// dispatching to Traverse*() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is NULL).
+ bool TraverseStmt(Stmt *S);
+
+ /// \brief Recursively visit a type, by dispatching to
+ /// Traverse*Type() based on the argument's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type).
+ bool TraverseType(QualType T);
+
+ /// \brief Recursively visit a type with location, by dispatching to
+ /// Traverse*TypeLoc() based on the argument type's getTypeClass() property.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is a Null type location).
+ bool TraverseTypeLoc(TypeLoc TL);
+
+ /// \brief Recursively visit a declaration, by dispatching to
+ /// Traverse*Decl() based on the argument's dynamic type.
+ ///
+ /// \returns false if the visitation was terminated early, true
+ /// otherwise (including when the argument is NULL).
+ bool TraverseDecl(Decl *D);
+
+ /// \brief Recursively visit a C++ nested-name-specifier.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifier(NestedNameSpecifier *NNS);
+
+ /// \brief Recursively visit a C++ nested-name-specifier with location
+ /// information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseNestedNameSpecifierLoc(NestedNameSpecifierLoc NNS);
+
+ /// \brief Recursively visit a name with its location information.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseDeclarationNameInfo(DeclarationNameInfo NameInfo);
+
+ /// \brief Recursively visit a template name and dispatch to the
+ /// appropriate method.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseTemplateName(TemplateName Template);
+
+ /// \brief Recursively visit a template argument and dispatch to the
+ /// appropriate method for the argument type.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ // FIXME: migrate callers to TemplateArgumentLoc instead.
+ bool TraverseTemplateArgument(const TemplateArgument &Arg);
+
+ /// \brief Recursively visit a template argument location and dispatch to the
+ /// appropriate method for the argument type.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseTemplateArgumentLoc(const TemplateArgumentLoc &ArgLoc);
+
+ /// \brief Recursively visit a set of template arguments.
+ /// This can be overridden by a subclass, but it's not expected that
+ /// will be needed -- this visitor always dispatches to another.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ // FIXME: take a TemplateArgumentLoc* (or TemplateArgumentListInfo) instead.
+ bool TraverseTemplateArguments(const TemplateArgument *Args,
+ unsigned NumArgs);
+
+ /// \brief Recursively visit a constructor initializer. This
+ /// automatically dispatches to another visitor for the initializer
+ /// expression, but not for the name of the initializer, so may
+ /// be overridden for clients that need access to the name.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseConstructorInitializer(CXXCtorInitializer *Init);
+
+ /// \brief Recursively visit a lambda capture.
+ ///
+ /// \returns false if the visitation was terminated early, true otherwise.
+ bool TraverseLambdaCapture(LambdaExpr::Capture C);
+
+ // ---- Methods on Stmts ----
+
+ // Declare Traverse*() for all concrete Stmt classes.
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ bool Traverse##CLASS(CLASS *S);
+#include "clang/AST/StmtNodes.inc"
+ // The above header #undefs ABSTRACT_STMT and STMT upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Stmt classes.
+ bool WalkUpFromStmt(Stmt *S) { return getDerived().VisitStmt(S); }
+ bool VisitStmt(Stmt *S) { return true; }
+#define STMT(CLASS, PARENT) \
+ bool WalkUpFrom##CLASS(CLASS *S) { \
+ TRY_TO(WalkUpFrom##PARENT(S)); \
+ TRY_TO(Visit##CLASS(S)); \
+ return true; \
+ } \
+ bool Visit##CLASS(CLASS *S) { return true; }
+#include "clang/AST/StmtNodes.inc"
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for unary
+ // operator methods. Unary operators are not classes in themselves
+ // (they're all opcodes in UnaryOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ bool TraverseUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnary##NAME(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ StmtQueue.queue(S->getSubExpr()); \
+ return true; \
+ } \
+ bool WalkUpFromUnary##NAME(UnaryOperator *S) { \
+ TRY_TO(WalkUpFromUnaryOperator(S)); \
+ TRY_TO(VisitUnary##NAME(S)); \
+ return true; \
+ } \
+ bool VisitUnary##NAME(UnaryOperator *S) { return true; }
+
+ UNARYOP_LIST()
+#undef OPERATOR
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for binary
+ // operator methods. Binary operators are not classes in themselves
+ // (they're all opcodes in BinaryOperator) but do have visitors.
+#define GENERAL_BINOP_FALLBACK(NAME, BINOP_TYPE) \
+ bool TraverseBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFromBin##NAME(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ StmtQueue.queue(S->getLHS()); \
+ StmtQueue.queue(S->getRHS()); \
+ return true; \
+ } \
+ bool WalkUpFromBin##NAME(BINOP_TYPE *S) { \
+ TRY_TO(WalkUpFrom##BINOP_TYPE(S)); \
+ TRY_TO(VisitBin##NAME(S)); \
+ return true; \
+ } \
+ bool VisitBin##NAME(BINOP_TYPE *S) { return true; }
+
+#define OPERATOR(NAME) GENERAL_BINOP_FALLBACK(NAME, BinaryOperator)
+ BINOP_LIST()
+#undef OPERATOR
+
+ // Define Traverse*(), WalkUpFrom*(), and Visit*() for compound
+ // assignment methods. Compound assignment operators are not
+ // classes in themselves (they're all opcodes in
+ // CompoundAssignOperator) but do have visitors.
+#define OPERATOR(NAME) \
+ GENERAL_BINOP_FALLBACK(NAME##Assign, CompoundAssignOperator)
+
+ CAO_LIST()
+#undef OPERATOR
+#undef GENERAL_BINOP_FALLBACK
+
+ // ---- Methods on Types ----
+ // FIXME: revamp to take TypeLoc's rather than Types.
+
+ // Declare Traverse*() for all concrete Type classes.
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) \
+ bool Traverse##CLASS##Type(CLASS##Type *T);
+#include "clang/AST/TypeNodes.def"
+ // The above header #undefs ABSTRACT_TYPE and TYPE upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Type classes.
+ bool WalkUpFromType(Type *T) { return getDerived().VisitType(T); }
+ bool VisitType(Type *T) { return true; }
+#define TYPE(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Type(CLASS##Type *T) { \
+ TRY_TO(WalkUpFrom##BASE(T)); \
+ TRY_TO(Visit##CLASS##Type(T)); \
+ return true; \
+ } \
+ bool Visit##CLASS##Type(CLASS##Type *T) { return true; }
+#include "clang/AST/TypeNodes.def"
+
+ // ---- Methods on TypeLocs ----
+ // FIXME: this currently just calls the matching Type methods
+
+ // Declare Traverse*() for all concrete Type classes.
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE) \
+ bool Traverse##CLASS##TypeLoc(CLASS##TypeLoc TL);
+#include "clang/AST/TypeLocNodes.def"
+ // The above header #undefs ABSTRACT_TYPELOC and TYPELOC upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all TypeLoc classes.
+ bool WalkUpFromTypeLoc(TypeLoc TL) { return getDerived().VisitTypeLoc(TL); }
+ bool VisitTypeLoc(TypeLoc TL) { return true; }
+
+ // QualifiedTypeLoc and UnqualTypeLoc are not declared in
+ // TypeNodes.def and thus need to be handled specially.
+ bool WalkUpFromQualifiedTypeLoc(QualifiedTypeLoc TL) {
+ return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+ }
+ bool VisitQualifiedTypeLoc(QualifiedTypeLoc TL) { return true; }
+ bool WalkUpFromUnqualTypeLoc(UnqualTypeLoc TL) {
+ return getDerived().VisitUnqualTypeLoc(TL.getUnqualifiedLoc());
+ }
+ bool VisitUnqualTypeLoc(UnqualTypeLoc TL) { return true; }
+
+ // Note that BASE includes trailing 'Type' which CLASS doesn't.
+#define TYPE(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##TypeLoc(CLASS##TypeLoc TL) { \
+ TRY_TO(WalkUpFrom##BASE##Loc(TL)); \
+ TRY_TO(Visit##CLASS##TypeLoc(TL)); \
+ return true; \
+ } \
+ bool Visit##CLASS##TypeLoc(CLASS##TypeLoc TL) { return true; }
+#include "clang/AST/TypeNodes.def"
+
+ // ---- Methods on Decls ----
+
+ // Declare Traverse*() for all concrete Decl classes.
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ bool Traverse##CLASS##Decl(CLASS##Decl *D);
+#include "clang/AST/DeclNodes.inc"
+ // The above header #undefs ABSTRACT_DECL and DECL upon exit.
+
+ // Define WalkUpFrom*() and empty Visit*() for all Decl classes.
+ bool WalkUpFromDecl(Decl *D) { return getDerived().VisitDecl(D); }
+ bool VisitDecl(Decl *D) { return true; }
+#define DECL(CLASS, BASE) \
+ bool WalkUpFrom##CLASS##Decl(CLASS##Decl *D) { \
+ TRY_TO(WalkUpFrom##BASE(D)); \
+ TRY_TO(Visit##CLASS##Decl(D)); \
+ return true; \
+ } \
+ bool Visit##CLASS##Decl(CLASS##Decl *D) { return true; }
+#include "clang/AST/DeclNodes.inc"
+
+private:
+ // These are helper methods used by more than one Traverse* method.
+ bool TraverseTemplateParameterListHelper(TemplateParameterList *TPL);
+ bool TraverseClassInstantiations(ClassTemplateDecl *D);
+ bool TraverseFunctionInstantiations(FunctionTemplateDecl *D) ;
+ bool TraverseTemplateArgumentLocsHelper(const TemplateArgumentLoc *TAL,
+ unsigned Count);
+ bool TraverseArrayTypeLocHelper(ArrayTypeLoc TL);
+ bool TraverseRecordHelper(RecordDecl *D);
+ bool TraverseCXXRecordHelper(CXXRecordDecl *D);
+ bool TraverseDeclaratorHelper(DeclaratorDecl *D);
+ bool TraverseDeclContextHelper(DeclContext *DC);
+ bool TraverseFunctionHelper(FunctionDecl *D);
+ bool TraverseVarHelper(VarDecl *D);
+
+ typedef SmallVector<Stmt *, 16> StmtsTy;
+ typedef SmallVector<StmtsTy *, 4> QueuesTy;
+
+ QueuesTy Queues;
+
+ class NewQueueRAII {
+ RecursiveASTVisitor &RAV;
+ public:
+ NewQueueRAII(StmtsTy &queue, RecursiveASTVisitor &RAV) : RAV(RAV) {
+ RAV.Queues.push_back(&queue);
+ }
+ ~NewQueueRAII() {
+ RAV.Queues.pop_back();
+ }
+ };
+
+ StmtsTy &getCurrentQueue() {
+ assert(!Queues.empty() && "base TraverseStmt was never called?");
+ return *Queues.back();
+ }
+
+public:
+ class StmtQueueAction {
+ StmtsTy &CurrQueue;
+ public:
+ explicit StmtQueueAction(RecursiveASTVisitor &RAV)
+ : CurrQueue(RAV.getCurrentQueue()) { }
+
+ void queue(Stmt *S) {
+ CurrQueue.push_back(S);
+ }
+ };
+};
+
+#define DISPATCH(NAME, CLASS, VAR) \
+ return getDerived().Traverse##NAME(static_cast<CLASS*>(VAR))
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseStmt(Stmt *S) {
+ if (!S)
+ return true;
+
+ StmtsTy Queue, StmtsToEnqueu;
+ Queue.push_back(S);
+ NewQueueRAII NQ(StmtsToEnqueu, *this);
+
+ while (!Queue.empty()) {
+ S = Queue.pop_back_val();
+ if (!S)
+ continue;
+
+ StmtsToEnqueu.clear();
+
+#define DISPATCH_STMT(NAME, CLASS, VAR) \
+ TRY_TO(Traverse##NAME(static_cast<CLASS*>(VAR))); break
+
+ // If we have a binary expr, dispatch to the subcode of the binop. A smart
+ // optimizer (e.g. LLVM) will fold this comparison into the switch stmt
+ // below.
+ if (BinaryOperator *BinOp = dyn_cast<BinaryOperator>(S)) {
+ switch (BinOp->getOpcode()) {
+#define OPERATOR(NAME) \
+ case BO_##NAME: DISPATCH_STMT(Bin##NAME, BinaryOperator, S);
+
+ BINOP_LIST()
+#undef OPERATOR
+#undef BINOP_LIST
+
+#define OPERATOR(NAME) \
+ case BO_##NAME##Assign: \
+ DISPATCH_STMT(Bin##NAME##Assign, CompoundAssignOperator, S);
+
+ CAO_LIST()
+#undef OPERATOR
+#undef CAO_LIST
+ }
+ } else if (UnaryOperator *UnOp = dyn_cast<UnaryOperator>(S)) {
+ switch (UnOp->getOpcode()) {
+#define OPERATOR(NAME) \
+ case UO_##NAME: DISPATCH_STMT(Unary##NAME, UnaryOperator, S);
+
+ UNARYOP_LIST()
+#undef OPERATOR
+#undef UNARYOP_LIST
+ }
+ } else {
+
+ // Top switch stmt: dispatch to TraverseFooStmt for each concrete FooStmt.
+ switch (S->getStmtClass()) {
+ case Stmt::NoStmtClass: break;
+#define ABSTRACT_STMT(STMT)
+#define STMT(CLASS, PARENT) \
+ case Stmt::CLASS##Class: DISPATCH_STMT(CLASS, CLASS, S);
+#include "clang/AST/StmtNodes.inc"
+ }
+ }
+
+ for (SmallVector<Stmt *, 8>::reverse_iterator
+ RI = StmtsToEnqueu.rbegin(),
+ RE = StmtsToEnqueu.rend(); RI != RE; ++RI)
+ Queue.push_back(*RI);
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseType(QualType T) {
+ if (T.isNull())
+ return true;
+
+ switch (T->getTypeClass()) {
+#define ABSTRACT_TYPE(CLASS, BASE)
+#define TYPE(CLASS, BASE) \
+ case Type::CLASS: DISPATCH(CLASS##Type, CLASS##Type, \
+ const_cast<Type*>(T.getTypePtr()));
+#include "clang/AST/TypeNodes.def"
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTypeLoc(TypeLoc TL) {
+ if (TL.isNull())
+ return true;
+
+ switch (TL.getTypeLocClass()) {
+#define ABSTRACT_TYPELOC(CLASS, BASE)
+#define TYPELOC(CLASS, BASE) \
+ case TypeLoc::CLASS: \
+ return getDerived().Traverse##CLASS##TypeLoc(*cast<CLASS##TypeLoc>(&TL));
+#include "clang/AST/TypeLocNodes.def"
+ }
+
+ return true;
+}
+
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDecl(Decl *D) {
+ if (!D)
+ return true;
+
+ // As a syntax visitor, we want to ignore declarations for
+ // implicitly-defined declarations (ones not typed explicitly by the
+ // user).
+ if (D->isImplicit())
+ return true;
+
+ switch (D->getKind()) {
+#define ABSTRACT_DECL(DECL)
+#define DECL(CLASS, BASE) \
+ case Decl::CLASS: DISPATCH(CLASS##Decl, CLASS##Decl, D);
+#include "clang/AST/DeclNodes.inc"
+ }
+
+ return true;
+}
+
+#undef DISPATCH
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifier(
+ NestedNameSpecifier *NNS) {
+ if (!NNS)
+ return true;
+
+ if (NNS->getPrefix())
+ TRY_TO(TraverseNestedNameSpecifier(NNS->getPrefix()));
+
+ switch (NNS->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseType(QualType(NNS->getAsType(), 0)));
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseNestedNameSpecifierLoc(
+ NestedNameSpecifierLoc NNS) {
+ if (!NNS)
+ return true;
+
+ if (NestedNameSpecifierLoc Prefix = NNS.getPrefix())
+ TRY_TO(TraverseNestedNameSpecifierLoc(Prefix));
+
+ switch (NNS.getNestedNameSpecifier()->getKind()) {
+ case NestedNameSpecifier::Identifier:
+ case NestedNameSpecifier::Namespace:
+ case NestedNameSpecifier::NamespaceAlias:
+ case NestedNameSpecifier::Global:
+ return true;
+
+ case NestedNameSpecifier::TypeSpec:
+ case NestedNameSpecifier::TypeSpecWithTemplate:
+ TRY_TO(TraverseTypeLoc(NNS.getTypeLoc()));
+ break;
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclarationNameInfo(
+ DeclarationNameInfo NameInfo) {
+ switch (NameInfo.getName().getNameKind()) {
+ case DeclarationName::CXXConstructorName:
+ case DeclarationName::CXXDestructorName:
+ case DeclarationName::CXXConversionFunctionName:
+ if (TypeSourceInfo *TSInfo = NameInfo.getNamedTypeInfo())
+ TRY_TO(TraverseTypeLoc(TSInfo->getTypeLoc()));
+
+ break;
+
+ case DeclarationName::Identifier:
+ case DeclarationName::ObjCZeroArgSelector:
+ case DeclarationName::ObjCOneArgSelector:
+ case DeclarationName::ObjCMultiArgSelector:
+ case DeclarationName::CXXOperatorName:
+ case DeclarationName::CXXLiteralOperatorName:
+ case DeclarationName::CXXUsingDirective:
+ break;
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateName(TemplateName Template) {
+ if (DependentTemplateName *DTN = Template.getAsDependentTemplateName())
+ TRY_TO(TraverseNestedNameSpecifier(DTN->getQualifier()));
+ else if (QualifiedTemplateName *QTN = Template.getAsQualifiedTemplateName())
+ TRY_TO(TraverseNestedNameSpecifier(QTN->getQualifier()));
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgument(
+ const TemplateArgument &Arg) {
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ return true;
+
+ case TemplateArgument::Type:
+ return getDerived().TraverseType(Arg.getAsType());
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
+
+ case TemplateArgument::Expression:
+ return getDerived().TraverseStmt(Arg.getAsExpr());
+
+ case TemplateArgument::Pack:
+ return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
+ Arg.pack_size());
+ }
+
+ return true;
+}
+
+// FIXME: no template name location?
+// FIXME: no source locations for a template argument pack?
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLoc(
+ const TemplateArgumentLoc &ArgLoc) {
+ const TemplateArgument &Arg = ArgLoc.getArgument();
+
+ switch (Arg.getKind()) {
+ case TemplateArgument::Null:
+ case TemplateArgument::Declaration:
+ case TemplateArgument::Integral:
+ return true;
+
+ case TemplateArgument::Type: {
+ // FIXME: how can TSI ever be NULL?
+ if (TypeSourceInfo *TSI = ArgLoc.getTypeSourceInfo())
+ return getDerived().TraverseTypeLoc(TSI->getTypeLoc());
+ else
+ return getDerived().TraverseType(Arg.getAsType());
+ }
+
+ case TemplateArgument::Template:
+ case TemplateArgument::TemplateExpansion:
+ if (ArgLoc.getTemplateQualifierLoc())
+ TRY_TO(getDerived().TraverseNestedNameSpecifierLoc(
+ ArgLoc.getTemplateQualifierLoc()));
+ return getDerived().TraverseTemplateName(
+ Arg.getAsTemplateOrTemplatePattern());
+
+ case TemplateArgument::Expression:
+ return getDerived().TraverseStmt(ArgLoc.getSourceExpression());
+
+ case TemplateArgument::Pack:
+ return getDerived().TraverseTemplateArguments(Arg.pack_begin(),
+ Arg.pack_size());
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArguments(
+ const TemplateArgument *Args,
+ unsigned NumArgs) {
+ for (unsigned I = 0; I != NumArgs; ++I) {
+ TRY_TO(TraverseTemplateArgument(Args[I]));
+ }
+
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseConstructorInitializer(
+ CXXCtorInitializer *Init) {
+ if (TypeSourceInfo *TInfo = Init->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+
+ if (Init->isWritten())
+ TRY_TO(TraverseStmt(Init->getInit()));
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaCapture(LambdaExpr::Capture C){
+ return true;
+}
+
+// ----------------- Type traversal -----------------
+
+// This macro makes available a variable T, the passed-in type.
+#define DEF_TRAVERSE_TYPE(TYPE, CODE) \
+ template<typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##TYPE (TYPE *T) { \
+ TRY_TO(WalkUpFrom##TYPE (T)); \
+ { CODE; } \
+ return true; \
+ }
+
+DEF_TRAVERSE_TYPE(BuiltinType, { })
+
+DEF_TRAVERSE_TYPE(ComplexType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(PointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(BlockPointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(LValueReferenceType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(RValueReferenceType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(MemberPointerType, {
+ TRY_TO(TraverseType(QualType(T->getClass(), 0)));
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(ConstantArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(IncompleteArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(VariableArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentSizedArrayType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentSizedExtVectorType, {
+ if (T->getSizeExpr())
+ TRY_TO(TraverseStmt(T->getSizeExpr()));
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(VectorType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(ExtVectorType, {
+ TRY_TO(TraverseType(T->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPE(FunctionNoProtoType, {
+ TRY_TO(TraverseType(T->getResultType()));
+ })
+
+DEF_TRAVERSE_TYPE(FunctionProtoType, {
+ TRY_TO(TraverseType(T->getResultType()));
+
+ for (FunctionProtoType::arg_type_iterator A = T->arg_type_begin(),
+ AEnd = T->arg_type_end();
+ A != AEnd; ++A) {
+ TRY_TO(TraverseType(*A));
+ }
+
+ for (FunctionProtoType::exception_iterator E = T->exception_begin(),
+ EEnd = T->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ })
+
+DEF_TRAVERSE_TYPE(UnresolvedUsingType, { })
+DEF_TRAVERSE_TYPE(TypedefType, { })
+
+DEF_TRAVERSE_TYPE(TypeOfExprType, {
+ TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(TypeOfType, {
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+ })
+
+DEF_TRAVERSE_TYPE(DecltypeType, {
+ TRY_TO(TraverseStmt(T->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPE(UnaryTransformType, {
+ TRY_TO(TraverseType(T->getBaseType()));
+ TRY_TO(TraverseType(T->getUnderlyingType()));
+ })
+
+DEF_TRAVERSE_TYPE(AutoType, {
+ TRY_TO(TraverseType(T->getDeducedType()));
+ })
+
+DEF_TRAVERSE_TYPE(RecordType, { })
+DEF_TRAVERSE_TYPE(EnumType, { })
+DEF_TRAVERSE_TYPE(TemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPE(SubstTemplateTypeParmPackType, { })
+
+DEF_TRAVERSE_TYPE(TemplateSpecializationType, {
+ TRY_TO(TraverseTemplateName(T->getTemplateName()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+ })
+
+DEF_TRAVERSE_TYPE(InjectedClassNameType, { })
+
+DEF_TRAVERSE_TYPE(AttributedType, {
+ TRY_TO(TraverseType(T->getModifiedType()));
+ })
+
+DEF_TRAVERSE_TYPE(ParenType, {
+ TRY_TO(TraverseType(T->getInnerType()));
+ })
+
+DEF_TRAVERSE_TYPE(ElaboratedType, {
+ if (T->getQualifier()) {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ }
+ TRY_TO(TraverseType(T->getNamedType()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentNameType, {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ })
+
+DEF_TRAVERSE_TYPE(DependentTemplateSpecializationType, {
+ TRY_TO(TraverseNestedNameSpecifier(T->getQualifier()));
+ TRY_TO(TraverseTemplateArguments(T->getArgs(), T->getNumArgs()));
+ })
+
+DEF_TRAVERSE_TYPE(PackExpansionType, {
+ TRY_TO(TraverseType(T->getPattern()));
+ })
+
+DEF_TRAVERSE_TYPE(ObjCInterfaceType, { })
+
+DEF_TRAVERSE_TYPE(ObjCObjectType, {
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (T->getBaseType().getTypePtr() != T)
+ TRY_TO(TraverseType(T->getBaseType()));
+ })
+
+DEF_TRAVERSE_TYPE(ObjCObjectPointerType, {
+ TRY_TO(TraverseType(T->getPointeeType()));
+ })
+
+DEF_TRAVERSE_TYPE(AtomicType, {
+ TRY_TO(TraverseType(T->getValueType()));
+ })
+
+#undef DEF_TRAVERSE_TYPE
+
+// ----------------- TypeLoc traversal -----------------
+
+// This macro makes available a variable TL, the passed-in TypeLoc.
+// If requested, it calls WalkUpFrom* for the Type in the given TypeLoc,
+// in addition to WalkUpFrom* for the TypeLoc itself, such that existing
+// clients that override the WalkUpFrom*Type() and/or Visit*Type() methods
+// continue to work.
+#define DEF_TRAVERSE_TYPELOC(TYPE, CODE) \
+ template<typename Derived> \
+ bool RecursiveASTVisitor<Derived>::Traverse##TYPE##Loc(TYPE##Loc TL) { \
+ if (getDerived().shouldWalkTypesOfTypeLocs()) \
+ TRY_TO(WalkUpFrom##TYPE(const_cast<TYPE*>(TL.getTypePtr()))); \
+ TRY_TO(WalkUpFrom##TYPE##Loc(TL)); \
+ { CODE; } \
+ return true; \
+ }
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseQualifiedTypeLoc(
+ QualifiedTypeLoc TL) {
+ // Move this over to the 'main' typeloc tree. Note that this is a
+ // move -- we pretend that we were really looking at the unqualified
+ // typeloc all along -- rather than a recursion, so we don't follow
+ // the normal CRTP plan of going through
+ // getDerived().TraverseTypeLoc. If we did, we'd be traversing
+ // twice for the same type (once as a QualifiedTypeLoc version of
+ // the type, once as an UnqualifiedTypeLoc version of the type),
+ // which in effect means we'd call VisitTypeLoc twice with the
+ // 'same' type. This solves that problem, at the cost of never
+ // seeing the qualified version of the type (unless the client
+ // subclasses TraverseQualifiedTypeLoc themselves). It's not a
+ // perfect solution. A perfect solution probably requires making
+ // QualifiedTypeLoc a wrapper around TypeLoc -- like QualType is a
+ // wrapper around Type* -- rather than being its own class in the
+ // type hierarchy.
+ return TraverseTypeLoc(TL.getUnqualifiedLoc());
+}
+
+DEF_TRAVERSE_TYPELOC(BuiltinType, { })
+
+// FIXME: ComplexTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ComplexType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(PointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(BlockPointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(LValueReferenceType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(RValueReferenceType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+// FIXME: location of base class?
+// We traverse this in the type case as well, but how is it not reached through
+// the pointee type?
+DEF_TRAVERSE_TYPELOC(MemberPointerType, {
+ TRY_TO(TraverseType(QualType(TL.getTypePtr()->getClass(), 0)));
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseArrayTypeLocHelper(ArrayTypeLoc TL) {
+ // This isn't available for ArrayType, but is for the ArrayTypeLoc.
+ TRY_TO(TraverseStmt(TL.getSizeExpr()));
+ return true;
+}
+
+DEF_TRAVERSE_TYPELOC(ConstantArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(IncompleteArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(VariableArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+DEF_TRAVERSE_TYPELOC(DependentSizedArrayType, {
+ TRY_TO(TraverseTypeLoc(TL.getElementLoc()));
+ return TraverseArrayTypeLocHelper(TL);
+ })
+
+// FIXME: order? why not size expr first?
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(DependentSizedExtVectorType, {
+ if (TL.getTypePtr()->getSizeExpr())
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getSizeExpr()));
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+// FIXME: VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(VectorType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+// FIXME: size and attributes
+// FIXME: base VectorTypeLoc is unfinished
+DEF_TRAVERSE_TYPELOC(ExtVectorType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getElementType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(FunctionNoProtoType, {
+ TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+ })
+
+// FIXME: location of exception specifications (attributes?)
+DEF_TRAVERSE_TYPELOC(FunctionProtoType, {
+ TRY_TO(TraverseTypeLoc(TL.getResultLoc()));
+
+ const FunctionProtoType *T = TL.getTypePtr();
+
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ if (TL.getArg(I)) {
+ TRY_TO(TraverseDecl(TL.getArg(I)));
+ } else if (I < T->getNumArgs()) {
+ TRY_TO(TraverseType(T->getArgType(I)));
+ }
+ }
+
+ for (FunctionProtoType::exception_iterator E = T->exception_begin(),
+ EEnd = T->exception_end();
+ E != EEnd; ++E) {
+ TRY_TO(TraverseType(*E));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(UnresolvedUsingType, { })
+DEF_TRAVERSE_TYPELOC(TypedefType, { })
+
+DEF_TRAVERSE_TYPELOC(TypeOfExprType, {
+ TRY_TO(TraverseStmt(TL.getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPELOC(TypeOfType, {
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+ })
+
+// FIXME: location of underlying expr
+DEF_TRAVERSE_TYPELOC(DecltypeType, {
+ TRY_TO(TraverseStmt(TL.getTypePtr()->getUnderlyingExpr()));
+ })
+
+DEF_TRAVERSE_TYPELOC(UnaryTransformType, {
+ TRY_TO(TraverseTypeLoc(TL.getUnderlyingTInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AutoType, {
+ TRY_TO(TraverseType(TL.getTypePtr()->getDeducedType()));
+ })
+
+DEF_TRAVERSE_TYPELOC(RecordType, { })
+DEF_TRAVERSE_TYPELOC(EnumType, { })
+DEF_TRAVERSE_TYPELOC(TemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmType, { })
+DEF_TRAVERSE_TYPELOC(SubstTemplateTypeParmPackType, { })
+
+// FIXME: use the loc for the template name?
+DEF_TRAVERSE_TYPELOC(TemplateSpecializationType, {
+ TRY_TO(TraverseTemplateName(TL.getTypePtr()->getTemplateName()));
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(InjectedClassNameType, { })
+
+DEF_TRAVERSE_TYPELOC(ParenType, {
+ TRY_TO(TraverseTypeLoc(TL.getInnerLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AttributedType, {
+ TRY_TO(TraverseTypeLoc(TL.getModifiedLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(ElaboratedType, {
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
+ TRY_TO(TraverseTypeLoc(TL.getNamedTypeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(DependentNameType, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(DependentTemplateSpecializationType, {
+ if (TL.getQualifierLoc()) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(TL.getQualifierLoc()));
+ }
+
+ for (unsigned I = 0, E = TL.getNumArgs(); I != E; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TL.getArgLoc(I)));
+ }
+ })
+
+DEF_TRAVERSE_TYPELOC(PackExpansionType, {
+ TRY_TO(TraverseTypeLoc(TL.getPatternLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(ObjCInterfaceType, { })
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectType, {
+ // We have to watch out here because an ObjCInterfaceType's base
+ // type is itself.
+ if (TL.getTypePtr()->getBaseType().getTypePtr() != TL.getTypePtr())
+ TRY_TO(TraverseTypeLoc(TL.getBaseLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(ObjCObjectPointerType, {
+ TRY_TO(TraverseTypeLoc(TL.getPointeeLoc()));
+ })
+
+DEF_TRAVERSE_TYPELOC(AtomicType, {
+ TRY_TO(TraverseTypeLoc(TL.getValueLoc()));
+ })
+
+#undef DEF_TRAVERSE_TYPELOC
+
+// ----------------- Decl traversal -----------------
+//
+// For a Decl, we automate (in the DEF_TRAVERSE_DECL macro) traversing
+// the children that come from the DeclContext associated with it.
+// Therefore each Traverse* only needs to worry about children other
+// than those.
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclContextHelper(DeclContext *DC) {
+ if (!DC)
+ return true;
+
+ for (DeclContext::decl_iterator Child = DC->decls_begin(),
+ ChildEnd = DC->decls_end();
+ Child != ChildEnd; ++Child) {
+ // BlockDecls are traversed through BlockExprs.
+ if (!isa<BlockDecl>(*Child))
+ TRY_TO(TraverseDecl(*Child));
+ }
+
+ return true;
+}
+
+// This macro makes available a variable D, the passed-in decl.
+#define DEF_TRAVERSE_DECL(DECL, CODE) \
+template<typename Derived> \
+bool RecursiveASTVisitor<Derived>::Traverse##DECL (DECL *D) { \
+ TRY_TO(WalkUpFrom##DECL (D)); \
+ { CODE; } \
+ TRY_TO(TraverseDeclContextHelper(dyn_cast<DeclContext>(D))); \
+ return true; \
+}
+
+DEF_TRAVERSE_DECL(AccessSpecDecl, { })
+
+DEF_TRAVERSE_DECL(BlockDecl, {
+ if (TypeSourceInfo *TInfo = D->getSignatureAsWritten())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+ TRY_TO(TraverseStmt(D->getBody()));
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+ })
+
+DEF_TRAVERSE_DECL(FileScopeAsmDecl, {
+ TRY_TO(TraverseStmt(D->getAsmString()));
+ })
+
+DEF_TRAVERSE_DECL(ImportDecl, { })
+
+DEF_TRAVERSE_DECL(FriendDecl, {
+ // Friend is either decl or a type.
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
+ })
+
+DEF_TRAVERSE_DECL(FriendTemplateDecl, {
+ if (D->getFriendType())
+ TRY_TO(TraverseTypeLoc(D->getFriendType()->getTypeLoc()));
+ else
+ TRY_TO(TraverseDecl(D->getFriendDecl()));
+ for (unsigned I = 0, E = D->getNumTemplateParameters(); I < E; ++I) {
+ TemplateParameterList *TPL = D->getTemplateParameterList(I);
+ for (TemplateParameterList::iterator ITPL = TPL->begin(),
+ ETPL = TPL->end();
+ ITPL != ETPL; ++ITPL) {
+ TRY_TO(TraverseDecl(*ITPL));
+ }
+ }
+ })
+
+DEF_TRAVERSE_DECL(ClassScopeFunctionSpecializationDecl, {
+ TRY_TO(TraverseDecl(D->getSpecialization()));
+ })
+
+DEF_TRAVERSE_DECL(LinkageSpecDecl, { })
+
+DEF_TRAVERSE_DECL(ObjCPropertyImplDecl, {
+ // FIXME: implement this
+ })
+
+DEF_TRAVERSE_DECL(StaticAssertDecl, {
+ TRY_TO(TraverseStmt(D->getAssertExpr()));
+ TRY_TO(TraverseStmt(D->getMessage()));
+ })
+
+DEF_TRAVERSE_DECL(TranslationUnitDecl, {
+ // Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
+
+DEF_TRAVERSE_DECL(NamespaceAliasDecl, {
+ // We shouldn't traverse an aliased namespace, since it will be
+ // defined (and, therefore, traversed) somewhere else.
+ //
+ // This return statement makes sure the traversal of nodes in
+ // decls_begin()/decls_end() (done in the DEF_TRAVERSE_DECL macro)
+ // is skipped - don't remove it.
+ return true;
+ })
+
+DEF_TRAVERSE_DECL(LabelDecl, {
+ // There is no code in a LabelDecl.
+})
+
+
+DEF_TRAVERSE_DECL(NamespaceDecl, {
+ // Code in an unnamed namespace shows up automatically in
+ // decls_begin()/decls_end(). Thus we don't need to recurse on
+ // D->getAnonymousNamespace().
+ })
+
+DEF_TRAVERSE_DECL(ObjCCompatibleAliasDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCCategoryImplDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCImplementationDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCInterfaceDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCProtocolDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(ObjCMethodDecl, {
+ if (D->getResultTypeSourceInfo()) {
+ TRY_TO(TraverseTypeLoc(D->getResultTypeSourceInfo()->getTypeLoc()));
+ }
+ for (ObjCMethodDecl::param_iterator
+ I = D->param_begin(), E = D->param_end(); I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseStmt(D->getBody()));
+ }
+ return true;
+ })
+
+DEF_TRAVERSE_DECL(ObjCPropertyDecl, {
+ // FIXME: implement
+ })
+
+DEF_TRAVERSE_DECL(UsingDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+ })
+
+DEF_TRAVERSE_DECL(UsingDirectiveDecl, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ })
+
+DEF_TRAVERSE_DECL(UsingShadowDecl, { })
+
+// A helper method for TemplateDecl's children.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateParameterListHelper(
+ TemplateParameterList *TPL) {
+ if (TPL) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ return true;
+}
+
+// A helper method for traversing the implicit instantiations of a
+// class template.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseClassInstantiations(
+ ClassTemplateDecl *D) {
+ ClassTemplateDecl::spec_iterator end = D->spec_end();
+ for (ClassTemplateDecl::spec_iterator it = D->spec_begin(); it != end; ++it) {
+ ClassTemplateSpecializationDecl* SD = *it;
+
+ switch (SD->getSpecializationKind()) {
+ // Visit the implicit instantiations with the requested pattern.
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ TRY_TO(TraverseDecl(SD));
+ break;
+
+ // We don't need to do anything on an explicit instantiation
+ // or explicit specialization because there will be an explicit
+ // node for it elsewhere.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplateDecl, {
+ CXXRecordDecl* TempDecl = D->getTemplatedDecl();
+ TRY_TO(TraverseDecl(TempDecl));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // class templates since they do not appear in the user code. The
+ // following code optionally traverses them.
+ //
+ // We only traverse the class instantiations when we see the canonical
+ // declaration of the template, to ensure we only visit them once.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D == D->getCanonicalDecl())
+ TRY_TO(TraverseClassInstantiations(D));
+
+ // Note that getInstantiatedFromMemberTemplate() is just a link
+ // from a template instantiation back to the template from which
+ // it was instantiated, and thus should not be traversed.
+ })
+
+// A helper method for traversing the instantiations of a
+// function while skipping its specializations.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionInstantiations(
+ FunctionTemplateDecl *D) {
+ FunctionTemplateDecl::spec_iterator end = D->spec_end();
+ for (FunctionTemplateDecl::spec_iterator it = D->spec_begin(); it != end;
+ ++it) {
+ FunctionDecl* FD = *it;
+ switch (FD->getTemplateSpecializationKind()) {
+ case TSK_Undeclared:
+ case TSK_ImplicitInstantiation:
+ // We don't know what kind of FunctionDecl this is.
+ TRY_TO(TraverseDecl(FD));
+ break;
+
+ // No need to visit explicit instantiations, we'll find the node
+ // eventually.
+ case TSK_ExplicitInstantiationDeclaration:
+ case TSK_ExplicitInstantiationDefinition:
+ break;
+
+ case TSK_ExplicitSpecialization:
+ break;
+ }
+ }
+
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FunctionTemplateDecl, {
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+
+ // By default, we do not traverse the instantiations of
+ // function templates since they do not appear in the user code. The
+ // following code optionally traverses them.
+ //
+ // We only traverse the function instantiations when we see the canonical
+ // declaration of the template, to ensure we only visit them once.
+ if (getDerived().shouldVisitTemplateInstantiations() &&
+ D == D->getCanonicalDecl())
+ TRY_TO(TraverseFunctionInstantiations(D));
+ })
+
+DEF_TRAVERSE_DECL(TemplateTemplateParmDecl, {
+ // D is the "T" in something like
+ // template <template <typename> class T> class container { };
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ if (D->hasDefaultArgument()) {
+ TRY_TO(TraverseTemplateArgumentLoc(D->getDefaultArgument()));
+ }
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+ })
+
+DEF_TRAVERSE_DECL(TemplateTypeParmDecl, {
+ // D is the "T" in something like "template<typename T> class vector;"
+ if (D->getTypeForDecl())
+ TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+ if (D->hasDefaultArgument())
+ TRY_TO(TraverseTypeLoc(D->getDefaultArgumentInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_DECL(TypedefDecl, {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the typedef, not something that was written in the
+ // source.
+ })
+
+DEF_TRAVERSE_DECL(TypeAliasDecl, {
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type alias, not something that was written in the
+ // source.
+ })
+
+DEF_TRAVERSE_DECL(TypeAliasTemplateDecl, {
+ TRY_TO(TraverseDecl(D->getTemplatedDecl()));
+ TRY_TO(TraverseTemplateParameterListHelper(D->getTemplateParameters()));
+ })
+
+DEF_TRAVERSE_DECL(UnresolvedUsingTypenameDecl, {
+ // A dependent using declaration which was marked with 'typename'.
+ // template<class T> class A : public B<T> { using typename B<T>::foo; };
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type, not something that was written in the
+ // source.
+ })
+
+DEF_TRAVERSE_DECL(EnumDecl, {
+ if (D->getTypeForDecl())
+ TRY_TO(TraverseType(QualType(D->getTypeForDecl(), 0)));
+
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ // The enumerators are already traversed by
+ // decls_begin()/decls_end().
+ })
+
+
+// Helper methods for RecordDecl and its children.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseRecordHelper(
+ RecordDecl *D) {
+ // We shouldn't traverse D->getTypeForDecl(); it's a result of
+ // declaring the type, not something that was written in the source.
+
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ return true;
+}
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseCXXRecordHelper(
+ CXXRecordDecl *D) {
+ if (!TraverseRecordHelper(D))
+ return false;
+ if (D->isCompleteDefinition()) {
+ for (CXXRecordDecl::base_class_iterator I = D->bases_begin(),
+ E = D->bases_end();
+ I != E; ++I) {
+ TRY_TO(TraverseTypeLoc(I->getTypeSourceInfo()->getTypeLoc()));
+ }
+ // We don't traverse the friends or the conversions, as they are
+ // already in decls_begin()/decls_end().
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(RecordDecl, {
+ TRY_TO(TraverseRecordHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(CXXRecordDecl, {
+ TRY_TO(TraverseCXXRecordHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(ClassTemplateSpecializationDecl, {
+ // For implicit instantiations ("set<int> x;"), we don't want to
+ // recurse at all, since the instatiated class isn't written in
+ // the source code anywhere. (Note the instatiated *type* --
+ // set<int> -- is written, and will still get a callback of
+ // TemplateSpecializationType). For explicit instantiations
+ // ("template set<int>;"), we do need a callback, since this
+ // is the only callback that's made for this instantiation.
+ // We use getTypeAsWritten() to distinguish.
+ if (TypeSourceInfo *TSI = D->getTypeAsWritten())
+ TRY_TO(TraverseTypeLoc(TSI->getTypeLoc()));
+
+ if (!getDerived().shouldVisitTemplateInstantiations() &&
+ D->getTemplateSpecializationKind() != TSK_ExplicitSpecialization)
+ // Returning from here skips traversing the
+ // declaration context of the ClassTemplateSpecializationDecl
+ // (embedded in the DEF_TRAVERSE_DECL() macro)
+ // which contains the instantiated members of the class.
+ return true;
+ })
+
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseTemplateArgumentLocsHelper(
+ const TemplateArgumentLoc *TAL, unsigned Count) {
+ for (unsigned I = 0; I < Count; ++I) {
+ TRY_TO(TraverseTemplateArgumentLoc(TAL[I]));
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(ClassTemplatePartialSpecializationDecl, {
+ // The partial specialization.
+ if (TemplateParameterList *TPL = D->getTemplateParameters()) {
+ for (TemplateParameterList::iterator I = TPL->begin(), E = TPL->end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ }
+ // The args that remains unspecialized.
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ D->getTemplateArgsAsWritten(), D->getNumTemplateArgsAsWritten()));
+
+ // Don't need the ClassTemplatePartialSpecializationHelper, even
+ // though that's our parent class -- we already visit all the
+ // template args here.
+ TRY_TO(TraverseCXXRecordHelper(D));
+
+ // Instantiations will have been visited with the primary template.
+ })
+
+DEF_TRAVERSE_DECL(EnumConstantDecl, {
+ TRY_TO(TraverseStmt(D->getInitExpr()));
+ })
+
+DEF_TRAVERSE_DECL(UnresolvedUsingValueDecl, {
+ // Like UnresolvedUsingTypenameDecl, but without the 'typename':
+ // template <class T> Class A : public Base<T> { using Base<T>::foo; };
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+ })
+
+DEF_TRAVERSE_DECL(IndirectFieldDecl, {})
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseDeclaratorHelper(DeclaratorDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ if (D->getTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+ else
+ TRY_TO(TraverseType(D->getType()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FieldDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ else if (D->hasInClassInitializer())
+ TRY_TO(TraverseStmt(D->getInClassInitializer()));
+ })
+
+DEF_TRAVERSE_DECL(ObjCAtDefsFieldDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ // FIXME: implement the rest.
+ })
+
+DEF_TRAVERSE_DECL(ObjCIvarDecl, {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ if (D->isBitField())
+ TRY_TO(TraverseStmt(D->getBitWidth()));
+ // FIXME: implement the rest.
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseFunctionHelper(FunctionDecl *D) {
+ TRY_TO(TraverseNestedNameSpecifierLoc(D->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(D->getNameInfo()));
+
+ // If we're an explicit template specialization, iterate over the
+ // template args that were explicitly specified. If we were doing
+ // this in typing order, we'd do it between the return type and
+ // the function args, but both are handled by the FunctionTypeLoc
+ // above, so we have to choose one side. I've decided to do before.
+ if (const FunctionTemplateSpecializationInfo *FTSI =
+ D->getTemplateSpecializationInfo()) {
+ if (FTSI->getTemplateSpecializationKind() != TSK_Undeclared &&
+ FTSI->getTemplateSpecializationKind() != TSK_ImplicitInstantiation) {
+ // A specialization might not have explicit template arguments if it has
+ // a templated return type and concrete arguments.
+ if (const ASTTemplateArgumentListInfo *TALI =
+ FTSI->TemplateArgumentsAsWritten) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(TALI->getTemplateArgs(),
+ TALI->NumTemplateArgs));
+ }
+ }
+ }
+
+ // Visit the function type itself, which can be either
+ // FunctionNoProtoType or FunctionProtoType, or a typedef. This
+ // also covers the return type and the function parameters,
+ // including exception specifications.
+ TRY_TO(TraverseTypeLoc(D->getTypeSourceInfo()->getTypeLoc()));
+
+ if (CXXConstructorDecl *Ctor = dyn_cast<CXXConstructorDecl>(D)) {
+ // Constructor initializers.
+ for (CXXConstructorDecl::init_iterator I = Ctor->init_begin(),
+ E = Ctor->init_end();
+ I != E; ++I) {
+ TRY_TO(TraverseConstructorInitializer(*I));
+ }
+ }
+
+ if (D->isThisDeclarationADefinition()) {
+ TRY_TO(TraverseStmt(D->getBody())); // Function body.
+ }
+ return true;
+}
+
+DEF_TRAVERSE_DECL(FunctionDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXMethodDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXConstructorDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+// CXXConversionDecl is the declaration of a type conversion operator.
+// It's not a cast expression.
+DEF_TRAVERSE_DECL(CXXConversionDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+DEF_TRAVERSE_DECL(CXXDestructorDecl, {
+ // We skip decls_begin/decls_end, which are already covered by
+ // TraverseFunctionHelper().
+ return TraverseFunctionHelper(D);
+ })
+
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseVarHelper(VarDecl *D) {
+ TRY_TO(TraverseDeclaratorHelper(D));
+ // Default params are taken care of when we traverse the ParmVarDecl.
+ if (!isa<ParmVarDecl>(D))
+ TRY_TO(TraverseStmt(D->getInit()));
+ return true;
+}
+
+DEF_TRAVERSE_DECL(VarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(ImplicitParamDecl, {
+ TRY_TO(TraverseVarHelper(D));
+ })
+
+DEF_TRAVERSE_DECL(NonTypeTemplateParmDecl, {
+ // A non-type template parameter, e.g. "S" in template<int S> class Foo ...
+ TRY_TO(TraverseDeclaratorHelper(D));
+ TRY_TO(TraverseStmt(D->getDefaultArgument()));
+ })
+
+DEF_TRAVERSE_DECL(ParmVarDecl, {
+ TRY_TO(TraverseVarHelper(D));
+
+ if (D->hasDefaultArg() &&
+ D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getUninstantiatedDefaultArg()));
+
+ if (D->hasDefaultArg() &&
+ !D->hasUninstantiatedDefaultArg() &&
+ !D->hasUnparsedDefaultArg())
+ TRY_TO(TraverseStmt(D->getDefaultArg()));
+ })
+
+#undef DEF_TRAVERSE_DECL
+
+// ----------------- Stmt traversal -----------------
+//
+// For stmts, we automate (in the DEF_TRAVERSE_STMT macro) iterating
+// over the children defined in children() (every stmt defines these,
+// though sometimes the range is empty). Each individual Traverse*
+// method only needs to worry about children other than those. To see
+// what children() does for a given class, see, e.g.,
+// http://clang.llvm.org/doxygen/Stmt_8cpp_source.html
+
+// This macro makes available a variable S, the passed-in stmt.
+#define DEF_TRAVERSE_STMT(STMT, CODE) \
+template<typename Derived> \
+bool RecursiveASTVisitor<Derived>::Traverse##STMT (STMT *S) { \
+ TRY_TO(WalkUpFrom##STMT(S)); \
+ StmtQueueAction StmtQueue(*this); \
+ { CODE; } \
+ for (Stmt::child_range range = S->children(); range; ++range) { \
+ StmtQueue.queue(*range); \
+ } \
+ return true; \
+}
+
+DEF_TRAVERSE_STMT(AsmStmt, {
+ StmtQueue.queue(S->getAsmString());
+ for (unsigned I = 0, E = S->getNumInputs(); I < E; ++I) {
+ StmtQueue.queue(S->getInputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumOutputs(); I < E; ++I) {
+ StmtQueue.queue(S->getOutputConstraintLiteral(I));
+ }
+ for (unsigned I = 0, E = S->getNumClobbers(); I < E; ++I) {
+ StmtQueue.queue(S->getClobber(I));
+ }
+ // children() iterates over inputExpr and outputExpr.
+ })
+
+DEF_TRAVERSE_STMT(MSAsmStmt, {
+ // FIXME: MS Asm doesn't currently parse Constraints, Clobbers, etc. Once
+ // added this needs to be implemented.
+ })
+
+DEF_TRAVERSE_STMT(CXXCatchStmt, {
+ TRY_TO(TraverseDecl(S->getExceptionDecl()));
+ // children() iterates over the handler block.
+ })
+
+DEF_TRAVERSE_STMT(DeclStmt, {
+ for (DeclStmt::decl_iterator I = S->decl_begin(), E = S->decl_end();
+ I != E; ++I) {
+ TRY_TO(TraverseDecl(*I));
+ }
+ // Suppress the default iteration over children() by
+ // returning. Here's why: A DeclStmt looks like 'type var [=
+ // initializer]'. The decls above already traverse over the
+ // initializers, so we don't have to do it again (which
+ // children() would do).
+ return true;
+ })
+
+
+// These non-expr stmts (most of them), do not need any action except
+// iterating over the children.
+DEF_TRAVERSE_STMT(BreakStmt, { })
+DEF_TRAVERSE_STMT(CXXTryStmt, { })
+DEF_TRAVERSE_STMT(CaseStmt, { })
+DEF_TRAVERSE_STMT(CompoundStmt, { })
+DEF_TRAVERSE_STMT(ContinueStmt, { })
+DEF_TRAVERSE_STMT(DefaultStmt, { })
+DEF_TRAVERSE_STMT(DoStmt, { })
+DEF_TRAVERSE_STMT(ForStmt, { })
+DEF_TRAVERSE_STMT(GotoStmt, { })
+DEF_TRAVERSE_STMT(IfStmt, { })
+DEF_TRAVERSE_STMT(IndirectGotoStmt, { })
+DEF_TRAVERSE_STMT(LabelStmt, { })
+DEF_TRAVERSE_STMT(AttributedStmt, { })
+DEF_TRAVERSE_STMT(NullStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtCatchStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtFinallyStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtSynchronizedStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtThrowStmt, { })
+DEF_TRAVERSE_STMT(ObjCAtTryStmt, { })
+DEF_TRAVERSE_STMT(ObjCForCollectionStmt, { })
+DEF_TRAVERSE_STMT(ObjCAutoreleasePoolStmt, { })
+DEF_TRAVERSE_STMT(CXXForRangeStmt, { })
+DEF_TRAVERSE_STMT(MSDependentExistsStmt, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+})
+DEF_TRAVERSE_STMT(ReturnStmt, { })
+DEF_TRAVERSE_STMT(SwitchStmt, { })
+DEF_TRAVERSE_STMT(WhileStmt, { })
+
+
+DEF_TRAVERSE_STMT(CXXDependentScopeMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ }
+ })
+
+DEF_TRAVERSE_STMT(DeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ })
+
+DEF_TRAVERSE_STMT(DependentScopeDeclRefExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getNameInfo()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getExplicitTemplateArgs().getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+ })
+
+DEF_TRAVERSE_STMT(MemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ TRY_TO(TraverseDeclarationNameInfo(S->getMemberNameInfo()));
+ TRY_TO(TraverseTemplateArgumentLocsHelper(
+ S->getTemplateArgs(), S->getNumTemplateArgs()));
+ })
+
+DEF_TRAVERSE_STMT(ImplicitCastExpr, {
+ // We don't traverse the cast type, as it's not written in the
+ // source code.
+ })
+
+DEF_TRAVERSE_STMT(CStyleCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXFunctionalCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXConstCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXDynamicCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXReinterpretCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXStaticCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+ })
+
+// InitListExpr is a tricky one, because we want to do all our work on
+// the syntactic form of the listexpr, but this method takes the
+// semantic form by default. We can't use the macro helper because it
+// calls WalkUp*() on the semantic form, before our code can convert
+// to the syntactic form.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseInitListExpr(InitListExpr *S) {
+ if (InitListExpr *Syn = S->getSyntacticForm())
+ S = Syn;
+ TRY_TO(WalkUpFromInitListExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ // All we need are the default actions. FIXME: use a helper function.
+ for (Stmt::child_range range = S->children(); range; ++range) {
+ StmtQueue.queue(*range);
+ }
+ return true;
+}
+
+// GenericSelectionExpr is a special case because the types and expressions
+// are interleaved. We also need to watch out for null types (default
+// generic associations).
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::
+TraverseGenericSelectionExpr(GenericSelectionExpr *S) {
+ TRY_TO(WalkUpFromGenericSelectionExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(S->getControllingExpr());
+ for (unsigned i = 0; i != S->getNumAssocs(); ++i) {
+ if (TypeSourceInfo *TS = S->getAssocTypeSourceInfo(i))
+ TRY_TO(TraverseTypeLoc(TS->getTypeLoc()));
+ StmtQueue.queue(S->getAssocExpr(i));
+ }
+ return true;
+}
+
+// PseudoObjectExpr is a special case because of the wierdness with
+// syntactic expressions and opaque values.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::
+TraversePseudoObjectExpr(PseudoObjectExpr *S) {
+ TRY_TO(WalkUpFromPseudoObjectExpr(S));
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(S->getSyntacticForm());
+ for (PseudoObjectExpr::semantics_iterator
+ i = S->semantics_begin(), e = S->semantics_end(); i != e; ++i) {
+ Expr *sub = *i;
+ if (OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(sub))
+ sub = OVE->getSourceExpr();
+ StmtQueue.queue(sub);
+ }
+ return true;
+}
+
+DEF_TRAVERSE_STMT(CXXScalarValueInitExpr, {
+ // This is called for code like 'return T()' where T is a built-in
+ // (i.e. non-class) type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXNewExpr, {
+ // The child-iterator will pick up the other arguments.
+ TRY_TO(TraverseTypeLoc(S->getAllocatedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(OffsetOfExpr, {
+ // The child-iterator will pick up the expression representing
+ // the field.
+ // FIMXE: for code like offsetof(Foo, a.b.c), should we get
+ // making a MemberExpr callbacks for Foo.a, Foo.a.b, and Foo.a.b.c?
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(UnaryExprOrTypeTraitExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isArgumentType())
+ TRY_TO(TraverseTypeLoc(S->getArgumentTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTypeidExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXUuidofExpr, {
+ // The child-iterator will pick up the arg if it's an expression,
+ // but not if it's a type.
+ if (S->isTypeOperand())
+ TRY_TO(TraverseTypeLoc(S->getTypeOperandSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(UnaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(BinaryTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getLhsTypeSourceInfo()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getRhsTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(TypeTraitExpr, {
+ for (unsigned I = 0, N = S->getNumArgs(); I != N; ++I)
+ TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
+})
+
+DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
+ TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(ExpressionTraitExpr, {
+ StmtQueue.queue(S->getQueriedExpression());
+ })
+
+DEF_TRAVERSE_STMT(VAArgExpr, {
+ // The child-iterator will pick up the expression argument.
+ TRY_TO(TraverseTypeLoc(S->getWrittenTypeInfo()->getTypeLoc()));
+ })
+
+DEF_TRAVERSE_STMT(CXXTemporaryObjectExpr, {
+ // This is called for code like 'return T()' where T is a class type.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+// Walk only the visible parts of lambda expressions.
+template<typename Derived>
+bool RecursiveASTVisitor<Derived>::TraverseLambdaExpr(LambdaExpr *S) {
+ for (LambdaExpr::capture_iterator C = S->explicit_capture_begin(),
+ CEnd = S->explicit_capture_end();
+ C != CEnd; ++C) {
+ TRY_TO(TraverseLambdaCapture(*C));
+ }
+
+ if (S->hasExplicitParameters() || S->hasExplicitResultType()) {
+ TypeLoc TL = S->getCallOperator()->getTypeSourceInfo()->getTypeLoc();
+ if (S->hasExplicitParameters() && S->hasExplicitResultType()) {
+ // Visit the whole type.
+ TRY_TO(TraverseTypeLoc(TL));
+ } else if (isa<FunctionProtoTypeLoc>(TL)) {
+ FunctionProtoTypeLoc Proto = cast<FunctionProtoTypeLoc>(TL);
+ if (S->hasExplicitParameters()) {
+ // Visit parameters.
+ for (unsigned I = 0, N = Proto.getNumArgs(); I != N; ++I) {
+ TRY_TO(TraverseDecl(Proto.getArg(I)));
+ }
+ } else {
+ TRY_TO(TraverseTypeLoc(Proto.getResultLoc()));
+ }
+ }
+ }
+
+ StmtQueueAction StmtQueue(*this);
+ StmtQueue.queue(S->getBody());
+ return true;
+}
+
+DEF_TRAVERSE_STMT(CXXUnresolvedConstructExpr, {
+ // This is called for code like 'T()', where T is a template argument.
+ TRY_TO(TraverseTypeLoc(S->getTypeSourceInfo()->getTypeLoc()));
+ })
+
+// These expressions all might take explicit template arguments.
+// We traverse those if so. FIXME: implement these.
+DEF_TRAVERSE_STMT(CXXConstructExpr, { })
+DEF_TRAVERSE_STMT(CallExpr, { })
+DEF_TRAVERSE_STMT(CXXMemberCallExpr, { })
+
+// These exprs (most of them), do not need any action except iterating
+// over the children.
+DEF_TRAVERSE_STMT(AddrLabelExpr, { })
+DEF_TRAVERSE_STMT(ArraySubscriptExpr, { })
+DEF_TRAVERSE_STMT(BlockExpr, {
+ TRY_TO(TraverseDecl(S->getBlockDecl()));
+ return true; // no child statements to loop through.
+})
+DEF_TRAVERSE_STMT(ChooseExpr, { })
+DEF_TRAVERSE_STMT(CompoundLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXBindTemporaryExpr, { })
+DEF_TRAVERSE_STMT(CXXBoolLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXDefaultArgExpr, { })
+DEF_TRAVERSE_STMT(CXXDeleteExpr, { })
+DEF_TRAVERSE_STMT(ExprWithCleanups, { })
+DEF_TRAVERSE_STMT(CXXNullPtrLiteralExpr, { })
+DEF_TRAVERSE_STMT(CXXPseudoDestructorExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ if (TypeSourceInfo *ScopeInfo = S->getScopeTypeInfo())
+ TRY_TO(TraverseTypeLoc(ScopeInfo->getTypeLoc()));
+ if (TypeSourceInfo *DestroyedTypeInfo = S->getDestroyedTypeInfo())
+ TRY_TO(TraverseTypeLoc(DestroyedTypeInfo->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(CXXThisExpr, { })
+DEF_TRAVERSE_STMT(CXXThrowExpr, { })
+DEF_TRAVERSE_STMT(UserDefinedLiteral, { })
+DEF_TRAVERSE_STMT(DesignatedInitExpr, { })
+DEF_TRAVERSE_STMT(ExtVectorElementExpr, { })
+DEF_TRAVERSE_STMT(GNUNullExpr, { })
+DEF_TRAVERSE_STMT(ImplicitValueInitExpr, { })
+DEF_TRAVERSE_STMT(ObjCBoolLiteralExpr, { })
+DEF_TRAVERSE_STMT(ObjCEncodeExpr, {
+ if (TypeSourceInfo *TInfo = S->getEncodedTypeSourceInfo())
+ TRY_TO(TraverseTypeLoc(TInfo->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(ObjCIsaExpr, { })
+DEF_TRAVERSE_STMT(ObjCIvarRefExpr, { })
+DEF_TRAVERSE_STMT(ObjCMessageExpr, { })
+DEF_TRAVERSE_STMT(ObjCPropertyRefExpr, { })
+DEF_TRAVERSE_STMT(ObjCSubscriptRefExpr, { })
+DEF_TRAVERSE_STMT(ObjCProtocolExpr, { })
+DEF_TRAVERSE_STMT(ObjCSelectorExpr, { })
+DEF_TRAVERSE_STMT(ObjCIndirectCopyRestoreExpr, { })
+DEF_TRAVERSE_STMT(ObjCBridgedCastExpr, {
+ TRY_TO(TraverseTypeLoc(S->getTypeInfoAsWritten()->getTypeLoc()));
+})
+DEF_TRAVERSE_STMT(ParenExpr, { })
+DEF_TRAVERSE_STMT(ParenListExpr, { })
+DEF_TRAVERSE_STMT(PredefinedExpr, { })
+DEF_TRAVERSE_STMT(ShuffleVectorExpr, { })
+DEF_TRAVERSE_STMT(StmtExpr, { })
+DEF_TRAVERSE_STMT(UnresolvedLookupExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(UnresolvedMemberExpr, {
+ TRY_TO(TraverseNestedNameSpecifierLoc(S->getQualifierLoc()));
+ if (S->hasExplicitTemplateArgs()) {
+ TRY_TO(TraverseTemplateArgumentLocsHelper(S->getTemplateArgs(),
+ S->getNumTemplateArgs()));
+ }
+})
+
+DEF_TRAVERSE_STMT(SEHTryStmt, {})
+DEF_TRAVERSE_STMT(SEHExceptStmt, {})
+DEF_TRAVERSE_STMT(SEHFinallyStmt,{})
+
+DEF_TRAVERSE_STMT(CXXOperatorCallExpr, { })
+DEF_TRAVERSE_STMT(OpaqueValueExpr, { })
+DEF_TRAVERSE_STMT(CUDAKernelCallExpr, { })
+
+// These operators (all of them) do not need any action except
+// iterating over the children.
+DEF_TRAVERSE_STMT(BinaryConditionalOperator, { })
+DEF_TRAVERSE_STMT(ConditionalOperator, { })
+DEF_TRAVERSE_STMT(UnaryOperator, { })
+DEF_TRAVERSE_STMT(BinaryOperator, { })
+DEF_TRAVERSE_STMT(CompoundAssignOperator, { })
+DEF_TRAVERSE_STMT(CXXNoexceptExpr, { })
+DEF_TRAVERSE_STMT(PackExpansionExpr, { })
+DEF_TRAVERSE_STMT(SizeOfPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmPackExpr, { })
+DEF_TRAVERSE_STMT(SubstNonTypeTemplateParmExpr, { })
+DEF_TRAVERSE_STMT(MaterializeTemporaryExpr, { })
+DEF_TRAVERSE_STMT(AtomicExpr, { })
+
+// These literals (all of them) do not need any action.
+DEF_TRAVERSE_STMT(IntegerLiteral, { })
+DEF_TRAVERSE_STMT(CharacterLiteral, { })
+DEF_TRAVERSE_STMT(FloatingLiteral, { })
+DEF_TRAVERSE_STMT(ImaginaryLiteral, { })
+DEF_TRAVERSE_STMT(StringLiteral, { })
+DEF_TRAVERSE_STMT(ObjCStringLiteral, { })
+DEF_TRAVERSE_STMT(ObjCBoxedExpr, { })
+DEF_TRAVERSE_STMT(ObjCArrayLiteral, { })
+DEF_TRAVERSE_STMT(ObjCDictionaryLiteral, { })
+
+// Traverse OpenCL: AsType, Convert.
+DEF_TRAVERSE_STMT(AsTypeExpr, { })
+
+// FIXME: look at the following tricky-seeming exprs to see if we
+// need to recurse on anything. These are ones that have methods
+// returning decls or qualtypes or nestednamespecifier -- though I'm
+// not sure if they own them -- or just seemed very complicated, or
+// had lots of sub-types to explore.
+//
+// VisitOverloadExpr and its children: recurse on template args? etc?
+
+// FIXME: go through all the stmts and exprs again, and see which of them
+// create new types, and recurse on the types (TypeLocs?) of those.
+// Candidates:
+//
+// http://clang.llvm.org/doxygen/classclang_1_1CXXTypeidExpr.html
+// http://clang.llvm.org/doxygen/classclang_1_1UnaryExprOrTypeTraitExpr.html
+// http://clang.llvm.org/doxygen/classclang_1_1TypesCompatibleExpr.html
+// Every class that has getQualifier.
+
+#undef DEF_TRAVERSE_STMT
+
+#undef TRY_TO
+
+} // end namespace cxindex
+} // end namespace clang
+
+#endif // LLVM_CLANG_LIBCLANG_RECURSIVEASTVISITOR_H
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index d3b64db..610bd91 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -5,14 +5,52 @@ clang_CXIndex_setGlobalOptions
clang_CXXMethod_isStatic
clang_CXXMethod_isVirtual
clang_Cursor_getArgument
+clang_Cursor_getBriefCommentText
+clang_Cursor_getCommentRange
+clang_Cursor_getParsedComment
+clang_Cursor_getRawCommentText
clang_Cursor_getNumArguments
clang_Cursor_getObjCSelectorIndex
clang_Cursor_getSpellingNameRange
clang_Cursor_getTranslationUnit
+clang_Cursor_isDynamicCall
clang_Cursor_isNull
clang_IndexAction_create
clang_IndexAction_dispose
clang_Range_isNull
+clang_Comment_getKind
+clang_Comment_getNumChildren
+clang_Comment_getChild
+clang_Comment_isWhitespace
+clang_InlineContentComment_hasTrailingNewline
+clang_TextComment_getText
+clang_InlineCommandComment_getCommandName
+clang_InlineCommandComment_getRenderKind
+clang_InlineCommandComment_getNumArgs
+clang_InlineCommandComment_getArgText
+clang_HTMLTagComment_getTagName
+clang_HTMLStartTagComment_isSelfClosing
+clang_HTMLStartTag_getNumAttrs
+clang_HTMLStartTag_getAttrName
+clang_HTMLStartTag_getAttrValue
+clang_BlockCommandComment_getCommandName
+clang_BlockCommandComment_getNumArgs
+clang_BlockCommandComment_getArgText
+clang_BlockCommandComment_getParagraph
+clang_ParamCommandComment_getParamName
+clang_ParamCommandComment_isParamIndexValid
+clang_ParamCommandComment_getParamIndex
+clang_ParamCommandComment_isDirectionExplicit
+clang_ParamCommandComment_getDirection
+clang_TParamCommandComment_getParamName
+clang_TParamCommandComment_isParamPositionValid
+clang_TParamCommandComment_getDepth
+clang_TParamCommandComment_getIndex
+clang_VerbatimBlockLineComment_getText
+clang_VerbatimLineComment_getText
+clang_HTMLTagComment_getAsString
+clang_FullComment_getAsHTML
+clang_FullComment_getAsXML
clang_annotateTokens
clang_codeCompleteAt
clang_codeCompleteGetContainerKind
@@ -43,6 +81,7 @@ clang_disposeDiagnostic
clang_disposeDiagnosticSet
clang_disposeIndex
clang_disposeOverriddenCursors
+clang_disposeCXPlatformAvailability
clang_disposeString
clang_disposeTokens
clang_disposeTranslationUnit
@@ -67,6 +106,7 @@ clang_getChildDiagnostics
clang_getClangVersion
clang_getCompletionAnnotation
clang_getCompletionAvailability
+clang_getCompletionBriefComment
clang_getCompletionChunkCompletionString
clang_getCompletionChunkKind
clang_getCompletionChunkText
@@ -85,6 +125,7 @@ clang_getCursorLanguage
clang_getCursorLexicalParent
clang_getCursorLinkage
clang_getCursorLocation
+clang_getCursorPlatformAvailability
clang_getCursorReferenceNameRange
clang_getCursorReferenced
clang_getCursorResultType
@@ -199,5 +240,14 @@ clang_saveTranslationUnit
clang_sortCodeCompletionResults
clang_toggleCrashRecovery
clang_tokenize
+clang_CompilationDatabase_fromDirectory
+clang_CompilationDatabase_dispose
+clang_CompilationDatabase_getCompileCommands
+clang_CompileCommands_dispose
+clang_CompileCommands_getSize
+clang_CompileCommands_getCommand
+clang_CompileCommand_getDirectory
+clang_CompileCommand_getNumArgs
+clang_CompileCommand_getArg
clang_visitChildren
clang_visitChildrenWithBlock
OpenPOWER on IntegriCloud