ParseAST.cpp revision 31e6c7ddfeeefe05b67220bc87fa23d4338d1056
1//===--- ASTStreamer.cpp - Provide streaming interface to ASTs ------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file was developed by Chris Lattner and is distributed under
6// the University of Illinois Open Source License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file implements the ASTStreamer interface.
11//
12//===----------------------------------------------------------------------===//
13
14#include "clang/Sema/ASTStreamer.h"
15#include "clang/AST/ASTContext.h"
16#include "clang/AST/ASTConsumer.h"
17#include "Sema.h"
18#include "clang/Parse/Action.h"
19#include "clang/Parse/Parser.h"
20using namespace clang;
21
22ASTConsumer::~ASTConsumer() {}
23
24namespace {
25  class ASTStreamer {
26    Parser P;
27    std::vector<Decl*> LastInGroupList;
28  public:
29    ASTStreamer(Preprocessor &pp, ASTContext &ctxt, unsigned MainFileID)
30      : P(pp, *new Sema(pp, ctxt, LastInGroupList)) {
31      pp.EnterMainSourceFile(MainFileID);
32
33      // Initialize the parser.
34      P.Initialize();
35    }
36
37    /// ReadTopLevelDecl - Parse and return the next top-level declaration.
38    Decl *ReadTopLevelDecl();
39
40    void PrintStats() const;
41
42    ~ASTStreamer() {
43      P.Finalize();
44      delete &P.getActions();
45    }
46  };
47}
48
49/// ReadTopLevelDecl - Parse and return the next top-level declaration.
50///
51Decl *ASTStreamer::ReadTopLevelDecl() {
52  Parser::DeclTy *Result;
53
54  /// If the previous time through we read something like 'int X, Y', return
55  /// the next declarator.
56  if (!LastInGroupList.empty()) {
57    Result = LastInGroupList.back();
58    LastInGroupList.pop_back();
59    return static_cast<Decl*>(Result);
60  }
61
62  do {
63    if (P.ParseTopLevelDecl(Result))
64      return 0;  // End of file.
65
66    // If we got a null return and something *was* parsed, try again.  This
67    // is due to a top-level semicolon, an action override, or a parse error
68    // skipping something.
69  } while (Result == 0);
70
71  // If we parsed a declspec with multiple declarators, reverse the list and
72  // return the first one.
73  if (!LastInGroupList.empty()) {
74    LastInGroupList.push_back((Decl*)Result);
75    std::reverse(LastInGroupList.begin(), LastInGroupList.end());
76    Result = LastInGroupList.back();
77    LastInGroupList.pop_back();
78  }
79
80  return static_cast<Decl*>(Result);
81}
82
83void ASTStreamer::PrintStats() const {
84  P.getActions().PrintStats();
85}
86
87//===----------------------------------------------------------------------===//
88// Public interface to the file
89//===----------------------------------------------------------------------===//
90
91/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
92/// the file is parsed.  This takes ownership of the ASTConsumer and
93/// ultimately deletes it.
94void clang::ParseAST(Preprocessor &PP, unsigned MainFileID,
95                     ASTConsumer *Consumer, bool PrintStats) {
96  // Collect global stats on Decls/Stmts (until we have a module streamer).
97  if (PrintStats) {
98    Decl::CollectingStats(true);
99    Stmt::CollectingStats(true);
100  }
101
102  ASTContext Context(PP.getSourceManager(), PP.getTargetInfo(),
103                     PP.getIdentifierTable(), PP.getSelectorTable());
104
105  ASTStreamer Streamer(PP, Context, MainFileID);
106
107  Consumer->Initialize(Context, MainFileID);
108
109  while (Decl *D = Streamer.ReadTopLevelDecl())
110    Consumer->HandleTopLevelDecl(D);
111
112  if (PrintStats) {
113    fprintf(stderr, "\nSTATISTICS:\n");
114    Streamer.PrintStats();
115    Context.PrintStats();
116    Decl::PrintStats();
117    Stmt::PrintStats();
118    Consumer->PrintStats();
119
120    Decl::CollectingStats(false);
121    Stmt::CollectingStats(false);
122  }
123
124  delete Consumer;
125}
126