[analyzer] Fix a false positive in sizeof malloc checker.

Don't warn when the sizeof argument is an array with the same element
type as the pointee of the return type.

llvm-svn: 163407
This commit is contained in:
Anna Zaks 2012-09-07 19:20:13 +00:00
parent a8d0ca070f
commit 694be01519
2 changed files with 63 additions and 33 deletions

View File

@ -184,42 +184,58 @@ public:
continue;
QualType SizeofType = SFinder.Sizeofs[0]->getTypeOfArgument();
if (!typesCompatible(BR.getContext(), PointeeType, SizeofType)) {
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);
if (typesCompatible(BR.getContext(), PointeeType, SizeofType))
continue;
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.EmitBasicReport(D, "Allocator sizeof operand mismatch",
categories::UnixAPI,
OS.str(),
L, Ranges.data(), Ranges.size());
// 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 =
PathDiagnosticLocation::createBegin(i->AllocCall->getCallee(),
BR.getSourceManager(), ADC);
BR.EmitBasicReport(D, "Allocator sizeof operand mismatch",
categories::UnixAPI,
OS.str(),
L, Ranges.data(), Ranges.size());
}
}
}

View File

@ -34,3 +34,17 @@ void ignore_const() {
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;
}