]> granicus.if.org Git - clang/commitdiff
[analyzer] Weaken assertion in trackNullOrUndefValue()
authorDevin Coughlin <dcoughlin@apple.com>
Fri, 19 Aug 2016 01:05:31 +0000 (01:05 +0000)
committerDevin Coughlin <dcoughlin@apple.com>
Fri, 19 Aug 2016 01:05:31 +0000 (01:05 +0000)
We should ignore paren casts when making sure that the semantic expression
in a PseudoObjectExpr for an ObjC getter is a message send.

This has no other intended functionality change.

Adding a test for this exposed an interesting issue in another test case
that only manifests under ARC. trackNullOrUndefValue() is not properly
suppressing for nil values that are the result of nil propagation from a nil
receiver when the nil is returned from a function. I've added a FIXME for that
missing suppression.

rdar://problem/27290568

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@279181 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
test/Analysis/inlining/false-positive-suppression.m

index 3b72244a52c69d8aba6f430964dd4958704958cd..a38d1d9bdb55ab891bffd89e397148c21379f1c5 100644 (file)
@@ -916,7 +916,7 @@ static const Expr *peelOffOuterExpr(const Expr *Ex,
     if (PropRef && PropRef->isMessagingGetter()) {
       const Expr *GetterMessageSend =
           POE->getSemanticExpr(POE->getNumSemanticExprs() - 1);
-      assert(isa<ObjCMessageExpr>(GetterMessageSend));
+      assert(isa<ObjCMessageExpr>(GetterMessageSend->IgnoreParenCasts()));
       return peelOffOuterExpr(GetterMessageSend, N);
     }
   }
index 1a5ff662c18ea7c9f64038a2e63b619f3c607167..685e29e2313184a448d84eacf79c65f00d9801fc 100644 (file)
@@ -1,8 +1,11 @@
 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config suppress-null-return-paths=false -verify %s
 // RUN: %clang_cc1 -analyze -analyzer-checker=core -verify -DSUPPRESSED=1 %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core -fobjc-arc -verify -DSUPPRESSED=1 %s
 // RUN: %clang_cc1 -analyze -analyzer-checker=core -analyzer-config avoid-suppressing-null-argument-paths=true -DSUPPRESSED=1 -DNULL_ARGS=1 -verify %s
 
-#ifdef SUPPRESSED
+#define ARC __has_feature(objc_arc)
+
+#if defined(SUPPRESSED) && !ARC
 // expected-no-diagnostics
 #endif
 
@@ -24,8 +27,9 @@ void testNilReceiverHelperA(int *x) {
 
 void testNilReceiverHelperB(int *x) {
   *x = 1;
-#ifndef SUPPRESSED
-  // expected-warning@-2 {{Dereference of null pointer}}
+// FIXME: Suppression for this case isn't working under ARC. It should.
+#if !defined(SUPPRESSED) || (defined(SUPPRESSED) && ARC)
+  // expected-warning@-3 {{Dereference of null pointer}}
 #endif
 }
 
@@ -40,13 +44,17 @@ void testNilReceiver(int coin) {
 // FALSE NEGATIVES (over-suppression)
 
 __attribute__((objc_root_class))
-@interface SomeClass
+@interface SomeClass {
+  int ivar;
+}
 -(int *)methodReturningNull;
 
 @property(readonly) int *propertyReturningNull;
 
 @property(readonly) int *synthesizedProperty;
 
+@property(readonly) SomeClass *propertyReturningNil;
+
 @end
 
 @interface SubOfSomeClass : SomeClass
@@ -64,6 +72,10 @@ __attribute__((objc_root_class))
   return 0;
 }
 
+-(SomeClass *)propertyReturningNil {
+  return 0;
+}
+
 +(int *)classPropertyReturningNull {
   return 0;
 }
@@ -103,6 +115,16 @@ void testClassPropertyReturningNull() {
 #endif
 }
 
+@implementation SomeClass (ForTestOfPropertyReturningNil)
+void testPropertyReturningNil(SomeClass *sc) {
+  SomeClass *result = sc.propertyReturningNil;
+  result->ivar = 1;
+#ifndef SUPPRESSED
+  // expected-warning@-2 {{Access to instance variable 'ivar' results in a dereference of a null pointer (loaded from variable 'result')}}
+#endif
+}
+@end
+
 void testSynthesizedPropertyReturningNull(SomeClass *sc) {
   if (sc.synthesizedProperty)
     return;