From 199fdd825f6eb930cea281d5b83615e617e54c2a Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Mon, 29 Oct 2012 17:31:53 +0000 Subject: [PATCH] [analyzer] Use the CallEnter node to get a value for tracked null arguments. Additionally, don't collect PostStore nodes -- they are often used in path diagnostics. Previously, we tried to track null arguments in the same way as any other null values, but in many cases the necessary nodes had already been collected (a memory optimization in ExplodedGraph). Now, we fall back to using the value of the argument at the time of the call, which may not always match the actual contents of the region, but often will. This is a precursor to improving our suppression heuristic. llvm-svn: 166940 --- .../Core/BugReporter/BugReporterVisitor.h | 13 +- .../StaticAnalyzer/Core/BugReporterVisitors.cpp | 73 +- clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp | 4 +- .../inlining/eager-reclamation-path-notes.c | 788 +++++++++++++++++++++ 4 files changed, 850 insertions(+), 28 deletions(-) create mode 100644 clang/test/Analysis/inlining/eager-reclamation-path-notes.c diff --git a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h index b4592c0..a378473 100644 --- a/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h +++ b/clang/include/clang/StaticAnalyzer/Core/BugReporter/BugReporterVisitor.h @@ -258,7 +258,18 @@ public: namespace bugreporter { -void trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R); +/// Attempts to add visitors to trace a null or undefined value back to its +/// point of origin, whether it is a symbol constrained to null or an explicit +/// assignment. +/// +/// \param N A node "downstream" from the evaluation of the statement. +/// \param S The statement whose value is null or undefined. +/// \param R The bug report to which visitors should be attached. +/// \param IsArg Whether the statement is an argument to an inlined function. +/// If this is the case, \p N \em must be the CallEnter node for +/// the function. +void trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, BugReport &R, + bool IsArg = false); const Stmt *GetDerefExpr(const ExplodedNode *N); const Stmt *GetDenomExpr(const ExplodedNode *N); diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 213a52a..dace7f3 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -283,6 +283,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, const ExplodedNode *StoreSite = 0; const Expr *InitE = 0; + bool IsParam = false; // First see if we reached the declaration of the region. if (const VarRegion *VR = dyn_cast(R)) { @@ -327,6 +328,7 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, CallEventRef<> Call = CallMgr.getCaller(CE->getCalleeContext(), Succ->getState()); InitE = Call->getArgExpr(Param->getFunctionScopeIndex()); + IsParam = true; } } @@ -337,12 +339,14 @@ PathDiagnosticPiece *FindLastStoreBRVisitor::VisitNode(const ExplodedNode *Succ, // If we have an expression that provided the value, try to track where it // came from. if (InitE) { - InitE = InitE->IgnoreParenCasts(); - - if (V.isUndef() || isa(V)) - bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR); - else - ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE, BR); + if (V.isUndef() || isa(V)) { + if (!IsParam) + InitE = InitE->IgnoreParenCasts(); + bugreporter::trackNullOrUndefValue(StoreSite, InitE, BR, IsParam); + } else { + ReturnVisitor::addVisitorIfNecessary(StoreSite, InitE->IgnoreParenCasts(), + BR); + } } if (!R->canPrintPretty()) @@ -522,30 +526,32 @@ TrackConstraintBRVisitor::VisitNode(const ExplodedNode *N, } void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, - BugReport &report) { + BugReport &report, bool IsArg) { if (!S || !N) return; if (const OpaqueValueExpr *OVE = dyn_cast(S)) S = OVE->getSourceExpr(); - ProgramStateManager &StateMgr = N->getState()->getStateManager(); - - // Walk through nodes until we get one that matches the statement exactly. - while (N) { - const ProgramPoint &pp = N->getLocation(); - if (const PostStmt *ps = dyn_cast(&pp)) { - if (ps->getStmt() == S) - break; - } else if (const CallExitEnd *CEE = dyn_cast(&pp)) { - if (CEE->getCalleeContext()->getCallSite() == S) - break; - } - N = N->getFirstPred(); - } + if (IsArg) { + assert(isa(N->getLocation()) && "Tracking arg but not at call"); + } else { + // Walk through nodes until we get one that matches the statement exactly. + do { + const ProgramPoint &pp = N->getLocation(); + if (const PostStmt *ps = dyn_cast(&pp)) { + if (ps->getStmt() == S) + break; + } else if (const CallExitEnd *CEE = dyn_cast(&pp)) { + if (CEE->getCalleeContext()->getCallSite() == S) + break; + } + N = N->getFirstPred(); + } while (N); - if (!N) - return; + if (!N) + return; + } ProgramStateRef state = N->getState(); @@ -560,11 +566,28 @@ void bugreporter::trackNullOrUndefValue(const ExplodedNode *N, const Stmt *S, // FIXME: Right now we only track VarDecls because it's non-trivial to // get a MemRegion for any other DeclRefExprs. if (const VarDecl *VD = dyn_cast(DR->getDecl())) { - const VarRegion *R = - StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); + ProgramStateManager &StateMgr = state->getStateManager(); + MemRegionManager &MRMgr = StateMgr.getRegionManager(); + const VarRegion *R = MRMgr.getVarRegion(VD, N->getLocationContext()); // Mark both the variable region and its contents as interesting. SVal V = state->getRawSVal(loc::MemRegionVal(R)); + + // If the value matches the default for the variable region, that + // might mean that it's been cleared out of the state. Fall back to + // the full argument expression (with casts and such intact). + if (IsArg) { + bool UseArgValue = V.isUnknownOrUndef() || V.isZeroConstant(); + if (!UseArgValue) { + const SymbolRegionValue *SRV = + dyn_cast_or_null(V.getAsLocSymbol()); + if (SRV) + UseArgValue = (SRV->getRegion() == R); + } + if (UseArgValue) + V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); + } + report.markInteresting(R); report.markInteresting(V); report.addVisitor(new UndefOrNullArgVisitor(R)); diff --git a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp index 9b70d68..c284bd7 100644 --- a/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExplodedGraph.cpp @@ -61,7 +61,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // // (1) 1 predecessor (that has one successor) // (2) 1 successor (that has one predecessor) - // (3) The ProgramPoint is for a PostStmt. + // (3) The ProgramPoint is for a PostStmt, but not a PostStore. // (4) There is no 'tag' for the ProgramPoint. // (5) The 'store' is the same as the predecessor. // (6) The 'GDM' is the same as the predecessor. @@ -85,7 +85,7 @@ bool ExplodedGraph::shouldCollect(const ExplodedNode *node) { // Condition 3. ProgramPoint progPoint = node->getLocation(); - if (!isa(progPoint)) + if (!isa(progPoint) || isa(progPoint)) return false; // Condition 4. diff --git a/clang/test/Analysis/inlining/eager-reclamation-path-notes.c b/clang/test/Analysis/inlining/eager-reclamation-path-notes.c new file mode 100644 index 0000000..6c7c05a --- /dev/null +++ b/clang/test/Analysis/inlining/eager-reclamation-path-notes.c @@ -0,0 +1,788 @@ +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=text -analyzer-config graph-trim-interval=5 -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-output=plist-multi-file -analyzer-config graph-trim-interval=5 %s -o %t.plist +// RUN: FileCheck --input-file=%t.plist %s + +void use(int *ptr, int val) { + *ptr = val; // expected-warning {{Dereference of null pointer (loaded from variable 'ptr')}} + // expected-note@-1 {{Dereference of null pointer (loaded from variable 'ptr')}} +} + +int compute() { + // Do something that will take enough processing to trigger trimming. + // FIXME: This is actually really sensitive. If the interval timing is just + // wrong, the node for the actual dereference may also be collected, and all + // the path notes will disappear. + return 2 + 3 + 4 + 5 + 6; +} + +void testSimple() { + int *p = 0; + // expected-note@-1 {{Variable 'p' initialized to a null pointer value}} + use(p, compute()); + // expected-note@-1 {{Passing null pointer value via 1st parameter 'ptr'}} + // expected-note@-2 {{Calling 'use'}} +} + + +void use2(int *ptr, int val) { + *ptr = val; // expected-warning {{Dereference of null pointer (loaded from variable 'ptr')}} + // expected-note@-1 {{Dereference of null pointer (loaded from variable 'ptr')}} +} + +void passThrough(int *p) { + use2(p, compute()); + // expected-note@-1 {{Passing null pointer value via 1st parameter 'ptr'}} + // expected-note@-2 {{Calling 'use2'}} +} + +void testChainedCalls() { + int *ptr = 0; + // expected-note@-1 {{Variable 'ptr' initialized to a null pointer value}} + passThrough(ptr); + // expected-note@-1 {{Passing null pointer value via 1st parameter 'p'}} + // expected-note@-2 {{Calling 'passThrough'}} +} + +// CHECK: diagnostics +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Variable 'p' initialized to a null pointer value +// CHECK-NEXT: message +// CHECK-NEXT: Variable 'p' initialized to a null pointer value +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line19 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col16 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col16 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col16 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col7 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'ptr' +// CHECK-NEXT: message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'ptr' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line21 +// CHECK-NEXT: col19 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling 'use' +// CHECK-NEXT: message +// CHECK-NEXT: Calling 'use' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line5 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entered call from 'testSimple' +// CHECK-NEXT: message +// CHECK-NEXT: Entered call from 'testSimple' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line5 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line5 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionDereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: categoryLogic error +// CHECK-NEXT: typeDereference of null pointer +// CHECK-NEXT: issue_context_kindfunction +// CHECK-NEXT: issue_contextuse +// CHECK-NEXT: issue_hash1 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line6 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line39 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line39 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line39 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Variable 'ptr' initialized to a null pointer value +// CHECK-NEXT: message +// CHECK-NEXT: Variable 'ptr' initialized to a null pointer value +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line39 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line39 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col13 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col13 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col15 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'p' +// CHECK-NEXT: message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'p' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line41 +// CHECK-NEXT: col18 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling 'passThrough' +// CHECK-NEXT: message +// CHECK-NEXT: Calling 'passThrough' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line32 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entered call from 'testChainedCalls' +// CHECK-NEXT: message +// CHECK-NEXT: Entered call from 'testChainedCalls' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line32 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line32 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col11 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col17 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'ptr' +// CHECK-NEXT: message +// CHECK-NEXT: Passing null pointer value via 1st parameter 'ptr' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line33 +// CHECK-NEXT: col20 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth1 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Calling 'use2' +// CHECK-NEXT: message +// CHECK-NEXT: Calling 'use2' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line27 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth2 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Entered call from 'passThrough' +// CHECK-NEXT: message +// CHECK-NEXT: Entered call from 'passThrough' +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line27 +// CHECK-NEXT: col1 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line27 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth2 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: message +// CHECK-NEXT: Dereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionDereference of null pointer (loaded from variable 'ptr') +// CHECK-NEXT: categoryLogic error +// CHECK-NEXT: typeDereference of null pointer +// CHECK-NEXT: issue_context_kindfunction +// CHECK-NEXT: issue_contextuse2 +// CHECK-NEXT: issue_hash1 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line28 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: -- 2.7.4