forked from OSchip/llvm-project
[Static Analyzer] General type checker based on dynamic type information.
Differential Revision: http://reviews.llvm.org/D12973 llvm-svn: 248041
This commit is contained in:
parent
34b9ef680f
commit
dce40c518d
|
@ -33,6 +33,7 @@ add_clang_library(clangStaticAnalyzerCheckers
|
|||
DirectIvarAssignment.cpp
|
||||
DivZeroChecker.cpp
|
||||
DynamicTypePropagation.cpp
|
||||
DynamicTypeChecker.cpp
|
||||
ExprInspectionChecker.cpp
|
||||
FixedAddressChecker.cpp
|
||||
GenericTaintChecker.cpp
|
||||
|
|
|
@ -129,6 +129,10 @@ def TestAfterDivZeroChecker : Checker<"TestAfterDivZero">,
|
|||
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 {
|
||||
|
|
|
@ -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>();
|
||||
}
|
|
@ -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::checkPostObjCMessage(const ObjCMethodCall &M,
|
|||
|
||||
const auto *ResultPtrType = ResultType->getAs<ObjCObjectPointerType>();
|
||||
|
||||
if (isReturnValueMisused(MessageExpr, ResultPtrType, RecSym, Method,
|
||||
*TypeArgs, M.getMessageKind() != OCM_Message, C))
|
||||
return;
|
||||
|
||||
if (!ResultPtrType || ResultPtrType->isUnspecialized())
|
||||
return;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
@protocol NSObject
|
||||
+ (id)alloc;
|
||||
- (id)init;
|
||||
@end
|
||||
|
||||
@protocol NSCopying
|
||||
@end
|
||||
|
||||
__attribute__((objc_root_class))
|
||||
@interface NSObject <NSObject>
|
||||
@end
|
||||
|
||||
@interface NSString : NSObject <NSCopying>
|
||||
@end
|
||||
|
||||
@interface NSMutableString : NSString
|
||||
@end
|
||||
|
||||
@interface NSNumber : NSObject <NSCopying>
|
||||
@end
|
||||
|
||||
void testTypeCheck(NSString* str) {
|
||||
id obj = str;
|
||||
NSNumber *num = obj; // expected-warning {{}}
|
||||
(void)num;
|
||||
}
|
|
@ -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(NSArray<NSNumber *> *a) {
|
|||
|
||||
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<NSString *> *> *arr) {
|
|||
|
||||
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 *> *arr) {
|
|||
// 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,15 +4519,44 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>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>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>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>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>2</string>
|
||||
|
@ -4572,35 +4571,6 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>
|
||||
|
@ -4693,15 +4663,44 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>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>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>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>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>4</string>
|
||||
|
@ -4716,35 +4715,6 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>
|
||||
|
@ -4837,57 +4807,57 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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 *> *arr) {
|
|||
// 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 *> *arr) {
|
|||
// 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,6 +5527,35 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>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>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>290</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>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>
|
||||
|
@ -5580,24 +5579,92 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>289</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>289</integer>
|
||||
// CHECK: <key>col</key><integer>7</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>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</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>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</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>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>7</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>289</integer>
|
||||
// CHECK: <key>col</key><integer>13</integer>
|
||||
// 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>289</integer>
|
||||
// CHECK: <key>col</key><integer>13</integer>
|
||||
// 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>289</integer>
|
||||
// CHECK: <key>col</key><integer>39</integer>
|
||||
// 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>
|
||||
|
@ -5609,74 +5676,6 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>start</key>
|
||||
// CHECK: <array>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>289</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>289</integer>
|
||||
// CHECK: <key>col</key><integer>7</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>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</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>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</integer>
|
||||
// CHECK: <key>file</key><integer>0</integer>
|
||||
// CHECK: </dict>
|
||||
// CHECK: <dict>
|
||||
// CHECK: <key>line</key><integer>291</integer>
|
||||
// CHECK: <key>col</key><integer>3</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>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>7</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>
|
||||
|
@ -6224,35 +6223,6 @@ void returnToIdVariable(NSArray<NSString *> *arr) {
|
|||
// 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 *> *arr) {
|
|||
// 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>Conversion from value of type 'NSArray<NSString *> *' to incompatible type 'NSSet *'</string>
|
||||
// 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>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 *> *arr) {
|
|||
// 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>
|
||||
|
|
Loading…
Reference in New Issue