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