[PATCH] D28495: [analyzer] Support inlining of '[self classMethod]' and '[[self class] classMethod]'

Devin Coughlin via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Mon Jan 9 18:41:30 PST 2017


dcoughlin added inline comments.


================
Comment at: lib/StaticAnalyzer/Core/CallEvent.cpp:972
+          Receiver == getSelfSVal().getAsRegion())
+        return RuntimeDefinition(findDefiningRedecl(E->getMethodDecl()));
+
----------------
Here is a case where dispatching via the compile-time type of E is not safe:

```
#import <Foundation/Foundation.h>

void clang_analyzer_eval(int);

@interface Parent : NSObject
+ (int)a;
+ (int)b;
@end

@interface Child : Parent
@end

@interface Other : NSObject
+(void)run;
@end

int main(int argc, const char * argv[]) {
  @autoreleasepool {
    [Other run];
  }
  return 0;
}

@implementation Other
+(void)run {
  int result = [Child a];

  clang_analyzer_eval(result == 12);
  printf("result is %d\n", result);
}
@end

@implementation Parent
+ (int)a; {
  return [self b];
}
+ (int)b; {
  return 12;
}
@end

@implementation Child
+ (int)b; {
  return 100;
}
@end
```

Running this code will print 'result is 100' but the clang_analyzer_eval() will incorrectly yield 'TRUE'.

What do you think about adding a new SVal for ObjC 'Class' values that know what interface declaration they come from? Then 'self' in a class method would be filled in with something meaningful in `ObjCMethodCall::getReceiverSVal()` and we could do proper dynamic dispatch for class methods just like we do for instance methods now.


================
Comment at: lib/StaticAnalyzer/Core/CallEvent.cpp:977
+      // limiting as the test cases in Analysis/inlining/InlineObjCClassMethod.m
+      // shows. A better way would be to accosiate the meta type with the symbol
+      // using the dynamic type info tracking and use it here.
----------------
accosiate-->associate


================
Comment at: test/Analysis/inlining/InlineObjCClassMethod.m:269
+  unsigned result0 = [self returns10];
+  clang_analyzer_eval(result0 == 10); // expected-warning{{TRUE}}
+}
----------------
I think it would be good to duplicate some of these tests in `-(void)instanceMethod` since calling `[self class]` is most-commonly used in instance methods:
```
  unsigned result2 = [[self class] returns30];
  clang_analyzer_eval(result2 == 30); // expected-warning{{TRUE}}
  unsigned result3 = [[super class] returns30];
  clang_analyzer_eval(result3 == 100); // expected-warning{{UNKNOWN}}
```


https://reviews.llvm.org/D28495





More information about the cfe-commits mailing list