]> granicus.if.org Git - clang/commitdiff
rename PrettyStackTraceDecl -> PrettyStackTraceActionsDecl.
authorChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 08:00:35 +0000 (08:00 +0000)
committerChris Lattner <sabre@nondot.org>
Thu, 5 Mar 2009 08:00:35 +0000 (08:00 +0000)
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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@66153 91177308-0d34-0410-b5e6-96231b3b80d8

Driver/Backend.cpp
include/clang/AST/DeclBase.h
include/clang/Parse/Action.h
lib/AST/DeclBase.cpp
lib/Parse/MinimalAction.cpp
lib/Parse/ParseDecl.cpp
lib/Parse/ParseDeclCXX.cpp
lib/Parse/ParseObjc.cpp
lib/Parse/ParseStmt.cpp

index cf53f3cc7548eb9820d5e0fed6c61ca71f3b7eea..e2633dfc3e6a334a6f0f6ba5d3a3256a9944b4e1 100644 (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())
index 7dee2a6561cd5dda6bfdacf644552d357baa197e..da9054f8d6ad6bfceb0e1b63ecfe36ef8f4fb2fd 100644 (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):
index 21ae8c021d6d9b7e88da9c36b1ab3a77f04c8f82..87faf4cf9e92020d7df67b860792bed46f1df2ad 100644 (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;
index 3e968c7896262711edf4008b8f405ff803071bae..1e7ef549b43472cd171b54861b2a201dc2685fc7 100644 (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
 //===----------------------------------------------------------------------===//
index 3b8694c5d7aba86aefda478dbc4fa54147487137..41ad36c83ee72501a8c9bc11743fee60814ee44c 100644 (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 << ": ";
index 6e0ffe5e2b68858daf5fa4d9874979c3b6e52127..50b6716df8cc8e301046f667e91c2798d34a95c8 100644 (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();
   
index 538185abc4e78ec5d37ade1c10215ad445826b04..ef577376753520bd46a565f13c96c9208e0811bb 100644 (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();
 
index 981333d7e9ebfe75e2dc313fe79206f5d9bd556c..e9bb3d7c31e28bf15a8a3a96bc3d98e491dce74b 100644 (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))
index cb9bdc7cfb7496265ca4ea1efe24c06e6ec3d63f..fe83247082366abf17c5c2c73d0ae12c8d666ca4 100644 (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