Index: cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp =================================================================== --- cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ cfe/trunk/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -35,6 +35,30 @@ }; } // end anonymous namespace +static bool isArrayIndexOutOfBounds(CheckerContext &C, const Expr *Ex) { + ProgramStateRef state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); + + if (!isa(Ex)) + return false; + + SVal Loc = state->getSVal(Ex, LCtx); + if (!Loc.isValid()) + return false; + + const MemRegion *MR = Loc.castAs().getRegion(); + const ElementRegion *ER = dyn_cast(MR); + if (!ER) + return false; + + DefinedOrUnknownSVal Idx = ER->getIndex().castAs(); + DefinedOrUnknownSVal NumElements = C.getStoreManager().getSizeInElements( + state, ER->getSuperRegion(), ER->getValueType()); + ProgramStateRef StInBound = state->assumeInBound(Idx, NumElements, true); + ProgramStateRef StOutBound = state->assumeInBound(Idx, NumElements, false); + return StOutBound && !StInBound; +} + void UndefResultChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { ProgramStateRef state = C.getState(); @@ -77,6 +101,8 @@ << " operand of '" << BinaryOperator::getOpcodeStr(B->getOpcode()) << "' is a garbage value"; + if (isArrayIndexOutOfBounds(C, Ex)) + OS << " due to array index out of bounds"; } else { // Neither operand was undefined, but the result is undefined. Index: cfe/trunk/test/Analysis/uninit-vals-ps.c =================================================================== --- cfe/trunk/test/Analysis/uninit-vals-ps.c +++ cfe/trunk/test/Analysis/uninit-vals-ps.c @@ -57,6 +57,12 @@ return s.x; // no-warning } +void f6(int x) { + int a[20]; + if (x == 25) {} + if (a[x] == 123) {} // expected-warning{{The left operand of '==' is a garbage value due to array index out of bounds}} +} + int ret_uninit() { int i; int *p = &i;