1 //===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the clang::ParseAST method. 10 // 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/Sema.h" 22 #include "clang/Sema/SemaConsumer.h" 23 #include "clang/Sema/TemplateInstCallback.h" 24 #include "llvm/Support/CrashRecoveryContext.h" 25 #include "llvm/Support/TimeProfiler.h" 26 #include <cstdio> 27 #include <memory> 28 29 using namespace clang; 30 31 namespace { 32 33 /// Resets LLVM's pretty stack state so that stack traces are printed correctly 34 /// when there are nested CrashRecoveryContexts and the inner one recovers from 35 /// a crash. 36 class ResetStackCleanup 37 : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, 38 const void> { 39 public: 40 ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top) 41 : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>( 42 Context, Top) {} 43 void recoverResources() override { 44 llvm::RestorePrettyStackState(resource); 45 } 46 }; 47 48 /// If a crash happens while the parser is active, an entry is printed for it. 49 class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { 50 const Parser &P; 51 public: 52 PrettyStackTraceParserEntry(const Parser &p) : P(p) {} 53 void print(raw_ostream &OS) const override; 54 }; 55 56 /// If a crash happens while the parser is active, print out a line indicating 57 /// what the current token is. 58 void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { 59 const Token &Tok = P.getCurToken(); 60 if (Tok.is(tok::eof)) { 61 OS << "<eof> parser at end of file\n"; 62 return; 63 } 64 65 if (Tok.getLocation().isInvalid()) { 66 OS << "<unknown> parser at unknown location\n"; 67 return; 68 } 69 70 const Preprocessor &PP = P.getPreprocessor(); 71 Tok.getLocation().print(OS, PP.getSourceManager()); 72 if (Tok.isAnnotation()) { 73 OS << ": at annotation token\n"; 74 } else { 75 // Do the equivalent of PP.getSpelling(Tok) except for the parts that would 76 // allocate memory. 77 bool Invalid = false; 78 const SourceManager &SM = P.getPreprocessor().getSourceManager(); 79 unsigned Length = Tok.getLength(); 80 const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); 81 if (Invalid) { 82 OS << ": unknown current parser token\n"; 83 return; 84 } 85 OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; 86 } 87 } 88 89 } // namespace 90 91 //===----------------------------------------------------------------------===// 92 // Public interface to the file 93 //===----------------------------------------------------------------------===// 94 95 /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as 96 /// the file is parsed. This inserts the parsed decls into the translation unit 97 /// held by Ctx. 98 /// 99 void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, 100 ASTContext &Ctx, bool PrintStats, 101 TranslationUnitKind TUKind, 102 CodeCompleteConsumer *CompletionConsumer, 103 bool SkipFunctionBodies) { 104 105 std::unique_ptr<Sema> S( 106 new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); 107 108 // Recover resources if we crash before exiting this method. 109 llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); 110 111 ParseAST(*S.get(), PrintStats, SkipFunctionBodies); 112 } 113 114 void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { 115 // Collect global stats on Decls/Stmts (until we have a module streamer). 116 if (PrintStats) { 117 Decl::EnableStatistics(); 118 Stmt::EnableStatistics(); 119 } 120 121 // Also turn on collection of stats inside of the Sema object. 122 bool OldCollectStats = PrintStats; 123 std::swap(OldCollectStats, S.CollectStats); 124 125 // Initialize the template instantiation observer chain. 126 // FIXME: See note on "finalize" below. 127 initialize(S.TemplateInstCallbacks, S); 128 129 ASTConsumer *Consumer = &S.getASTConsumer(); 130 131 std::unique_ptr<Parser> ParseOP( 132 new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); 133 Parser &P = *ParseOP.get(); 134 135 llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> 136 CleanupPrettyStack(llvm::SavePrettyStackState()); 137 PrettyStackTraceParserEntry CrashInfo(P); 138 139 // Recover resources if we crash before exiting this method. 140 llvm::CrashRecoveryContextCleanupRegistrar<Parser> 141 CleanupParser(ParseOP.get()); 142 143 S.getPreprocessor().EnterMainSourceFile(); 144 ExternalASTSource *External = S.getASTContext().getExternalSource(); 145 if (External) 146 External->StartTranslationUnit(Consumer); 147 148 // If a PCH through header is specified that does not have an include in 149 // the source, or a PCH is being created with #pragma hdrstop with nothing 150 // after the pragma, there won't be any tokens or a Lexer. 151 bool HaveLexer = S.getPreprocessor().getCurrentLexer(); 152 153 if (HaveLexer) { 154 llvm::TimeTraceScope TimeScope("Frontend"); 155 P.Initialize(); 156 Parser::DeclGroupPtrTy ADecl; 157 Sema::ModuleImportState ImportState; 158 EnterExpressionEvaluationContext PotentiallyEvaluated( 159 S, Sema::ExpressionEvaluationContext::PotentiallyEvaluated); 160 161 for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl, ImportState); !AtEOF; 162 AtEOF = P.ParseTopLevelDecl(ADecl, ImportState)) { 163 // If we got a null return and something *was* parsed, ignore it. This 164 // is due to a top-level semicolon, an action override, or a parse error 165 // skipping something. 166 if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) 167 return; 168 } 169 } 170 171 // Process any TopLevelDecls generated by #pragma weak. 172 for (Decl *D : S.WeakTopLevelDecls()) 173 Consumer->HandleTopLevelDecl(DeclGroupRef(D)); 174 175 // For C++20 modules, the codegen for module initializers needs to be altered 176 // and to be able to use a name based on the module name. 177 178 // At this point, we should know if we are building a non-header C++20 module. 179 if (S.getLangOpts().CPlusPlusModules && !S.getLangOpts().IsHeaderFile && 180 !S.getLangOpts().CurrentModule.empty()) { 181 // If we are building the module from source, then the top level module 182 // will be here. 183 Module *CodegenModule = S.getCurrentModule(); 184 bool Interface = true; 185 if (CodegenModule) 186 // We only use module initializers for interfaces (including partition 187 // implementation units). 188 Interface = S.currentModuleIsInterface(); 189 else 190 // If we are building the module from a PCM file, then the module can be 191 // found here. 192 CodegenModule = S.getPreprocessor().getCurrentModule(); 193 // If neither. then .... 194 assert(CodegenModule && "codegen for a module, but don't know which?"); 195 if (Interface) 196 S.getASTContext().setModuleForCodeGen(CodegenModule); 197 } 198 Consumer->HandleTranslationUnit(S.getASTContext()); 199 200 // Finalize the template instantiation observer chain. 201 // FIXME: This (and init.) should be done in the Sema class, but because 202 // Sema does not have a reliable "Finalize" function (it has a 203 // destructor, but it is not guaranteed to be called ("-disable-free")). 204 // So, do the initialization above and do the finalization here: 205 finalize(S.TemplateInstCallbacks, S); 206 207 std::swap(OldCollectStats, S.CollectStats); 208 if (PrintStats) { 209 llvm::errs() << "\nSTATISTICS:\n"; 210 if (HaveLexer) P.getActions().PrintStats(); 211 S.getASTContext().PrintStats(); 212 Decl::PrintStats(); 213 Stmt::PrintStats(); 214 Consumer->PrintStats(); 215 } 216 } 217