29 using namespace clang;
33 class DynamicTypeChecker :
public Checker<check::PostStmt<ImplicitCastExpr>> {
34 mutable std::unique_ptr<BugType> BT;
35 void initBugType()
const {
38 new BugType(
this,
"Dynamic and static type mismatch",
"Type Error"));
43 DynamicTypeBugVisitor(
const MemRegion *Reg) : Reg(Reg) {}
45 void Profile(llvm::FoldingSetNodeID &
ID)
const override {
51 std::shared_ptr<PathDiagnosticPiece> VisitNode(
const ExplodedNode *N,
52 BugReporterContext &BRC,
53 BugReport &BR)
override;
61 const MemRegion *Reg,
const Stmt *ReportedNode,
62 CheckerContext &C)
const;
69 void DynamicTypeChecker::reportTypeError(
QualType DynamicType,
72 const Stmt *ReportedNode,
73 CheckerContext &C)
const {
76 llvm::raw_svector_ostream
OS(Buf);
77 OS <<
"Object has a dynamic type '";
80 OS <<
"' which is incompatible with static type '";
84 std::unique_ptr<BugReport> R(
85 new BugReport(*BT, OS.str(), C.generateNonFatalErrorNode()));
86 R->markInteresting(Reg);
87 R->addVisitor(llvm::make_unique<DynamicTypeBugVisitor>(Reg));
89 C.emitReport(std::move(R));
92 std::shared_ptr<PathDiagnosticPiece>
93 DynamicTypeChecker::DynamicTypeBugVisitor::VisitNode(
const ExplodedNode *N,
94 BugReporterContext &BRC,
101 if (!TrackedType.isValid())
104 if (TrackedTypePrev.isValid() &&
105 TrackedTypePrev.getType() == TrackedType.getType())
113 const LangOptions &LangOpts = BRC.getASTContext().getLangOpts();
116 llvm::raw_svector_ostream
OS(Buf);
119 LangOpts, llvm::Twine());
120 OS <<
"' is inferred from ";
122 if (
const auto *ExplicitCast = dyn_cast<ExplicitCastExpr>(S)) {
123 OS <<
"explicit cast (from '";
128 LangOpts, llvm::Twine());
130 }
else if (
const auto *ImplicitCast = dyn_cast<ImplicitCastExpr>(S)) {
131 OS <<
"implicit cast (from '";
136 LangOpts, llvm::Twine());
139 OS <<
"this context";
143 PathDiagnosticLocation Pos(S, BRC.getSourceManager(),
144 N->getLocationContext());
145 return std::make_shared<PathDiagnosticEventPiece>(Pos, OS.str(),
true,
159 CheckerContext &C)
const {
164 const MemRegion *Region = C.getSVal(CE).getAsRegion();
171 if (!DynTypeInfo.isValid())
174 QualType DynType = DynTypeInfo.getType();
180 if (!DynObjCType || !StaticObjCType)
189 DynObjCType = DynObjCType->stripObjCKindOfTypeAndQuals(ASTCtxt);
199 if (DynTypeInfo.canBeASubClass() &&
203 reportTypeError(DynType, StaticType, Region, CE, C);
206 void ento::registerDynamicTypeChecker(CheckerManager &mgr) {
207 mgr.registerChecker<DynamicTypeChecker>();
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.
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)
static const Stmt * getStmt(const ExplodedNode *N)
Given an exploded node, retrieve the statement that should be used for the diagnostic location...
CastKind getCastKind() const
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Dataflow Directional Tag Classes.
DynamicTypeInfo getDynamicTypeInfo(ProgramStateRef State, const MemRegion *Reg)
Get dynamic type information for a region.
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...
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...