1212795Sdim//===--- ParseAST.cpp - Provide the clang::ParseAST method ----------------===// 2212795Sdim// 3212795Sdim// The LLVM Compiler Infrastructure 4212795Sdim// 5212795Sdim// This file is distributed under the University of Illinois Open Source 6212795Sdim// License. See LICENSE.TXT for details. 7212795Sdim// 8212795Sdim//===----------------------------------------------------------------------===// 9212795Sdim// 10212795Sdim// This file implements the clang::ParseAST method. 11212795Sdim// 12212795Sdim//===----------------------------------------------------------------------===// 13212795Sdim 14212795Sdim#include "clang/Parse/ParseAST.h" 15212795Sdim#include "clang/AST/ASTConsumer.h" 16245431Sdim#include "clang/AST/ASTContext.h" 17212795Sdim#include "clang/AST/DeclCXX.h" 18212795Sdim#include "clang/AST/ExternalASTSource.h" 19212795Sdim#include "clang/AST/Stmt.h" 20252723Sdim#include "clang/Parse/ParseDiagnostic.h" 21212795Sdim#include "clang/Parse/Parser.h" 22252723Sdim#include "clang/Sema/CodeCompleteConsumer.h" 23252723Sdim#include "clang/Sema/ExternalSemaSource.h" 24252723Sdim#include "clang/Sema/Sema.h" 25252723Sdim#include "clang/Sema/SemaConsumer.h" 26221345Sdim#include "llvm/ADT/OwningPtr.h" 27221345Sdim#include "llvm/Support/CrashRecoveryContext.h" 28212795Sdim#include <cstdio> 29212795Sdim 30212795Sdimusing namespace clang; 31212795Sdim 32252723Sdimnamespace { 33252723Sdim 34252723Sdim/// If a crash happens while the parser is active, an entry is printed for it. 35252723Sdimclass PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry { 36252723Sdim const Parser &P; 37252723Sdimpublic: 38252723Sdim PrettyStackTraceParserEntry(const Parser &p) : P(p) {} 39252723Sdim virtual void print(raw_ostream &OS) const; 40252723Sdim}; 41252723Sdim 42252723Sdim/// If a crash happens while the parser is active, print out a line indicating 43252723Sdim/// what the current token is. 44252723Sdimvoid PrettyStackTraceParserEntry::print(raw_ostream &OS) const { 45252723Sdim const Token &Tok = P.getCurToken(); 46252723Sdim if (Tok.is(tok::eof)) { 47252723Sdim OS << "<eof> parser at end of file\n"; 48252723Sdim return; 49252723Sdim } 50252723Sdim 51252723Sdim if (Tok.getLocation().isInvalid()) { 52252723Sdim OS << "<unknown> parser at unknown location\n"; 53252723Sdim return; 54252723Sdim } 55252723Sdim 56252723Sdim const Preprocessor &PP = P.getPreprocessor(); 57252723Sdim Tok.getLocation().print(OS, PP.getSourceManager()); 58252723Sdim if (Tok.isAnnotation()) { 59252723Sdim OS << ": at annotation token\n"; 60252723Sdim } else { 61252723Sdim // Do the equivalent of PP.getSpelling(Tok) except for the parts that would 62252723Sdim // allocate memory. 63252723Sdim bool Invalid = false; 64252723Sdim const SourceManager &SM = P.getPreprocessor().getSourceManager(); 65252723Sdim unsigned Length = Tok.getLength(); 66252723Sdim const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid); 67252723Sdim if (Invalid) { 68252723Sdim OS << ": unknown current parser token\n"; 69252723Sdim return; 70252723Sdim } 71252723Sdim OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n"; 72252723Sdim } 73252723Sdim} 74252723Sdim 75252723Sdim} // namespace 76252723Sdim 77212795Sdim//===----------------------------------------------------------------------===// 78212795Sdim// Public interface to the file 79212795Sdim//===----------------------------------------------------------------------===// 80212795Sdim 81212795Sdim/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as 82212795Sdim/// the file is parsed. This inserts the parsed decls into the translation unit 83212795Sdim/// held by Ctx. 84212795Sdim/// 85212795Sdimvoid clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer, 86212795Sdim ASTContext &Ctx, bool PrintStats, 87226890Sdim TranslationUnitKind TUKind, 88235633Sdim CodeCompleteConsumer *CompletionConsumer, 89235633Sdim bool SkipFunctionBodies) { 90221345Sdim 91252723Sdim OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer)); 92221345Sdim 93221345Sdim // Recover resources if we crash before exiting this method. 94235633Sdim llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get()); 95221345Sdim 96235633Sdim ParseAST(*S.get(), PrintStats, SkipFunctionBodies); 97212795Sdim} 98212795Sdim 99235633Sdimvoid clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) { 100212795Sdim // Collect global stats on Decls/Stmts (until we have a module streamer). 101212795Sdim if (PrintStats) { 102235633Sdim Decl::EnableStatistics(); 103235633Sdim Stmt::EnableStatistics(); 104212795Sdim } 105212795Sdim 106224145Sdim // Also turn on collection of stats inside of the Sema object. 107224145Sdim bool OldCollectStats = PrintStats; 108224145Sdim std::swap(OldCollectStats, S.CollectStats); 109224145Sdim 110212795Sdim ASTConsumer *Consumer = &S.getASTConsumer(); 111212795Sdim 112235633Sdim OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S, 113235633Sdim SkipFunctionBodies)); 114221345Sdim Parser &P = *ParseOP.get(); 115221345Sdim 116221345Sdim PrettyStackTraceParserEntry CrashInfo(P); 117221345Sdim 118221345Sdim // Recover resources if we crash before exiting this method. 119221345Sdim llvm::CrashRecoveryContextCleanupRegistrar<Parser> 120235633Sdim CleanupParser(ParseOP.get()); 121221345Sdim 122212795Sdim S.getPreprocessor().EnterMainSourceFile(); 123212795Sdim P.Initialize(); 124245431Sdim 125245431Sdim // C11 6.9p1 says translation units must have at least one top-level 126245431Sdim // declaration. C++ doesn't have this restriction. We also don't want to 127245431Sdim // complain if we have a precompiled header, although technically if the PCH 128245431Sdim // is empty we should still emit the (pedantic) diagnostic. 129245431Sdim Parser::DeclGroupPtrTy ADecl; 130245431Sdim ExternalASTSource *External = S.getASTContext().getExternalSource(); 131245431Sdim if (External) 132212795Sdim External->StartTranslationUnit(Consumer); 133235633Sdim 134245431Sdim if (P.ParseTopLevelDecl(ADecl)) { 135245431Sdim if (!External && !S.getLangOpts().CPlusPlus) 136245431Sdim P.Diag(diag::ext_empty_translation_unit); 137245431Sdim } else { 138245431Sdim do { 139245431Sdim // If we got a null return and something *was* parsed, ignore it. This 140245431Sdim // is due to a top-level semicolon, an action override, or a parse error 141245431Sdim // skipping something. 142245431Sdim if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get())) 143252723Sdim return; 144245431Sdim } while (!P.ParseTopLevelDecl(ADecl)); 145245431Sdim } 146245431Sdim 147212795Sdim // Process any TopLevelDecls generated by #pragma weak. 148263509Sdim for (SmallVectorImpl<Decl *>::iterator 149212795Sdim I = S.WeakTopLevelDecls().begin(), 150212795Sdim E = S.WeakTopLevelDecls().end(); I != E; ++I) 151212795Sdim Consumer->HandleTopLevelDecl(DeclGroupRef(*I)); 152212795Sdim 153212795Sdim Consumer->HandleTranslationUnit(S.getASTContext()); 154224145Sdim 155224145Sdim std::swap(OldCollectStats, S.CollectStats); 156212795Sdim if (PrintStats) { 157224145Sdim llvm::errs() << "\nSTATISTICS:\n"; 158212795Sdim P.getActions().PrintStats(); 159212795Sdim S.getASTContext().PrintStats(); 160212795Sdim Decl::PrintStats(); 161212795Sdim Stmt::PrintStats(); 162212795Sdim Consumer->PrintStats(); 163212795Sdim } 164212795Sdim} 165