]> granicus.if.org Git - clang/commitdiff
malloc size checker: Ignore const'ness of pointer types when determining of a sizeof...
authorTed Kremenek <kremenek@apple.com>
Tue, 1 May 2012 00:10:19 +0000 (00:10 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 1 May 2012 00:10:19 +0000 (00:10 +0000)
Fixes <rdar://problem/11292586>.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155864 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/MallocSizeofChecker.cpp
test/Analysis/malloc-sizeof.c

index 08a9da1fe3ef9a8880be6bd8a7be54fc5c4213af..7a494746a9445463414ce9843a54f5fecd21e247 100644 (file)
@@ -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 =
index d2b3bcf3c84deee7293b767e70bcd3c6b027e136..1665108e2f4e437f42e6cf9ce9b9c03796c9e108 100644 (file)
@@ -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);
+}