using namespace llvm;
namespace {
- class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
+ class VISIBILITY_HIDDEN BackendConsumer : public ASTConsumer {
BackendAction Action;
CompileOptions CompileOpts;
const std::string &InputFile;
std::string OutputFile;
bool GenerateDebugInfo;
+ ASTContext *Context;
Timer LLVMIRGeneration;
Timer CodeGenerationTime;
public:
BackendConsumer(BackendAction action, Diagnostic &Diags,
const LangOptions &langopts, const CompileOptions &compopts,
- const std::string& infile, const std::string& outfile,
- bool debug) :
+ const std::string &infile, const std::string &outfile,
+ bool debug) :
Action(action),
CompileOpts(compopts),
InputFile(infile),
}
virtual void InitializeTU(TranslationUnit& TU) {
+ Context = &TU.getContext();
if (CompileOpts.TimePasses)
LLVMIRGeneration.startTimer();
}
virtual void HandleTopLevelDecl(Decl *D) {
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ Context->getSourceManager(),
+ "LLVM IR generation of declaration");
if (CompileOpts.TimePasses)
LLVMIRGeneration.startTimer();
}
virtual void HandleTranslationUnit(TranslationUnit& TU) {
- if (CompileOpts.TimePasses)
- LLVMIRGeneration.startTimer();
+ {
+ PrettyStackTraceString CrashInfo("per-file LLVM IR generation");
+ if (CompileOpts.TimePasses)
+ LLVMIRGeneration.startTimer();
- Gen->HandleTranslationUnit(TU);
+ Gen->HandleTranslationUnit(TU);
- if (CompileOpts.TimePasses)
- LLVMIRGeneration.stopTimer();
+ if (CompileOpts.TimePasses)
+ LLVMIRGeneration.stopTimer();
+ }
- // EmitAssembly times itself.
+ // EmitAssembly times and registers crash info itself.
EmitAssembly();
// Force a flush here in case we never get released.
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
+ PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
+ Context->getSourceManager(),
+ "LLVM IR generation of declaration");
Gen->HandleTagDeclDefinition(D);
}
};
return;
-
TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);
// Make sure IR generation is happy with the module. This is
// would like to have the option of streaming code generation.
if (PerFunctionPasses) {
+ PrettyStackTraceString CrashInfo("per-function optimization");
+
PerFunctionPasses->doInitialization();
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (!I->isDeclaration())
PerFunctionPasses->doFinalization();
}
- if (PerModulePasses)
+ if (PerModulePasses) {
+ PrettyStackTraceString CrashInfo("per-module optimization passes");
PerModulePasses->run(*M);
+ }
if (CodeGenPasses) {
+ PrettyStackTraceString CrashInfo("code generation");
CodeGenPasses->doInitialization();
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I)
if (!I->isDeclaration())
#include "clang/AST/Type.h"
// FIXME: Layering violation
#include "clang/Parse/AccessSpecifier.h"
+#include "llvm/Support/PrettyStackTrace.h"
namespace clang {
class DeclContext;
}
};
+/// PrettyStackTraceDecl - If a crash occurs, indicate that it happened when
+/// doing something to a specific decl.
+class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
+ Decl *TheDecl;
+ SourceLocation Loc;
+ SourceManager &SM;
+ const char *Message;
+public:
+ PrettyStackTraceDecl(Decl *theDecl, SourceLocation L,
+ SourceManager &sm, const char *Msg)
+ : TheDecl(theDecl), Loc(L), SM(sm), Message(Msg) {}
+
+ virtual void print(llvm::raw_ostream &OS) const;
+};
+
+
/// DeclContext - This is used only as base class of specific decl types that
/// can act as declaration contexts. These decls are (only the top classes
/// that directly derive from DeclContext are mentioned, not their subclasses):
AttributeList *AttrList);
};
-
-class PrettyStackTraceDecl : public llvm::PrettyStackTraceEntry {
+/// PrettyStackTraceActionsDecl - If a crash occurs in the parser while parsing
+/// something related to a virtualized decl, include that virtualized decl in
+/// the stack trace.
+class PrettyStackTraceActionsDecl : public llvm::PrettyStackTraceEntry {
Action::DeclTy *TheDecl;
SourceLocation Loc;
Action &Actions;
SourceManager &SM;
const char *Message;
public:
- PrettyStackTraceDecl(Action::DeclTy *Decl, SourceLocation L,
- Action &actions, SourceManager &sm, const char *Msg)
+ PrettyStackTraceActionsDecl(Action::DeclTy *Decl, SourceLocation L,
+ Action &actions, SourceManager &sm,
+ const char *Msg)
: TheDecl(Decl), Loc(L), Actions(actions), SM(sm), Message(Msg) {}
virtual void print(llvm::raw_ostream &OS) const;
#include "clang/AST/ASTContext.h"
#include "clang/AST/Type.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cstdio>
#include <functional>
}
}
+//===----------------------------------------------------------------------===//
+// PrettyStackTraceDecl Implementation
+//===----------------------------------------------------------------------===//
+
+void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
+ SourceLocation TheLoc = Loc;
+ if (TheLoc.isInvalid() && TheDecl)
+ TheLoc = TheDecl->getLocation();
+
+ if (TheLoc.isValid()) {
+ TheLoc.print(OS, SM);
+ OS << ": ";
+ }
+
+ OS << Message;
+
+ if (NamedDecl *DN = dyn_cast_or_null<NamedDecl>(TheDecl))
+ OS << " '" << DN->getQualifiedNameAsString() << '\'';
+ OS << '\n';
+}
+
//===----------------------------------------------------------------------===//
// Decl Implementation
//===----------------------------------------------------------------------===//
}
-void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
+void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
if (Loc.isValid()) {
Loc.print(OS, SM);
OS << ": ";
///
void Parser::ParseStructUnionBody(SourceLocation RecordLoc,
unsigned TagType, DeclTy *TagDecl) {
- PrettyStackTraceDecl CrashInfo(TagDecl, RecordLoc, Actions,
- PP.getSourceManager(),
- "parsing struct/union body");
+ PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
+ PP.getSourceManager(),
+ "parsing struct/union body");
SourceLocation LBraceLoc = ConsumeBrace();
DeclTy *NamespcDecl =
Actions.ActOnStartNamespaceDef(CurScope, IdentLoc, Ident, LBrace);
- PrettyStackTraceDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
- PP.getSourceManager(),
- "parsing namespace");
+ PrettyStackTraceActionsDecl CrashInfo(NamespcDecl, NamespaceLoc, Actions,
+ PP.getSourceManager(),
+ "parsing namespace");
while (Tok.isNot(tok::r_brace) && Tok.isNot(tok::eof))
ParseExternalDeclaration();
TagType == DeclSpec::TST_union ||
TagType == DeclSpec::TST_class) && "Invalid TagType!");
- PrettyStackTraceDecl CrashInfo(TagDecl, RecordLoc, Actions,
- PP.getSourceManager(),
- "parsing struct/union/class body");
+ PrettyStackTraceActionsDecl CrashInfo(TagDecl, RecordLoc, Actions,
+ PP.getSourceManager(),
+ "parsing struct/union/class body");
SourceLocation LBraceLoc = ConsumeBrace();
Parser::DeclTy *Parser::ParseObjCMethodDefinition() {
DeclTy *MDecl = ParseObjCMethodPrototype(ObjCImpDecl);
- PrettyStackTraceDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
- PP.getSourceManager(),
- "parsing Objective-C method");
+ PrettyStackTraceActionsDecl CrashInfo(MDecl, Tok.getLocation(), Actions,
+ PP.getSourceManager(),
+ "parsing Objective-C method");
// parse optional ';'
if (Tok.is(tok::semi))
assert(Tok.is(tok::l_brace));
SourceLocation LBraceLoc = Tok.getLocation();
- PrettyStackTraceDecl CrashInfo(Decl, LBraceLoc, Actions,
- PP.getSourceManager(),
- "parsing function body");
+ PrettyStackTraceActionsDecl CrashInfo(Decl, LBraceLoc, Actions,
+ PP.getSourceManager(),
+ "parsing function body");
// Do not enter a scope for the brace, as the arguments are in the same scope
// (the function body) as the body itself. Instead, just read the statement