[PATCH] D11427: [Static Analyzer] Checker for Obj-C generics

Anna Zaks zaks.anna at gmail.com
Mon Jul 27 17:04:56 PDT 2015


zaks.anna added a comment.

Add tests for checking element retrieval and tracking with ObjC subscript syntax for arrays and dictionaries.

Also see:
http://llvm.org/docs/CodingStandards.html#use-early-exits-and-continue-to-simplify-code
http://llvm.org/docs/CodingStandards.html#don-t-use-else-after-a-return


================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:334
@@ +333,3 @@
+
+void ObjCGenericsChecker::checkPostObjCMessage(const ObjCMethodCall &M,
+                                               CheckerContext &C) const {
----------------
Add comment explaining that this callback is used to infer the types. Specifically, if a class method is called on a symbol, we use it to infer the type of the symbol.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:338
@@ +337,3 @@
+
+  ProgramStateRef State = C.getState();
+  SymbolRef Sym = M.getReturnValue().getAsSymbol();
----------------
Move State down, where it's used.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:346
@@ +345,3 @@
+  if (MessageExpr->getReceiverKind() != ObjCMessageExpr::Class ||
+      Sel.getAsString() != "class")
+    return;
----------------
Clarify what you are doing here.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:414
@@ +413,3 @@
+
+  // When the receiver type is id, or some super class of the tracked type (and
+  // kindof type), look up the method in the tracked type, not in the receiver
----------------
Split funding a tighter method definition into a subroutine.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:421
@@ +420,3 @@
+      MessageExpr->getReceiverKind() == ObjCMessageExpr::Class) {
+    if (ASTCtxt.getObjCIdType() == ReceiverType ||
+        ASTCtxt.getObjCClassType() == ReceiverType ||
----------------
Should checking for id, class and kindof be a helper method?

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:425
@@ +424,3 @@
+         ASTCtxt.canAssignObjCInterfaces(ReceiverObjectPtrType,
+                                         *TrackedType))) {
+      const ObjCInterfaceDecl *InterfaceDecl =
----------------
What if ASTCtxt.canAssignObjCInterfaces is false here? Shouldn't we warn?
Will we warn elsewhere? Let's make sure we have a test case. And add a comment.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:444
@@ +443,3 @@
+  Optional<ArrayRef<QualType>> TypeArgs =
+      (*TrackedType)->getObjCSubstitutions(Method->getDeclContext());
+  // This case might happen when there is an unspecialized override of a
----------------
Should we use the type on which this is defined and not the tracked type?

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:453
@@ +452,3 @@
+    // We can't do any type-checking on a type-dependent argument.
+    if (Arg->isTypeDependent())
+      continue;
----------------
Why are we not checking other parameter types? Will those bugs get caught by casts? I guess yes..

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:458
@@ +457,3 @@
+
+    QualType OrigParamType = Param->getType();
+    const auto *ParamTypedef = OrigParamType->getAs<TypedefType>();
----------------
Why isObjCTypeParamDependent is not used here?

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:485
@@ +484,3 @@
+    if (ArgSym) {
+      const ObjCObjectPointerType *const *TrackedType =
+          State->get<TypeParamMap>(ArgSym);
----------------
Let's not shadow TrackedType.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:495
@@ +494,3 @@
+    // accepted.
+    if (!ASTCtxt.canAssignObjCInterfaces(ParamObjectPtrType,
+                                         ArgObjectPtrType) &&
----------------
This would be simplified if you pull out the negation; you essentially, list the cases where we do not warn on parameters:
 1) arg can be assigned to (subtype of) param
 2) covariant parameter types and param is a subtype of arg

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:500
@@ +499,3 @@
+                                          ParamObjectPtrType))) {
+      ExplodedNode *N = C.addTransition();
+      reportBug(ArgObjectPtrType, ParamObjectPtrType, N, Sym, C);
----------------
This just returns the previous state. 

If you want to create a node, you need to tag it; see the tags on leak reports.


================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:513
@@ +512,3 @@
+      ASTCtxt, *TypeArgs, ObjCSubstitutionContext::Result);
+  if (IsInstanceType)
+    ResultType = QualType(*TrackedType, 0);
----------------
We should not use TrackedType in the case lookup failed.
Can the TrackedType be less specialized that the return type?
Maybe rename as IsDeclaredAsInstanceType?

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:532
@@ +531,3 @@
+
+  if (!ExprTypeAboveCast || !ResultPtrType)
+    return;
----------------
What are we doing here?
I prefer not to have any AST pattern matching.

================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:539
@@ +538,3 @@
+      !ASTCtxt.canAssignObjCInterfaces(ResultPtrType, ExprTypeAboveCast)) {
+    ExplodedNode *N = C.addTransition();
+    reportBug(ResultPtrType, ExprTypeAboveCast, N, Sym, C);
----------------
This returns predecessor..


http://reviews.llvm.org/D11427







More information about the cfe-commits mailing list