Skip to content
This repository was archived by the owner on Nov 1, 2021. It is now read-only.

Commit ac7cc2d

Browse files
committed
[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 git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@186639 91177308-0d34-0410-b5e6-96231b3b80d8
1 parent 8fed3f4 commit ac7cc2d

File tree

6 files changed

+74
-9
lines changed

6 files changed

+74
-9
lines changed

include/clang/Analysis/AnalysisContext.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ class LocationContext : public llvm::FoldingSetNode {
256256

257257
virtual void Profile(llvm::FoldingSetNodeID &ID) = 0;
258258

259+
void dumpStack(raw_ostream &OS, StringRef Indent = "") const;
259260
LLVM_ATTRIBUTE_USED void dumpStack() const;
260261

261262
public:

lib/Analysis/AnalysisDeclContext.cpp

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -410,7 +410,7 @@ bool LocationContext::isParentOf(const LocationContext *LC) const {
410410
return false;
411411
}
412412

413-
void LocationContext::dumpStack() const {
413+
void LocationContext::dumpStack(raw_ostream &OS, StringRef Indent) const {
414414
ASTContext &Ctx = getAnalysisDeclContext()->getASTContext();
415415
PrintingPolicy PP(Ctx.getLangOpts());
416416
PP.TerseOutput = 1;
@@ -419,22 +419,26 @@ void LocationContext::dumpStack() const {
419419
for (const LocationContext *LCtx = this; LCtx; LCtx = LCtx->getParent()) {
420420
switch (LCtx->getKind()) {
421421
case StackFrame:
422-
llvm::errs() << '#' << Frame++ << ' ';
423-
cast<StackFrameContext>(LCtx)->getDecl()->print(llvm::errs(), PP);
424-
llvm::errs() << '\n';
422+
OS << Indent << '#' << Frame++ << ' ';
423+
cast<StackFrameContext>(LCtx)->getDecl()->print(OS, PP);
424+
OS << '\n';
425425
break;
426426
case Scope:
427-
llvm::errs() << " (scope)\n";
427+
OS << Indent << " (scope)\n";
428428
break;
429429
case Block:
430-
llvm::errs() << " (block context: "
430+
OS << Indent << " (block context: "
431431
<< cast<BlockInvocationContext>(LCtx)->getContextData()
432432
<< ")\n";
433433
break;
434434
}
435435
}
436436
}
437437

438+
void LocationContext::dumpStack() const {
439+
dumpStack(llvm::errs());
440+
}
441+
438442
//===----------------------------------------------------------------------===//
439443
// Lazily generated map to query the external variables referenced by a Block.
440444
//===----------------------------------------------------------------------===//

lib/StaticAnalyzer/Checkers/ExprInspectionChecker.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ class ExprInspectionChecker : public Checker< eval::Call > {
2222

2323
void analyzerEval(const CallExpr *CE, CheckerContext &C) const;
2424
void analyzerCheckInlined(const CallExpr *CE, CheckerContext &C) const;
25+
void analyzerCrash(const CallExpr *CE, CheckerContext &C) const;
2526

2627
typedef void (ExprInspectionChecker::*FnCheck)(const CallExpr *,
2728
CheckerContext &C) const;
@@ -39,6 +40,7 @@ bool ExprInspectionChecker::evalCall(const CallExpr *CE,
3940
.Case("clang_analyzer_eval", &ExprInspectionChecker::analyzerEval)
4041
.Case("clang_analyzer_checkInlined",
4142
&ExprInspectionChecker::analyzerCheckInlined)
43+
.Case("clang_analyzer_crash", &ExprInspectionChecker::analyzerCrash)
4244
.Default(0);
4345

4446
if (!Handler)
@@ -117,6 +119,11 @@ void ExprInspectionChecker::analyzerCheckInlined(const CallExpr *CE,
117119
C.emitReport(R);
118120
}
119121

122+
void ExprInspectionChecker::analyzerCrash(const CallExpr *CE,
123+
CheckerContext &C) const {
124+
LLVM_BUILTIN_TRAP;
125+
}
126+
120127
void ento::registerExprInspectionChecker(CheckerManager &Mgr) {
121128
Mgr.registerChecker<ExprInspectionChecker>();
122129
}

lib/StaticAnalyzer/Core/ExprEngine.cpp

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#define DEBUG_TYPE "ExprEngine"
1717

1818
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
19+
#include "PrettyStackTraceLocationContext.h"
1920
#include "clang/AST/CharUnits.h"
2021
#include "clang/AST/ParentMap.h"
2122
#include "clang/AST/StmtCXX.h"
@@ -263,6 +264,7 @@ void ExprEngine::processEndWorklist(bool hasWorkRemaining) {
263264

264265
void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
265266
unsigned StmtIdx, NodeBuilderContext *Ctx) {
267+
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
266268
currStmtIdx = StmtIdx;
267269
currBldrCtx = Ctx;
268270

@@ -280,7 +282,6 @@ void ExprEngine::processCFGElement(const CFGElement E, ExplodedNode *Pred,
280282
ProcessImplicitDtor(E.castAs<CFGImplicitDtor>(), Pred);
281283
return;
282284
}
283-
currBldrCtx = 0;
284285
}
285286

286287
static bool shouldRemoveDeadBindings(AnalysisManager &AMgr,
@@ -1202,7 +1203,8 @@ bool ExprEngine::replayWithoutInlining(ExplodedNode *N,
12021203
void ExprEngine::processCFGBlockEntrance(const BlockEdge &L,
12031204
NodeBuilderWithSinks &nodeBuilder,
12041205
ExplodedNode *Pred) {
1205-
1206+
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
1207+
12061208
// FIXME: Refactor this into a checker.
12071209
if (nodeBuilder.getContext().blockCount() >= AMgr.options.maxBlockVisitOnPath) {
12081210
static SimpleProgramPointTag tag("ExprEngine : Block count exceeded");
@@ -1326,6 +1328,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term,
13261328
ExplodedNodeSet &Dst,
13271329
const CFGBlock *DstT,
13281330
const CFGBlock *DstF) {
1331+
PrettyStackTraceLocationContext StackCrashInfo(Pred->getLocationContext());
13291332
currBldrCtx = &BldCtx;
13301333

13311334
// Check for NULL conditions; e.g. "for(;;)"
@@ -1426,6 +1429,7 @@ void ExprEngine::processStaticInitializer(const DeclStmt *DS,
14261429
clang::ento::ExplodedNodeSet &Dst,
14271430
const CFGBlock *DstT,
14281431
const CFGBlock *DstF) {
1432+
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
14291433
currBldrCtx = &BuilderCtx;
14301434

14311435
const VarDecl *VD = cast<VarDecl>(DS->getSingleDecl());
@@ -1491,6 +1495,7 @@ void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) {
14911495
/// nodes when the control reaches the end of a function.
14921496
void ExprEngine::processEndOfFunction(NodeBuilderContext& BC,
14931497
ExplodedNode *Pred) {
1498+
PrettyStackTraceLocationContext CrashInfo(Pred->getLocationContext());
14941499
StateMgr.EndPath(Pred->getState());
14951500

14961501
ExplodedNodeSet Dst;

lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#define DEBUG_TYPE "ExprEngine"
1515

1616
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
17+
#include "PrettyStackTraceLocationContext.h"
1718
#include "clang/AST/CXXInheritance.h"
1819
#include "clang/AST/DeclCXX.h"
1920
#include "clang/AST/ParentMap.h"
@@ -39,6 +40,8 @@ STATISTIC(NumReachedInlineCountMax,
3940
void ExprEngine::processCallEnter(CallEnter CE, ExplodedNode *Pred) {
4041
// Get the entry block in the CFG of the callee.
4142
const StackFrameContext *calleeCtx = CE.getCalleeContext();
43+
PrettyStackTraceLocationContext CrashInfo(calleeCtx);
44+
4245
const CFG *CalleeCFG = calleeCtx->getCFG();
4346
const CFGBlock *Entry = &(CalleeCFG->getEntry());
4447

@@ -214,7 +217,7 @@ static bool isTemporaryPRValue(const CXXConstructExpr *E, SVal V) {
214217
/// 5. PostStmt<CallExpr>
215218
void ExprEngine::processCallExit(ExplodedNode *CEBNode) {
216219
// Step 1 CEBNode was generated before the call.
217-
220+
PrettyStackTraceLocationContext CrashInfo(CEBNode->getLocationContext());
218221
const StackFrameContext *calleeCtx =
219222
CEBNode->getLocationContext()->getCurrentStackFrame();
220223

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//==- PrettyStackTraceLocationContext.h - show analysis backtrace --*- C++ -*-//
2+
//
3+
// The LLVM Compiler Infrastructure
4+
//
5+
// This file is distributed under the University of Illinois Open Source
6+
// License. See LICENSE.TXT for details.
7+
//
8+
//===----------------------------------------------------------------------===//
9+
10+
#ifndef LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H
11+
#define LLVM_CLANG_STATICANALYZER_PRETTYSTACKTRACELOCATIONCONTEXT_H
12+
13+
#include "clang/Analysis/AnalysisContext.h"
14+
15+
namespace clang {
16+
namespace ento {
17+
18+
/// While alive, includes the current analysis stack in a crash trace.
19+
///
20+
/// Example:
21+
/// \code
22+
/// 0. Program arguments: ...
23+
/// 1. <eof> parser at end of file
24+
/// 2. While analyzing stack:
25+
/// #0 void inlined()
26+
/// #1 void test()
27+
/// 3. crash-trace.c:6:3: Error evaluating statement
28+
/// \endcode
29+
class PrettyStackTraceLocationContext : public llvm::PrettyStackTraceEntry {
30+
const LocationContext *LCtx;
31+
public:
32+
PrettyStackTraceLocationContext(const LocationContext *LC) : LCtx(LC) {
33+
assert(LCtx);
34+
}
35+
36+
virtual void print(raw_ostream &OS) const {
37+
OS << "While analyzing stack: \n";
38+
LCtx->dumpStack(OS, "\t");
39+
}
40+
};
41+
42+
} // end ento namespace
43+
} // end clang namespace
44+
45+
#endif

0 commit comments

Comments
 (0)