ParseAST.cpp 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. //===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. //
  10. // This file implements the clang::ParseAST method.
  11. //
  12. //===----------------------------------------------------------------------===//
  13. #include "clang/Parse/ParseAST.h"
  14. #include "clang/AST/ASTConsumer.h"
  15. #include "clang/AST/ASTContext.h"
  16. #include "clang/AST/ExternalASTSource.h"
  17. #include "clang/AST/Stmt.h"
  18. #include "clang/Parse/ParseDiagnostic.h"
  19. #include "clang/Parse/Parser.h"
  20. #include "clang/Sema/CodeCompleteConsumer.h"
  21. #include "clang/Sema/ExternalSemaSource.h"
  22. #include "clang/Sema/Sema.h"
  23. #include "clang/Sema/SemaConsumer.h"
  24. #include "clang/Sema/SemaHLSL.h" // HLSL Change
  25. #include "llvm/Support/CrashRecoveryContext.h"
  26. #include <cstdio>
  27. #include <memory>
  28. using namespace clang;
  29. namespace {
  30. /// If a crash happens while the parser is active, an entry is printed for it.
  31. class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
  32. const Parser &P;
  33. public:
  34. PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
  35. void print(raw_ostream &OS) const override;
  36. };
  37. /// If a crash happens while the parser is active, print out a line indicating
  38. /// what the current token is.
  39. void PrettyStackTraceParserEntry::print(raw_ostream &OS) const {
  40. const Token &Tok = P.getCurToken();
  41. if (Tok.is(tok::eof)) {
  42. OS << "<eof> parser at end of file\n";
  43. return;
  44. }
  45. if (Tok.getLocation().isInvalid()) {
  46. OS << "<unknown> parser at unknown location\n";
  47. return;
  48. }
  49. const Preprocessor &PP = P.getPreprocessor();
  50. Tok.getLocation().print(OS, PP.getSourceManager());
  51. if (Tok.isAnnotation()) {
  52. OS << ": at annotation token\n";
  53. } else {
  54. // Do the equivalent of PP.getSpelling(Tok) except for the parts that would
  55. // allocate memory.
  56. bool Invalid = false;
  57. const SourceManager &SM = P.getPreprocessor().getSourceManager();
  58. unsigned Length = Tok.getLength();
  59. const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid);
  60. if (Invalid) {
  61. OS << ": unknown current parser token\n";
  62. return;
  63. }
  64. OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n";
  65. }
  66. }
  67. } // namespace
  68. //===----------------------------------------------------------------------===//
  69. // Public interface to the file
  70. //===----------------------------------------------------------------------===//
  71. /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
  72. /// the file is parsed. This inserts the parsed decls into the translation unit
  73. /// held by Ctx.
  74. ///
  75. void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
  76. ASTContext &Ctx, bool PrintStats,
  77. TranslationUnitKind TUKind,
  78. CodeCompleteConsumer *CompletionConsumer,
  79. bool SkipFunctionBodies) {
  80. std::unique_ptr<Sema> S(
  81. new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
  82. // Recover resources if we crash before exiting this method.
  83. llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
  84. ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
  85. }
  86. void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
  87. // Collect global stats on Decls/Stmts (until we have a module streamer).
  88. if (PrintStats) {
  89. Decl::EnableStatistics();
  90. Stmt::EnableStatistics();
  91. }
  92. // Also turn on collection of stats inside of the Sema object.
  93. bool OldCollectStats = PrintStats;
  94. std::swap(OldCollectStats, S.CollectStats);
  95. ASTConsumer *Consumer = &S.getASTConsumer();
  96. std::unique_ptr<Parser> ParseOP(
  97. new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
  98. Parser &P = *ParseOP.get();
  99. PrettyStackTraceParserEntry CrashInfo(P);
  100. // Recover resources if we crash before exiting this method.
  101. llvm::CrashRecoveryContextCleanupRegistrar<Parser>
  102. CleanupParser(ParseOP.get());
  103. S.getPreprocessor().EnterMainSourceFile();
  104. P.Initialize();
  105. // C11 6.9p1 says translation units must have at least one top-level
  106. // declaration. C++ doesn't have this restriction. We also don't want to
  107. // complain if we have a precompiled header, although technically if the PCH
  108. // is empty we should still emit the (pedantic) diagnostic.
  109. Parser::DeclGroupPtrTy ADecl;
  110. ExternalASTSource *External = S.getASTContext().getExternalSource();
  111. if (External)
  112. External->StartTranslationUnit(Consumer);
  113. if (!S.getDiagnostics().hasUnrecoverableErrorOccurred()) { // HLSL Change: Skip if fatal error already occurred
  114. if (P.ParseTopLevelDecl(ADecl)) {
  115. if (!External && !S.getLangOpts().CPlusPlus)
  116. P.Diag(diag::ext_empty_translation_unit);
  117. } else {
  118. do {
  119. // If we got a null return and something *was* parsed, ignore it. This
  120. // is due to a top-level semicolon, an action override, or a parse error
  121. // skipping something.
  122. if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
  123. return;
  124. } while (!P.ParseTopLevelDecl(ADecl));
  125. }
  126. } // HLSL Change: Skip if fatal error already occurred
  127. // Process any TopLevelDecls generated by #pragma weak.
  128. for (Decl *D : S.WeakTopLevelDecls())
  129. Consumer->HandleTopLevelDecl(DeclGroupRef(D));
  130. // HLSL Change Starts
  131. // Provide the opportunity to generate translation-unit level validation
  132. // errors in the front-end, without relying on code generation being
  133. // available.
  134. hlsl::DiagnoseTranslationUnit(&S);
  135. // HLSL Change Ends
  136. Consumer->HandleTranslationUnit(S.getASTContext());
  137. std::swap(OldCollectStats, S.CollectStats);
  138. if (PrintStats) {
  139. llvm::errs() << "\nSTATISTICS:\n";
  140. P.getActions().PrintStats();
  141. S.getASTContext().PrintStats();
  142. Decl::PrintStats();
  143. Stmt::PrintStats();
  144. Consumer->PrintStats();
  145. }
  146. }