[PATCH] D11427: [Static Analyzer] Checker for Obj-C generics
Anna Zaks
zaks.anna at gmail.com
Fri Jul 24 14:38:45 PDT 2015
zaks.anna added a comment.
Here is a partial review. Some comments below and others are inline.
Thanks!
Anna.
- Add at least one test that tests for the full error message.
- Add a test that tests path-sensitive output (the plist file) after testing that that looks correct in Xcode. For example, how is GenericsBugVisitor tested? That should be easy with $ awk '{print "// CHECK: "$0}' in.txt > out.txt
- nit: It would be helpful if you could use descriptive names for each test.
================
Comment at: lib/StaticAnalyzer/Checkers/Checkers.td:456
@@ +455,3 @@
+def ObjCGenericsChecker : Checker<"ObjCGenerics">,
+ HelpText<"Checks for type errors.">,
+ DescFile<"ObjCGenericsChecker.cpp">;
----------------
Please, provide better description of the checker.
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:11
@@ +10,3 @@
+// This checker tries to find type errors that the compiler is not able to catch
+// due to the implicit conversions that was introduced for backward
+// compatibility.
----------------
"was" -> "were"
Please, add some documentation on what this checker is trying to catch and how it works.
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:92
@@ +91,3 @@
+// ProgramState trait - a map from symbol to its type with specified params.
+REGISTER_MAP_WITH_PROGRAMSTATE(TypeParamMap, SymbolRef,
+ const ObjCObjectPointerType *)
----------------
"type with specified params" -> "specialized type"?
Also, maybe we should move this above the GenericsBugVisitor declaration for greater visibility?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:173
@@ +172,3 @@
+ const ObjCObjectPointerType *MostInformativeCandidate, ASTContext &C) {
+ // Checking if from and two are the same classes modulo specialization.
+ if (From->getInterfaceDecl()->getCanonicalDecl() ==
----------------
"two" -> "to"
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:197
@@ +196,3 @@
+static const ObjCObjectPointerType *
+getMostInformativeDerivedClass(const ObjCObjectPointerType *From,
+ const ObjCObjectPointerType *To, ASTContext &C) {
----------------
Could you add a comment on what this does?
Is there a precondition on the arguments (To and From)? We seem to be walking up the hierarchy of To.
Is To always guaranteed to have a super class? What ensures that?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:224
@@ +223,3 @@
+
+ ASTContext &ASTCtxt = C.getASTContext();
+
----------------
Move this after the check?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:229
@@ +228,3 @@
+
+ // In order to detect subtype relation properly, strip the kindofness.
+ OrigObjectPtrType = OrigObjectPtrType->stripObjCKindOfTypeAndQuals(ASTCtxt);
----------------
Could you explain more why are we skipping kindoff?
Is there a test case for this?
Let's add more __kindof tests.
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:253
@@ +252,3 @@
+ // If OrigObjectType could convert to DestObjectType, this could be an
+ // implicit cast. Handle it as implicit cast.
+ if (isa<ExplicitCastExpr>(CE) && !OrigToDest) {
----------------
Comment does not seem to match the code below.
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:257
@@ +256,3 @@
+ // However a downcast may also lose information. E. g.:
+ // MutableMap<T, U> : Map
+ // The downcast to mutable map loses the information about the types of the
----------------
Should the Map be specialized in this example?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:270
@@ +269,3 @@
+ }
+ return;
+ }
----------------
We ignore the cast on the else branch (mismatched type)?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:280
@@ +279,3 @@
+ State = State->set<TypeParamMap>(Sym, OrigObjectPtrType);
+ C.addTransition(State);
+ }
----------------
Simplify the code by using early returns.
Also, try to add comments with intuition on what cases are covered.
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:297
@@ +296,3 @@
+ reportBug(*TrackedType, DestObjectPtrType, N, Sym, C);
+ return;
+ }
----------------
This will not get caught by the check below?
================
Comment at: lib/StaticAnalyzer/Checkers/ObjCGenericsChecker.cpp:326
@@ +325,3 @@
+static const Expr *stripImplicitIdCast(const Expr *E, ASTContext &ASTCtxt) {
+ const ImplicitCastExpr *CE = dyn_cast<ImplicitCastExpr>(E);
+ if (CE && CE->getCastKind() == CK_BitCast &&
----------------
Shouldn't we strip more than id casts?
================
Comment at: test/Analysis/generics.m:45
@@ +44,3 @@
+ at interface MutableArray<T> : NSArray<T>
+- (int)addObject:(T)obj;
+ at end
----------------
I'd prefer if these were copied directly from the headers, without modifications. Ex:
@interface NSMutableArray<ObjectType> : NSArray<ObjectType>
- (void)addObject:(ObjectType)anObject;
http://reviews.llvm.org/D11427
More information about the cfe-commits
mailing list