From 49f28ca787d8db7cac3c8898334f70ea55374c98 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 5 Mar 2009 08:00:35 +0000 Subject: [PATCH] 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. parser at end of file 2. t.c:1:5: LLVM IR generation of declaration 'a' Abort for IR generation crashes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66153 91177308-0d34-0410-b5e6-96231b3b80d8 --- Driver/Backend.cpp | 37 +++++++++++++++++++++++++----------- include/clang/AST/DeclBase.h | 17 +++++++++++++++++ include/clang/Parse/Action.h | 11 +++++++---- lib/AST/DeclBase.cpp | 22 +++++++++++++++++++++ lib/Parse/MinimalAction.cpp | 2 +- lib/Parse/ParseDecl.cpp | 6 +++--- lib/Parse/ParseDeclCXX.cpp | 12 ++++++------ lib/Parse/ParseObjc.cpp | 6 +++--- lib/Parse/ParseStmt.cpp | 6 +++--- 9 files changed, 88 insertions(+), 31 deletions(-) diff --git a/Driver/Backend.cpp b/Driver/Backend.cpp index cf53f3cc75..e2633dfc3e 100644 --- a/Driver/Backend.cpp +++ b/Driver/Backend.cpp @@ -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()) diff --git a/include/clang/AST/DeclBase.h b/include/clang/AST/DeclBase.h index 7dee2a6561..da9054f8d6 100644 --- a/include/clang/AST/DeclBase.h +++ b/include/clang/AST/DeclBase.h @@ -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): diff --git a/include/clang/Parse/Action.h b/include/clang/Parse/Action.h index 21ae8c021d..87faf4cf9e 100644 --- a/include/clang/Parse/Action.h +++ b/include/clang/Parse/Action.h @@ -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; diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp index 3e968c7896..1e7ef549b4 100644 --- a/lib/AST/DeclBase.cpp +++ b/lib/AST/DeclBase.cpp @@ -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 #include #include @@ -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(TheDecl)) + OS << " '" << DN->getQualifiedNameAsString() << '\''; + OS << '\n'; +} + //===----------------------------------------------------------------------===// // Decl Implementation //===----------------------------------------------------------------------===// diff --git a/lib/Parse/MinimalAction.cpp b/lib/Parse/MinimalAction.cpp index 3b8694c5d7..41ad36c83e 100644 --- a/lib/Parse/MinimalAction.cpp +++ b/lib/Parse/MinimalAction.cpp @@ -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 << ": "; diff --git a/lib/Parse/ParseDecl.cpp b/lib/Parse/ParseDecl.cpp index 6e0ffe5e2b..50b6716df8 100644 --- a/lib/Parse/ParseDecl.cpp +++ b/lib/Parse/ParseDecl.cpp @@ -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(); diff --git a/lib/Parse/ParseDeclCXX.cpp b/lib/Parse/ParseDeclCXX.cpp index 538185abc4..ef57737675 100644 --- a/lib/Parse/ParseDeclCXX.cpp +++ b/lib/Parse/ParseDeclCXX.cpp @@ -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(); diff --git a/lib/Parse/ParseObjc.cpp b/lib/Parse/ParseObjc.cpp index 981333d7e9..e9bb3d7c31 100644 --- a/lib/Parse/ParseObjc.cpp +++ b/lib/Parse/ParseObjc.cpp @@ -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)) diff --git a/lib/Parse/ParseStmt.cpp b/lib/Parse/ParseStmt.cpp index cb9bdc7cfb..fe83247082 100644 --- a/lib/Parse/ParseStmt.cpp +++ b/lib/Parse/ParseStmt.cpp @@ -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 -- 2.40.0