diff options
author | Ted Kremenek <kremenek@apple.com> | 2012-05-01 00:10:19 +0000 |
---|---|---|
committer | Ted Kremenek <kremenek@apple.com> | 2012-05-01 00:10:19 +0000 |
commit | 88db6a2daa8bb55fe924773805f42616c8a4f314 (patch) | |
tree | 813ae48abe0468af18d75d37b659d2e6bd913178 | |
parent | 4e1b292146936432dd6c76ba413f700eb1cd3432 (diff) |
malloc size checker: Ignore const'ness of pointer types when determining of a sizeof() type is compatible with a pointed type.
Fixes <rdar://problem/11292586>.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155864 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp | 25 | ||||
-rw-r--r-- | test/Analysis/malloc-sizeof.c | 8 |
2 files changed, 32 insertions, 1 deletions
diff --git a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp index 08a9da1fe3..7a494746a9 100644 --- a/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp +++ b/lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp @@ -139,6 +139,29 @@ public: } }; +// Determine if the pointee and sizeof types are compatible. Here +// we ignore constness of pointer types. +static bool typesCompatible(ASTContext &C, QualType A, QualType B) { + while (true) { + A = A.getCanonicalType(); + B = B.getCanonicalType(); + + if (A.getTypePtr() == B.getTypePtr()) + return true; + + if (const PointerType *ptrA = A->getAs<PointerType>()) + if (const PointerType *ptrB = B->getAs<PointerType>()) { + A = ptrA->getPointeeType(); + B = ptrB->getPointeeType(); + continue; + } + + break; + } + + return false; +} + class MallocSizeofChecker : public Checker<check::ASTCodeBody> { public: void checkASTCodeBody(const Decl *D, AnalysisManager& mgr, @@ -166,7 +189,7 @@ public: continue; QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument(); - if (!BR.getContext().hasSameUnqualifiedType(PointeeType, SizeofType)) { + if (!typesCompatible(BR.getContext(), PointeeType, SizeofType)) { const TypeSourceInfo *TSI = 0; if (i->CastedExprParent.is<const VarDecl *>()) { TSI = diff --git a/test/Analysis/malloc-sizeof.c b/test/Analysis/malloc-sizeof.c index d2b3bcf3c8..1665108e2f 100644 --- a/test/Analysis/malloc-sizeof.c +++ b/test/Analysis/malloc-sizeof.c @@ -5,6 +5,7 @@ void *malloc(size_t size); void *calloc(size_t nmemb, size_t size); void *realloc(void *ptr, size_t size); +void free(void *ptr); struct A {}; struct B {}; @@ -25,3 +26,10 @@ void foo() { struct A *ap6 = realloc(ap5, sizeof(struct A)); struct A *ap7 = realloc(ap5, sizeof(struct B)); // expected-warning {{Result of 'realloc' is converted to type 'struct A *', whose pointee type 'struct A' is incompatible with sizeof operand type 'struct B'}} } + +// Don't warn when the types differ only by constness. +void ignore_const() { + const char **x = (const char **)malloc(1 * sizeof(char *)); // no-warning + const char ***y = (const char ***)malloc(1 * sizeof(char *)); // expected-warning {{pointee type 'const char **' is incompatible with sizeof operand type 'char *'}} + free(x); +} |