[analyzer] Assume that reference symbols are non-null.

By doing this in the constraint managers, we can ensure that ANY reference
whose value we don't know gets the effect, even if it's not a top-level
parameter.

llvm-svn: 162246
This commit is contained in:
Jordan Rose 2012-08-21 00:27:33 +00:00
parent 309856ae9f
commit 075d5d2e99
3 changed files with 33 additions and 2 deletions

View File

@ -363,6 +363,10 @@ const llvm::APSInt* BasicConstraintManager::getSymVal(ProgramStateRef state,
bool BasicConstraintManager::isNotEqual(ProgramStateRef state,
SymbolRef sym,
const llvm::APSInt& V) const {
// Special case: references are known to be non-zero.
if (sym->getType(getBasicVals().getContext())->isReferenceType())
if (V == 0)
return true;
// Retrieve the NE-set associated with the given symbol.
const ConstNotEqTy::data_type* T = state->get<ConstNotEq>(sym);

View File

@ -380,7 +380,17 @@ RangeConstraintManager::GetRange(ProgramStateRef state, SymbolRef sym) {
// given symbol type.
BasicValueFactory &BV = getBasicVals();
QualType T = sym->getType(BV.getContext());
return RangeSet(F, BV.getMinValue(T), BV.getMaxValue(T));
RangeSet Result(F, BV.getMinValue(T), BV.getMaxValue(T));
// Special case: references are known to be non-zero.
if (T->isReferenceType()) {
APSIntType IntType = BV.getAPSIntType(T);
Result = Result.Intersect(BV, F, ++IntType.getZeroValue(),
--IntType.getZeroValue());
}
return Result;
}
//===------------------------------------------------------------------------===

View File

@ -1,3 +1,4 @@
// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=basic -verify -Wno-null-dereference %s
// RUN: %clang_cc1 -analyze -analyzer-checker=core,experimental.core,debug.ExprInspection -analyzer-store=region -analyzer-constraints=range -verify -Wno-null-dereference %s
void clang_analyzer_eval(bool);
@ -110,6 +111,16 @@ void testRetroactiveNullReference(int *x) {
y = 5; // expected-warning{{Dereference of null pointer}}
}
void testReferenceAddress(int &x) {
clang_analyzer_eval(&x != 0); // expected-warning{{TRUE}}
clang_analyzer_eval(&ref() != 0); // expected-warning{{TRUE}}
struct S { int &x; };
extern S *getS();
clang_analyzer_eval(&getS()->x != 0); // expected-warning{{TRUE}}
}
// ------------------------------------
// False negatives
@ -127,5 +138,11 @@ namespace rdar11212286 {
B *x = 0;
return *x; // should warn here!
}
}
void testReferenceFieldAddress() {
struct S { int &x; };
extern S getS();
clang_analyzer_eval(&getS().x != 0); // expected-warning{{UNKNOWN}}
}