23 #include "llvm/ADT/SmallString.h"
24 #include "llvm/Support/raw_ostream.h"
26 using namespace clang;
31 typedef std::pair<const TypeSourceInfo *, const CallExpr *> TypeCallPair;
32 typedef llvm::PointerUnion<const Stmt *, const VarDecl *> ExprParent;
34 class CastedAllocFinder
40 ExprParent CastedExprParent;
41 const Expr *CastedExpr;
45 CallRecord(ExprParent CastedExprParent,
const Expr *CastedExpr,
48 : CastedExprParent(CastedExprParent), CastedExpr(CastedExpr),
49 ExplicitCastType(ExplicitCastType), AllocCall(AllocCall) {}
52 typedef std::vector<CallRecord> CallVec;
56 II_malloc(&Ctx->Idents.get(
"malloc")),
57 II_calloc(&Ctx->Idents.get(
"calloc")),
58 II_realloc(&Ctx->Idents.get(
"realloc")) {}
60 void VisitChild(ExprParent Parent,
const Stmt *
S) {
61 TypeCallPair AllocCall = Visit(S);
62 if (AllocCall.second && AllocCall.second != S)
63 Calls.push_back(CallRecord(Parent, cast<Expr>(S), AllocCall.first,
67 void VisitChildren(
const Stmt *S) {
68 for (
const Stmt *Child : S->children())
73 TypeCallPair VisitCastExpr(
const CastExpr *E) {
82 TypeCallPair VisitParenExpr(
const ParenExpr *E) {
86 TypeCallPair VisitStmt(
const Stmt *S) {
88 return TypeCallPair();
91 TypeCallPair VisitCallExpr(
const CallExpr *E) {
96 if (II == II_malloc || II == II_calloc || II == II_realloc)
99 return TypeCallPair();
102 TypeCallPair VisitDeclStmt(
const DeclStmt *S) {
103 for (
const auto *I : S->
decls())
104 if (
const VarDecl *VD = dyn_cast<VarDecl>(I))
105 if (
const Expr *Init = VD->getInit())
106 VisitChild(VD, Init);
107 return TypeCallPair();
113 std::vector<const UnaryExprOrTypeTraitExpr *> Sizeofs;
124 void VisitParenExpr(
const ParenExpr *E) {
132 Sizeofs.push_back(E);
166 QualType ElemType = AT->getElementType();
167 if (typesCompatible(C, PT, AT->getElementType()))
175 class MallocSizeofChecker :
public Checker<check::ASTCodeBody> {
182 for (CastedAllocFinder::CallVec::iterator i =
Finder.Calls.begin(),
183 e =
Finder.Calls.end(); i != e; ++i) {
184 QualType CastedType = i->CastedExpr->getType();
192 ae = i->AllocCall->arg_end(); ai != ae; ++ai) {
193 if (!(*ai)->getType()->isIntegralOrUnscopedEnumerationType())
196 SizeofFinder SFinder;
198 if (SFinder.Sizeofs.size() != 1)
201 QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
203 if (typesCompatible(BR.
getContext(), PointeeType, SizeofType))
208 if (compatibleWithArrayType(BR.
getContext(), PointeeType, SizeofType))
212 if (i->CastedExprParent.is<
const VarDecl *>()) {
214 i->CastedExprParent.get<
const VarDecl *>()->getTypeSourceInfo();
216 TSI = i->ExplicitCastType;
220 llvm::raw_svector_ostream OS(buf);
223 const FunctionDecl *Callee = i->AllocCall->getDirectCallee();
228 OS <<
" is converted to a pointer of type '"
229 << PointeeType.
getAsString() <<
"', which is incompatible with "
230 <<
"sizeof operand type '" << SizeofType.
getAsString() <<
"'";
232 Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
233 Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
IdentifierInfo * getIdentifier() const
bool isVoidPointerType() const
std::string getAsString() const
A container of type source information.
UnaryExprOrTypeTrait getKind() const
const char *const UnixAPI
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
ASTContext & getContext()
A builtin binary operation expression such as "x + y" or "x <= y".
TypeSourceInfo * getTypeInfoAsWritten() const
AnalysisDeclContext * getAnalysisDeclContext(const Decl *D)
const ArrayType * getAsArrayTypeUnsafe() const
QualType getPointeeType() const
StringRef getName() const
Return the actual identifier string.
Defines the clang::TypeLoc interface and its subclasses.
static PathDiagnosticLocation createBegin(const Decl *D, const SourceManager &SM)
Create a location for the beginning of the declaration.
TypeLoc getTypeLoc() const
Return the TypeLoc wrapper for the type source info.
ASTMatchFinder *const Finder
CHECKER * registerChecker()
Used to register checkers.
void EmitBasicReport(const Decl *DeclWithIssue, const CheckerBase *Checker, StringRef BugName, StringRef BugCategory, StringRef BugStr, PathDiagnosticLocation Loc, ArrayRef< SourceRange > Ranges=None)
const Type * getTypePtr() const
virtual Stmt * getBody() const
FunctionDecl * getDirectCallee()
If the callee is a FunctionDecl, return it. Otherwise return 0.
SourceRange getSourceRange() const LLVM_READONLY
Get the full source range.
QualType getCanonicalType() const
SourceManager & getSourceManager()
const Expr * getSubExpr() const
bool isPointerType() const