From: Jordan Rose Date: Fri, 24 May 2013 21:43:11 +0000 (+0000) Subject: [analyzer] Treat analyzer-synthesized function bodies like implicit bodies. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=d474da062565596015558856333423199aed5eb1;p=clang [analyzer] Treat analyzer-synthesized function bodies like implicit bodies. When generating path notes, implicit function bodies are shown at the call site, so that, say, copying a POD type in C++ doesn't jump you to a header file. This is especially important when the synthesized function itself calls another function (or block), in which case we should try to jump the user around as little as possible. By checking whether a called function has a body in the AST, we can tell if the analyzer synthesized the body, and if we should therefore collapse the call down to the call site like a true implicitly-defined function. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@182677 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/BugReporter.cpp b/lib/StaticAnalyzer/Core/BugReporter.cpp index b45d051322..9659205e87 100644 --- a/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -210,6 +210,13 @@ static bool removeUnneededCalls(PathPieces &pieces, BugReport *R, return containsSomethingInteresting; } +/// Returns true if the given decl has been implicitly given a body, either by +/// the analyzer or by the compiler proper. +static bool hasImplicitBody(const Decl *D) { + assert(D); + return D->isImplicit() || !D->hasBody(); +} + /// Recursively scan through a path and make sure that all call pieces have /// valid locations. Note that all other pieces with invalid locations should /// have already been pruned out. @@ -224,11 +231,10 @@ static void adjustCallLocations(PathPieces &Pieces, } if (LastCallLocation) { - if (!Call->callEnter.asLocation().isValid() || - Call->getCaller()->isImplicit()) + bool CallerIsImplicit = hasImplicitBody(Call->getCaller()); + if (CallerIsImplicit || !Call->callEnter.asLocation().isValid()) Call->callEnter = *LastCallLocation; - if (!Call->callReturn.asLocation().isValid() || - Call->getCaller()->isImplicit()) + if (CallerIsImplicit || !Call->callReturn.asLocation().isValid()) Call->callReturn = *LastCallLocation; } @@ -236,7 +242,7 @@ static void adjustCallLocations(PathPieces &Pieces, // it contains any informative diagnostics. PathDiagnosticLocation *ThisCallLocation; if (Call->callEnterWithin.asLocation().isValid() && - !Call->getCallee()->isImplicit()) + !hasImplicitBody(Call->getCallee())) ThisCallLocation = &Call->callEnterWithin; else ThisCallLocation = &Call->callEnter; diff --git a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp index 7801834ab2..82d8f37105 100644 --- a/lib/StaticAnalyzer/Core/PathDiagnostic.cpp +++ b/lib/StaticAnalyzer/Core/PathDiagnostic.cpp @@ -982,7 +982,7 @@ IntrusiveRefCntPtr PathDiagnosticCallPiece::getCallEnterWithinCallerEvent() const { if (!callEnterWithin.asLocation().isValid()) return 0; - if (Callee->isImplicit()) + if (Callee->isImplicit() || !Callee->hasBody()) return 0; if (const CXXMethodDecl *MD = dyn_cast(Callee)) if (MD->isDefaulted()) diff --git a/test/Analysis/inlining/path-notes.m b/test/Analysis/inlining/path-notes.m index 602bad188a..501942d682 100644 --- a/test/Analysis/inlining/path-notes.m +++ b/test/Analysis/inlining/path-notes.m @@ -85,10 +85,10 @@ int testDispatchSyncInlining() { // expected-note@+2 {{Calling 'dispatch_sync'}} // expected-note@+1 {{Returning from 'dispatch_sync'}} dispatch_sync(globalQueue, ^{ - // expected-note@7 {{Calling anonymous block}} + // expected-note@-1 {{Calling anonymous block}} + // expected-note@-2 {{Returning to caller}} x = 0; // expected-note@-1 {{The value 0 is assigned to 'x'}} - // expected-note@7 {{Returning to caller}} }); return 1 / x; // expected-warning{{Division by zero}} @@ -105,7 +105,7 @@ int testDispatchSyncInliningNoPruning(int coin) { // expected-note@+1 {{Calling 'dispatch_sync'}} dispatch_sync(globalQueue, ^{ - // expected-note@7 {{Calling anonymous block}} + // expected-note@-1 {{Calling anonymous block}} int x; // expected-note@-1 {{'x' declared without an initial value}} ^{ y = x; }(); // expected-warning{{Variable 'x' is uninitialized when captured by block}} @@ -582,12 +582,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col15 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -599,7 +599,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -607,7 +607,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -628,24 +628,25 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col1 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Entered call from 'testDispatchSyncInlining' -// CHECK-NEXT: message -// CHECK-NEXT: Entered call from 'testDispatchSyncInlining' -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col1 +// CHECK-NEXT: line89 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line89 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: depth1 // CHECK-NEXT: extended_message // CHECK-NEXT: Calling anonymous block @@ -656,7 +657,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -674,12 +675,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -687,12 +688,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line90 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line90 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -704,7 +705,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line90 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -712,12 +713,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line90 // CHECK-NEXT: col5 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line89 +// CHECK-NEXT: line90 // CHECK-NEXT: col9 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -733,10 +734,25 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col1 +// CHECK-NEXT: line89 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line89 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line92 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: depth1 // CHECK-NEXT: extended_message // CHECK-NEXT: Returning to caller @@ -747,7 +763,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -755,7 +771,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -780,12 +796,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line87 +// CHECK-NEXT: line89 // CHECK-NEXT: col15 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -873,12 +889,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: end // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col15 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -890,7 +906,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -898,7 +914,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -919,24 +935,25 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col1 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Entered call from 'testDispatchSyncInliningNoPruning' -// CHECK-NEXT: message -// CHECK-NEXT: Entered call from 'testDispatchSyncInliningNoPruning' -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line7 -// CHECK-NEXT: col1 +// CHECK-NEXT: line108 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line108 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line113 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: depth1 // CHECK-NEXT: extended_message // CHECK-NEXT: Calling anonymous block @@ -947,7 +964,7 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: @@ -965,12 +982,12 @@ id testCreateArrayLiteral(id myNil) { // CHECK-NEXT: start // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: // CHECK-NEXT: -// CHECK-NEXT: line107 +// CHECK-NEXT: line108 // CHECK-NEXT: col30 // CHECK-NEXT: file0 // CHECK-NEXT: diff --git a/test/Analysis/unix-fns.c b/test/Analysis/unix-fns.c index 46c10136ed..8f286a0495 100644 --- a/test/Analysis/unix-fns.c +++ b/test/Analysis/unix-fns.c @@ -1492,24 +1492,25 @@ void test_inline_dispatch_once() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line40 -// CHECK-NEXT: col1 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: depth1 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Entered call from 'test_dispatch_sync' -// CHECK-NEXT: message -// CHECK-NEXT: Entered call from 'test_dispatch_sync' -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line40 -// CHECK-NEXT: col1 +// CHECK-NEXT: line190 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line190 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line194 +// CHECK-NEXT: col4 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: depth1 // CHECK-NEXT: extended_message // CHECK-NEXT: Calling anonymous block @@ -1974,24 +1975,25 @@ void test_inline_dispatch_once() { // CHECK-NEXT: kindevent // CHECK-NEXT: location // CHECK-NEXT: -// CHECK-NEXT: line39 -// CHECK-NEXT: col1 -// CHECK-NEXT: file0 -// CHECK-NEXT: -// CHECK-NEXT: depth2 -// CHECK-NEXT: extended_message -// CHECK-NEXT: Entered call from '_dispatch_once' -// CHECK-NEXT: message -// CHECK-NEXT: Entered call from '_dispatch_once' -// CHECK-NEXT: -// CHECK-NEXT: -// CHECK-NEXT: kindevent -// CHECK-NEXT: location -// CHECK-NEXT: -// CHECK-NEXT: line39 -// CHECK-NEXT: col1 +// CHECK-NEXT: line177 +// CHECK-NEXT: col3 // CHECK-NEXT: file0 // CHECK-NEXT: +// CHECK-NEXT: ranges +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line177 +// CHECK-NEXT: col3 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: line177 +// CHECK-NEXT: col33 +// CHECK-NEXT: file0 +// CHECK-NEXT: +// CHECK-NEXT: +// CHECK-NEXT: // CHECK-NEXT: depth2 // CHECK-NEXT: extended_message // CHECK-NEXT: Calling anonymous block