xref: /netbsd-src/external/apache2/llvm/dist/clang/lib/Parse/ParseAST.cpp (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg //===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg //
97330f729Sjoerg // This file implements the clang::ParseAST method.
107330f729Sjoerg //
117330f729Sjoerg //===----------------------------------------------------------------------===//
127330f729Sjoerg 
137330f729Sjoerg #include "clang/Parse/ParseAST.h"
147330f729Sjoerg #include "clang/AST/ASTConsumer.h"
157330f729Sjoerg #include "clang/AST/ASTContext.h"
167330f729Sjoerg #include "clang/AST/ExternalASTSource.h"
177330f729Sjoerg #include "clang/AST/Stmt.h"
187330f729Sjoerg #include "clang/Parse/ParseDiagnostic.h"
197330f729Sjoerg #include "clang/Parse/Parser.h"
207330f729Sjoerg #include "clang/Sema/CodeCompleteConsumer.h"
217330f729Sjoerg #include "clang/Sema/Sema.h"
227330f729Sjoerg #include "clang/Sema/SemaConsumer.h"
237330f729Sjoerg #include "clang/Sema/TemplateInstCallback.h"
247330f729Sjoerg #include "llvm/Support/CrashRecoveryContext.h"
257330f729Sjoerg #include "llvm/Support/TimeProfiler.h"
267330f729Sjoerg #include <cstdio>
277330f729Sjoerg #include <memory>
287330f729Sjoerg 
297330f729Sjoerg using namespace clang;
307330f729Sjoerg 
317330f729Sjoerg namespace {
327330f729Sjoerg 
337330f729Sjoerg /// Resets LLVM's pretty stack state so that stack traces are printed correctly
347330f729Sjoerg /// when there are nested CrashRecoveryContexts and the inner one recovers from
357330f729Sjoerg /// a crash.
367330f729Sjoerg class ResetStackCleanup
377330f729Sjoerg     : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup,
387330f729Sjoerg                                                    const void> {
397330f729Sjoerg public:
ResetStackCleanup(llvm::CrashRecoveryContext * Context,const void * Top)407330f729Sjoerg   ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top)
417330f729Sjoerg       : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>(
427330f729Sjoerg             Context, Top) {}
recoverResources()437330f729Sjoerg   void recoverResources() override {
447330f729Sjoerg     llvm::RestorePrettyStackState(resource);
457330f729Sjoerg   }
467330f729Sjoerg };
477330f729Sjoerg 
487330f729Sjoerg /// If a crash happens while the parser is active, an entry is printed for it.
497330f729Sjoerg class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
507330f729Sjoerg   const Parser &P;
517330f729Sjoerg public:
PrettyStackTraceParserEntry(const Parser & p)527330f729Sjoerg   PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
537330f729Sjoerg   void print(raw_ostream &OS) const override;
547330f729Sjoerg };
557330f729Sjoerg 
567330f729Sjoerg /// If a crash happens while the parser is active, print out a line indicating
577330f729Sjoerg /// what the current token is.
print(raw_ostream & OS) const587330f729Sjoerg void PrettyStackTraceParserEntry::print(raw_ostream &OS) const {
597330f729Sjoerg   const Token &Tok = P.getCurToken();
607330f729Sjoerg   if (Tok.is(tok::eof)) {
617330f729Sjoerg     OS << "<eof> parser at end of file\n";
627330f729Sjoerg     return;
637330f729Sjoerg   }
647330f729Sjoerg 
657330f729Sjoerg   if (Tok.getLocation().isInvalid()) {
667330f729Sjoerg     OS << "<unknown> parser at unknown location\n";
677330f729Sjoerg     return;
687330f729Sjoerg   }
697330f729Sjoerg 
707330f729Sjoerg   const Preprocessor &PP = P.getPreprocessor();
717330f729Sjoerg   Tok.getLocation().print(OS, PP.getSourceManager());
727330f729Sjoerg   if (Tok.isAnnotation()) {
737330f729Sjoerg     OS << ": at annotation token\n";
747330f729Sjoerg   } else {
757330f729Sjoerg     // Do the equivalent of PP.getSpelling(Tok) except for the parts that would
767330f729Sjoerg     // allocate memory.
777330f729Sjoerg     bool Invalid = false;
787330f729Sjoerg     const SourceManager &SM = P.getPreprocessor().getSourceManager();
797330f729Sjoerg     unsigned Length = Tok.getLength();
807330f729Sjoerg     const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid);
817330f729Sjoerg     if (Invalid) {
827330f729Sjoerg       OS << ": unknown current parser token\n";
837330f729Sjoerg       return;
847330f729Sjoerg     }
857330f729Sjoerg     OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n";
867330f729Sjoerg   }
877330f729Sjoerg }
887330f729Sjoerg 
897330f729Sjoerg }  // namespace
907330f729Sjoerg 
917330f729Sjoerg //===----------------------------------------------------------------------===//
927330f729Sjoerg // Public interface to the file
937330f729Sjoerg //===----------------------------------------------------------------------===//
947330f729Sjoerg 
957330f729Sjoerg /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
967330f729Sjoerg /// the file is parsed.  This inserts the parsed decls into the translation unit
977330f729Sjoerg /// held by Ctx.
987330f729Sjoerg ///
ParseAST(Preprocessor & PP,ASTConsumer * Consumer,ASTContext & Ctx,bool PrintStats,TranslationUnitKind TUKind,CodeCompleteConsumer * CompletionConsumer,bool SkipFunctionBodies)997330f729Sjoerg void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
1007330f729Sjoerg                      ASTContext &Ctx, bool PrintStats,
1017330f729Sjoerg                      TranslationUnitKind TUKind,
1027330f729Sjoerg                      CodeCompleteConsumer *CompletionConsumer,
1037330f729Sjoerg                      bool SkipFunctionBodies) {
1047330f729Sjoerg 
1057330f729Sjoerg   std::unique_ptr<Sema> S(
1067330f729Sjoerg       new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
1077330f729Sjoerg 
1087330f729Sjoerg   // Recover resources if we crash before exiting this method.
1097330f729Sjoerg   llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
1107330f729Sjoerg 
1117330f729Sjoerg   ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
1127330f729Sjoerg }
1137330f729Sjoerg 
ParseAST(Sema & S,bool PrintStats,bool SkipFunctionBodies)1147330f729Sjoerg void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
1157330f729Sjoerg   // Collect global stats on Decls/Stmts (until we have a module streamer).
1167330f729Sjoerg   if (PrintStats) {
1177330f729Sjoerg     Decl::EnableStatistics();
1187330f729Sjoerg     Stmt::EnableStatistics();
1197330f729Sjoerg   }
1207330f729Sjoerg 
1217330f729Sjoerg   // Also turn on collection of stats inside of the Sema object.
1227330f729Sjoerg   bool OldCollectStats = PrintStats;
1237330f729Sjoerg   std::swap(OldCollectStats, S.CollectStats);
1247330f729Sjoerg 
1257330f729Sjoerg   // Initialize the template instantiation observer chain.
1267330f729Sjoerg   // FIXME: See note on "finalize" below.
1277330f729Sjoerg   initialize(S.TemplateInstCallbacks, S);
1287330f729Sjoerg 
1297330f729Sjoerg   ASTConsumer *Consumer = &S.getASTConsumer();
1307330f729Sjoerg 
1317330f729Sjoerg   std::unique_ptr<Parser> ParseOP(
1327330f729Sjoerg       new Parser(S.getPreprocessor(), S, SkipFunctionBodies));
1337330f729Sjoerg   Parser &P = *ParseOP.get();
1347330f729Sjoerg 
1357330f729Sjoerg   llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup>
1367330f729Sjoerg       CleanupPrettyStack(llvm::SavePrettyStackState());
1377330f729Sjoerg   PrettyStackTraceParserEntry CrashInfo(P);
1387330f729Sjoerg 
1397330f729Sjoerg   // Recover resources if we crash before exiting this method.
1407330f729Sjoerg   llvm::CrashRecoveryContextCleanupRegistrar<Parser>
1417330f729Sjoerg     CleanupParser(ParseOP.get());
1427330f729Sjoerg 
1437330f729Sjoerg   S.getPreprocessor().EnterMainSourceFile();
1447330f729Sjoerg   ExternalASTSource *External = S.getASTContext().getExternalSource();
1457330f729Sjoerg   if (External)
1467330f729Sjoerg     External->StartTranslationUnit(Consumer);
1477330f729Sjoerg 
1487330f729Sjoerg   // If a PCH through header is specified that does not have an include in
1497330f729Sjoerg   // the source, or a PCH is being created with #pragma hdrstop with nothing
1507330f729Sjoerg   // after the pragma, there won't be any tokens or a Lexer.
1517330f729Sjoerg   bool HaveLexer = S.getPreprocessor().getCurrentLexer();
1527330f729Sjoerg 
1537330f729Sjoerg   if (HaveLexer) {
154*e038c9c4Sjoerg     llvm::TimeTraceScope TimeScope("Frontend");
1557330f729Sjoerg     P.Initialize();
1567330f729Sjoerg     Parser::DeclGroupPtrTy ADecl;
1577330f729Sjoerg     for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF;
1587330f729Sjoerg          AtEOF = P.ParseTopLevelDecl(ADecl)) {
1597330f729Sjoerg       // If we got a null return and something *was* parsed, ignore it.  This
1607330f729Sjoerg       // is due to a top-level semicolon, an action override, or a parse error
1617330f729Sjoerg       // skipping something.
1627330f729Sjoerg       if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
1637330f729Sjoerg         return;
1647330f729Sjoerg     }
1657330f729Sjoerg   }
1667330f729Sjoerg 
1677330f729Sjoerg   // Process any TopLevelDecls generated by #pragma weak.
1687330f729Sjoerg   for (Decl *D : S.WeakTopLevelDecls())
1697330f729Sjoerg     Consumer->HandleTopLevelDecl(DeclGroupRef(D));
1707330f729Sjoerg 
1717330f729Sjoerg   Consumer->HandleTranslationUnit(S.getASTContext());
1727330f729Sjoerg 
1737330f729Sjoerg   // Finalize the template instantiation observer chain.
1747330f729Sjoerg   // FIXME: This (and init.) should be done in the Sema class, but because
1757330f729Sjoerg   // Sema does not have a reliable "Finalize" function (it has a
1767330f729Sjoerg   // destructor, but it is not guaranteed to be called ("-disable-free")).
1777330f729Sjoerg   // So, do the initialization above and do the finalization here:
1787330f729Sjoerg   finalize(S.TemplateInstCallbacks, S);
1797330f729Sjoerg 
1807330f729Sjoerg   std::swap(OldCollectStats, S.CollectStats);
1817330f729Sjoerg   if (PrintStats) {
1827330f729Sjoerg     llvm::errs() << "\nSTATISTICS:\n";
1837330f729Sjoerg     if (HaveLexer) P.getActions().PrintStats();
1847330f729Sjoerg     S.getASTContext().PrintStats();
1857330f729Sjoerg     Decl::PrintStats();
1867330f729Sjoerg     Stmt::PrintStats();
1877330f729Sjoerg     Consumer->PrintStats();
1887330f729Sjoerg   }
1897330f729Sjoerg }
190