30class DynamicTypeChecker :
public Checker<check::PostStmt<ImplicitCastExpr>> {
31 const BugType BT{
this,
"Dynamic and static type mismatch",
"Type Error"};
33 class DynamicTypeBugVisitor :
public BugReporterVisitor {
35 DynamicTypeBugVisitor(
const MemRegion *Reg) : Reg(Reg) {}
37 void Profile(llvm::FoldingSetNodeID &ID)
const override {
44 BugReporterContext &BRC,
45 PathSensitiveBugReport &BR)
override;
52 void reportTypeError(QualType DynamicType, QualType StaticType,
53 const MemRegion *Reg,
const Stmt *ReportedNode,
54 CheckerContext &
C)
const;
57 void checkPostStmt(
const ImplicitCastExpr *CE, CheckerContext &
C)
const;
64 const Stmt *ReportedNode,
67 llvm::raw_svector_ostream
OS(Buf);
68 OS <<
"Object has a dynamic type '";
71 OS <<
"' which is incompatible with static type '";
75 auto R = std::make_unique<PathSensitiveBugReport>(
76 BT,
OS.str(),
C.generateNonFatalErrorNode());
77 R->markInteresting(Reg);
78 R->addVisitor(std::make_unique<DynamicTypeBugVisitor>(Reg));
80 C.emitReport(std::move(R));
84 const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
93 if (TrackedTypePrev.
isValid() &&
104 SmallString<256> Buf;
105 llvm::raw_svector_ostream
OS(Buf);
108 LangOpts, llvm::Twine());
109 OS <<
"' is inferred from ";
111 if (
const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
112 OS <<
"explicit cast (from '";
114 Qualifiers(),
OS, LangOpts, llvm::Twine());
117 LangOpts, llvm::Twine());
119 }
else if (
const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
120 OS <<
"implicit cast (from '";
122 Qualifiers(),
OS, LangOpts, llvm::Twine());
125 LangOpts, llvm::Twine());
128 OS <<
"this context";
134 return std::make_shared<PathDiagnosticEventPiece>(Pos,
OS.str(),
true);
142 return Decl->getDefinition();
146void DynamicTypeChecker::checkPostStmt(
const ImplicitCastExpr *CE,
147 CheckerContext &
C)
const {
152 const MemRegion *Region =
C.getSVal(CE).getAsRegion();
162 QualType DynType = DynTypeInfo.
getType();
163 QualType StaticType = CE->
getType();
165 const auto *DynObjCType = DynType->
getAs<ObjCObjectPointerType>();
166 const auto *StaticObjCType = StaticType->
getAs<ObjCObjectPointerType>();
168 if (!DynObjCType || !StaticObjCType)
174 ASTContext &ASTCtxt =
C.getASTContext();
177 DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
191 reportTypeError(DynType, StaticType, Region, CE,
C);
194void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
198bool ento::shouldRegisterDynamicTypeChecker(
const CheckerManager &mgr) {
static bool hasDefinition(const ObjCObjectPointerType *ObjPtr)
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT)
canAssignObjCInterfaces - Return true if the two interface types are compatible for assignment from R...
const LangOptions & getLangOpts() const
CastKind getCastKind() const
Decl - This represents one declaration (or definition), e.g.
Represents an ObjC class declaration.
Represents a pointer to an Objective C object.
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface.
A (possibly-)qualified type.
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
Stmt - This represents one statement.
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
const T * getAs() const
Member-template getAs<specific type>'.
ASTContext & getASTContext() const
const SourceManager & getSourceManager() const
CHECKER * registerChecker(AT &&...Args)
Register a single-part checker (derived from Checker): construct its singleton instance,...
Simple checker classes that implement one frontend (i.e.
bool canBeASubClass() const
Returns false if the type information is precise (the type 'DynTy' is the only type in the lattice),...
QualType getType() const
Returns the currently inferred upper bound on the runtime type.
bool isValid() const
Returns true if the dynamic type info is available.
const ProgramStateRef & getState() const
const Stmt * getStmtForDiagnostics() const
If the node's program point corresponds to a statement, retrieve that statement.
const LocationContext * getLocationContext() const
ExplodedNode * getFirstPred()
MemRegion - The root abstract class for all memory regions.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
@ OS
Indicates that the tracking object is a descendant of a referenced-counted OSObject,...
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get dynamic type information for the region MR.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
The JSON file list parser is used to communicate input to InstallAPI.