r248041 - [Static Analyzer] General type checker based on dynamic type information.

Gabor Horvath via cfe-commits cfe-commits at lists.llvm.org
Fri Sep 18 14:15:38 PDT 2015


Author: xazax
Date: Fri Sep 18 16:15:37 2015
New Revision: 248041

URL: http://llvm.org/viewvc/llvm-project?rev=248041&view=rev
Log:
[Static Analyzer] General type checker based on dynamic type information.

Differential Revision: http://reviews.llvm.org/D12973


Added:
    cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
    cfe/trunk/test/Analysis/dynamic_type_check.m
Modified:
    cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
    cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
    cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
    cfe/trunk/test/Analysis/generics.m

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt?rev=248041&r1=248040&r2=248041&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/CMakeLists.txt Fri Sep 18 16:15:37 2015
@@ -33,6 +33,7 @@ add_clang_library(clangStaticAnalyzerChe
   DirectIvarAssignment.cpp
   DivZeroChecker.cpp
   DynamicTypePropagation.cpp
+  DynamicTypeChecker.cpp
   ExprInspectionChecker.cpp
   FixedAddressChecker.cpp
   GenericTaintChecker.cpp

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td?rev=248041&r1=248040&r2=248041&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/Checkers.td Fri Sep 18 16:15:37 2015
@@ -129,6 +129,10 @@ def TestAfterDivZeroChecker : Checker<"T
   HelpText<"Check for division by variable that is later compared against 0. Either the comparison is useless or there is division by zero.">,
   DescFile<"TestAfterDivZeroChecker.cpp">;
 
+def DynamicTypeChecker : Checker<"DynamicTypeChecker">,
+  HelpText<"Check for cases where the dynamic and the static type of an object are unrelated.">,
+  DescFile<"DynamicTypeChecker.cpp">;
+
 } // end "alpha.core"
 
 let ParentPackage = Nullability in {

Added: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp?rev=248041&view=auto
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp (added)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypeChecker.cpp Fri Sep 18 16:15:37 2015
@@ -0,0 +1,202 @@
+//== DynamicTypeChecker.cpp ------------------------------------ -*- C++ -*--=//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This checker looks for cases where the dynamic type of an object is unrelated
+// to its static type. The type information utilized by this check is collected
+// by the DynamicTypePropagation checker. This check does not report any type
+// error for ObjC Generic types, in order to avoid duplicate erros from the
+// ObjC Generics checker. This checker is not supposed to modify the program
+// state, it is just the observer of the type information provided by other
+// checkers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "ClangSACheckers.h"
+#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
+#include "clang/StaticAnalyzer/Core/Checker.h"
+#include "clang/StaticAnalyzer/Core/CheckerManager.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicTypeMap.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
+
+using namespace clang;
+using namespace ento;
+
+namespace {
+class DynamicTypeChecker : public Checker<check::PostStmt<ImplicitCastExpr>> {
+  mutable std::unique_ptr<BugType> BT;
+  void initBugType() const {
+    if (!BT)
+      BT.reset(
+          new BugType(this, "Dynamic and static type mismatch", "Type Error"));
+  }
+
+  class DynamicTypeBugVisitor
+      : public BugReporterVisitorImpl<DynamicTypeBugVisitor> {
+  public:
+    DynamicTypeBugVisitor(const MemRegion *Reg) : Reg(Reg) {}
+
+    void Profile(llvm::FoldingSetNodeID &ID) const override {
+      static int X = 0;
+      ID.AddPointer(&X);
+      ID.AddPointer(Reg);
+    }
+
+    PathDiagnosticPiece *VisitNode(const ExplodedNode *N,
+                                   const ExplodedNode *PrevN,
+                                   BugReporterContext &BRC,
+                                   BugReport &BR) override;
+
+  private:
+    // The tracked region.
+    const MemRegion *Reg;
+  };
+
+  void reportTypeError(QualType DynamicType, QualType StaticType,
+                       const MemRegion *Reg, const Stmt *ReportedNode,
+                       CheckerContext &C) const;
+
+public:
+  void checkPostStmt(const ImplicitCastExpr *CE, CheckerContext &C) const;
+};
+}
+
+void DynamicTypeChecker::reportTypeError(QualType DynamicType,
+                                         QualType StaticType,
+                                         const MemRegion *Reg,
+                                         const Stmt *ReportedNode,
+                                         CheckerContext &C) const {
+  initBugType();
+  SmallString<192> Buf;
+  llvm::raw_svector_ostream OS(Buf);
+  OS << "Object has a dynamic type '";
+  QualType::print(DynamicType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(),
+                  llvm::Twine());
+  OS << "' which is incompatible with static type '";
+  QualType::print(StaticType.getTypePtr(), Qualifiers(), OS, C.getLangOpts(),
+                  llvm::Twine());
+  OS << "'";
+  std::unique_ptr<BugReport> R(
+      new BugReport(*BT, OS.str(), C.generateNonFatalErrorNode()));
+  R->markInteresting(Reg);
+  R->addVisitor(llvm::make_unique<DynamicTypeBugVisitor>(Reg));
+  R->addRange(ReportedNode->getSourceRange());
+  C.emitReport(std::move(R));
+}
+
+PathDiagnosticPiece *DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
+    const ExplodedNode *N, const ExplodedNode *PrevN, BugReporterContext &BRC,
+    BugReport &BR) {
+  ProgramStateRef State = N->getState();
+  ProgramStateRef StatePrev = PrevN->getState();
+
+  DynamicTypeInfo TrackedType = getDynamicTypeInfo(State, Reg);
+  DynamicTypeInfo TrackedTypePrev = getDynamicTypeInfo(StatePrev, Reg);
+  if (!TrackedType.isValid())
+    return nullptr;
+
+  if (TrackedTypePrev.isValid() &&
+      TrackedTypePrev.getType() == TrackedType.getType())
+    return nullptr;
+
+  // Retrieve the associated statement.
+  const Stmt *S = nullptr;
+  ProgramPoint ProgLoc = N->getLocation();
+  if (Optional<StmtPoint> SP = ProgLoc.getAs<StmtPoint>()) {
+    S = SP->getStmt();
+  }
+
+  if (!S)
+    return nullptr;
+
+  const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
+
+  SmallString<256> Buf;
+  llvm::raw_svector_ostream OS(Buf);
+  OS << "Type '";
+  QualType::print(TrackedType.getType().getTypePtr(), Qualifiers(), OS,
+                  LangOpts, llvm::Twine());
+  OS << "' is inferred from ";
+
+  if (const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
+    OS << "explicit cast (from '";
+    QualType::print(ExplicitCast->getSubExpr()->getType().getTypePtr(),
+                    Qualifiers(), OS, LangOpts, llvm::Twine());
+    OS << "' to '";
+    QualType::print(ExplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+                    LangOpts, llvm::Twine());
+    OS << "')";
+  } else if (const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
+    OS << "implicit cast (from '";
+    QualType::print(ImplicitCast->getSubExpr()->getType().getTypePtr(),
+                    Qualifiers(), OS, LangOpts, llvm::Twine());
+    OS << "' to '";
+    QualType::print(ImplicitCast->getType().getTypePtr(), Qualifiers(), OS,
+                    LangOpts, llvm::Twine());
+    OS << "')";
+  } else {
+    OS << "this context";
+  }
+
+  // Generate the extra diagnostic.
+  PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
+                             N->getLocationContext());
+  return new PathDiagnosticEventPiece(Pos, OS.str(), true, nullptr);
+}
+
+// TODO: consider checking explicit casts?
+void DynamicTypeChecker::checkPostStmt(const ImplicitCastExpr *CE,
+                                       CheckerContext &C) const {
+  // TODO: C++ support.
+  if (CE->getCastKind() != CK_BitCast)
+    return;
+
+  const MemRegion *Region = C.getSVal(CE).getAsRegion();
+  if (!Region)
+    return;
+
+  ProgramStateRef State = C.getState();
+  DynamicTypeInfo DynTypeInfo = getDynamicTypeInfo(State, Region);
+
+  if (!DynTypeInfo.isValid())
+    return;
+
+  QualType DynType = DynTypeInfo.getType();
+  QualType StaticType = CE->getType();
+
+  const auto *DynObjCType = DynType->getAs<ObjCObjectPointerType>();
+  const auto *StaticObjCType = StaticType->getAs<ObjCObjectPointerType>();
+
+  if (!DynObjCType || !StaticObjCType)
+    return;
+
+  ASTContext &ASTCtxt = C.getASTContext();
+
+  // Strip kindeofness to correctly detect subtyping relationships.
+  DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+  StaticObjCType = StaticObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
+
+  // Specialized objects are handled by the generics checker.
+  if (StaticObjCType->isSpecialized())
+    return;
+
+  if (ASTCtxt.canAssignObjCInterfaces(StaticObjCType, DynObjCType))
+    return;
+
+  if (DynTypeInfo.canBeASubClass() &&
+      ASTCtxt.canAssignObjCInterfaces(DynObjCType, StaticObjCType))
+    return;
+
+  reportTypeError(DynType, StaticType, Region, CE, C);
+}
+
+void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
+  mgr.registerChecker<DynamicTypeChecker>();
+}

Modified: cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp?rev=248041&r1=248040&r2=248041&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Checkers/DynamicTypePropagation.cpp Fri Sep 18 16:15:37 2015
@@ -22,7 +22,6 @@
 //===----------------------------------------------------------------------===//
 
 #include "ClangSACheckers.h"
-#include "clang/AST/ParentMap.h"
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Basic/Builtins.h"
 #include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
@@ -98,13 +97,6 @@ class DynamicTypePropagation:
                          const ObjCObjectPointerType *To, ExplodedNode *N,
                          SymbolRef Sym, CheckerContext &C,
                          const Stmt *ReportedNode = nullptr) const;
-
-  bool isReturnValueMisused(const ObjCMessageExpr *MessageExpr,
-                            const ObjCObjectPointerType *TrackedType,
-                            SymbolRef Sym, const ObjCMethodDecl *Method,
-                            ArrayRef<QualType> TypeArgs,
-                            bool SubscriptOrProperty, CheckerContext &C) const;
-
 public:
   void checkPreCall(const CallEvent &Call, CheckerContext &C) const;
   void checkPostCall(const CallEvent &Call, CheckerContext &C) const;
@@ -684,46 +676,6 @@ static QualType getReturnTypeForMethod(
   return ResultType;
 }
 
-/// Validate that the return type of a message expression is used correctly.
-/// Returns true in case an error is detected.
-bool DynamicTypePropagation::isReturnValueMisused(
-    const ObjCMessageExpr *MessageExpr,
-    const ObjCObjectPointerType *ResultPtrType, SymbolRef Sym,
-    const ObjCMethodDecl *Method, ArrayRef<QualType> TypeArgs,
-    bool SubscriptOrProperty, CheckerContext &C) const {
-  if (!ResultPtrType)
-    return false;
-
-  ASTContext &ASTCtxt = C.getASTContext();
-  const Stmt *Parent =
-      C.getCurrentAnalysisDeclContext()->getParentMap().getParent(MessageExpr);
-  if (SubscriptOrProperty) {
-    // Properties and subscripts are not direct parents.
-    Parent =
-        C.getCurrentAnalysisDeclContext()->getParentMap().getParent(Parent);
-  }
-
-  const auto *ImplicitCast = dyn_cast_or_null<ImplicitCastExpr>(Parent);
-  if (!ImplicitCast || ImplicitCast->getCastKind() != CK_BitCast)
-    return false;
-
-  const auto *ExprTypeAboveCast =
-      ImplicitCast->getType()->getAs<ObjCObjectPointerType>();
-  if (!ExprTypeAboveCast)
-    return false;
-
-  // Only warn on unrelated types to avoid too many false positives on
-  // downcasts.
-  if (!ASTCtxt.canAssignObjCInterfaces(ExprTypeAboveCast, ResultPtrType) &&
-      !ASTCtxt.canAssignObjCInterfaces(ResultPtrType, ExprTypeAboveCast)) {
-    static CheckerProgramPointTag Tag(this, "ReturnTypeMismatch");
-    ExplodedNode *N = C.addTransition(C.getState(), &Tag);
-    reportGenericsBug(ResultPtrType, ExprTypeAboveCast, N, Sym, C);
-    return true;
-  }
-  return false;
-}
-
 /// When the receiver has a tracked type, use that type to validate the
 /// argumments of the message expression and the return value.
 void DynamicTypePropagation::checkPreObjCMessage(const ObjCMethodCall &M,
@@ -881,10 +833,6 @@ void DynamicTypePropagation::checkPostOb
 
   const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
 
-  if (isReturnValueMisused(MessageExpr, ResultPtrType, RecSym, Method,
-                           *TypeArgs, M.getMessageKind() != OCM_Message, C))
-    return;
-
   if (!ResultPtrType || ResultPtrType->isUnspecialized())
     return;
 

Added: cfe/trunk/test/Analysis/dynamic_type_check.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/dynamic_type_check.m?rev=248041&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/dynamic_type_check.m (added)
+++ cfe/trunk/test/Analysis/dynamic_type_check.m Fri Sep 18 16:15:37 2015
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.core.DynamicTypeChecker -verify %s
+
+
+#define nil 0
+typedef unsigned long NSUInteger;
+typedef int BOOL;
+
+ at protocol NSObject
++ (id)alloc;
+- (id)init;
+ at end
+
+ at protocol NSCopying
+ at end
+
+__attribute__((objc_root_class))
+ at interface NSObject <NSObject>
+ at end
+
+ at interface NSString : NSObject <NSCopying>
+ at end
+
+ at interface NSMutableString : NSString
+ at end
+
+ at interface NSNumber : NSObject <NSCopying>
+ at end
+
+void testTypeCheck(NSString* str) {
+  id obj = str;
+  NSNumber *num = obj; // expected-warning {{}}
+  (void)num;
+}

Modified: cfe/trunk/test/Analysis/generics.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/generics.m?rev=248041&r1=248040&r2=248041&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/generics.m (original)
+++ cfe/trunk/test/Analysis/generics.m Fri Sep 18 16:15:37 2015
@@ -1,5 +1,5 @@
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics -verify -Wno-objc-method-access %s
-// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics -verify -Wno-objc-method-access %s -analyzer-output=plist -o %t.plist
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,alpha.osx.cocoa.ObjCGenerics,alpha.core.DynamicTypeChecker -verify -Wno-objc-method-access %s -analyzer-output=plist -o %t.plist
 // RUN: FileCheck --input-file %t.plist %s
 
 #if !__has_feature(objc_generics)
@@ -236,13 +236,13 @@ void enforceDynamicRulesInsteadOfStatic(
 
 void workWithProperties(NSArray<NSNumber *> *a) {
   NSArray *b = a;
-  NSString *str = [b getObjAtIndex: 0]; // expected-warning {{Conversion}}
+  NSString *str = [b getObjAtIndex: 0]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}
   NSNumber *num = [b getObjAtIndex: 0];
-  str = [b firstObject]; // expected-warning {{Conversion}}
+  str = [b firstObject]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}
   num = [b firstObject];
-  str = b.firstObject; // expected-warning {{Conversion}}
+  str = b.firstObject; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}
   num = b.firstObject;
-  str = b[0]; // expected-warning {{Conversion}}
+  str = b[0]; // expected-warning {{Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'}}
   num = b[0];
 }
 
@@ -318,15 +318,14 @@ void eraseSpecialization(NSArray<NSArray
 
 void returnToUnrelatedType(NSArray<NSArray<NSString *> *> *arr) {
   NSArray *erased = arr;
-  NSSet* a = [erased firstObject]; // expected-warning {{Conversion}}
+  NSSet* a = [erased firstObject]; // expected-warning {{Object has a dynamic type 'NSArray<NSString *> *' which is incompatible with static type 'NSSet *'}}
   (void)a;
 }
 
 void returnToIdVariable(NSArray<NSString *> *arr) {
   NSArray *erased = arr;
   id a = [erased firstObject];
-  // TODO: Warn in this case. Possibly in a separate checker.
-  NSNumber *res = a;
+  NSNumber *res = a; // expected-warning {{Object has a dynamic type 'NSString *' which is incompatible with static type 'NSNumber *'}}
 }
 
 // CHECK:  <array>
@@ -4428,35 +4427,6 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:    <key>path</key>
 // CHECK:    <array>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>238</integer>
-// CHECK:       <key>col</key><integer>16</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>depth</key><integer>0</integer>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
-// CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -4549,57 +4519,57 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:     </dict>
-// CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>workWithProperties</string>
-// CHECK:   <key>issue_hash</key><string>2</string>
-// CHECK:   <key>location</key>
-// CHECK:   <dict>
-// CHECK:    <key>line</key><integer>239</integer>
-// CHECK:    <key>col</key><integer>19</integer>
-// CHECK:    <key>file</key><integer>0</integer>
-// CHECK:   </dict>
-// CHECK:   </dict>
-// CHECK:   <dict>
-// CHECK:    <key>path</key>
-// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>238</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>239</integer>
+// CHECK:       <key>col</key><integer>19</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>239</integer>
+// CHECK:          <key>col</key><integer>19</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>239</integer>
+// CHECK:          <key>col</key><integer>38</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_hash</key><string>2</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>239</integer>
+// CHECK:    <key>col</key><integer>19</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
@@ -4693,57 +4663,57 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:     </dict>
-// CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>workWithProperties</string>
-// CHECK:   <key>issue_hash</key><string>4</string>
-// CHECK:   <key>location</key>
-// CHECK:   <dict>
-// CHECK:    <key>line</key><integer>241</integer>
-// CHECK:    <key>col</key><integer>9</integer>
-// CHECK:    <key>file</key><integer>0</integer>
-// CHECK:   </dict>
-// CHECK:   </dict>
-// CHECK:   <dict>
-// CHECK:    <key>path</key>
-// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>238</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>241</integer>
+// CHECK:       <key>col</key><integer>9</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>241</integer>
+// CHECK:          <key>col</key><integer>9</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>241</integer>
+// CHECK:          <key>col</key><integer>23</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_hash</key><string>4</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>241</integer>
+// CHECK:    <key>col</key><integer>9</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
@@ -4837,57 +4807,57 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:     </dict>
-// CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>workWithProperties</string>
-// CHECK:   <key>issue_hash</key><string>6</string>
-// CHECK:   <key>location</key>
-// CHECK:   <dict>
-// CHECK:    <key>line</key><integer>243</integer>
-// CHECK:    <key>col</key><integer>11</integer>
-// CHECK:    <key>file</key><integer>0</integer>
-// CHECK:   </dict>
-// CHECK:   </dict>
-// CHECK:   <dict>
-// CHECK:    <key>path</key>
-// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>238</integer>
-// CHECK:       <key>col</key><integer>16</integer>
+// CHECK:       <key>line</key><integer>243</integer>
+// CHECK:       <key>col</key><integer>9</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>243</integer>
+// CHECK:          <key>col</key><integer>9</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>238</integer>
-// CHECK:          <key>col</key><integer>16</integer>
+// CHECK:          <key>line</key><integer>243</integer>
+// CHECK:          <key>col</key><integer>21</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:        </array>
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSNumber *> *' is inferred from implicit cast (from 'NSArray<NSNumber *> *' to 'NSArray *')</string>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>workWithProperties</string>
+// CHECK:   <key>issue_hash</key><string>6</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>243</integer>
+// CHECK:    <key>col</key><integer>9</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
@@ -4981,15 +4951,44 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
+// CHECK:      <string>Type 'NSNumber *' is inferred from this context</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>245</integer>
+// CHECK:       <key>col</key><integer>9</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>245</integer>
+// CHECK:          <key>col</key><integer>9</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>245</integer>
+// CHECK:          <key>col</key><integer>12</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSNumber *' to incompatible type 'NSString *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSNumber *' which is incompatible with static type 'NSString *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>workWithProperties</string>
 // CHECK:   <key>issue_hash</key><string>8</string>
@@ -5436,35 +5435,6 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:    <key>path</key>
 // CHECK:    <array>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>289</integer>
-// CHECK:       <key>col</key><integer>13</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>289</integer>
-// CHECK:          <key>col</key><integer>13</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>289</integer>
-// CHECK:          <key>col</key><integer>39</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>depth</key><integer>0</integer>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
-// CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -5557,46 +5527,28 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
 // CHECK:     </dict>
-// CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
-// CHECK:   <key>issue_context_kind</key><string>function</string>
-// CHECK:   <key>issue_context</key><string>trackedClassVariables</string>
-// CHECK:   <key>issue_hash</key><string>2</string>
-// CHECK:   <key>location</key>
-// CHECK:   <dict>
-// CHECK:    <key>line</key><integer>290</integer>
-// CHECK:    <key>col</key><integer>28</integer>
-// CHECK:    <key>file</key><integer>0</integer>
-// CHECK:   </dict>
-// CHECK:   </dict>
-// CHECK:   <dict>
-// CHECK:    <key>path</key>
-// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>event</string>
 // CHECK:      <key>location</key>
 // CHECK:      <dict>
-// CHECK:       <key>line</key><integer>289</integer>
-// CHECK:       <key>col</key><integer>13</integer>
+// CHECK:       <key>line</key><integer>290</integer>
+// CHECK:       <key>col</key><integer>28</integer>
 // CHECK:       <key>file</key><integer>0</integer>
 // CHECK:      </dict>
 // CHECK:      <key>ranges</key>
 // CHECK:      <array>
 // CHECK:        <array>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>289</integer>
-// CHECK:          <key>col</key><integer>13</integer>
+// CHECK:          <key>line</key><integer>290</integer>
+// CHECK:          <key>col</key><integer>28</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
 // CHECK:         <dict>
-// CHECK:          <key>line</key><integer>289</integer>
+// CHECK:          <key>line</key><integer>290</integer>
 // CHECK:          <key>col</key><integer>39</integer>
 // CHECK:          <key>file</key><integer>0</integer>
 // CHECK:         </dict>
@@ -5604,10 +5556,28 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
 // CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
+// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
+// CHECK:    <key>type</key><string>Generics</string>
+// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>trackedClassVariables</string>
+// CHECK:   <key>issue_hash</key><string>2</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>290</integer>
+// CHECK:    <key>col</key><integer>28</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
 // CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
@@ -5701,6 +5671,35 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>291</integer>
+// CHECK:       <key>col</key><integer>7</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>291</integer>
+// CHECK:          <key>col</key><integer>7</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>291</integer>
+// CHECK:          <key>col</key><integer>19</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
 // CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
 // CHECK:      <key>message</key>
 // CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSArray<NSNumber *> *'</string>
@@ -6224,35 +6223,6 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:    <key>path</key>
 // CHECK:    <array>
 // CHECK:     <dict>
-// CHECK:      <key>kind</key><string>event</string>
-// CHECK:      <key>location</key>
-// CHECK:      <dict>
-// CHECK:       <key>line</key><integer>320</integer>
-// CHECK:       <key>col</key><integer>21</integer>
-// CHECK:       <key>file</key><integer>0</integer>
-// CHECK:      </dict>
-// CHECK:      <key>ranges</key>
-// CHECK:      <array>
-// CHECK:        <array>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>320</integer>
-// CHECK:          <key>col</key><integer>21</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:         <dict>
-// CHECK:          <key>line</key><integer>320</integer>
-// CHECK:          <key>col</key><integer>23</integer>
-// CHECK:          <key>file</key><integer>0</integer>
-// CHECK:         </dict>
-// CHECK:        </array>
-// CHECK:      </array>
-// CHECK:      <key>depth</key><integer>0</integer>
-// CHECK:      <key>extended_message</key>
-// CHECK:      <string>Type 'NSArray<NSArray<NSString *> *> *' is inferred from implicit cast (from 'NSArray<NSArray<NSString *> *> *' to 'NSArray *')</string>
-// CHECK:      <key>message</key>
-// CHECK:      <string>Type 'NSArray<NSArray<NSString *> *> *' is inferred from implicit cast (from 'NSArray<NSArray<NSString *> *> *' to 'NSArray *')</string>
-// CHECK:     </dict>
-// CHECK:     <dict>
 // CHECK:      <key>kind</key><string>control</string>
 // CHECK:      <key>edges</key>
 // CHECK:       <array>
@@ -6345,15 +6315,44 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:      </array>
 // CHECK:      <key>depth</key><integer>0</integer>
 // CHECK:      <key>extended_message</key>
-// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSSet *'</string>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type 'NSArray<NSString *> *' is inferred from this context</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>321</integer>
+// CHECK:       <key>col</key><integer>14</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>321</integer>
+// CHECK:          <key>col</key><integer>14</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>321</integer>
+// CHECK:          <key>col</key><integer>33</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Object has a dynamic type 'NSArray<NSString *> *' which is incompatible with static type 'NSSet *'</string>
 // CHECK:      <key>message</key>
-// CHECK:      <string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSSet *'</string>
+// CHECK:      <string>Object has a dynamic type 'NSArray<NSString *> *' which is incompatible with static type 'NSSet *'</string>
 // CHECK:     </dict>
 // CHECK:    </array>
-// CHECK:    <key>description</key><string>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSSet *'</string>
-// CHECK:    <key>category</key><string>Core Foundation/Objective-C</string>
-// CHECK:    <key>type</key><string>Generics</string>
-// CHECK:    <key>check_name</key><string>core.DynamicTypePropagation</string>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSArray<NSString *> *' which is incompatible with static type 'NSSet *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
 // CHECK:   <key>issue_context_kind</key><string>function</string>
 // CHECK:   <key>issue_context</key><string>returnToUnrelatedType</string>
 // CHECK:   <key>issue_hash</key><string>2</string>
@@ -6364,4 +6363,182 @@ void returnToIdVariable(NSArray<NSString
 // CHECK:    <key>file</key><integer>0</integer>
 // CHECK:   </dict>
 // CHECK:   </dict>
+// CHECK:   <dict>
+// CHECK:    <key>path</key>
+// CHECK:    <array>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>326</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>326</integer>
+// CHECK:            <key>col</key><integer>9</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>327</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>327</integer>
+// CHECK:            <key>col</key><integer>4</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>327</integer>
+// CHECK:       <key>col</key><integer>10</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>327</integer>
+// CHECK:          <key>col</key><integer>10</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>327</integer>
+// CHECK:          <key>col</key><integer>29</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Type 'NSString *' is inferred from this context</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Type 'NSString *' is inferred from this context</string>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>327</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>327</integer>
+// CHECK:            <key>col</key><integer>4</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>control</string>
+// CHECK:      <key>edges</key>
+// CHECK:       <array>
+// CHECK:        <dict>
+// CHECK:         <key>start</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>3</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>10</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:         <key>end</key>
+// CHECK:          <array>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:           <dict>
+// CHECK:            <key>line</key><integer>328</integer>
+// CHECK:            <key>col</key><integer>19</integer>
+// CHECK:            <key>file</key><integer>0</integer>
+// CHECK:           </dict>
+// CHECK:          </array>
+// CHECK:        </dict>
+// CHECK:       </array>
+// CHECK:     </dict>
+// CHECK:     <dict>
+// CHECK:      <key>kind</key><string>event</string>
+// CHECK:      <key>location</key>
+// CHECK:      <dict>
+// CHECK:       <key>line</key><integer>328</integer>
+// CHECK:       <key>col</key><integer>19</integer>
+// CHECK:       <key>file</key><integer>0</integer>
+// CHECK:      </dict>
+// CHECK:      <key>ranges</key>
+// CHECK:      <array>
+// CHECK:        <array>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>328</integer>
+// CHECK:          <key>col</key><integer>19</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:         <dict>
+// CHECK:          <key>line</key><integer>328</integer>
+// CHECK:          <key>col</key><integer>19</integer>
+// CHECK:          <key>file</key><integer>0</integer>
+// CHECK:         </dict>
+// CHECK:        </array>
+// CHECK:      </array>
+// CHECK:      <key>depth</key><integer>0</integer>
+// CHECK:      <key>extended_message</key>
+// CHECK:      <string>Object has a dynamic type 'NSString *' which is incompatible with static type 'NSNumber *'</string>
+// CHECK:      <key>message</key>
+// CHECK:      <string>Object has a dynamic type 'NSString *' which is incompatible with static type 'NSNumber *'</string>
+// CHECK:     </dict>
+// CHECK:    </array>
+// CHECK:    <key>description</key><string>Object has a dynamic type 'NSString *' which is incompatible with static type 'NSNumber *'</string>
+// CHECK:    <key>category</key><string>Type Error</string>
+// CHECK:    <key>type</key><string>Dynamic and static type mismatch</string>
+// CHECK:    <key>check_name</key><string>alpha.core.DynamicTypeChecker</string>
+// CHECK:   <key>issue_context_kind</key><string>function</string>
+// CHECK:   <key>issue_context</key><string>returnToIdVariable</string>
+// CHECK:   <key>issue_hash</key><string>3</string>
+// CHECK:   <key>location</key>
+// CHECK:   <dict>
+// CHECK:    <key>line</key><integer>328</integer>
+// CHECK:    <key>col</key><integer>19</integer>
+// CHECK:    <key>file</key><integer>0</integer>
+// CHECK:   </dict>
+// CHECK:   </dict>
 // CHECK:  </array>




More information about the cfe-commits mailing list