//===--- ASTStreamer.cpp - Provide streaming interface to ASTs ------------===// // // The LLVM Compiler Infrastructure // // This file was developed by Chris Lattner and is distributed under // the University of Illinois Open Source License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // This file implements the ASTStreamer interface. // //===----------------------------------------------------------------------===// #include "clang/Sema/ASTStreamer.h" #include "clang/AST/ASTContext.h" #include "clang/AST/ASTConsumer.h" #include "Sema.h" #include "clang/Parse/Action.h" #include "clang/Parse/Parser.h" using namespace clang; ASTConsumer::~ASTConsumer() {} namespace { class ASTStreamer { Parser P; std::vector LastInGroupList; public: ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID) : P(pp, *new Sema(pp, ctxt, LastInGroupList)) { pp.EnterMainSourceFile(MainFileID); // Initialize the parser. P.Initialize(); } /// ReadTopLevelDecl - Parse and return the next top-level declaration. Decl *ReadTopLevelDecl(); void PrintStats() const; ~ASTStreamer() { P.Finalize(); delete &P.getActions(); } }; } /// ReadTopLevelDecl - Parse and return the next top-level declaration. /// Decl *ASTStreamer::ReadTopLevelDecl() { Parser::DeclTy *Result; /// If the previous time through we read something like 'int X, Y', return /// the next declarator. if (!LastInGroupList.empty()) { Result = LastInGroupList.back(); LastInGroupList.pop_back(); return static_cast(Result); } do { if (P.ParseTopLevelDecl(Result)) return 0; // End of file. // If we got a null return and something *was* parsed, try again. This // is due to a top-level semicolon, an action override, or a parse error // skipping something. } while (Result == 0); // If we parsed a declspec with multiple declarators, reverse the list and // return the first one. if (!LastInGroupList.empty()) { LastInGroupList.push_back((Decl*)Result); std::reverse(LastInGroupList.begin(), LastInGroupList.end()); Result = LastInGroupList.back(); LastInGroupList.pop_back(); } return static_cast(Result); } void ASTStreamer::PrintStats() const { P.getActions().PrintStats(); } //===----------------------------------------------------------------------===// // Public interface to the file //===----------------------------------------------------------------------===// /// ParseAST - Parse the entire file specified, notifying the ASTConsumer as /// the file is parsed. void clang::ParseAST(Preprocessor &PP, unsigned MainFileID, ASTConsumer &Consumer, bool PrintStats) { // Collect global stats on Decls/Stmts (until we have a module streamer). if (PrintStats) { Decl::CollectingStats(true); Stmt::CollectingStats(true); } ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(), PP.getIdentifierTable(), PP.getSelectorTable()); ASTStreamer Streamer(PP, Context, MainFileID); Consumer.Initialize(Context, MainFileID); while (Decl *D = Streamer.ReadTopLevelDecl()) Consumer.HandleTopLevelDecl(D); Consumer.HandleObjcMetaDataEmission(); if (PrintStats) { fprintf(stderr, "\nSTATISTICS:\n"); Streamer.PrintStats(); Context.PrintStats(); Decl::PrintStats(); Stmt::PrintStats(); Consumer.PrintStats(); Decl::CollectingStats(false); Stmt::CollectingStats(false); } }