Mercurial > hg > CbC > CbC_llvm
diff clang/lib/Parse/ParseAST.cpp @ 150:1d019706d866
LLVM10
author | anatofuz |
---|---|
date | Thu, 13 Feb 2020 15:10:13 +0900 |
parents | |
children | c4bab56944e8 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/clang/lib/Parse/ParseAST.cpp Thu Feb 13 15:10:13 2020 +0900 @@ -0,0 +1,189 @@ +//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file implements the clang::ParseAST method. +// +//===----------------------------------------------------------------------===// + +#include "clang/Parse/ParseAST.h" +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/ExternalASTSource.h" +#include "clang/AST/Stmt.h" +#include "clang/Parse/ParseDiagnostic.h" +#include "clang/Parse/Parser.h" +#include "clang/Sema/CodeCompleteConsumer.h" +#include "clang/Sema/Sema.h" +#include "clang/Sema/SemaConsumer.h" +#include "clang/Sema/TemplateInstCallback.h" +#include "llvm/Support/CrashRecoveryContext.h" +#include "llvm/Support/TimeProfiler.h" +#include <cstdio> +#include <memory> + +using namespace clang; + +namespace { + +/// Resets LLVM's pretty stack state so that stack traces are printed correctly +/// when there are nested CrashRecoveryContexts and the inner one recovers from +/// a crash. +class ResetStackCleanup + : public llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, + const void> { +public: + ResetStackCleanup(llvm::CrashRecoveryContext *Context, const void *Top) + : llvm::CrashRecoveryContextCleanupBase<ResetStackCleanup, const void>( + Context, Top) {} + void recoverResources() override { + llvm::RestorePrettyStackState(resource); + } +}; + +/// If a crash happens while the parser is active, an entry is printed for it. +class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { + const Parser &P; +public: + PrettyStackTraceParserEntry(const Parser &p) : P(p) {} + void print(raw_ostream &OS) const override; +}; + +/// If a crash happens while the parser is active, print out a line indicating +/// what the current token is. +void PrettyStackTraceParserEntry::print(raw_ostream &OS) const { + const Token &Tok = P.getCurToken(); + if (Tok.is(tok::eof)) { + OS << "<eof> parser at end of file\n"; + return; + } + + if (Tok.getLocation().isInvalid()) { + OS << "<unknown> parser at unknown location\n"; + return; + } + + const Preprocessor &PP = P.getPreprocessor(); + Tok.getLocation().print(OS, PP.getSourceManager()); + if (Tok.isAnnotation()) { + OS << ": at annotation token\n"; + } else { + // Do the equivalent of PP.getSpelling(Tok) except for the parts that would + // allocate memory. + bool Invalid = false; + const SourceManager &SM = P.getPreprocessor().getSourceManager(); + unsigned Length = Tok.getLength(); + const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); + if (Invalid) { + OS << ": unknown current parser token\n"; + return; + } + OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; + } +} + +} // namespace + +//===----------------------------------------------------------------------===// +// Public interface to the file +//===----------------------------------------------------------------------===// + +/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as +/// the file is parsed. This inserts the parsed decls into the translation unit +/// held by Ctx. +/// +void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, + ASTContext &Ctx, bool PrintStats, + TranslationUnitKind TUKind, + CodeCompleteConsumer *CompletionConsumer, + bool SkipFunctionBodies) { + + std::unique_ptr<Sema> S( + new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); + + ParseAST(*S.get(), PrintStats, SkipFunctionBodies); +} + +void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { + // Collect global stats on Decls/Stmts (until we have a module streamer). + if (PrintStats) { + Decl::EnableStatistics(); + Stmt::EnableStatistics(); + } + + // Also turn on collection of stats inside of the Sema object. + bool OldCollectStats = PrintStats; + std::swap(OldCollectStats, S.CollectStats); + + // Initialize the template instantiation observer chain. + // FIXME: See note on "finalize" below. + initialize(S.TemplateInstCallbacks, S); + + ASTConsumer *Consumer = &S.getASTConsumer(); + + std::unique_ptr<Parser> ParseOP( + new Parser(S.getPreprocessor(), S, SkipFunctionBodies)); + Parser &P = *ParseOP.get(); + + llvm::CrashRecoveryContextCleanupRegistrar<const void, ResetStackCleanup> + CleanupPrettyStack(llvm::SavePrettyStackState()); + PrettyStackTraceParserEntry CrashInfo(P); + + // Recover resources if we crash before exiting this method. + llvm::CrashRecoveryContextCleanupRegistrar<Parser> + CleanupParser(ParseOP.get()); + + S.getPreprocessor().EnterMainSourceFile(); + ExternalASTSource *External = S.getASTContext().getExternalSource(); + if (External) + External->StartTranslationUnit(Consumer); + + // If a PCH through header is specified that does not have an include in + // the source, or a PCH is being created with #pragma hdrstop with nothing + // after the pragma, there won't be any tokens or a Lexer. + bool HaveLexer = S.getPreprocessor().getCurrentLexer(); + + if (HaveLexer) { + llvm::TimeTraceScope TimeScope("Frontend"); + P.Initialize(); + Parser::DeclGroupPtrTy ADecl; + for (bool AtEOF = P.ParseFirstTopLevelDecl(ADecl); !AtEOF; + AtEOF = P.ParseTopLevelDecl(ADecl)) { + // If we got a null return and something *was* parsed, ignore it. This + // is due to a top-level semicolon, an action override, or a parse error + // skipping something. + if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) + return; + } + } + + // Process any TopLevelDecls generated by #pragma weak. + for (Decl *D : S.WeakTopLevelDecls()) + Consumer->HandleTopLevelDecl(DeclGroupRef(D)); + + Consumer->HandleTranslationUnit(S.getASTContext()); + + // Finalize the template instantiation observer chain. + // FIXME: This (and init.) should be done in the Sema class, but because + // Sema does not have a reliable "Finalize" function (it has a + // destructor, but it is not guaranteed to be called ("-disable-free")). + // So, do the initialization above and do the finalization here: + finalize(S.TemplateInstCallbacks, S); + + std::swap(OldCollectStats, S.CollectStats); + if (PrintStats) { + llvm::errs() << "\nSTATISTICS:\n"; + if (HaveLexer) P.getActions().PrintStats(); + S.getASTContext().PrintStats(); + Decl::PrintStats(); + Stmt::PrintStats(); + Consumer->PrintStats(); + } +}