CompilationResult.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581
  1. ///////////////////////////////////////////////////////////////////////////////
  2. // //
  3. // CompilationResult.h //
  4. // Copyright (C) Microsoft Corporation. All rights reserved. //
  5. // This file is distributed under the University of Illinois Open Source //
  6. // License. See LICENSE.TXT for details. //
  7. // //
  8. // This file provides a class to parse a translation unit and return the //
  9. // diagnostic results and AST tree. //
  10. // //
  11. ///////////////////////////////////////////////////////////////////////////////
  12. #include <memory>
  13. #include <vector>
  14. #include <string>
  15. #include <iostream>
  16. #include <cassert>
  17. #include <sstream>
  18. #include <algorithm>
  19. #include <atomic>
  20. #include "dxc/Support/WinIncludes.h"
  21. #include "dxc/dxcapi.h"
  22. #include "dxc/dxcisense.h"
  23. #include "dxc/Support/dxcapi.use.h"
  24. #include "llvm/Support/Atomic.h"
  25. inline HRESULT IFE(HRESULT hr) {
  26. if (FAILED(hr)) {
  27. throw std::runtime_error("COM call failed");
  28. }
  29. return hr;
  30. }
  31. inline HRESULT GetFirstChildFromCursor(IDxcCursor *cursor,
  32. IDxcCursor **pResult) {
  33. HRESULT hr;
  34. IDxcCursor **children = nullptr;
  35. unsigned childrenCount;
  36. hr = cursor->GetChildren(0, 1, &childrenCount, &children);
  37. if (SUCCEEDED(hr) && childrenCount == 1) {
  38. *pResult = children[0];
  39. } else {
  40. *pResult = nullptr;
  41. hr = E_FAIL;
  42. }
  43. CoTaskMemFree(children);
  44. return hr;
  45. }
  46. class TrivialDxcUnsavedFile : IDxcUnsavedFile
  47. {
  48. private:
  49. volatile std::atomic<llvm::sys::cas_flag> m_dwRef;
  50. LPCSTR m_fileName;
  51. LPCSTR m_contents;
  52. unsigned m_length;
  53. public:
  54. TrivialDxcUnsavedFile(LPCSTR fileName, LPCSTR contents)
  55. : m_dwRef(0), m_fileName(fileName), m_contents(contents)
  56. {
  57. m_length = (unsigned)strlen(m_contents);
  58. }
  59. static HRESULT Create(LPCSTR fileName, LPCSTR contents, IDxcUnsavedFile** pResult)
  60. {
  61. CComPtr<TrivialDxcUnsavedFile> pNewValue = new TrivialDxcUnsavedFile(fileName, contents);
  62. return pNewValue.QueryInterface(pResult);
  63. }
  64. ULONG STDMETHODCALLTYPE AddRef() { return (ULONG)++m_dwRef; }
  65. ULONG STDMETHODCALLTYPE Release() {
  66. ULONG result = (ULONG)--m_dwRef;
  67. if (result == 0) delete this;
  68. return result;
  69. }
  70. HRESULT STDMETHODCALLTYPE QueryInterface(REFIID iid, void** ppvObject)
  71. {
  72. if (ppvObject == nullptr) return E_POINTER;
  73. if (IsEqualIID(iid, __uuidof(IUnknown)) ||
  74. IsEqualIID(iid, __uuidof(INoMarshal)) ||
  75. IsEqualIID(iid, __uuidof(IDxcUnsavedFile)))
  76. {
  77. *ppvObject = reinterpret_cast<IDxcUnsavedFile*>(this);
  78. reinterpret_cast<IDxcUnsavedFile*>(this)->AddRef();
  79. return S_OK;
  80. }
  81. return E_NOINTERFACE;
  82. }
  83. HRESULT STDMETHODCALLTYPE GetFileName(LPSTR* pFileName)
  84. {
  85. *pFileName = (LPSTR)CoTaskMemAlloc(1 + strlen(m_fileName));
  86. strcpy(*pFileName, m_fileName);
  87. return S_OK;
  88. }
  89. HRESULT STDMETHODCALLTYPE GetContents(LPSTR* pContents)
  90. {
  91. *pContents = (LPSTR)CoTaskMemAlloc(m_length + 1);
  92. memcpy(*pContents, m_contents, m_length + 1);
  93. return S_OK;
  94. }
  95. HRESULT STDMETHODCALLTYPE GetLength(unsigned* pLength)
  96. {
  97. *pLength = m_length;
  98. return S_OK;
  99. }
  100. };
  101. class HlslIntellisenseSupport : public dxc::DxcDllSupport {
  102. public:
  103. HlslIntellisenseSupport() {}
  104. HlslIntellisenseSupport(HlslIntellisenseSupport &&other)
  105. : dxc::DxcDllSupport(std::move(other)) {}
  106. HRESULT CreateIntellisense(_Outptr_ IDxcIntelliSense **pResult) {
  107. return CreateInstance(CLSID_DxcIntelliSense, pResult);
  108. }
  109. };
  110. /// Summary of the results of a clang compilation operation.
  111. class CompilationResult
  112. {
  113. private:
  114. // Keep Intellisense alive.
  115. std::shared_ptr<HlslIntellisenseSupport> IsenseSupport;
  116. /// The top-level Intellisense object.
  117. CComPtr<IDxcIntelliSense> Intellisense;
  118. /// The libclang index for the compilation operation.
  119. CComPtr<IDxcIndex> Index;
  120. /// The number of diagnostic messages emitted.
  121. unsigned NumDiagnostics;
  122. /// The number of diagnostic messages emitted that indicate errors.
  123. unsigned NumErrorDiagnostics;
  124. /// The diagnostic messages emitted.
  125. std::vector<std::string> DiagnosticMessages;
  126. /// The severity of diagnostic messages.
  127. std::vector<DxcDiagnosticSeverity> DiagnosticSeverities;
  128. // Hide the copy constructor.
  129. CompilationResult(const CompilationResult&);
  130. public:
  131. CompilationResult(std::shared_ptr<HlslIntellisenseSupport> support, IDxcIntelliSense* isense, IDxcIndex* index, IDxcTranslationUnit* tu) :
  132. IsenseSupport(support),
  133. Intellisense(isense),
  134. Index(index),
  135. NumErrorDiagnostics(0),
  136. TU(tu)
  137. {
  138. if (tu) {
  139. IFE(tu->GetNumDiagnostics(&NumDiagnostics));
  140. } else {
  141. NumDiagnostics = 0;
  142. }
  143. DxcDiagnosticDisplayOptions diagnosticOptions;
  144. IFE(isense->GetDefaultDiagnosticDisplayOptions(&diagnosticOptions));
  145. for (unsigned i = 0; i < NumDiagnostics; i++) {
  146. CComPtr<IDxcDiagnostic> diagnostic;
  147. IFE(tu->GetDiagnostic(i, &diagnostic));
  148. LPSTR format;
  149. IFE(diagnostic->FormatDiagnostic(diagnosticOptions, &format));
  150. DiagnosticMessages.push_back(std::string(format));
  151. CoTaskMemFree(format);
  152. DxcDiagnosticSeverity severity;
  153. IFE(diagnostic->GetSeverity(&severity));
  154. DiagnosticSeverities.push_back(severity);
  155. if (IsErrorSeverity(severity)) {
  156. NumErrorDiagnostics++;
  157. }
  158. }
  159. assert(NumErrorDiagnostics <= NumDiagnostics && "else counting code in loop is incorrect");
  160. assert(DiagnosticMessages.size() == NumDiagnostics && "else some diagnostics have no message");
  161. assert(DiagnosticSeverities.size() == NumDiagnostics && "else some diagnostics have no severity");
  162. }
  163. CompilationResult(CompilationResult&& other) :
  164. IsenseSupport(std::move(other.IsenseSupport)) {
  165. // Allow move constructor.
  166. Intellisense = other.Intellisense; other.Intellisense = nullptr;
  167. Index = other.Index; other.Index = nullptr;
  168. TU = other.TU; other.TU = nullptr;
  169. NumDiagnostics = other.NumDiagnostics;
  170. NumErrorDiagnostics = other.NumErrorDiagnostics;
  171. DiagnosticMessages = std::move(other.DiagnosticMessages);
  172. DiagnosticSeverities = std::move(other.DiagnosticSeverities);
  173. }
  174. ~CompilationResult() { Dispose(); }
  175. /// The translation unit resulting from the compilation.
  176. CComPtr<IDxcTranslationUnit> TU;
  177. static const char *getDefaultFileName() { return "filename.hlsl"; }
  178. static std::shared_ptr<HlslIntellisenseSupport> DefaultHlslSupport;
  179. static std::shared_ptr<HlslIntellisenseSupport> GetHlslSupport() {
  180. if (DefaultHlslSupport.get() != nullptr) {
  181. return DefaultHlslSupport;
  182. }
  183. std::shared_ptr<HlslIntellisenseSupport> result = std::make_shared<HlslIntellisenseSupport>();
  184. IFE(result->Initialize());
  185. return result;
  186. }
  187. static CompilationResult CreateForProgramAndArgs(const char* text, size_t textLen,
  188. _In_count_(commandLineArgsCount) const char* commandLineArgs[],
  189. unsigned commandLineArgsCount,
  190. _In_opt_ DxcTranslationUnitFlags* options = nullptr)
  191. {
  192. std::shared_ptr<HlslIntellisenseSupport> support(GetHlslSupport());
  193. CComPtr<IDxcIntelliSense> isense;
  194. IFE(support->CreateIntellisense(&isense));
  195. CComPtr<IDxcIndex> tuIndex;
  196. CComPtr<IDxcTranslationUnit> tu;
  197. const char *fileName = getDefaultFileName();
  198. if (textLen == 0) textLen = strlen(text);
  199. IFE(isense->CreateIndex(&tuIndex));
  200. CComPtr<IDxcUnsavedFile> unsavedFile;
  201. IFE(TrivialDxcUnsavedFile::Create(fileName, text, &unsavedFile));
  202. DxcTranslationUnitFlags localOptions;
  203. if (options == nullptr)
  204. {
  205. IFE(isense->GetDefaultEditingTUOptions(&localOptions));
  206. }
  207. else
  208. {
  209. localOptions = *options;
  210. }
  211. IFE(tuIndex->ParseTranslationUnit(fileName,
  212. commandLineArgs, commandLineArgsCount,
  213. &(unsavedFile.p), 1, localOptions, &tu));
  214. return CompilationResult(support, isense.p, tuIndex.p, tu.p);
  215. }
  216. static CompilationResult
  217. CreateForProgram(const char *text, size_t textLen,
  218. _In_opt_ DxcTranslationUnitFlags *options = nullptr) {
  219. const char *commandLineArgs[] = {"-c", "-ferror-limit=200"};
  220. unsigned commandLineArgsCount = _countof(commandLineArgs);
  221. return CreateForProgramAndArgs(text, textLen, commandLineArgs,
  222. commandLineArgsCount, options);
  223. }
  224. static CompilationResult CreateForCommandLine(char* arguments, const char* fileName) {
  225. std::shared_ptr<HlslIntellisenseSupport> support(GetHlslSupport());
  226. return CreateForCommandLine(arguments, fileName, support);
  227. }
  228. static CompilationResult CreateForCommandLine(char* arguments, const char* fileName, std::shared_ptr<HlslIntellisenseSupport> support) {
  229. CComPtr<IDxcIntelliSense> isense;
  230. IFE(support->CreateIntellisense(&isense));
  231. CComPtr<IDxcIndex> tuIndex;
  232. CComPtr<IDxcTranslationUnit> tu;
  233. const char* commandLineArgs[32];
  234. unsigned commandLineArgsCount = 0;
  235. char* nextArg = arguments;
  236. // Set a very high number of errors to avoid giving up too early.
  237. commandLineArgs[commandLineArgsCount++] = "-ferror-limit=2000";
  238. // Turn on spell checking for compatibility. This produces error messages
  239. // that suggest corrected spellings.
  240. commandLineArgs[commandLineArgsCount++] = "-fspell-checking";
  241. // Turn off color diagnostics to avoid control characters in diagnostic
  242. // stream.
  243. commandLineArgs[commandLineArgsCount++] = "-fno-color-diagnostics";
  244. IFE(isense->CreateIndex(&tuIndex));
  245. // Split command line arguments by spaces
  246. if (nextArg) {
  247. // skip leading spaces
  248. while (*nextArg == ' ')
  249. nextArg++;
  250. commandLineArgs[commandLineArgsCount++] = nextArg;
  251. while ((*nextArg != '\0')) {
  252. if (*nextArg == ' ') {
  253. *nextArg = 0;
  254. commandLineArgs[commandLineArgsCount++] = nextArg + 1;
  255. }
  256. nextArg++;
  257. }
  258. }
  259. DxcTranslationUnitFlags options;
  260. IFE(isense->GetDefaultEditingTUOptions(&options));
  261. IFE(tuIndex->ParseTranslationUnit(fileName, commandLineArgs,
  262. commandLineArgsCount, nullptr, 0, options,
  263. &tu));
  264. return CompilationResult(support, isense.p, tuIndex.p, tu.p);
  265. }
  266. bool IsTUAvailable() const { return TU != nullptr; }
  267. bool ParseSucceeded() const { return TU != nullptr && NumErrorDiagnostics == 0; }
  268. static bool IsErrorSeverity(DxcDiagnosticSeverity severity)
  269. {
  270. return (severity == DxcDiagnostic_Error || severity == DxcDiagnostic_Fatal);
  271. }
  272. /// Gets a string with all error messages concatenated, one per line.
  273. std::string GetTextForErrors() const {
  274. assert(DiagnosticMessages.size() == NumDiagnostics && "otherwise some diagnostics have no message");
  275. assert(DiagnosticSeverities.size() == NumDiagnostics && "otherwise some diagnostics have no severity");
  276. std::stringstream ostr;
  277. for (size_t i = 0; i < DiagnosticMessages.size(); i++) {
  278. if (IsErrorSeverity(DiagnosticSeverities[i])) {
  279. ostr << DiagnosticMessages[i] << '\n';
  280. }
  281. }
  282. return ostr.str();
  283. }
  284. /// Releases resources, including the translation unit AST.
  285. void Dispose()
  286. {
  287. TU = nullptr;
  288. Index = nullptr;
  289. Intellisense = nullptr;
  290. IsenseSupport = nullptr;
  291. }
  292. private:
  293. #if SUPPORTS_CURSOR_WALK
  294. struct CursorStringData {
  295. std::stringstream &ostr;
  296. std::vector<CXCursor> cursors;
  297. CursorStringData(std::stringstream &the_ostr) : ostr(the_ostr) {}
  298. };
  299. static
  300. CXChildVisitResult AppendCursorStringCallback(
  301. CXCursor cursor, CXCursor parent, CXClientData client_data)
  302. {
  303. CursorStringData* d = (CursorStringData*)client_data;
  304. auto cursorsStart = std::begin(d->cursors);
  305. auto cursorsEnd = std::end(d->cursors);
  306. auto parentLocation = std::find(cursorsStart, cursorsEnd, parent);
  307. assert(parentLocation != cursorsEnd && "otherwise the parent was not visited previously");
  308. AppendCursorString(cursor, parentLocation - cursorsStart, d->ostr);
  309. d->cursors.resize(1 + (parentLocation - cursorsStart));
  310. d->cursors.push_back(cursor);
  311. return CXChildVisit_Recurse;
  312. }
  313. #endif
  314. static
  315. void AppendCursorString(IDxcCursor* cursor, size_t indent, std::stringstream& ostr)
  316. {
  317. if (indent > 0) {
  318. std::streamsize prior = ostr.width();
  319. ostr.width(indent);
  320. ostr << ' ';
  321. ostr.width(prior);
  322. }
  323. CComPtr<IDxcType> type;
  324. DxcCursorKind kind;
  325. cursor->GetKind(&kind);
  326. cursor->GetCursorType(&type);
  327. switch (kind)
  328. {
  329. case DxcCursor_UnexposedDecl: ostr << "UnexposedDecl"; break;
  330. case DxcCursor_StructDecl: ostr << "StructDecl"; break;
  331. case DxcCursor_UnionDecl: ostr << "UnionDecl"; break;
  332. case DxcCursor_ClassDecl: ostr << "ClassDecl"; break;
  333. case DxcCursor_EnumDecl: ostr << "EnumDecl"; break;
  334. case DxcCursor_FieldDecl: ostr << "FieldDecl"; break;
  335. case DxcCursor_EnumConstantDecl: ostr << "EnumConstantDecl"; break;
  336. case DxcCursor_FunctionDecl: ostr << "FunctionDecl"; break;
  337. case DxcCursor_VarDecl: ostr << "VarDecl"; break;
  338. case DxcCursor_ParmDecl: ostr << "ParmDecl"; break;
  339. case DxcCursor_ObjCInterfaceDecl: ostr << "ObjCInterfaceDecl"; break;
  340. case DxcCursor_ObjCCategoryDecl: ostr << "ObjCCategoryDecl"; break;
  341. case DxcCursor_ObjCProtocolDecl: ostr << "ObjCProtocolDecl"; break;
  342. case DxcCursor_ObjCPropertyDecl: ostr << "ObjCPropertyDecl"; break;
  343. case DxcCursor_ObjCIvarDecl: ostr << "ObjCIvarDecl"; break;
  344. case DxcCursor_ObjCInstanceMethodDecl: ostr << "ObjCInstanceMethodDecl"; break;
  345. case DxcCursor_ObjCClassMethodDecl: ostr << "ObjCClassMethodDecl"; break;
  346. case DxcCursor_ObjCImplementationDecl: ostr << "ObjCImplementationDecl"; break;
  347. case DxcCursor_ObjCCategoryImplDecl: ostr << "ObjCCategoryImplDecl"; break;
  348. case DxcCursor_TypedefDecl: ostr << "TypedefDecl"; break;
  349. case DxcCursor_CXXMethod: ostr << "CXXMethod"; break;
  350. case DxcCursor_Namespace: ostr << "Namespace"; break;
  351. case DxcCursor_LinkageSpec: ostr << "LinkageSpec"; break;
  352. case DxcCursor_Constructor: ostr << "Constructor"; break;
  353. case DxcCursor_Destructor: ostr << "Destructor"; break;
  354. case DxcCursor_ConversionFunction: ostr << "ConversionFunction"; break;
  355. case DxcCursor_TemplateTypeParameter: ostr << "TemplateTypeParameter"; break;
  356. case DxcCursor_NonTypeTemplateParameter: ostr << "NonTypeTemplateParameter"; break;
  357. case DxcCursor_TemplateTemplateParameter: ostr << "TemplateTemplateParameter"; break;
  358. case DxcCursor_FunctionTemplate: ostr << "FunctionTemplate"; break;
  359. case DxcCursor_ClassTemplate: ostr << "ClassTemplate"; break;
  360. case DxcCursor_ClassTemplatePartialSpecialization: ostr << "ClassTemplatePartialSpecialization"; break;
  361. case DxcCursor_NamespaceAlias: ostr << "NamespaceAlias"; break;
  362. case DxcCursor_UsingDirective: ostr << "UsingDirective"; break;
  363. case DxcCursor_UsingDeclaration: ostr << "UsingDeclaration"; break;
  364. case DxcCursor_TypeAliasDecl: ostr << "TypeAliasDecl"; break;
  365. case DxcCursor_ObjCSynthesizeDecl: ostr << "ObjCSynthesizeDecl"; break;
  366. case DxcCursor_ObjCDynamicDecl: ostr << "ObjCDynamicDecl"; break;
  367. case DxcCursor_CXXAccessSpecifier: ostr << "CXXAccessSpecifier"; break;
  368. case DxcCursor_ObjCSuperClassRef: ostr << "ObjCSuperClassRef"; break;
  369. case DxcCursor_ObjCProtocolRef: ostr << "ObjCProtocolRef"; break;
  370. case DxcCursor_ObjCClassRef: ostr << "ObjCClassRef"; break;
  371. case DxcCursor_TypeRef: ostr << "TypeRef"; break;
  372. case DxcCursor_CXXBaseSpecifier: ostr << "CXXBaseSpecifier"; break;
  373. case DxcCursor_TemplateRef: ostr << "TemplateRef"; break;
  374. case DxcCursor_NamespaceRef: ostr << "NamespaceRef"; break;
  375. case DxcCursor_MemberRef: ostr << "MemberRef"; break;
  376. case DxcCursor_LabelRef: ostr << "LabelRef"; break;
  377. case DxcCursor_OverloadedDeclRef: ostr << "OverloadedDeclRef"; break;
  378. case DxcCursor_VariableRef: ostr << "VariableRef"; break;
  379. case DxcCursor_InvalidFile: ostr << "InvalidFile"; break;
  380. case DxcCursor_NoDeclFound: ostr << "NoDeclFound"; break;
  381. case DxcCursor_NotImplemented: ostr << "NotImplemented"; break;
  382. case DxcCursor_InvalidCode: ostr << "InvalidCode"; break;
  383. case DxcCursor_UnexposedExpr: ostr << "UnexposedExpr"; break;
  384. case DxcCursor_DeclRefExpr: ostr << "DeclRefExpr"; break;
  385. case DxcCursor_MemberRefExpr: ostr << "MemberRefExpr"; break;
  386. case DxcCursor_CallExpr: ostr << "CallExpr"; break;
  387. case DxcCursor_ObjCMessageExpr: ostr << "ObjCMessageExpr"; break;
  388. case DxcCursor_BlockExpr: ostr << "BlockExpr"; break;
  389. case DxcCursor_IntegerLiteral: ostr << "IntegerLiteral"; break;
  390. case DxcCursor_FloatingLiteral: ostr << "FloatingLiteral"; break;
  391. case DxcCursor_ImaginaryLiteral: ostr << "ImaginaryLiteral"; break;
  392. case DxcCursor_StringLiteral: ostr << "StringLiteral"; break;
  393. case DxcCursor_CharacterLiteral: ostr << "CharacterLiteral"; break;
  394. case DxcCursor_ParenExpr: ostr << "ParenExpr"; break;
  395. case DxcCursor_UnaryOperator: ostr << "UnaryOperator"; break;
  396. case DxcCursor_ArraySubscriptExpr: ostr << "ArraySubscriptExpr"; break;
  397. case DxcCursor_BinaryOperator: ostr << "BinaryOperator"; break;
  398. case DxcCursor_CompoundAssignOperator: ostr << "CompoundAssignOperator"; break;
  399. case DxcCursor_ConditionalOperator: ostr << "ConditionalOperator"; break;
  400. case DxcCursor_CStyleCastExpr: ostr << "CStyleCastExpr"; break;
  401. case DxcCursor_CompoundLiteralExpr: ostr << "CompoundLiteralExpr"; break;
  402. case DxcCursor_InitListExpr: ostr << "InitListExpr"; break;
  403. case DxcCursor_AddrLabelExpr: ostr << "AddrLabelExpr"; break;
  404. case DxcCursor_StmtExpr: ostr << "StmtExpr"; break;
  405. case DxcCursor_GenericSelectionExpr: ostr << "GenericSelectionExpr"; break;
  406. case DxcCursor_GNUNullExpr: ostr << "GNUNullExpr"; break;
  407. case DxcCursor_CXXStaticCastExpr: ostr << "CXXStaticCastExpr"; break;
  408. case DxcCursor_CXXDynamicCastExpr: ostr << "CXXDynamicCastExpr"; break;
  409. case DxcCursor_CXXReinterpretCastExpr: ostr << "CXXReinterpretCastExpr"; break;
  410. case DxcCursor_CXXConstCastExpr: ostr << "CXXConstCastExpr"; break;
  411. case DxcCursor_CXXFunctionalCastExpr: ostr << "CXXFunctionalCastExpr"; break;
  412. case DxcCursor_CXXTypeidExpr: ostr << "CXXTypeidExpr"; break;
  413. case DxcCursor_CXXBoolLiteralExpr: ostr << "CXXBoolLiteralExpr"; break;
  414. case DxcCursor_CXXNullPtrLiteralExpr: ostr << "CXXNullPtrLiteralExpr"; break;
  415. case DxcCursor_CXXThisExpr: ostr << "CXXThisExpr"; break;
  416. case DxcCursor_CXXThrowExpr: ostr << "CXXThrowExpr"; break;
  417. case DxcCursor_CXXNewExpr: ostr << "CXXNewExpr"; break;
  418. case DxcCursor_CXXDeleteExpr: ostr << "CXXDeleteExpr"; break;
  419. case DxcCursor_UnaryExpr: ostr << "UnaryExpr"; break;
  420. case DxcCursor_ObjCStringLiteral: ostr << "ObjCStringLiteral"; break;
  421. case DxcCursor_ObjCEncodeExpr: ostr << "ObjCEncodeExpr"; break;
  422. case DxcCursor_ObjCSelectorExpr: ostr << "ObjCSelectorExpr"; break;
  423. case DxcCursor_ObjCProtocolExpr: ostr << "ObjCProtocolExpr"; break;
  424. case DxcCursor_ObjCBridgedCastExpr: ostr << "ObjCBridgedCastExpr"; break;
  425. case DxcCursor_PackExpansionExpr: ostr << "PackExpansionExpr"; break;
  426. case DxcCursor_SizeOfPackExpr: ostr << "SizeOfPackExpr"; break;
  427. case DxcCursor_LambdaExpr: ostr << "LambdaExpr"; break;
  428. case DxcCursor_ObjCBoolLiteralExpr: ostr << "ObjCBoolLiteralExpr"; break;
  429. case DxcCursor_ObjCSelfExpr: ostr << "ObjCSelfExpr"; break;
  430. case DxcCursor_UnexposedStmt: ostr << "UnexposedStmt"; break;
  431. case DxcCursor_LabelStmt: ostr << "LabelStmt"; break;
  432. case DxcCursor_CompoundStmt: ostr << "CompoundStmt"; break;
  433. case DxcCursor_CaseStmt: ostr << "CaseStmt"; break;
  434. case DxcCursor_DefaultStmt: ostr << "DefaultStmt"; break;
  435. case DxcCursor_IfStmt: ostr << "IfStmt"; break;
  436. case DxcCursor_SwitchStmt: ostr << "SwitchStmt"; break;
  437. case DxcCursor_WhileStmt: ostr << "WhileStmt"; break;
  438. case DxcCursor_DoStmt: ostr << "DoStmt"; break;
  439. case DxcCursor_ForStmt: ostr << "ForStmt"; break;
  440. case DxcCursor_GotoStmt: ostr << "GotoStmt"; break;
  441. case DxcCursor_IndirectGotoStmt: ostr << "IndirectGotoStmt"; break;
  442. case DxcCursor_ContinueStmt: ostr << "ContinueStmt"; break;
  443. case DxcCursor_BreakStmt: ostr << "BreakStmt"; break;
  444. case DxcCursor_ReturnStmt: ostr << "ReturnStmt"; break;
  445. case DxcCursor_GCCAsmStmt: ostr << "GCCAsmStmt"; break;
  446. case DxcCursor_ObjCAtTryStmt: ostr << "ObjCAtTryStmt"; break;
  447. case DxcCursor_ObjCAtCatchStmt: ostr << "ObjCAtCatchStmt"; break;
  448. case DxcCursor_ObjCAtFinallyStmt: ostr << "ObjCAtFinallyStmt"; break;
  449. case DxcCursor_ObjCAtThrowStmt: ostr << "ObjCAtThrowStmt"; break;
  450. case DxcCursor_ObjCAtSynchronizedStmt: ostr << "ObjCAtSynchronizedStmt"; break;
  451. case DxcCursor_ObjCAutoreleasePoolStmt: ostr << "ObjCAutoreleasePoolStmt"; break;
  452. case DxcCursor_ObjCForCollectionStmt: ostr << "ObjCForCollectionStmt"; break;
  453. case DxcCursor_CXXCatchStmt: ostr << "CXXCatchStmt"; break;
  454. case DxcCursor_CXXTryStmt: ostr << "CXXTryStmt"; break;
  455. case DxcCursor_CXXForRangeStmt: ostr << "CXXForRangeStmt"; break;
  456. case DxcCursor_SEHTryStmt: ostr << "SEHTryStmt"; break;
  457. case DxcCursor_SEHExceptStmt: ostr << "SEHExceptStmt"; break;
  458. case DxcCursor_SEHFinallyStmt: ostr << "SEHFinallyStmt"; break;
  459. case DxcCursor_MSAsmStmt: ostr << "MSAsmStmt"; break;
  460. case DxcCursor_NullStmt: ostr << "NullStmt"; break;
  461. case DxcCursor_DeclStmt: ostr << "DeclStmt"; break;
  462. case DxcCursor_OMPParallelDirective: ostr << "OMPParallelDirective"; break;
  463. case DxcCursor_TranslationUnit: ostr << "TranslationUnit"; break;
  464. case DxcCursor_UnexposedAttr: ostr << "UnexposedAttr"; break;
  465. #if 0
  466. CXCursor_IBActionAttr = 401,
  467. CXCursor_IBOutletAttr = 402,
  468. CXCursor_IBOutletCollectionAttr = 403,
  469. CXCursor_CXXFinalAttr = 404,
  470. CXCursor_CXXOverrideAttr = 405,
  471. CXCursor_AnnotateAttr = 406,
  472. CXCursor_AsmLabelAttr = 407,
  473. CXCursor_PackedAttr = 408,
  474. /* Preprocessing */
  475. CXCursor_PreprocessingDirective = 500,
  476. CXCursor_MacroDefinition = 501,
  477. CXCursor_MacroExpansion = 502,
  478. CXCursor_InclusionDirective = 503,
  479. case CXCursor_FunctionDecl:
  480. break;
  481. case CXCursor_ClassDecl:
  482. ostr << "class decl";
  483. break;
  484. case CXCursor_TranslationUnit:
  485. ostr << "translation unit";
  486. break;
  487. #endif
  488. default:
  489. ostr << "unknown/unhandled cursor kind " << kind;
  490. break;
  491. }
  492. DxcTypeKind typeKind;
  493. if (type != nullptr && SUCCEEDED(type->GetKind(&typeKind)) &&
  494. typeKind != DxcTypeKind_Invalid) {
  495. LPSTR name;
  496. type->GetSpelling(&name);
  497. ostr << " [type " << name << "]";
  498. CoTaskMemFree(name);
  499. }
  500. ostr << '\n';
  501. // Recurse.
  502. IDxcCursor** children = nullptr;
  503. unsigned childrenCount;
  504. cursor->GetChildren(0, 64, &childrenCount, &children);
  505. for (unsigned i = 0; i < childrenCount; i++) {
  506. AppendCursorString(children[i], indent + 1, ostr);
  507. children[i]->Release();
  508. }
  509. CoTaskMemFree(children);
  510. }
  511. public:
  512. std::string BuildASTString() {
  513. if (TU == nullptr) {
  514. return "<failed to build - TU is null>";
  515. }
  516. CComPtr<IDxcCursor> cursor;
  517. std::stringstream ostr;
  518. this->TU->GetCursor(&cursor);
  519. AppendCursorString(cursor, 0, ostr);
  520. return ostr.str();
  521. }
  522. };