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