NoQ updated this revision to Diff 99300.
NoQ added a comment.
Herald added a subscriber: xazax.hun.
Automatically pop up from bodyfarm-originated code in
`PathDiagnosticLocation::getStmt()`.
Avoid putting "Calling..." and "Returning..." notes on Objective-C
auto-synthesized property calls, because they would never call visible code
later.
Test the newly added path notes.
https://reviews.llvm.org/D32437
Files:
include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
lib/StaticAnalyzer/Core/PathDiagnostic.cpp
test/Analysis/nullability-notes.m
Index: test/Analysis/nullability-notes.m
===================================================================
--- /dev/null
+++ test/Analysis/nullability-notes.m
@@ -0,0 +1,18 @@
+// RUN: %clang_analyze_cc1 -fblocks -analyzer-checker=core,nullability.NullPassedToNonnull,nullability.NullReturnedFromNonnull,nullability.NullablePassedToNonnull,nullability.NullableReturnedFromNonnull,nullability.NullableDereferenced -analyzer-output=text -verify %s
+
+#include "Inputs/system-header-simulator-for-nullability.h"
+
+void takesNonnull(NSObject *_Nonnull y);
+
+@interface ClassWithProperties: NSObject
+@property(copy, nullable) NSObject *x;
+-(void) method;
+@end;
+@implementation ClassWithProperties
+-(void) method {
+ // no-crash
+ NSObject *x = self.x; // expected-note{{Nullability 'nullable' is inferred}}
+ takesNonnull(x); // expected-warning{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
+ // expected-note@-1{{Nullable pointer is passed to a callee that requires a non-null 1st parameter}}
+}
+@end
Index: lib/StaticAnalyzer/Core/PathDiagnostic.cpp
===================================================================
--- lib/StaticAnalyzer/Core/PathDiagnostic.cpp
+++ lib/StaticAnalyzer/Core/PathDiagnostic.cpp
@@ -695,6 +695,18 @@
}
const Stmt *PathDiagnosticLocation::getStmt(const ExplodedNode *N) {
+ // We cannot place diagnostics on autosynthesized code.
+ // Put them onto the call site through which we jumped into autosynthesized
+ // code for the first time.
+ const LocationContext *LC = N->getLocationContext();
+ if (LC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
+ const LocationContext *ParentLC = LC->getParent();
+ while (ParentLC->getAnalysisDeclContext()->isBodyAutosynthesized()) {
+ LC = ParentLC;
+ ParentLC = LC->getParent();
+ }
+ return LC->getCurrentStackFrame()->getCallSite();
+ }
ProgramPoint P = N->getLocation();
if (Optional<StmtPoint> SP = P.getAs<StmtPoint>())
return SP->getStmt();
@@ -912,6 +924,12 @@
callEnterWithin = PathDiagnosticLocation::createBegin(Callee, SM);
callEnter = getLocationForCaller(CalleeCtx, CE.getLocationContext(), SM);
+
+ // Otherwise IsCalleeAnAutosynthesizedPropertyAccessor defaults to false.
+ if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(Callee))
+ IsCalleeAnAutosynthesizedPropertyAccessor = (
+ MD->isPropertyAccessor() &&
+ CalleeCtx->getAnalysisDeclContext()->isBodyAutosynthesized());
}
static inline void describeClass(raw_ostream &Out, const CXXRecordDecl *D,
@@ -986,7 +1004,7 @@
std::shared_ptr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallEnterEvent() const {
- if (!Callee)
+ if (!Callee || IsCalleeAnAutosynthesizedPropertyAccessor)
return nullptr;
SmallString<256> buf;
@@ -1020,7 +1038,7 @@
std::shared_ptr<PathDiagnosticEventPiece>
PathDiagnosticCallPiece::getCallExitEvent() const {
- if (NoExit)
+ if (NoExit || IsCalleeAnAutosynthesizedPropertyAccessor)
return nullptr;
SmallString<256> buf;
Index: lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
===================================================================
--- lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
+++ lib/StaticAnalyzer/Checkers/NullabilityChecker.cpp
@@ -326,7 +326,7 @@
// Retrieve the associated statement.
const Stmt *S = TrackedNullab->getNullabilitySource();
- if (!S) {
+ if (!S || S->getLocStart().isInvalid()) {
S = PathDiagnosticLocation::getStmt(N);
}
Index: include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
===================================================================
--- include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
+++ include/clang/StaticAnalyzer/Core/BugReporter/PathDiagnostic.h
@@ -550,20 +550,26 @@
class PathDiagnosticCallPiece : public PathDiagnosticPiece {
PathDiagnosticCallPiece(const Decl *callerD,
const PathDiagnosticLocation &callReturnPos)
- : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
- NoExit(false), callReturn(callReturnPos) {}
+ : PathDiagnosticPiece(Call), Caller(callerD), Callee(nullptr),
+ NoExit(false), IsCalleeAnAutosynthesizedPropertyAccessor(false),
+ callReturn(callReturnPos) {}
PathDiagnosticCallPiece(PathPieces &oldPath, const Decl *caller)
- : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
- NoExit(true), path(oldPath) {}
-
+ : PathDiagnosticPiece(Call), Caller(caller), Callee(nullptr),
+ NoExit(true), IsCalleeAnAutosynthesizedPropertyAccessor(false),
+ path(oldPath) {}
+
const Decl *Caller;
const Decl *Callee;
// Flag signifying that this diagnostic has only call enter and no matching
// call exit.
bool NoExit;
+ // Flag signifying that the callee function is an Objective-C autosynthesized
+ // property getter or setter.
+ bool IsCalleeAnAutosynthesizedPropertyAccessor;
+
// The custom string, which should appear after the call Return Diagnostic.
// TODO: Should we allow multiple diagnostics?
std::string CallStackMessage;
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits