blob: 1d1272b379cd6c130337a8588afd7c43c556a60a [file] [log] [blame] [edit]
///////////////////////////////////////////////////////////////////////////////
// //
// CompilationResult.h //
// Copyright (C) Microsoft Corporation. All rights reserved. //
// This file is distributed under the University of Illinois Open Source //
// License. See LICENSE.TXT for details. //
// //
// This file provides a class to parse a translation unit and return the //
// diagnostic results and AST tree. //
// //
///////////////////////////////////////////////////////////////////////////////
#include <algorithm>
#include <atomic>
#include <cassert>
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
#include <vector>
#include "dxc/Support/WinIncludes.h"
#include "dxc/Support/microcom.h"
#include "dxc/Support/dxcapi.use.h"
#include "dxc/dxcapi.h"
#include "dxc/dxcisense.h"
#include "llvm/Support/Atomic.h"
inline HRESULT IFE(HRESULT hr) {
if (FAILED(hr)) {
throw std::runtime_error("COM call failed");
}
return hr;
}
inline HRESULT GetFirstChildFromCursor(IDxcCursor *cursor,
IDxcCursor **pResult) {
HRESULT hr;
IDxcCursor **children = nullptr;
unsigned childrenCount;
hr = cursor->GetChildren(0, 1, &childrenCount, &children);
if (SUCCEEDED(hr) && childrenCount == 1) {
*pResult = children[0];
} else {
*pResult = nullptr;
hr = E_FAIL;
}
CoTaskMemFree(children);
return hr;
}
class TrivialDxcUnsavedFile : public IDxcUnsavedFile {
private:
DXC_MICROCOM_REF_FIELD(m_dwRef)
LPCSTR m_fileName;
LPCSTR m_contents;
unsigned m_length;
public:
DXC_MICROCOM_ADDREF_RELEASE_IMPL(m_dwRef)
TrivialDxcUnsavedFile(LPCSTR fileName, LPCSTR contents)
: m_dwRef(0), m_fileName(fileName), m_contents(contents) {
m_length = (unsigned)strlen(m_contents);
}
static HRESULT Create(LPCSTR fileName, LPCSTR contents,
IDxcUnsavedFile **pResult) {
CComPtr<TrivialDxcUnsavedFile> pNewValue =
new TrivialDxcUnsavedFile(fileName, contents);
return pNewValue.QueryInterface(pResult);
}
HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid,
void **ppvObject) override {
if (ppvObject == nullptr)
return E_POINTER;
if (IsEqualIID(iid, __uuidof(IUnknown)) ||
IsEqualIID(iid, __uuidof(INoMarshal)) ||
IsEqualIID(iid, __uuidof(IDxcUnsavedFile))) {
*ppvObject = reinterpret_cast<IDxcUnsavedFile *>(this);
reinterpret_cast<IDxcUnsavedFile *>(this)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
HRESULT STDMETHODCALLTYPE GetFileName(LPSTR *pFileName) override {
*pFileName = (LPSTR)CoTaskMemAlloc(1 + strlen(m_fileName));
strcpy(*pFileName, m_fileName);
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetContents(LPSTR *pContents) override {
*pContents = (LPSTR)CoTaskMemAlloc(m_length + 1);
memcpy(*pContents, m_contents, m_length + 1);
return S_OK;
}
HRESULT STDMETHODCALLTYPE GetLength(unsigned *pLength) override {
*pLength = m_length;
return S_OK;
}
};
class HlslIntellisenseSupport : public dxc::DxcDllSupport {
public:
HlslIntellisenseSupport() {}
HlslIntellisenseSupport(HlslIntellisenseSupport &&other)
: dxc::DxcDllSupport(std::move(other)) {}
HRESULT CreateIntellisense(IDxcIntelliSense **pResult) {
return CreateInstance(CLSID_DxcIntelliSense, pResult);
}
};
/// Summary of the results of a clang compilation operation.
class CompilationResult {
private:
// Keep Intellisense alive.
std::shared_ptr<HlslIntellisenseSupport> IsenseSupport;
/// The top-level Intellisense object.
CComPtr<IDxcIntelliSense> Intellisense;
/// The libclang index for the compilation operation.
CComPtr<IDxcIndex> Index;
/// The number of diagnostic messages emitted.
unsigned NumDiagnostics;
/// The number of diagnostic messages emitted that indicate errors.
unsigned NumErrorDiagnostics;
/// The diagnostic messages emitted.
std::vector<std::string> DiagnosticMessages;
/// The severity of diagnostic messages.
std::vector<DxcDiagnosticSeverity> DiagnosticSeverities;
// Hide the copy constructor.
CompilationResult(const CompilationResult &);
public:
CompilationResult(std::shared_ptr<HlslIntellisenseSupport> support,
IDxcIntelliSense *isense, IDxcIndex *index,
IDxcTranslationUnit *tu)
: IsenseSupport(support), Intellisense(isense), Index(index),
NumErrorDiagnostics(0), TU(tu) {
if (tu) {
IFE(tu->GetNumDiagnostics(&NumDiagnostics));
} else {
NumDiagnostics = 0;
}
DxcDiagnosticDisplayOptions diagnosticOptions;
IFE(isense->GetDefaultDiagnosticDisplayOptions(&diagnosticOptions));
for (unsigned i = 0; i < NumDiagnostics; i++) {
CComPtr<IDxcDiagnostic> diagnostic;
IFE(tu->GetDiagnostic(i, &diagnostic));
LPSTR format;
IFE(diagnostic->FormatDiagnostic(diagnosticOptions, &format));
DiagnosticMessages.push_back(std::string(format));
CoTaskMemFree(format);
DxcDiagnosticSeverity severity;
IFE(diagnostic->GetSeverity(&severity));
DiagnosticSeverities.push_back(severity);
if (IsErrorSeverity(severity)) {
NumErrorDiagnostics++;
}
}
assert(NumErrorDiagnostics <= NumDiagnostics &&
"else counting code in loop is incorrect");
assert(DiagnosticMessages.size() == NumDiagnostics &&
"else some diagnostics have no message");
assert(DiagnosticSeverities.size() == NumDiagnostics &&
"else some diagnostics have no severity");
}
CompilationResult(CompilationResult &&other)
: IsenseSupport(std::move(other.IsenseSupport)) {
// Allow move constructor.
Intellisense = other.Intellisense;
other.Intellisense = nullptr;
Index = other.Index;
other.Index = nullptr;
TU = other.TU;
other.TU = nullptr;
NumDiagnostics = other.NumDiagnostics;
NumErrorDiagnostics = other.NumErrorDiagnostics;
DiagnosticMessages = std::move(other.DiagnosticMessages);
DiagnosticSeverities = std::move(other.DiagnosticSeverities);
}
~CompilationResult() { Dispose(); }
/// The translation unit resulting from the compilation.
CComPtr<IDxcTranslationUnit> TU;
static const char *getDefaultFileName() { return "filename.hlsl"; }
static std::shared_ptr<HlslIntellisenseSupport> DefaultHlslSupport;
static std::shared_ptr<HlslIntellisenseSupport> GetHlslSupport() {
if (DefaultHlslSupport.get() != nullptr) {
return DefaultHlslSupport;
}
std::shared_ptr<HlslIntellisenseSupport> result =
std::make_shared<HlslIntellisenseSupport>();
IFE(result->Initialize());
return result;
}
static CompilationResult
CreateForProgramAndArgs(const char *text, size_t textLen,
const char *commandLineArgs[],
unsigned commandLineArgsCount,
DxcTranslationUnitFlags *options = nullptr) {
std::shared_ptr<HlslIntellisenseSupport> support(GetHlslSupport());
CComPtr<IDxcIntelliSense> isense;
IFE(support->CreateIntellisense(&isense));
CComPtr<IDxcIndex> tuIndex;
CComPtr<IDxcTranslationUnit> tu;
const char *fileName = getDefaultFileName();
if (textLen == 0)
textLen = strlen(text);
IFE(isense->CreateIndex(&tuIndex));
CComPtr<IDxcUnsavedFile> unsavedFile;
IFE(TrivialDxcUnsavedFile::Create(fileName, text, &unsavedFile));
DxcTranslationUnitFlags localOptions;
if (options == nullptr) {
IFE(isense->GetDefaultEditingTUOptions(&localOptions));
} else {
localOptions = *options;
}
IFE(tuIndex->ParseTranslationUnit(fileName, commandLineArgs,
commandLineArgsCount, &(unsavedFile.p), 1,
localOptions, &tu));
return CompilationResult(support, isense.p, tuIndex.p, tu.p);
}
static CompilationResult
CreateForProgram(const char *text, size_t textLen,
DxcTranslationUnitFlags *options = nullptr) {
const char *commandLineArgs[] = {"-c", "-ferror-limit=200"};
unsigned commandLineArgsCount = _countof(commandLineArgs);
return CreateForProgramAndArgs(text, textLen, commandLineArgs,
commandLineArgsCount, options);
}
static CompilationResult CreateForCommandLine(char *arguments,
const char *fileName) {
std::shared_ptr<HlslIntellisenseSupport> support(GetHlslSupport());
return CreateForCommandLine(arguments, fileName, support);
}
static CompilationResult
CreateForCommandLine(char *arguments, const char *fileName,
std::shared_ptr<HlslIntellisenseSupport> support) {
CComPtr<IDxcIntelliSense> isense;
IFE(support->CreateIntellisense(&isense));
CComPtr<IDxcIndex> tuIndex;
CComPtr<IDxcTranslationUnit> tu;
const char *commandLineArgs[32];
unsigned commandLineArgsCount = 0;
char *nextArg = arguments;
// Set a very high number of errors to avoid giving up too early.
commandLineArgs[commandLineArgsCount++] = "-ferror-limit=2000";
// Turn on spell checking for compatibility. This produces error messages
// that suggest corrected spellings.
commandLineArgs[commandLineArgsCount++] = "-fspell-checking";
// Turn off color diagnostics to avoid control characters in diagnostic
// stream.
commandLineArgs[commandLineArgsCount++] = "-fno-color-diagnostics";
IFE(isense->CreateIndex(&tuIndex));
// Split command line arguments by spaces
if (nextArg) {
// skip leading spaces
while (*nextArg == ' ')
nextArg++;
commandLineArgs[commandLineArgsCount++] = nextArg;
while ((*nextArg != '\0')) {
if (*nextArg == ' ') {
*nextArg = 0;
commandLineArgs[commandLineArgsCount++] = nextArg + 1;
}
nextArg++;
}
}
DxcTranslationUnitFlags options;
IFE(isense->GetDefaultEditingTUOptions(&options));
IFE(tuIndex->ParseTranslationUnit(fileName, commandLineArgs,
commandLineArgsCount, nullptr, 0, options,
&tu));
return CompilationResult(support, isense.p, tuIndex.p, tu.p);
}
bool IsTUAvailable() const { return TU != nullptr; }
bool ParseSucceeded() const {
return TU != nullptr && NumErrorDiagnostics == 0;
}
static bool IsErrorSeverity(DxcDiagnosticSeverity severity) {
return (severity == DxcDiagnostic_Error || severity == DxcDiagnostic_Fatal);
}
/// Gets a string with all error messages concatenated, one per line.
std::string GetTextForErrors() const {
assert(DiagnosticMessages.size() == NumDiagnostics &&
"otherwise some diagnostics have no message");
assert(DiagnosticSeverities.size() == NumDiagnostics &&
"otherwise some diagnostics have no severity");
std::stringstream ostr;
for (size_t i = 0; i < DiagnosticMessages.size(); i++) {
if (IsErrorSeverity(DiagnosticSeverities[i])) {
ostr << DiagnosticMessages[i] << '\n';
}
}
return ostr.str();
}
/// Releases resources, including the translation unit AST.
void Dispose() {
TU = nullptr;
Index = nullptr;
Intellisense = nullptr;
IsenseSupport = nullptr;
}
private:
#if SUPPORTS_CURSOR_WALK
struct CursorStringData {
std::stringstream &ostr;
std::vector<CXCursor> cursors;
CursorStringData(std::stringstream &the_ostr) : ostr(the_ostr) {}
};
static CXChildVisitResult
AppendCursorStringCallback(CXCursor cursor, CXCursor parent,
CXClientData client_data) {
CursorStringData *d = (CursorStringData *)client_data;
auto cursorsStart = std::begin(d->cursors);
auto cursorsEnd = std::end(d->cursors);
auto parentLocation = std::find(cursorsStart, cursorsEnd, parent);
assert(parentLocation != cursorsEnd &&
"otherwise the parent was not visited previously");
AppendCursorString(cursor, parentLocation - cursorsStart, d->ostr);
d->cursors.resize(1 + (parentLocation - cursorsStart));
d->cursors.push_back(cursor);
return CXChildVisit_Recurse;
}
#endif
static void AppendCursorString(IDxcCursor *cursor, size_t indent,
std::stringstream &ostr) {
if (indent > 0) {
std::streamsize prior = ostr.width();
ostr.width(indent);
ostr << ' ';
ostr.width(prior);
}
CComPtr<IDxcType> type;
DxcCursorKind kind;
cursor->GetKind(&kind);
cursor->GetCursorType(&type);
switch (kind) {
case DxcCursor_UnexposedDecl:
ostr << "UnexposedDecl";
break;
case DxcCursor_StructDecl:
ostr << "StructDecl";
break;
case DxcCursor_UnionDecl:
ostr << "UnionDecl";
break;
case DxcCursor_ClassDecl:
ostr << "ClassDecl";
break;
case DxcCursor_EnumDecl:
ostr << "EnumDecl";
break;
case DxcCursor_FieldDecl:
ostr << "FieldDecl";
break;
case DxcCursor_EnumConstantDecl:
ostr << "EnumConstantDecl";
break;
case DxcCursor_FunctionDecl:
ostr << "FunctionDecl";
break;
case DxcCursor_VarDecl:
ostr << "VarDecl";
break;
case DxcCursor_ParmDecl:
ostr << "ParmDecl";
break;
case DxcCursor_ObjCInterfaceDecl:
ostr << "ObjCInterfaceDecl";
break;
case DxcCursor_ObjCCategoryDecl:
ostr << "ObjCCategoryDecl";
break;
case DxcCursor_ObjCProtocolDecl:
ostr << "ObjCProtocolDecl";
break;
case DxcCursor_ObjCPropertyDecl:
ostr << "ObjCPropertyDecl";
break;
case DxcCursor_ObjCIvarDecl:
ostr << "ObjCIvarDecl";
break;
case DxcCursor_ObjCInstanceMethodDecl:
ostr << "ObjCInstanceMethodDecl";
break;
case DxcCursor_ObjCClassMethodDecl:
ostr << "ObjCClassMethodDecl";
break;
case DxcCursor_ObjCImplementationDecl:
ostr << "ObjCImplementationDecl";
break;
case DxcCursor_ObjCCategoryImplDecl:
ostr << "ObjCCategoryImplDecl";
break;
case DxcCursor_TypedefDecl:
ostr << "TypedefDecl";
break;
case DxcCursor_CXXMethod:
ostr << "CXXMethod";
break;
case DxcCursor_Namespace:
ostr << "Namespace";
break;
case DxcCursor_LinkageSpec:
ostr << "LinkageSpec";
break;
case DxcCursor_Constructor:
ostr << "Constructor";
break;
case DxcCursor_Destructor:
ostr << "Destructor";
break;
case DxcCursor_ConversionFunction:
ostr << "ConversionFunction";
break;
case DxcCursor_TemplateTypeParameter:
ostr << "TemplateTypeParameter";
break;
case DxcCursor_NonTypeTemplateParameter:
ostr << "NonTypeTemplateParameter";
break;
case DxcCursor_TemplateTemplateParameter:
ostr << "TemplateTemplateParameter";
break;
case DxcCursor_FunctionTemplate:
ostr << "FunctionTemplate";
break;
case DxcCursor_ClassTemplate:
ostr << "ClassTemplate";
break;
case DxcCursor_ClassTemplatePartialSpecialization:
ostr << "ClassTemplatePartialSpecialization";
break;
case DxcCursor_NamespaceAlias:
ostr << "NamespaceAlias";
break;
case DxcCursor_UsingDirective:
ostr << "UsingDirective";
break;
case DxcCursor_UsingDeclaration:
ostr << "UsingDeclaration";
break;
case DxcCursor_TypeAliasDecl:
ostr << "TypeAliasDecl";
break;
case DxcCursor_ObjCSynthesizeDecl:
ostr << "ObjCSynthesizeDecl";
break;
case DxcCursor_ObjCDynamicDecl:
ostr << "ObjCDynamicDecl";
break;
case DxcCursor_CXXAccessSpecifier:
ostr << "CXXAccessSpecifier";
break;
case DxcCursor_ObjCSuperClassRef:
ostr << "ObjCSuperClassRef";
break;
case DxcCursor_ObjCProtocolRef:
ostr << "ObjCProtocolRef";
break;
case DxcCursor_ObjCClassRef:
ostr << "ObjCClassRef";
break;
case DxcCursor_TypeRef:
ostr << "TypeRef";
break;
case DxcCursor_CXXBaseSpecifier:
ostr << "CXXBaseSpecifier";
break;
case DxcCursor_TemplateRef:
ostr << "TemplateRef";
break;
case DxcCursor_NamespaceRef:
ostr << "NamespaceRef";
break;
case DxcCursor_MemberRef:
ostr << "MemberRef";
break;
case DxcCursor_LabelRef:
ostr << "LabelRef";
break;
case DxcCursor_OverloadedDeclRef:
ostr << "OverloadedDeclRef";
break;
case DxcCursor_VariableRef:
ostr << "VariableRef";
break;
case DxcCursor_InvalidFile:
ostr << "InvalidFile";
break;
case DxcCursor_NoDeclFound:
ostr << "NoDeclFound";
break;
case DxcCursor_NotImplemented:
ostr << "NotImplemented";
break;
case DxcCursor_InvalidCode:
ostr << "InvalidCode";
break;
case DxcCursor_UnexposedExpr:
ostr << "UnexposedExpr";
break;
case DxcCursor_DeclRefExpr:
ostr << "DeclRefExpr";
break;
case DxcCursor_MemberRefExpr:
ostr << "MemberRefExpr";
break;
case DxcCursor_CallExpr:
ostr << "CallExpr";
break;
case DxcCursor_ObjCMessageExpr:
ostr << "ObjCMessageExpr";
break;
case DxcCursor_BlockExpr:
ostr << "BlockExpr";
break;
case DxcCursor_IntegerLiteral:
ostr << "IntegerLiteral";
break;
case DxcCursor_FloatingLiteral:
ostr << "FloatingLiteral";
break;
case DxcCursor_ImaginaryLiteral:
ostr << "ImaginaryLiteral";
break;
case DxcCursor_StringLiteral:
ostr << "StringLiteral";
break;
case DxcCursor_CharacterLiteral:
ostr << "CharacterLiteral";
break;
case DxcCursor_ParenExpr:
ostr << "ParenExpr";
break;
case DxcCursor_UnaryOperator:
ostr << "UnaryOperator";
break;
case DxcCursor_ArraySubscriptExpr:
ostr << "ArraySubscriptExpr";
break;
case DxcCursor_BinaryOperator:
ostr << "BinaryOperator";
break;
case DxcCursor_CompoundAssignOperator:
ostr << "CompoundAssignOperator";
break;
case DxcCursor_ConditionalOperator:
ostr << "ConditionalOperator";
break;
case DxcCursor_CStyleCastExpr:
ostr << "CStyleCastExpr";
break;
case DxcCursor_CompoundLiteralExpr:
ostr << "CompoundLiteralExpr";
break;
case DxcCursor_InitListExpr:
ostr << "InitListExpr";
break;
case DxcCursor_AddrLabelExpr:
ostr << "AddrLabelExpr";
break;
case DxcCursor_StmtExpr:
ostr << "StmtExpr";
break;
case DxcCursor_GenericSelectionExpr:
ostr << "GenericSelectionExpr";
break;
case DxcCursor_GNUNullExpr:
ostr << "GNUNullExpr";
break;
case DxcCursor_CXXStaticCastExpr:
ostr << "CXXStaticCastExpr";
break;
case DxcCursor_CXXDynamicCastExpr:
ostr << "CXXDynamicCastExpr";
break;
case DxcCursor_CXXReinterpretCastExpr:
ostr << "CXXReinterpretCastExpr";
break;
case DxcCursor_CXXConstCastExpr:
ostr << "CXXConstCastExpr";
break;
case DxcCursor_CXXFunctionalCastExpr:
ostr << "CXXFunctionalCastExpr";
break;
case DxcCursor_CXXTypeidExpr:
ostr << "CXXTypeidExpr";
break;
case DxcCursor_CXXBoolLiteralExpr:
ostr << "CXXBoolLiteralExpr";
break;
case DxcCursor_CXXNullPtrLiteralExpr:
ostr << "CXXNullPtrLiteralExpr";
break;
case DxcCursor_CXXThisExpr:
ostr << "CXXThisExpr";
break;
case DxcCursor_CXXThrowExpr:
ostr << "CXXThrowExpr";
break;
case DxcCursor_CXXNewExpr:
ostr << "CXXNewExpr";
break;
case DxcCursor_CXXDeleteExpr:
ostr << "CXXDeleteExpr";
break;
case DxcCursor_UnaryExpr:
ostr << "UnaryExpr";
break;
case DxcCursor_ObjCStringLiteral:
ostr << "ObjCStringLiteral";
break;
case DxcCursor_ObjCEncodeExpr:
ostr << "ObjCEncodeExpr";
break;
case DxcCursor_ObjCSelectorExpr:
ostr << "ObjCSelectorExpr";
break;
case DxcCursor_ObjCProtocolExpr:
ostr << "ObjCProtocolExpr";
break;
case DxcCursor_ObjCBridgedCastExpr:
ostr << "ObjCBridgedCastExpr";
break;
case DxcCursor_PackExpansionExpr:
ostr << "PackExpansionExpr";
break;
case DxcCursor_SizeOfPackExpr:
ostr << "SizeOfPackExpr";
break;
case DxcCursor_LambdaExpr:
ostr << "LambdaExpr";
break;
case DxcCursor_ObjCBoolLiteralExpr:
ostr << "ObjCBoolLiteralExpr";
break;
case DxcCursor_ObjCSelfExpr:
ostr << "ObjCSelfExpr";
break;
case DxcCursor_UnexposedStmt:
ostr << "UnexposedStmt";
break;
case DxcCursor_LabelStmt:
ostr << "LabelStmt";
break;
case DxcCursor_CompoundStmt:
ostr << "CompoundStmt";
break;
case DxcCursor_CaseStmt:
ostr << "CaseStmt";
break;
case DxcCursor_DefaultStmt:
ostr << "DefaultStmt";
break;
case DxcCursor_IfStmt:
ostr << "IfStmt";
break;
case DxcCursor_SwitchStmt:
ostr << "SwitchStmt";
break;
case DxcCursor_WhileStmt:
ostr << "WhileStmt";
break;
case DxcCursor_DoStmt:
ostr << "DoStmt";
break;
case DxcCursor_ForStmt:
ostr << "ForStmt";
break;
case DxcCursor_GotoStmt:
ostr << "GotoStmt";
break;
case DxcCursor_IndirectGotoStmt:
ostr << "IndirectGotoStmt";
break;
case DxcCursor_ContinueStmt:
ostr << "ContinueStmt";
break;
case DxcCursor_BreakStmt:
ostr << "BreakStmt";
break;
case DxcCursor_ReturnStmt:
ostr << "ReturnStmt";
break;
case DxcCursor_GCCAsmStmt:
ostr << "GCCAsmStmt";
break;
case DxcCursor_ObjCAtTryStmt:
ostr << "ObjCAtTryStmt";
break;
case DxcCursor_ObjCAtCatchStmt:
ostr << "ObjCAtCatchStmt";
break;
case DxcCursor_ObjCAtFinallyStmt:
ostr << "ObjCAtFinallyStmt";
break;
case DxcCursor_ObjCAtThrowStmt:
ostr << "ObjCAtThrowStmt";
break;
case DxcCursor_ObjCAtSynchronizedStmt:
ostr << "ObjCAtSynchronizedStmt";
break;
case DxcCursor_ObjCAutoreleasePoolStmt:
ostr << "ObjCAutoreleasePoolStmt";
break;
case DxcCursor_ObjCForCollectionStmt:
ostr << "ObjCForCollectionStmt";
break;
case DxcCursor_CXXCatchStmt:
ostr << "CXXCatchStmt";
break;
case DxcCursor_CXXTryStmt:
ostr << "CXXTryStmt";
break;
case DxcCursor_CXXForRangeStmt:
ostr << "CXXForRangeStmt";
break;
case DxcCursor_SEHTryStmt:
ostr << "SEHTryStmt";
break;
case DxcCursor_SEHExceptStmt:
ostr << "SEHExceptStmt";
break;
case DxcCursor_SEHFinallyStmt:
ostr << "SEHFinallyStmt";
break;
case DxcCursor_MSAsmStmt:
ostr << "MSAsmStmt";
break;
case DxcCursor_NullStmt:
ostr << "NullStmt";
break;
case DxcCursor_DeclStmt:
ostr << "DeclStmt";
break;
case DxcCursor_OMPParallelDirective:
ostr << "OMPParallelDirective";
break;
case DxcCursor_TranslationUnit:
ostr << "TranslationUnit";
break;
case DxcCursor_UnexposedAttr:
ostr << "UnexposedAttr";
break;
#if 0
CXCursor_IBActionAttr = 401,
CXCursor_IBOutletAttr = 402,
CXCursor_IBOutletCollectionAttr = 403,
CXCursor_CXXFinalAttr = 404,
CXCursor_CXXOverrideAttr = 405,
CXCursor_AnnotateAttr = 406,
CXCursor_AsmLabelAttr = 407,
CXCursor_PackedAttr = 408,
/* Preprocessing */
CXCursor_PreprocessingDirective = 500,
CXCursor_MacroDefinition = 501,
CXCursor_MacroExpansion = 502,
CXCursor_InclusionDirective = 503,
case CXCursor_FunctionDecl:
break;
case CXCursor_ClassDecl:
ostr << "class decl";
break;
case CXCursor_TranslationUnit:
ostr << "translation unit";
break;
#endif
default:
ostr << "unknown/unhandled cursor kind " << kind;
break;
}
DxcTypeKind typeKind;
if (type != nullptr && SUCCEEDED(type->GetKind(&typeKind)) &&
typeKind != DxcTypeKind_Invalid) {
LPSTR name;
type->GetSpelling(&name);
ostr << " [type " << name << "]";
CoTaskMemFree(name);
}
ostr << '\n';
// Recurse.
IDxcCursor **children = nullptr;
unsigned childrenCount;
cursor->GetChildren(0, 64, &childrenCount, &children);
for (unsigned i = 0; i < childrenCount; i++) {
AppendCursorString(children[i], indent + 1, ostr);
children[i]->Release();
}
CoTaskMemFree(children);
}
public:
std::string BuildASTString() {
if (TU == nullptr) {
return "<failed to build - TU is null>";
}
CComPtr<IDxcCursor> cursor;
std::stringstream ostr;
this->TU->GetCursor(&cursor);
AppendCursorString(cursor, 0, ostr);
return ostr.str();
}
};