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