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