From bd61a95481aebeaf8e9efec9a17ad5c4b6e6552a Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Thu, 5 Mar 2009 00:00:31 +0000 Subject: [PATCH] Include information about compound statements when crashing in sema or the parser. For example, we now print out: 0. t.c:5:10: in compound statement {} 1. t.c:3:12: in compound statement {} 2. clang t.c -fsyntax-only llvm-svn: 66108 --- clang/include/clang/Basic/PrettyStackTrace.h | 37 ++++++++++++++++ clang/include/clang/Basic/SourceLocation.h | 6 ++- clang/lib/Basic/SourceLocation.cpp | 46 +++++++++++++++----- clang/lib/Parse/ParseDecl.cpp | 4 +- clang/lib/Parse/ParseStmt.cpp | 9 +++- 5 files changed, 85 insertions(+), 17 deletions(-) create mode 100644 clang/include/clang/Basic/PrettyStackTrace.h diff --git a/clang/include/clang/Basic/PrettyStackTrace.h b/clang/include/clang/Basic/PrettyStackTrace.h new file mode 100644 index 000000000000..8ee833bf673b --- /dev/null +++ b/clang/include/clang/Basic/PrettyStackTrace.h @@ -0,0 +1,37 @@ +//===- clang/Basic/PrettyStackTrace.h - Pretty Crash Handling --*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file defines the PrettyStackTraceEntry class, which is used to make +// crashes give more contextual information about what the program was doing +// when it crashed. +// +//===----------------------------------------------------------------------===// + +#ifndef CLANG_BASIC_PRETTYSTACKTRACE_H +#define CLANG_BASIC_PRETTYSTACKTRACE_H + +#include "clang/Basic/SourceLocation.h" +#include "llvm/Support/PrettyStackTrace.h" + +namespace clang { + + /// PrettyStackTraceLoc - If a crash happens while one of these objects are + /// live, . + class PrettyStackTraceLoc : public llvm::PrettyStackTraceEntry { + SourceManager &SM; + SourceLocation Loc; + const char *Message; + public: + PrettyStackTraceLoc(SourceManager &sm, SourceLocation L, const char *Msg) + : SM(sm), Loc(L), Message(Msg) {} + virtual void print(llvm::raw_ostream &OS) const; + }; +} + +#endif diff --git a/clang/include/clang/Basic/SourceLocation.h b/clang/include/clang/Basic/SourceLocation.h index b75214004949..b5906e1393b8 100644 --- a/clang/include/clang/Basic/SourceLocation.h +++ b/clang/include/clang/Basic/SourceLocation.h @@ -14,12 +14,13 @@ #ifndef LLVM_CLANG_SOURCELOCATION_H #define LLVM_CLANG_SOURCELOCATION_H -#include #include "llvm/Bitcode/SerializationFwd.h" #include +#include namespace llvm { class MemoryBuffer; + class raw_ostream; template struct DenseMapInfo; } @@ -134,7 +135,8 @@ public: /// ReadVal - Read a SourceLocation object from Bitcode. static SourceLocation ReadVal(llvm::Deserializer& D); - + + void print(llvm::raw_ostream &OS, const SourceManager &SM) const; void dump(const SourceManager &SM) const; }; diff --git a/clang/lib/Basic/SourceLocation.cpp b/clang/lib/Basic/SourceLocation.cpp index 73e231adc8f3..fd90b5a2ce99 100644 --- a/clang/lib/Basic/SourceLocation.cpp +++ b/clang/lib/Basic/SourceLocation.cpp @@ -13,14 +13,31 @@ //===----------------------------------------------------------------------===// #include "clang/Basic/SourceLocation.h" +#include "clang/Basic/PrettyStackTrace.h" #include "clang/Basic/SourceManager.h" #include "llvm/Bitcode/Serialize.h" #include "llvm/Bitcode/Deserialize.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" #include - using namespace clang; +//===----------------------------------------------------------------------===// +// PrettyStackTraceLoc +//===----------------------------------------------------------------------===// + +void PrettyStackTraceLoc::print(llvm::raw_ostream &OS) const { + if (Loc.isValid()) { + Loc.print(OS, SM); + OS << ": "; + } + OS << Message << '\n'; +} + +//===----------------------------------------------------------------------===// +// SourceLocation +//===----------------------------------------------------------------------===// + void SourceLocation::Emit(llvm::Serializer& S) const { S.EmitInt(getRawEncoding()); } @@ -29,28 +46,31 @@ SourceLocation SourceLocation::ReadVal(llvm::Deserializer& D) { return SourceLocation::getFromRawEncoding(D.ReadInt()); } -void SourceLocation::dump(const SourceManager &SM) const { +void SourceLocation::print(llvm::raw_ostream &OS, const SourceManager &SM)const{ if (!isValid()) { - fprintf(stderr, ""); + OS << ""; return; } if (isFileID()) { PresumedLoc PLoc = SM.getPresumedLoc(*this); - // The instantiation and spelling pos is identical for file locs. - fprintf(stderr, "%s:%d:%d", - PLoc.getFilename(), PLoc.getLine(), PLoc.getColumn()); + OS << PLoc.getFilename() << ':' << PLoc.getLine() + << ':' << PLoc.getColumn(); return; } - SM.getInstantiationLoc(*this).dump(SM); - - fprintf(stderr, " "); + SM.getInstantiationLoc(*this).print(OS, SM); + + OS << " '; } +void SourceLocation::dump(const SourceManager &SM) const { + print(llvm::errs(), SM); + llvm::errs().flush(); +} void SourceRange::Emit(llvm::Serializer& S) const { B.Emit(S); @@ -63,6 +83,10 @@ SourceRange SourceRange::ReadVal(llvm::Deserializer& D) { return SourceRange(A,B); } +//===----------------------------------------------------------------------===// +// FullSourceLoc +//===----------------------------------------------------------------------===// + FileID FullSourceLoc::getFileID() const { assert(isValid()); return SrcMgr->getFileID(*this); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7aef5ff06942..b24b80eb7114 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -1848,7 +1848,6 @@ void Parser::ParseDirectDeclarator(Declarator &D) { // If we reached this point, we are either in C/ObjC or the token didn't // satisfy any of the C++-specific checks. - if (Tok.is(tok::identifier) && D.mayHaveIdentifier()) { assert(!getLang().CPlusPlus && "There's a C++-specific check for tok::identifier above"); @@ -2080,7 +2079,8 @@ void Parser::ParseFunctionDeclarator(SourceLocation LParenLoc, Declarator &D, // Enter function-declaration scope, limiting any declarators to the // function prototype scope, including parameter declarators. - ParseScope PrototypeScope(this, Scope::FunctionPrototypeScope|Scope::DeclScope); + ParseScope PrototypeScope(this, + Scope::FunctionPrototypeScope|Scope::DeclScope); bool IsVariadic = false; SourceLocation EllipsisLoc; diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp index 208338a71a4f..4f7affc69cae 100644 --- a/clang/lib/Parse/ParseStmt.cpp +++ b/clang/lib/Parse/ParseStmt.cpp @@ -15,10 +15,11 @@ #include "clang/Parse/Parser.h" #include "ExtensionRAIIObject.h" #include "AstGuard.h" -#include "clang/Basic/Diagnostic.h" -#include "clang/Basic/SourceManager.h" #include "clang/Parse/DeclSpec.h" #include "clang/Parse/Scope.h" +#include "clang/Basic/Diagnostic.h" +#include "clang/Basic/PrettyStackTrace.h" +#include "clang/Basic/SourceManager.h" using namespace clang; //===----------------------------------------------------------------------===// @@ -409,6 +410,10 @@ Parser::OwningStmtResult Parser::ParseCompoundStatement(bool isStmtExpr) { /// consume the '}' at the end of the block. It does not manipulate the scope /// stack. Parser::OwningStmtResult Parser::ParseCompoundStatementBody(bool isStmtExpr) { + PrettyStackTraceLoc CrashInfo(PP.getSourceManager(), + Tok.getLocation(), + "in compound statement ('{}')"); + SourceLocation LBraceLoc = ConsumeBrace(); // eat the '{'. // TODO: "__label__ X, Y, Z;" is the GNU "Local Label" extension. These are