From: Ted Kremenek Date: Tue, 1 May 2012 00:10:19 +0000 (+0000) Subject: malloc size checker: Ignore const'ness of pointer types when determining of a sizeof... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=88db6a2daa8bb55fe924773805f42616c8a4f314;p=clang malloc size checker: Ignore const'ness of pointer types when determining of a sizeof() type is compatible with a pointed type. Fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155864 91177308-0d34-0410-b5e6-96231b3b80d8 --- 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()) + if (const PointerType *ptrB = B->getAs()) { + A = ptrA->getPointeeType(); + B = ptrB->getPointeeType(); + continue; + } + + break; + } + + return false; +} + class MallocSizeofChecker : public Checker { 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()) { 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); +}