ParseAST.cpp revision 478851c3ed6bd784e7377dffd8e57b200c1b9ba9
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/Parse/ParseDiagnostic.h"
16#include "clang/Sema/Sema.h"
17#include "clang/Sema/CodeCompleteConsumer.h"
18#include "clang/Sema/SemaConsumer.h"
19#include "clang/Sema/ExternalSemaSource.h"
20#include "clang/AST/ASTConsumer.h"
21#include "clang/AST/ASTContext.h"
22#include "clang/AST/DeclCXX.h"
23#include "clang/AST/ExternalASTSource.h"
24#include "clang/AST/Stmt.h"
25#include "clang/Parse/Parser.h"
26#include "llvm/ADT/OwningPtr.h"
27#include "llvm/Support/CrashRecoveryContext.h"
28#include <cstdio>
29
30using namespace clang;
31
32//===----------------------------------------------------------------------===//
33// Public interface to the file
34//===----------------------------------------------------------------------===//
35
36/// ParseAST - Parse the entire file specified, notifying the ASTConsumer as
37/// the file is parsed.  This inserts the parsed decls into the translation unit
38/// held by Ctx.
39///
40void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
41                     ASTContext &Ctx, bool PrintStats,
42                     TranslationUnitKind TUKind,
43                     CodeCompleteConsumer *CompletionConsumer,
44                     bool SkipFunctionBodies) {
45
46  OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer,
47                                   TUKind,
48                                   CompletionConsumer));
49
50  // Recover resources if we crash before exiting this method.
51  llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
52
53  ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
54}
55
56void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
57  // Collect global stats on Decls/Stmts (until we have a module streamer).
58  if (PrintStats) {
59    Decl::EnableStatistics();
60    Stmt::EnableStatistics();
61  }
62
63  // Also turn on collection of stats inside of the Sema object.
64  bool OldCollectStats = PrintStats;
65  std::swap(OldCollectStats, S.CollectStats);
66
67  ASTConsumer *Consumer = &S.getASTConsumer();
68
69  OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
70                                       SkipFunctionBodies));
71  Parser &P = *ParseOP.get();
72
73  PrettyStackTraceParserEntry CrashInfo(P);
74
75  // Recover resources if we crash before exiting this method.
76  llvm::CrashRecoveryContextCleanupRegistrar<Parser>
77    CleanupParser(ParseOP.get());
78
79  S.getPreprocessor().EnterMainSourceFile();
80  P.Initialize();
81  S.Initialize();
82
83  // C11 6.9p1 says translation units must have at least one top-level
84  // declaration. C++ doesn't have this restriction. We also don't want to
85  // complain if we have a precompiled header, although technically if the PCH
86  // is empty we should still emit the (pedantic) diagnostic.
87  Parser::DeclGroupPtrTy ADecl;
88  ExternalASTSource *External = S.getASTContext().getExternalSource();
89  if (External)
90    External->StartTranslationUnit(Consumer);
91
92  if (P.ParseTopLevelDecl(ADecl)) {
93    if (!External && !S.getLangOpts().CPlusPlus)
94      P.Diag(diag::ext_empty_translation_unit);
95  } else {
96    do {
97      // If we got a null return and something *was* parsed, ignore it.  This
98      // is due to a top-level semicolon, an action override, or a parse error
99      // skipping something.
100      if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
101	return;
102    } while (!P.ParseTopLevelDecl(ADecl));
103  }
104
105  // Process any TopLevelDecls generated by #pragma weak.
106  for (SmallVector<Decl*,2>::iterator
107       I = S.WeakTopLevelDecls().begin(),
108       E = S.WeakTopLevelDecls().end(); I != E; ++I)
109    Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
110
111  Consumer->HandleTranslationUnit(S.getASTContext());
112
113  std::swap(OldCollectStats, S.CollectStats);
114  if (PrintStats) {
115    llvm::errs() << "\nSTATISTICS:\n";
116    P.getActions().PrintStats();
117    S.getASTContext().PrintStats();
118    Decl::PrintStats();
119    Stmt::PrintStats();
120    Consumer->PrintStats();
121  }
122}
123