}
};
+// 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,
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 =
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 {};
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);
+}