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";
133 return std::make_shared<PathDiagnosticEventPiece>(Pos,
OS.str(),
true);
141 return Decl->getDefinition();
145void DynamicTypeChecker::checkPostStmt(
const ImplicitCastExpr *CE,
146 CheckerContext &
C)
const {
151 const MemRegion *Region =
C.getSVal(CE).getAsRegion();
161 QualType DynType = DynTypeInfo.
getType();
162 QualType StaticType = CE->
getType();
164 const auto *DynObjCType = DynType->
getAs<ObjCObjectPointerType>();
165 const auto *StaticObjCType = StaticType->
getAs<ObjCObjectPointerType>();
167 if (!DynObjCType || !StaticObjCType)
173 ASTContext &ASTCtxt =
C.getASTContext();
176 DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
190 reportTypeError(DynType, StaticType, Region, CE,
C);
193void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
197bool 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.
ExplodedNode * getFirstPred()
const StackFrame * getStackFrame() const
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.