[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

llvm-svn: 279181

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

index 3b72244..a38d1d9 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 1a5ff66..685e29e 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;