From c8a78a37bb215f0b4088e04d115fc87419f898ba Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Sat, 6 Oct 2012 01:19:30 +0000 Subject: [PATCH] [analyzer] Handle implicit statements used for end-of-path nodes' source locs. Some implicit statements, such as the implicit 'self' inserted for "free" Objective-C ivar access, have invalid source locations. If one of these statements is the location where an issue is reported, we'll now look at the enclosing statements for a valid source location. llvm-svn: 165354 --- clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp | 21 +- clang/test/Analysis/plist-output.m | 299 ++++++++++++++++++++--- 2 files changed, 278 insertions(+), 42 deletions(-) diff --git a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index d37ac4a..258ad25 100644 --- a/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/clang/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -612,21 +612,26 @@ PathDiagnosticLocation assert(N && "Cannot create a location with a null node."); const ExplodedNode *NI = N; + const Stmt *S = 0; while (NI) { ProgramPoint P = NI->getLocation(); - const LocationContext *LC = P.getLocationContext(); if (const StmtPoint *PS = dyn_cast(&P)) - return PathDiagnosticLocation(PS->getStmt(), SM, LC); - else if (const BlockEdge *BE = dyn_cast(&P)) { - const Stmt *Term = BE->getSrc()->getTerminator(); - if (Term) { - return PathDiagnosticLocation(Term, SM, LC); - } - } + S = PS->getStmt(); + else if (const BlockEdge *BE = dyn_cast(&P)) + S = BE->getSrc()->getTerminator(); + if (S) + break; NI = NI->succ_empty() ? 0 : *(NI->succ_begin()); } + if (S) { + const LocationContext *LC = NI->getLocationContext(); + if (S->getLocStart().isValid()) + return PathDiagnosticLocation(S, SM, LC); + return PathDiagnosticLocation(getValidSourceLocation(S, LC), SM); + } + return createDeclEnd(N->getLocationContext(), SM); } diff --git a/clang/test/Analysis/plist-output.m b/clang/test/Analysis/plist-output.m index 52073e4..7e821ab 100644 --- a/clang/test/Analysis/plist-output.m +++ b/clang/test/Analysis/plist-output.m @@ -77,6 +77,17 @@ int test_cond_assign() { *p = 0xDEADBEEF; // expected-warning {{deference}} } } + +// The original source for the above Radar contains another problem: +// if the end-of-path node is an implicit statement, it may not have a valid +// source location. +- (void)test2 { + if (bar_cond_assign()) { + id foo = [[RDar10797980 alloc] init]; // leak + } + (void)y; // first statement after the 'if' is an implicit 'self' DeclRefExpr +} + @end // Test that loops are documented in the path. @@ -1789,6 +1800,64 @@ void rdar12280665() { // CHECK-NEXT: path // CHECK-NEXT: // CHECK-NEXT: +// CHECK-NEXT: kindevent +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col10 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col40 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Value stored to 'foo' during its initialization is never read +// CHECK-NEXT: message +// CHECK-NEXT: Value stored to 'foo' during its initialization is never read +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionValue stored to 'foo' during its initialization is never read +// CHECK-NEXT: categoryDead store +// CHECK-NEXT: typeDead initialization +// CHECK-NEXT: issue_context_kindObjective-C method +// CHECK-NEXT: issue_contexttest2 +// CHECK-NEXT: issue_hash2 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col8 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: kindcontrol // CHECK-NEXT: edges // CHECK-NEXT: @@ -1796,25 +1865,187 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line85 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line85 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// 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: line86 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col6 +// CHECK-NEXT: file0 +// CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// 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: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col40 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Method returns an Objective-C object with a +1 retain count +// CHECK-NEXT: message +// CHECK-NEXT: Method returns an Objective-C object with a +1 retain count +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line86 +// CHECK-NEXT: col14 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line88 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line88 +// CHECK-NEXT: col9 +// 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: line88 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: depth0 +// CHECK-NEXT: extended_message +// CHECK-NEXT: Object leaked: object allocated and stored into 'foo' is not referenced later in this execution path and has a retain count of +1 +// CHECK-NEXT: message +// CHECK-NEXT: Object leaked: object allocated and stored into 'foo' is not referenced later in this execution path and has a retain count of +1 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: descriptionPotential leak of an object stored into 'foo' +// CHECK-NEXT: categoryMemory (Core Foundation/Objective-C) +// CHECK-NEXT: typeLeak +// CHECK-NEXT: issue_context_kindObjective-C method +// CHECK-NEXT: issue_contexttest2 +// CHECK-NEXT: issue_hash4 +// CHECK-NEXT: location +// CHECK-NEXT: +// CHECK-NEXT: line88 +// CHECK-NEXT: col9 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: path +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: kindcontrol +// CHECK-NEXT: edges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: start +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line95 +// CHECK-NEXT: col5 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: end +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line96 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1830,12 +2061,12 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1843,12 +2074,12 @@ void rdar12280665() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line100 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line100 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1864,12 +2095,12 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line100 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line100 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1877,12 +2108,12 @@ void rdar12280665() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1894,7 +2125,7 @@ void rdar12280665() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1902,12 +2133,12 @@ void rdar12280665() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1927,12 +2158,12 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line84 +// CHECK-NEXT: line95 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1940,12 +2171,12 @@ void rdar12280665() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1961,12 +2192,12 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col4 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line85 +// CHECK-NEXT: line96 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1974,12 +2205,12 @@ void rdar12280665() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1991,7 +2222,7 @@ void rdar12280665() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -1999,12 +2230,12 @@ void rdar12280665() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col10 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2024,12 +2255,12 @@ void rdar12280665() { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line86 +// CHECK-NEXT: line97 // CHECK-NEXT: col7 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2037,12 +2268,12 @@ void rdar12280665() { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2054,7 +2285,7 @@ void rdar12280665() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2062,12 +2293,12 @@ void rdar12280665() { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col6 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -2088,7 +2319,7 @@ void rdar12280665() { // CHECK-NEXT: issue_hash4 // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line98 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: -- 2.7.4