#include "clang/Parse/ParseAST.h"
#include "clang/AST/ASTConsumer.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/ParseDiagnostic.h"
#include "clang/Parse/Parser.h"
#include "clang/Sema/CodeCompleteConsumer.h"
#include "clang/Sema/ExternalSemaSource.h"
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaConsumer.h"
#include "llvm/ADT/OwningPtr.h"
#include "llvm/Support/CrashRecoveryContext.h"
#include <cstdio>
using namespace clang;
namespace {
class PrettyStackTraceParserEntry : public llvm::PrettyStackTraceEntry {
const Parser &P;
public:
PrettyStackTraceParserEntry(const Parser &p) : P(p) {}
virtual void print(raw_ostream &OS) const;
};
void PrettyStackTraceParserEntry::print(raw_ostream &OS) const {
const Token &Tok = P.getCurToken();
if (Tok.is(tok::eof)) {
OS << "<eof> parser at end of file\n";
return;
}
if (Tok.getLocation().isInvalid()) {
OS << "<unknown> parser at unknown location\n";
return;
}
const Preprocessor &PP = P.getPreprocessor();
Tok.getLocation().print(OS, PP.getSourceManager());
if (Tok.isAnnotation()) {
OS << ": at annotation token\n";
} else {
bool Invalid = false;
const SourceManager &SM = P.getPreprocessor().getSourceManager();
unsigned Length = Tok.getLength();
const char *Spelling = SM.getCharacterData(Tok.getLocation(), &Invalid);
if (Invalid) {
OS << ": unknown current parser token\n";
return;
}
OS << ": current parser token '" << StringRef(Spelling, Length) << "'\n";
}
}
}
void clang::ParseAST(Preprocessor &PP, ASTConsumer *Consumer,
ASTContext &Ctx, bool PrintStats,
TranslationUnitKind TUKind,
CodeCompleteConsumer *CompletionConsumer,
bool SkipFunctionBodies) {
OwningPtr<Sema> S(new Sema(PP, Ctx, *Consumer, TUKind, CompletionConsumer));
llvm::CrashRecoveryContextCleanupRegistrar<Sema> CleanupSema(S.get());
ParseAST(*S.get(), PrintStats, SkipFunctionBodies);
}
void clang::ParseAST(Sema &S, bool PrintStats, bool SkipFunctionBodies) {
if (PrintStats) {
Decl::EnableStatistics();
Stmt::EnableStatistics();
}
bool OldCollectStats = PrintStats;
std::swap(OldCollectStats, S.CollectStats);
ASTConsumer *Consumer = &S.getASTConsumer();
OwningPtr<Parser> ParseOP(new Parser(S.getPreprocessor(), S,
SkipFunctionBodies));
Parser &P = *ParseOP.get();
PrettyStackTraceParserEntry CrashInfo(P);
llvm::CrashRecoveryContextCleanupRegistrar<Parser>
CleanupParser(ParseOP.get());
S.getPreprocessor().EnterMainSourceFile();
P.Initialize();
Parser::DeclGroupPtrTy ADecl;
ExternalASTSource *External = S.getASTContext().getExternalSource();
if (External)
External->StartTranslationUnit(Consumer);
if (P.ParseTopLevelDecl(ADecl)) {
if (!External && !S.getLangOpts().CPlusPlus)
P.Diag(diag::ext_empty_translation_unit);
} else {
do {
if (ADecl && !Consumer->HandleTopLevelDecl(ADecl.get()))
return;
} while (!P.ParseTopLevelDecl(ADecl));
}
for (SmallVectorImpl<Decl *>::iterator
I = S.WeakTopLevelDecls().begin(),
E = S.WeakTopLevelDecls().end(); I != E; ++I)
Consumer->HandleTopLevelDecl(DeclGroupRef(*I));
Consumer->HandleTranslationUnit(S.getASTContext());
std::swap(OldCollectStats, S.CollectStats);
if (PrintStats) {
llvm::errs() << "\nSTATISTICS:\n";
P.getActions().PrintStats();
S.getASTContext().PrintStats();
Decl::PrintStats();
Stmt::PrintStats();
Consumer->PrintStats();
}
}