28 using namespace clang;
32 class DynamicTypeChecker :
public Checker<check::PostStmt<ImplicitCastExpr>> {
33 mutable std::unique_ptr<BugType> BT;
34 void initBugType()
const {
37 new BugType(
this,
"Dynamic and static type mismatch",
"Type Error"));
42 DynamicTypeBugVisitor(
const MemRegion *Reg) : Reg(Reg) {}
44 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
51 BugReporterContext &BRC,
52 PathSensitiveBugReport &BR)
override;
60 const MemRegion *Reg,
const Stmt *ReportedNode,
61 CheckerContext &C)
const;
71 const Stmt *ReportedNode,
72 CheckerContext &C)
const {
75 llvm::raw_svector_ostream
OS(Buf);
76 OS <<
"Object has a dynamic type '";
79 OS <<
"' which is incompatible with static type '";
83 auto R = std::make_unique<PathSensitiveBugReport>(
84 *BT, OS.str(), C.generateNonFatalErrorNode());
85 R->markInteresting(Reg);
86 R->addVisitor(std::make_unique<DynamicTypeBugVisitor>(Reg));
88 C.emitReport(std::move(R));
92 const ExplodedNode *N, BugReporterContext &BRC, PathSensitiveBugReport &) {
98 if (!TrackedType.isValid())
101 if (TrackedTypePrev.isValid() &&
102 TrackedTypePrev.getType() == TrackedType.getType())
106 const Stmt *S = N->getStmtForDiagnostics();
110 const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
113 llvm::raw_svector_ostream
OS(Buf);
116 LangOpts, llvm::Twine());
117 OS <<
"' is inferred from ";
119 if (
const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
120 OS <<
"explicit cast (from '";
125 LangOpts, llvm::Twine());
127 }
else if (
const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
128 OS <<
"implicit cast (from '";
133 LangOpts, llvm::Twine());
136 OS <<
"this context";
140 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
141 N->getLocationContext());
142 return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
true);
155 CheckerContext &C)
const {
160 const MemRegion *Region = C.getSVal(CE).getAsRegion();
167 if (!DynTypeInfo.isValid())
170 QualType DynType = DynTypeInfo.getType();
176 if (!DynObjCType || !StaticObjCType)
185 DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
195 if (DynTypeInfo.canBeASubClass() &&
199 reportTypeError(DynType, StaticType, Region, CE, C);
202 void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
203 mgr.registerChecker<DynamicTypeChecker>();
206 bool ento::shouldRegisterDynamicTypeChecker(
const LangOptions &LO) {
A (possibly-)qualified type.
Stmt - This represents one statement.
Decl - This represents one declaration (or definition), e.g.
IntrusiveRefCntPtr< const ProgramState > ProgramStateRef
const T * getAs() const
Member-template getAs<specific type>'.
The collection of all-type qualifiers we support.
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
bool isSpecialized() const
Whether this type is specialized, meaning that it has type arguments.
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
const ObjCObjectPointerType * stripObjCKindOfTypeAndQuals(const ASTContext &ctx) const
Strip off the Objective-C "kindof" type and (with it) any protocol qualifiers.
std::shared_ptr< PathDiagnosticPiece > PathDiagnosticPieceRef
void print(raw_ostream &OS, const PrintingPolicy &Policy, const Twine &PlaceHolder=Twine(), unsigned Indentation=0) const
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Represents an ObjC class declaration.
static bool hasDefinition(const ObjCObjectPointerType *ObjPtr)
CastKind getCastKind() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Dataflow Directional Tag Classes.
ObjCInterfaceDecl * getDefinition()
Retrieve the definition of this class, or NULL if this class has been forward-declared (with @class) ...
Represents a pointer to an Objective C object.
Indicates that the tracking object is a descendant of a referenced-counted OSObject, used in the Darwin kernel.
ObjCInterfaceDecl * getInterfaceDecl() const
If this pointer points to an Objective @interface type, gets the declaration for that interface...
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *MR)
Get dynamic type information for the region MR.
bool canAssignObjCInterfaces(const ObjCObjectPointerType *LHSOPT, const ObjCObjectPointerType *RHSOPT)
canAssignObjCInterfaces - Return true if the two interface types are compatible for assignment from R...
X
Add a minimal nested name specifier fixit hint to allow lookup of a tag name from an outer enclosing ...
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...