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