forked from OSchip/llvm-project
[analyzer] Include analysis stack in crash traces.
Sample output: 0. Program arguments: ... 1. <eof> parser at end of file 2. While analyzing stack: #0 void inlined() #1 void test() 3. crash-trace.c:6:3: Error evaluating statement llvm-svn: 186639
This commit is contained in:
parent
978c839315
commit
e9c57229f9
|
@ -256,6 +256,7 @@ public:
|
|||
|
||||
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
|
||||
|
||||
void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
|
||||
LLVM_ATTRIBUTE_USED void dumpStack() const;
|
||||
|
||||
public:
|
||||
|
|
|
@ -410,7 +410,7 @@ bool LocationContext::isParentOf(const LocationContext *LC) const {
|
|||
return false;
|
||||
}
|
||||
|
||||
void LocationContext::dumpStack() const {
|
||||
void LocationContext::dumpStack(raw_ostream &OS, StringRef Indent) const {
|
||||
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
|
||||
PrintingPolicy PP(Ctx.getLangOpts());
|
||||
PP.TerseOutput = 1;
|
||||
|
@ -419,15 +419,15 @@ void LocationContext::dumpStack() const {
|
|||
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
|
||||
switch (LCtx->getKind()) {
|
||||
case StackFrame:
|
||||
llvm::errs() << '#' << Frame++ << ' ';
|
||||
cast<StackFrameContext>(LCtx)->getDecl()->print(llvm::errs(), PP);
|
||||
llvm::errs() << '\n';
|
||||
OS << Indent << '#' << Frame++ << ' ';
|
||||
cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP);
|
||||
OS << '\n';
|
||||
break;
|
||||
case Scope:
|
||||
llvm::errs() << " (scope)\n";
|
||||
OS << Indent << " (scope)\n";
|
||||
break;
|
||||
case Block:
|
||||
llvm::errs() << " (block context: "
|
||||
OS << Indent << " (block context: "
|
||||
<< cast<BlockInvocationContext>(LCtx)->getContextData()
|
||||
<< ")\n";
|
||||
break;
|
||||
|
@ -435,6 +435,10 @@ void LocationContext::dumpStack() const {
|
|||
}
|
||||
}
|
||||
|
||||
void LocationContext::dumpStack() const {
|
||||
dumpStack(llvm::errs());
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
// Lazily generated map to query the external variables referenced by a Block.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
|
|
@ -22,6 +22,7 @@ class ExprInspectionChecker : public Checker< eval::Call > {
|
|||
|
||||
void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
|
||||
void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
|
||||
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
|
||||
|
||||
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
|
||||
CheckerContext &C) const;
|
||||
|
@ -39,6 +40,7 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
|
|||
.Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
|
||||
.Case("clang_analyzer_checkInlined",
|
||||
&ExprInspectionChecker::analyzerCheckInlined)
|
||||
.Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
|
||||
.Default(0);
|
||||
|
||||
if (!Handler)
|
||||
|
@ -117,6 +119,11 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
|
|||
C.emitReport(R);
|
||||
}
|
||||
|
||||
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
|
||||
CheckerContext &C) const {
|
||||
LLVM_BUILTIN_TRAP;
|
||||
}
|
||||
|
||||
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
|
||||
Mgr.registerChecker<ExprInspectionChecker>();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#define DEBUG_TYPE "ExprEngine"
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "PrettyStackTraceLocationContext.h"
|
||||
#include "clang/AST/CharUnits.h"
|
||||
#include "clang/AST/ParentMap.h"
|
||||
#include "clang/AST/StmtCXX.h"
|
||||
|
@ -263,6 +264,7 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
|
|||
|
||||
void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
|
||||
unsigned StmtIdx, NodeBuilderContext *Ctx) {
|
||||
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
|
||||
currStmtIdx = StmtIdx;
|
||||
currBldrCtx = Ctx;
|
||||
|
||||
|
@ -280,7 +282,6 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
|
|||
ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
|
||||
return;
|
||||
}
|
||||
currBldrCtx = 0;
|
||||
}
|
||||
|
||||
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
|
||||
|
@ -1202,7 +1203,8 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
|
|||
void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
|
||||
NodeBuilderWithSinks &nodeBuilder,
|
||||
ExplodedNode *Pred) {
|
||||
|
||||
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
|
||||
|
||||
// FIXME: Refactor this into a checker.
|
||||
if (nodeBuilder.getContext().blockCount() >= AMgr.options.maxBlockVisitOnPath) {
|
||||
static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
|
||||
|
@ -1326,6 +1328,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
|
|||
ExplodedNodeSet &Dst,
|
||||
const CFGBlock *DstT,
|
||||
const CFGBlock *DstF) {
|
||||
PrettyStackTraceLocationContext StackCrashInfo(Pred->getLocationContext());
|
||||
currBldrCtx = &BldCtx;
|
||||
|
||||
// Check for NULL conditions; e.g. "for(;;)"
|
||||
|
@ -1426,6 +1429,7 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
|
|||
clang::ento::ExplodedNodeSet &Dst,
|
||||
const CFGBlock *DstT,
|
||||
const CFGBlock *DstF) {
|
||||
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
|
||||
currBldrCtx = &BuilderCtx;
|
||||
|
||||
const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
|
||||
|
@ -1491,6 +1495,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
|
|||
/// nodes when the control reaches the end of a function.
|
||||
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
|
||||
ExplodedNode *Pred) {
|
||||
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
|
||||
StateMgr.EndPath(Pred->getState());
|
||||
|
||||
ExplodedNodeSet Dst;
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#define DEBUG_TYPE "ExprEngine"
|
||||
|
||||
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
||||
#include "PrettyStackTraceLocationContext.h"
|
||||
#include "clang/AST/CXXInheritance.h"
|
||||
#include "clang/AST/DeclCXX.h"
|
||||
#include "clang/AST/ParentMap.h"
|
||||
|
@ -39,6 +40,8 @@ STATISTIC(NumReachedInlineCountMax,
|
|||
void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
|
||||
// Get the entry block in the CFG of the callee.
|
||||
const StackFrameContext *calleeCtx = CE.getCalleeContext();
|
||||
PrettyStackTraceLocationContext CrashInfo(calleeCtx);
|
||||
|
||||
const CFG *CalleeCFG = calleeCtx->getCFG();
|
||||
const CFGBlock *Entry = &(CalleeCFG->getEntry());
|
||||
|
||||
|
@ -214,7 +217,7 @@ static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) {
|
|||
/// 5. PostStmt<CallExpr>
|
||||
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
|
||||
// Step 1 CEBNode was generated before the call.
|
||||
|
||||
PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
|
||||
const StackFrameContext *calleeCtx =
|
||||
CEBNode->getLocationContext()->getCurrentStackFrame();
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
//==- PrettyStackTraceLocationContext.h - show analysis backtrace --*- C++ -*-//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H
|
||||
#define LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H
|
||||
|
||||
#include "clang/Analysis/AnalysisContext.h"
|
||||
|
||||
namespace clang {
|
||||
namespace ento {
|
||||
|
||||
/// While alive, includes the current analysis stack in a crash trace.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// 0. Program arguments: ...
|
||||
/// 1. <eof> parser at end of file
|
||||
/// 2. While analyzing stack:
|
||||
/// #0 void inlined()
|
||||
/// #1 void test()
|
||||
/// 3. crash-trace.c:6:3: Error evaluating statement
|
||||
/// \endcode
|
||||
class PrettyStackTraceLocationContext : public llvm::PrettyStackTraceEntry {
|
||||
const LocationContext *LCtx;
|
||||
public:
|
||||
PrettyStackTraceLocationContext(const LocationContext *LC) : LCtx(LC) {
|
||||
assert(LCtx);
|
||||
}
|
||||
|
||||
virtual void print(raw_ostream &OS) const {
|
||||
OS << "While analyzing stack: \n";
|
||||
LCtx->dumpStack(OS, "\t");
|
||||
}
|
||||
};
|
||||
|
||||
} // end ento namespace
|
||||
} // end clang namespace
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue