continue;
QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
- if (!typesCompatible(BR.getContext(), PointeeType, SizeofType)) {
- const TypeSourceInfo *TSI = 0;
- if (i->CastedExprParent.is<const VarDecl *>()) {
- TSI =
+
+ if (typesCompatible(BR.getContext(), PointeeType, SizeofType))
+ continue;
+
+ // If the argument to sizeof is an array, the result could be a
+ // pointer to the array element.
+ if (const ArrayType *AT = dyn_cast<ArrayType>(SizeofType)) {
+ QualType ElemType = AT->getElementType();
+ if (typesCompatible(BR.getContext(), PointeeType,
+ AT->getElementType()))
+ continue;
+
+ // For now, let's only reason about arrays of built in types.
+ if (!ElemType->isBuiltinType())
+ continue;
+ }
+
+
+ const TypeSourceInfo *TSI = 0;
+ if (i->CastedExprParent.is<const VarDecl *>()) {
+ TSI =
i->CastedExprParent.get<const VarDecl *>()->getTypeSourceInfo();
- } else {
- TSI = i->ExplicitCastType;
- }
-
- SmallString<64> buf;
- llvm::raw_svector_ostream OS(buf);
-
- OS << "Result of ";
- const FunctionDecl *Callee = i->AllocCall->getDirectCallee();
- if (Callee && Callee->getIdentifier())
- OS << '\'' << Callee->getIdentifier()->getName() << '\'';
- else
- OS << "call";
- OS << " is converted to a pointer of type '"
- << PointeeType.getAsString() << "', which is incompatible with "
- << "sizeof operand type '" << SizeofType.getAsString() << "'";
- llvm::SmallVector<SourceRange, 4> Ranges;
- Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
- Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
- if (TSI)
- Ranges.push_back(TSI->getTypeLoc().getSourceRange());
-
- PathDiagnosticLocation L =
+ } else {
+ TSI = i->ExplicitCastType;
+ }
+
+ SmallString<64> buf;
+ llvm::raw_svector_ostream OS(buf);
+
+ OS << "Result of ";
+ const FunctionDecl *Callee = i->AllocCall->getDirectCallee();
+ if (Callee && Callee->getIdentifier())
+ OS << '\'' << Callee->getIdentifier()->getName() << '\'';
+ else
+ OS << "call";
+ OS << " is converted to a pointer of type '"
+ << PointeeType.getAsString() << "', which is incompatible with "
+ << "sizeof operand type '" << SizeofType.getAsString() << "'";
+ llvm::SmallVector<SourceRange, 4> Ranges;
+ Ranges.push_back(i->AllocCall->getCallee()->getSourceRange());
+ Ranges.push_back(SFinder.Sizeofs[0]->getSourceRange());
+ if (TSI)
+ Ranges.push_back(TSI->getTypeLoc().getSourceRange());
+
+ PathDiagnosticLocation L =
PathDiagnosticLocation::createBegin(i->AllocCall->getCallee(),
- BR.getSourceManager(), ADC);
+ BR.getSourceManager(), ADC);
- BR.EmitBasicReport(D, "Allocator sizeof operand mismatch",
- categories::UnixAPI,
- OS.str(),
- L, Ranges.data(), Ranges.size());
- }
+ BR.EmitBasicReport(D, "Allocator sizeof operand mismatch",
+ categories::UnixAPI,
+ OS.str(),
+ L, Ranges.data(), Ranges.size());
}
}
}
const char ***y = (const char ***)malloc(1 * sizeof(char *)); // expected-warning {{Result of 'malloc' is converted to a pointer of type 'const char **', which is incompatible with sizeof operand type 'char *'}}
free(x);
}
+
+int *mallocArraySize() {
+ static const int sTable[10];
+ static const int nestedTable[10][10];
+ int *table = malloc(sizeof sTable);
+ int *table1 = malloc(sizeof nestedTable);
+ return table;
+}
+
+int *mallocWrongArraySize() {
+ static const double sTable[10];
+ int *table = malloc(sizeof sTable); // expected-warning {{Result of 'malloc' is converted to a pointer of type 'int', which is incompatible with sizeof operand type 'const double [10]'}}
+ return table;
+}