rename PrettyStackTraceDecl -> PrettyStackTraceActionsDecl.

Introduce a new PrettyStackTraceDecl.
Use it to add the top level LLVM IR generation stuff in 
Backend.cpp to stack traces.  We now get crashes like:

Stack dump:
0.	Program arguments: clang t.c -emit-llvm 
1.	<eof> parser at end of file
2.	t.c:1:5: LLVM IR generation of declaration 'a'
Abort

for IR generation crashes.

llvm-svn: 66153
This commit is contained in:
Chris Lattner 2009-03-05 08:00:35 +00:00
parent 1d09f6a221
commit eae6cb6154
9 changed files with 88 additions and 31 deletions

View File

@ -39,12 +39,13 @@ using namespace clang;
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;
@ -78,8 +79,8 @@ namespace {
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),
@ -105,6 +106,7 @@ namespace {
}
virtual void InitializeTU(TranslationUnit& TU) {
Context = &TU.getContext();
if (CompileOpts.TimePasses)
LLVMIRGeneration.startTimer();
@ -121,6 +123,9 @@ namespace {
}
virtual void HandleTopLevelDecl(Decl *D) {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of declaration");
if (CompileOpts.TimePasses)
LLVMIRGeneration.startTimer();
@ -131,15 +136,18 @@ namespace {
}
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.
@ -148,6 +156,9 @@ namespace {
}
virtual void HandleTagDeclDefinition(TagDecl *D) {
PrettyStackTraceDecl CrashInfo(D, SourceLocation(),
Context->getSourceManager(),
"LLVM IR generation of declaration");
Gen->HandleTagDeclDefinition(D);
}
};
@ -359,7 +370,6 @@ void BackendConsumer::EmitAssembly() {
return;
TimeRegion Region(CompileOpts.TimePasses ? &CodeGenerationTime : 0);
// Make sure IR generation is happy with the module. This is
@ -388,6 +398,8 @@ void BackendConsumer::EmitAssembly() {
// 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())
@ -395,10 +407,13 @@ void BackendConsumer::EmitAssembly() {
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())

View File

@ -18,6 +18,7 @@
#include "clang/AST/Type.h"
// FIXME: Layering violation
#include "clang/Parse/AccessSpecifier.h"
#include "llvm/Support/PrettyStackTrace.h"
namespace clang {
class DeclContext;
@ -327,6 +328,22 @@ protected:
}
};
/// 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):

View File

@ -1516,16 +1516,19 @@ public:
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;

View File

@ -19,6 +19,7 @@
#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>
@ -91,6 +92,27 @@ void Decl::addDeclKind(Kind k) {
}
}
//===----------------------------------------------------------------------===//
// 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
//===----------------------------------------------------------------------===//

View File

@ -42,7 +42,7 @@ Action::DeclTy *Action::ActOnUsingDirective(Scope *CurScope,
}
void PrettyStackTraceDecl::print(llvm::raw_ostream &OS) const {
void PrettyStackTraceActionsDecl::print(llvm::raw_ostream &OS) const {
if (Loc.isValid()) {
Loc.print(OS, SM);
OS << ": ";

View File

@ -1096,9 +1096,9 @@ ParseStructDeclaration(DeclSpec &DS,
///
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();

View File

@ -73,9 +73,9 @@ Parser::DeclTy *Parser::ParseNamespace(unsigned Context) {
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();
@ -793,9 +793,9 @@ void Parser::ParseCXXMemberSpecification(SourceLocation RecordLoc,
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();

View File

@ -1356,9 +1356,9 @@ Parser::OwningStmtResult Parser::ParseObjCTryStmt(SourceLocation atLoc) {
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))

View File

@ -1288,9 +1288,9 @@ Parser::DeclTy *Parser::ParseFunctionStatementBody(DeclTy *Decl) {
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