Author: dergachev Date: Mon Jun 5 08:36:28 2017 New Revision: 304713 URL: http://llvm.org/viewvc/llvm-project?rev=304713&view=rev Log: [analyzer] Don't add arrow to the inlined function's decl when it has no body.
In plist output mode with alternate path diagnostics, when entering a function, we draw an arrow from the caller to the beginning of the callee's declaration. Upon exiting, however, we draw the arrow from the last statement in the callee function. The former makes little sense when the declaration is not a definition, i.e. has no body, which may happen in case the body is coming from a body farm, eg. Objective-C autosynthesized property accessor. Differential Revision: https://reviews.llvm.org/D33671 Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp cfe/trunk/test/Analysis/nullability-notes.m Modified: cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp?rev=304713&r1=304712&r2=304713&view=diff ============================================================================== --- cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp (original) +++ cfe/trunk/lib/StaticAnalyzer/Core/BugReporter.cpp Mon Jun 5 08:36:28 2017 @@ -1671,9 +1671,15 @@ static bool GenerateAlternateExtensivePa // Add an edge to the start of the function. const StackFrameContext *CalleeLC = CE->getCalleeContext(); const Decl *D = CalleeLC->getDecl(); - addEdgeToPath(PD.getActivePath(), PrevLoc, - PathDiagnosticLocation::createBegin(D, SM), - CalleeLC); + // Add the edge only when the callee has body. We jump to the beginning + // of the *declaration*, however we expect it to be followed by the + // body. This isn't the case for autosynthesized property accessors in + // Objective-C. No need for a similar extra check for CallExit points + // because the exit edge comes from a statement (i.e. return), + // not from declaration. + if (D->hasBody()) + addEdgeToPath(PD.getActivePath(), PrevLoc, + PathDiagnosticLocation::createBegin(D, SM), CalleeLC); // Did we visit an entire call? bool VisitedEntireCall = PD.isWithinCall(); Modified: cfe/trunk/test/Analysis/nullability-notes.m URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/nullability-notes.m?rev=304713&r1=304712&r2=304713&view=diff ============================================================================== --- cfe/trunk/test/Analysis/nullability-notes.m (original) +++ cfe/trunk/test/Analysis/nullability-notes.m Mon Jun 5 08:36:28 2017 @@ -1,11 +1,13 @@ // RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s +// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=plist -analyzer-config path-diagnostics-alternate=true -o %t.plist %s +// RUN: FileCheck --input-file=%t.plist %s #include "Inputs/system-header-simulator-for-nullability.h" void takesNonnull(NSObject *_Nonnull y); @interface ClassWithProperties: NSObject -@property(copy, nullable) NSObject *x; +@property(copy, nullable) NSObject *x; // plist check ensures no control flow piece from here to 'self.x'. -(void) method; @end; @implementation ClassWithProperties @@ -16,3 +18,187 @@ void takesNonnull(NSObject *_Nonnull y); // expected-note@-1{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}} } @end + +// CHECK: <key>diagnostics</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>path</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>10</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>1</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>Nullability 'nullable' is inferred</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>Nullability 'nullable' is inferred</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>22</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>10</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>control</string> +// CHECK-NEXT: <key>edges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>start</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>16</integer> +// CHECK-NEXT: <key>col</key><integer>10</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>end</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>14</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>kind</key><string>event</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <key>ranges</key> +// CHECK-NEXT: <array> +// CHECK-NEXT: <array> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>16</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>16</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>depth</key><integer>0</integer> +// CHECK-NEXT: <key>extended_message</key> +// CHECK-NEXT: <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string> +// CHECK-NEXT: <key>message</key> +// CHECK-NEXT: <string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> +// CHECK-NEXT: <key>description</key><string>Nullable pointer is passed to a callee that requires a non-null 1st parameter</string> +// CHECK-NEXT: <key>category</key><string>Memory error</string> +// CHECK-NEXT: <key>type</key><string>Nullability</string> +// CHECK-NEXT: <key>check_name</key><string>nullability.NullPassedToNonnull</string> +// CHECK-NEXT: <!-- This hash is experimental and going to change! --> +// CHECK-NEXT: <key>issue_hash_content_of_line_in_context</key><string>b6bc8126de8e6eb3375483a656fe858d</string> +// CHECK-NEXT: <key>issue_context_kind</key><string>Objective-C method</string> +// CHECK-NEXT: <key>issue_context</key><string>method</string> +// CHECK-NEXT: <key>issue_hash_function_offset</key><string>3</string> +// CHECK-NEXT: <key>location</key> +// CHECK-NEXT: <dict> +// CHECK-NEXT: <key>line</key><integer>17</integer> +// CHECK-NEXT: <key>col</key><integer>3</integer> +// CHECK-NEXT: <key>file</key><integer>0</integer> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </dict> +// CHECK-NEXT: </array> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits