diff options
Diffstat (limited to 'clang/lib')
49 files changed, 544 insertions, 428 deletions
diff --git a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp index 7dad2421bf5..df5620b803a 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AdjustedReturnValueChecker.cpp @@ -38,19 +38,20 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE, // Fetch the signature of the called function. const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); - SVal V = state->getSVal(CE); + SVal V = state->getSVal(CE, LCtx); if (V.isUnknown()) return; // Casting to void? Discard the value. if (expectedResultTy->isVoidType()) { - C.addTransition(state->BindExpr(CE, UnknownVal())); + C.addTransition(state->BindExpr(CE, LCtx, UnknownVal())); return; } - const MemRegion *callee = state->getSVal(CE->getCallee()).getAsRegion(); + const MemRegion *callee = state->getSVal(CE->getCallee(), LCtx).getAsRegion(); if (!callee) return; @@ -82,7 +83,7 @@ void AdjustedReturnValueChecker::checkPostStmt(const CallExpr *CE, // the cast avoids some assertion failures elsewhere. SValBuilder &svalBuilder = C.getSValBuilder(); V = svalBuilder.evalCast(V, expectedResultTy, actualResultTy); - C.addTransition(state->BindExpr(CE, V)); + C.addTransition(state->BindExpr(CE, LCtx, V)); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp index 8296eb93c5a..a3dc9648f4d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/AttrNonNullChecker.cpp @@ -34,9 +34,10 @@ public: void AttrNonNullChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); // Check if the callee has a 'nonnull' attribute. - SVal X = state->getSVal(CE->getCallee()); + SVal X = state->getSVal(CE->getCallee(), LCtx); const FunctionDecl *FD = X.getAsFunctionDecl(); if (!FD) @@ -55,7 +56,7 @@ void AttrNonNullChecker::checkPreStmt(const CallExpr *CE, if (!Att->isNonNull(idx)) continue; - SVal V = state->getSVal(*I); + SVal V = state->getSVal(*I, LCtx); DefinedSVal *DV = dyn_cast<DefinedSVal>(&V); // If the value is unknown or undefined, we can't perform this check. diff --git a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp index 1f627297ec8..fbe4671ddc5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BasicObjCFoundationChecks.cpp @@ -129,7 +129,7 @@ void NilArgChecker::checkPreObjCMessage(ObjCMessage msg, Name == "compare:options:range:locale:" || Name == "componentsSeparatedByCharactersInSet:" || Name == "initWithFormat:") { - if (isNil(msg.getArgSVal(0, C.getState()))) + if (isNil(msg.getArgSVal(0, C.getLocationContext(), C.getState()))) WarnNilArg(C, msg, 0); } } @@ -262,7 +262,8 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, return; // Get the value of the "theType" argument. - SVal TheTypeVal = state->getSVal(CE->getArg(1)); + const LocationContext *LCtx = C.getLocationContext(); + SVal TheTypeVal = state->getSVal(CE->getArg(1), LCtx); // FIXME: We really should allow ranges of valid theType values, and // bifurcate the state appropriately. @@ -280,7 +281,7 @@ void CFNumberCreateChecker::checkPreStmt(const CallExpr *CE, // Look at the value of the integer being passed by reference. Essentially // we want to catch cases where the value passed in is not equal to the // size of the type being created. - SVal TheValueExpr = state->getSVal(CE->getArg(2)); + SVal TheValueExpr = state->getSVal(CE->getArg(2), LCtx); // FIXME: Eventually we should handle arbitrary locations. We can do this // by having an enhanced memory model that does low-level typing. @@ -382,7 +383,7 @@ void CFRetainReleaseChecker::checkPreStmt(const CallExpr *CE, // Get the argument's value. const Expr *Arg = CE->getArg(0); - SVal ArgVal = state->getSVal(Arg); + SVal ArgVal = state->getSVal(Arg, C.getLocationContext()); DefinedSVal *DefArgVal = dyn_cast<DefinedSVal>(&ArgVal); if (!DefArgVal) return; @@ -593,7 +594,8 @@ void VariadicMethodTypeChecker::checkPreObjCMessage(ObjCMessage msg, continue; // Ignore pointer constants. - if (isa<loc::ConcreteInt>(msg.getArgSVal(I, state))) + if (isa<loc::ConcreteInt>(msg.getArgSVal(I, C.getLocationContext(), + state))) continue; // Ignore pointer types annotated with 'NSObject' attribute. diff --git a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp index 2cf1209f51d..50938fa777b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/BuiltinFunctionChecker.cpp @@ -33,6 +33,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); const FunctionDecl *FD = C.getCalleeDecl(CE); + const LocationContext *LCtx = C.getLocationContext(); if (!FD) return false; @@ -45,8 +46,8 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, case Builtin::BI__builtin_expect: { // For __builtin_expect, just return the value of the subexpression. assert (CE->arg_begin() != CE->arg_end()); - SVal X = state->getSVal(*(CE->arg_begin())); - C.addTransition(state->BindExpr(CE, X)); + SVal X = state->getSVal(*(CE->arg_begin()), LCtx); + C.addTransition(state->BindExpr(CE, LCtx, X)); return true; } @@ -60,7 +61,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, // SVal of the argument directly. If we save the extent in bits, we // cannot represent values like symbol*8. DefinedOrUnknownSVal Size = - cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()))); + cast<DefinedOrUnknownSVal>(state->getSVal(*(CE->arg_begin()), LCtx)); SValBuilder& svalBuilder = C.getSValBuilder(); DefinedOrUnknownSVal Extent = R->getExtent(svalBuilder); @@ -68,7 +69,7 @@ bool BuiltinFunctionChecker::evalCall(const CallExpr *CE, svalBuilder.evalEQ(state, Extent, Size); state = state->assume(extentMatchesSizeArg, true); - C.addTransition(state->BindExpr(CE, loc::MemRegionVal(R))); + C.addTransition(state->BindExpr(CE, LCtx, loc::MemRegionVal(R))); return true; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp index 49d8bf5388b..bc8d184af7f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CStringChecker.cpp @@ -329,12 +329,13 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C, SValBuilder &svalBuilder = C.getSValBuilder(); ASTContext &Ctx = svalBuilder.getContext(); + const LocationContext *LCtx = C.getLocationContext(); QualType sizeTy = Size->getType(); QualType PtrTy = Ctx.getPointerType(Ctx.CharTy); // Check that the first buffer is non-null. - SVal BufVal = state->getSVal(FirstBuf); + SVal BufVal = state->getSVal(FirstBuf, LCtx); state = checkNonNull(C, state, FirstBuf, BufVal); if (!state) return NULL; @@ -342,7 +343,7 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C, // Get the access length and make sure it is known. // FIXME: This assumes the caller has already checked that the access length // is positive. And that it's unsigned. - SVal LengthVal = state->getSVal(Size); + SVal LengthVal = state->getSVal(Size, LCtx); NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); if (!Length) return state; @@ -368,7 +369,7 @@ const ProgramState *CStringChecker::CheckBufferAccess(CheckerContext &C, // If there's a second buffer, check it as well. if (SecondBuf) { - BufVal = state->getSVal(SecondBuf); + BufVal = state->getSVal(SecondBuf, LCtx); state = checkNonNull(C, state, SecondBuf, BufVal); if (!state) return NULL; @@ -403,8 +404,9 @@ const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C, const ProgramState *stateTrue, *stateFalse; // Get the buffer values and make sure they're known locations. - SVal firstVal = state->getSVal(First); - SVal secondVal = state->getSVal(Second); + const LocationContext *LCtx = C.getLocationContext(); + SVal firstVal = state->getSVal(First, LCtx); + SVal secondVal = state->getSVal(Second, LCtx); Loc *firstLoc = dyn_cast<Loc>(&firstVal); if (!firstLoc) @@ -456,7 +458,7 @@ const ProgramState *CStringChecker::CheckOverlap(CheckerContext &C, } // Get the length, and make sure it too is known. - SVal LengthVal = state->getSVal(Size); + SVal LengthVal = state->getSVal(Size, LCtx); NonLoc *Length = dyn_cast<NonLoc>(&LengthVal); if (!Length) return state; @@ -846,7 +848,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, CurrentFunctionDescription = "memory copy function"; // See if the size argument is zero. - SVal sizeVal = state->getSVal(Size); + const LocationContext *LCtx = C.getLocationContext(); + SVal sizeVal = state->getSVal(Size, LCtx); QualType sizeTy = Size->getType(); const ProgramState *stateZeroSize, *stateNonZeroSize; @@ -854,12 +857,12 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, assumeZero(C, state, sizeVal, sizeTy); // Get the value of the Dest. - SVal destVal = state->getSVal(Dest); + SVal destVal = state->getSVal(Dest, LCtx); // If the size is zero, there won't be any actual memory access, so // just bind the return value to the destination buffer and return. if (stateZeroSize) { - stateZeroSize = stateZeroSize->BindExpr(CE, destVal); + stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, destVal); C.addTransition(stateZeroSize); } @@ -874,7 +877,7 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, return; // Get the value of the Src. - SVal srcVal = state->getSVal(Source); + SVal srcVal = state->getSVal(Source, LCtx); // Ensure the source is not null. If it is NULL there will be a // NULL pointer dereference. @@ -910,20 +913,20 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, Dest->getType()); // The byte after the last byte copied is the return value. - state = state->BindExpr(CE, lastElement); + state = state->BindExpr(CE, LCtx, lastElement); } else { // If we don't know how much we copied, we can at least // conjure a return value for later. unsigned Count = C.getCurrentBlockCount(); SVal result = C.getSValBuilder().getConjuredSymbolVal(NULL, CE, Count); - state = state->BindExpr(CE, result); + state = state->BindExpr(CE, LCtx, result); } } else { // All other copies return the destination buffer. // (Well, bcopy() has a void return type, but this won't hurt.) - state = state->BindExpr(CE, destVal); + state = state->BindExpr(CE, LCtx, destVal); } // Invalidate the destination. @@ -931,7 +934,8 @@ void CStringChecker::evalCopyCommon(CheckerContext &C, // can use LazyCompoundVals to copy the source values into the destination. // This would probably remove any existing bindings past the end of the // copied region, but that's still an improvement over blank invalidation. - state = InvalidateBuffer(C, state, Dest, state->getSVal(Dest)); + state = InvalidateBuffer(C, state, Dest, + state->getSVal(Dest, C.getLocationContext())); C.addTransition(state); } } @@ -982,7 +986,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { SValBuilder &svalBuilder = C.getSValBuilder(); // See if the size argument is zero. - SVal sizeVal = state->getSVal(Size); + const LocationContext *LCtx = C.getLocationContext(); + SVal sizeVal = state->getSVal(Size, LCtx); QualType sizeTy = Size->getType(); const ProgramState *stateZeroSize, *stateNonZeroSize; @@ -993,7 +998,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { // have to check either of the buffers. if (stateZeroSize) { state = stateZeroSize; - state = state->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); + state = state->BindExpr(CE, LCtx, + svalBuilder.makeZeroVal(CE->getType())); C.addTransition(state); } @@ -1003,8 +1009,10 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { // If we know the two buffers are the same, we know the result is 0. // First, get the two buffers' addresses. Another checker will have already // made sure they're not undefined. - DefinedOrUnknownSVal LV = cast<DefinedOrUnknownSVal>(state->getSVal(Left)); - DefinedOrUnknownSVal RV = cast<DefinedOrUnknownSVal>(state->getSVal(Right)); + DefinedOrUnknownSVal LV = + cast<DefinedOrUnknownSVal>(state->getSVal(Left, LCtx)); + DefinedOrUnknownSVal RV = + cast<DefinedOrUnknownSVal>(state->getSVal(Right, LCtx)); // See if they are the same. DefinedOrUnknownSVal SameBuf = svalBuilder.evalEQ(state, LV, RV); @@ -1017,7 +1025,8 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { state = StSameBuf; state = CheckBufferAccess(C, state, Size, Left); if (state) { - state = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); + state = StSameBuf->BindExpr(CE, LCtx, + svalBuilder.makeZeroVal(CE->getType())); C.addTransition(state); } } @@ -1031,7 +1040,7 @@ void CStringChecker::evalMemcmp(CheckerContext &C, const CallExpr *CE) const { // The return value is the comparison result, which we don't know. unsigned Count = C.getCurrentBlockCount(); SVal CmpV = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); - state = state->BindExpr(CE, CmpV); + state = state->BindExpr(CE, LCtx, CmpV); C.addTransition(state); } } @@ -1054,10 +1063,11 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, bool IsStrnlen) const { CurrentFunctionDescription = "string length function"; const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); if (IsStrnlen) { const Expr *maxlenExpr = CE->getArg(1); - SVal maxlenVal = state->getSVal(maxlenExpr); + SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); const ProgramState *stateZeroSize, *stateNonZeroSize; llvm::tie(stateZeroSize, stateNonZeroSize) = @@ -1067,7 +1077,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, // have to check the string itself. if (stateZeroSize) { SVal zero = C.getSValBuilder().makeZeroVal(CE->getType()); - stateZeroSize = stateZeroSize->BindExpr(CE, zero); + stateZeroSize = stateZeroSize->BindExpr(CE, LCtx, zero); C.addTransition(stateZeroSize); } @@ -1081,7 +1091,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, // Check that the string argument is non-null. const Expr *Arg = CE->getArg(0); - SVal ArgVal = state->getSVal(Arg); + SVal ArgVal = state->getSVal(Arg, LCtx); state = checkNonNull(C, state, Arg, ArgVal); @@ -1105,7 +1115,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, // It's a little unfortunate to be getting this again, // but it's not that expensive... const Expr *maxlenExpr = CE->getArg(1); - SVal maxlenVal = state->getSVal(maxlenExpr); + SVal maxlenVal = state->getSVal(maxlenExpr, LCtx); NonLoc *strLengthNL = dyn_cast<NonLoc>(&strLength); NonLoc *maxlenValNL = dyn_cast<NonLoc>(&maxlenVal); @@ -1170,7 +1180,7 @@ void CStringChecker::evalstrLengthCommon(CheckerContext &C, const CallExpr *CE, // Bind the return value. assert(!result.isUnknown() && "Should have conjured a value by now"); - state = state->BindExpr(CE, result); + state = state->BindExpr(CE, LCtx, result); C.addTransition(state); } @@ -1219,10 +1229,11 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, bool isAppending) const { CurrentFunctionDescription = "string copy function"; const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); // Check that the destination is non-null. const Expr *Dst = CE->getArg(0); - SVal DstVal = state->getSVal(Dst); + SVal DstVal = state->getSVal(Dst, LCtx); state = checkNonNull(C, state, Dst, DstVal); if (!state) @@ -1230,7 +1241,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, // Check that the source is non-null. const Expr *srcExpr = CE->getArg(1); - SVal srcVal = state->getSVal(srcExpr); + SVal srcVal = state->getSVal(srcExpr, LCtx); state = checkNonNull(C, state, srcExpr, srcVal); if (!state) return; @@ -1257,7 +1268,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, if (isBounded) { // Get the max number of characters to copy. const Expr *lenExpr = CE->getArg(2); - SVal lenVal = state->getSVal(lenExpr); + SVal lenVal = state->getSVal(lenExpr, LCtx); // Protect against misdeclared strncpy(). lenVal = svalBuilder.evalCast(lenVal, sizeTy, lenExpr->getType()); @@ -1512,7 +1523,7 @@ void CStringChecker::evalStrcpyCommon(CheckerContext &C, const CallExpr *CE, } // Set the return value. - state = state->BindExpr(CE, Result); + state = state->BindExpr(CE, LCtx, Result); C.addTransition(state); } @@ -1542,17 +1553,18 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, bool isBounded, bool ignoreCase) const { CurrentFunctionDescription = "string comparison function"; const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); // Check that the first string is non-null const Expr *s1 = CE->getArg(0); - SVal s1Val = state->getSVal(s1); + SVal s1Val = state->getSVal(s1, LCtx); state = checkNonNull(C, state, s1, s1Val); if (!state) return; // Check that the second string is non-null. const Expr *s2 = CE->getArg(1); - SVal s2Val = state->getSVal(s2); + SVal s2Val = state->getSVal(s2, LCtx); state = checkNonNull(C, state, s2, s2Val); if (!state) return; @@ -1582,7 +1594,8 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, // If the two arguments might be the same buffer, we know the result is 0, // and we only need to check one size. if (StSameBuf) { - StSameBuf = StSameBuf->BindExpr(CE, svalBuilder.makeZeroVal(CE->getType())); + StSameBuf = StSameBuf->BindExpr(CE, LCtx, + svalBuilder.makeZeroVal(CE->getType())); C.addTransition(StSameBuf); // If the two arguments are GUARANTEED to be the same, we're done! @@ -1608,7 +1621,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, if (isBounded) { // Get the max number of characters to compare. const Expr *lenExpr = CE->getArg(2); - SVal lenVal = state->getSVal(lenExpr); + SVal lenVal = state->getSVal(lenExpr, LCtx); // If the length is known, we can get the right substrings. if (const llvm::APSInt *len = svalBuilder.getKnownValue(state, lenVal)) { @@ -1645,7 +1658,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, // Build the SVal of the comparison and bind the return value. SVal resultVal = svalBuilder.makeIntVal(result, CE->getType()); - state = state->BindExpr(CE, resultVal); + state = state->BindExpr(CE, LCtx, resultVal); } } @@ -1653,7 +1666,7 @@ void CStringChecker::evalStrcmpCommon(CheckerContext &C, const CallExpr *CE, // Conjure a symbolic value. It's the best we can do. unsigned Count = C.getCurrentBlockCount(); SVal resultVal = svalBuilder.getConjuredSymbolVal(NULL, CE, Count); - state = state->BindExpr(CE, resultVal); + state = state->BindExpr(CE, LCtx, resultVal); } // Record this as a possible path. @@ -1728,7 +1741,7 @@ void CStringChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { if (!MR) continue; - SVal StrVal = state->getSVal(Init); + SVal StrVal = state->getSVal(Init, C.getLocationContext()); assert(StrVal.isValid() && "Initializer string is unknown or undefined"); DefinedOrUnknownSVal strLength = cast<DefinedOrUnknownSVal>(getCStringLength(C, state, Init, StrVal)); diff --git a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp index 914b806dd74..f5f0c1655b9 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CallAndMessageChecker.cpp @@ -193,7 +193,8 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, CheckerContext &C) const{ const Expr *Callee = CE->getCallee()->IgnoreParens(); - SVal L = C.getState()->getSVal(Callee); + const LocationContext *LCtx = C.getLocationContext(); + SVal L = C.getState()->getSVal(Callee, LCtx); if (L.isUndef()) { if (!BT_call_undef) @@ -210,7 +211,7 @@ void CallAndMessageChecker::checkPreStmt(const CallExpr *CE, EmitBadCall(BT_call_null.get(), C, CE); } - PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState()), + PreVisitProcessArgs(C, CallOrObjCMessage(CE, C.getState(), LCtx), "Function call argument is an uninitialized value", BT_call_arg); } @@ -219,10 +220,11 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, CheckerContext &C) const { const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); // FIXME: Handle 'super'? if (const Expr *receiver = msg.getInstanceReceiver()) { - SVal recVal = state->getSVal(receiver); + SVal recVal = state->getSVal(receiver, LCtx); if (recVal.isUndef()) { if (ExplodedNode *N = C.generateSink()) { if (!BT_msg_undef) @@ -255,7 +257,8 @@ void CallAndMessageChecker::checkPreObjCMessage(ObjCMessage msg, "Argument for property setter is an uninitialized value" : "Argument in message expression is an uninitialized value"; // Check for any arguments that are uninitialized/undefined. - PreVisitProcessArgs(C, CallOrObjCMessage(msg, state), bugDesc, BT_msg_arg); + PreVisitProcessArgs(C, CallOrObjCMessage(msg, state, LCtx), + bugDesc, BT_msg_arg); } void CallAndMessageChecker::emitNilReceiverBug(CheckerContext &C, @@ -298,11 +301,12 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, // return different values depending on the return type and the architecture. QualType RetTy = msg.getType(Ctx); CanQualType CanRetTy = Ctx.getCanonicalType(RetTy); + const LocationContext *LCtx = C.getLocationContext(); if (CanRetTy->isStructureOrClassType()) { // Structure returns are safe since the compiler zeroes them out. SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx)); - C.addTransition(state->BindExpr(msg.getOriginExpr(), V)); + C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V)); return; } @@ -339,7 +343,7 @@ void CallAndMessageChecker::HandleNilReceiver(CheckerContext &C, // of this case unless we have *a lot* more knowledge. // SVal V = C.getSValBuilder().makeZeroVal(msg.getType(Ctx)); - C.addTransition(state->BindExpr(msg.getOriginExpr(), V)); + C.addTransition(state->BindExpr(msg.getOriginExpr(), LCtx, V)); return; } diff --git a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp index 84a9e6b3c52..32b60d91540 100644 --- a/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/CastSizeChecker.cpp @@ -45,7 +45,7 @@ void CastSizeChecker::checkPreStmt(const CastExpr *CE,CheckerContext &C) const { return; const ProgramState *state = C.getState(); - const MemRegion *R = state->getSVal(E).getAsRegion(); + const MemRegion *R = state->getSVal(E, C.getLocationContext()).getAsRegion(); if (R == 0) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp index fa79f218661..22f7b775a54 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ChrootChecker.cpp @@ -105,7 +105,7 @@ void ChrootChecker::Chdir(CheckerContext &C, const CallExpr *CE) const { // After chdir("/"), enter the jail, set the enum value JAIL_ENTERED. const Expr *ArgExpr = CE->getArg(0); - SVal ArgVal = state->getSVal(ArgExpr); + SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext()); if (const MemRegion *R = ArgVal.getAsRegion()) { R = R->StripCasts(); diff --git a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp index d4fbfa14b9e..12fd6f4e76d 100644 --- a/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/DivZeroChecker.cpp @@ -42,7 +42,7 @@ void DivZeroChecker::checkPreStmt(const BinaryOperator *B, !B->getRHS()->getType()->isScalarType()) return; - SVal Denom = C.getState()->getSVal(B->getRHS()); + SVal Denom = C.getState()->getSVal(B->getRHS(), C.getLocationContext()); const DefinedSVal *DV = dyn_cast<DefinedSVal>(&Denom); // Divide-by-undefined handled in the generic checking for uses of diff --git a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp index 7bdd4f34a73..d570da001e8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/FixedAddressChecker.cpp @@ -45,8 +45,7 @@ void FixedAddressChecker::checkPreStmt(const BinaryOperator *B, return; const ProgramState *state = C.getState(); - - SVal RV = state->getSVal(B->getRHS()); + SVal RV = state->getSVal(B->getRHS(), C.getLocationContext()); if (!RV.isConstant() || RV.isZeroConstant()) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp index f09d670c1ff..9e67e21cc3c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/GenericTaintChecker.cpp @@ -154,7 +154,7 @@ SymbolRef GenericTaintChecker::getPointedToSymbol(CheckerContext &C, const Expr* Arg, bool IssueWarning) const { const ProgramState *State = C.getState(); - SVal AddrVal = State->getSVal(Arg->IgnoreParens()); + SVal AddrVal = State->getSVal(Arg->IgnoreParens(), C.getLocationContext()); if (AddrVal.isUnknownOrUndef()) return 0; @@ -185,7 +185,8 @@ const ProgramState *GenericTaintChecker::preFscanf(const CallExpr *CE, const ProgramState *State = C.getState(); // Check is the file descriptor is tainted. - if (State->isTainted(CE->getArg(0)) || isStdin(CE->getArg(0), C)) + if (State->isTainted(CE->getArg(0), C.getLocationContext()) || + isStdin(CE->getArg(0), C)) return State->set<TaintOnPreVisit>(PrevisitTaintArgs); return 0; } @@ -196,7 +197,8 @@ const ProgramState * GenericTaintChecker::preAnyArgs(const CallExpr *CE, for (unsigned int i = 0; i < CE->getNumArgs(); ++i) { const ProgramState *State = C.getState(); const Expr *Arg = CE->getArg(i); - if (State->isTainted(Arg) || State->isTainted(getPointedToSymbol(C, Arg))) + if (State->isTainted(Arg, C.getLocationContext()) || + State->isTainted(getPointedToSymbol(C, Arg))) return State = State->set<TaintOnPreVisit>(PrevisitTaintRet); } return 0; @@ -209,7 +211,7 @@ const ProgramState *GenericTaintChecker::postDefault(const CallExpr *CE, // Check if we know that the result needs to be tainted based on the // pre-visit analysis. if (State->get<TaintOnPreVisit>() == PrevisitTaintRet) { - State = State->addTaint(CE); + State = State->addTaint(CE, C.getLocationContext()); return State->set<TaintOnPreVisit>(PrevisitNone); } @@ -220,7 +222,7 @@ const ProgramState *GenericTaintChecker::postScanf(const CallExpr *CE, CheckerContext &C) const { const ProgramState *State = C.getState(); assert(CE->getNumArgs() >= 2); - SVal x = State->getSVal(CE->getArg(1)); + SVal x = State->getSVal(CE->getArg(1), C.getLocationContext()); // All arguments except for the very first one should get taint. for (unsigned int i = 1; i < CE->getNumArgs(); ++i) { // The arguments are pointer arguments. The data they are pointing at is @@ -262,13 +264,13 @@ const ProgramState *GenericTaintChecker::postFscanf(const CallExpr *CE, const ProgramState *GenericTaintChecker::postRetTaint(const CallExpr *CE, CheckerContext &C) const { - return C.getState()->addTaint(CE); + return C.getState()->addTaint(CE, C.getLocationContext()); } bool GenericTaintChecker::isStdin(const Expr *E, CheckerContext &C) const { const ProgramState *State = C.getState(); - SVal Val = State->getSVal(E); + SVal Val = State->getSVal(E, C.getLocationContext()); // stdin is a pointer, so it would be a region. const MemRegion *MemReg = Val.getAsRegion(); diff --git a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp index a3ebf0b750a..ef830e8684e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IdempotentOperationChecker.cpp @@ -142,9 +142,9 @@ void IdempotentOperationChecker::checkPreStmt(const BinaryOperator *B, } const ProgramState *state = C.getState(); - - SVal LHSVal = state->getSVal(LHS); - SVal RHSVal = state->getSVal(RHS); + const LocationContext *LCtx = C.getLocationContext(); + SVal LHSVal = state->getSVal(LHS, LCtx); + SVal RHSVal = state->getSVal(RHS, LCtx); // If either value is unknown, we can't be 100% sure of all paths. if (LHSVal.isUnknownOrUndef() || RHSVal.isUnknownOrUndef()) { diff --git a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp index ab3242bdf5b..341d42510b5 100644 --- a/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp @@ -254,7 +254,7 @@ const ProgramState *IteratorsChecker::handleAssign(const ProgramState *state, lexp = M->GetTemporaryExpr(); if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp)) lexp = ICE->getSubExpr(); - SVal sv = state->getSVal(lexp); + SVal sv = state->getSVal(lexp, LC); const MemRegion *MR = sv.getAsRegion(); if (!MR) return state; @@ -574,7 +574,7 @@ void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE, const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase()); if (!DRE || getTemplateKind(DRE->getType()) != VectorKind) return; - SVal tsv = C.getState()->getSVal(DRE); + SVal tsv = C.getState()->getSVal(DRE, C.getLocationContext()); // Get the MemRegion associated with the container instance. const MemRegion *MR = tsv.getAsRegion(); if (!MR) diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp index 78707e7e8ae..0a675e562ce 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSKeychainAPIChecker.cpp @@ -220,7 +220,7 @@ static bool isBadDeallocationArgument(const MemRegion *Arg) { static SymbolRef getAsPointeeSymbol(const Expr *Expr, CheckerContext &C) { const ProgramState *State = C.getState(); - SVal ArgV = State->getSVal(Expr); + SVal ArgV = State->getSVal(Expr, C.getLocationContext()); if (const loc::MemRegionVal *X = dyn_cast<loc::MemRegionVal>(&ArgV)) { StoreManager& SM = C.getStoreManager(); @@ -325,7 +325,7 @@ void MacOSKeychainAPIChecker::checkPreStmt(const CallExpr *CE, // Check the argument to the deallocator. const Expr *ArgExpr = CE->getArg(FunctionsToTrack[idx].Param); - SVal ArgSVal = State->getSVal(ArgExpr); + SVal ArgSVal = State->getSVal(ArgExpr, C.getLocationContext()); // Undef is reported by another checker. if (ArgSVal.isUndef()) @@ -462,7 +462,8 @@ void MacOSKeychainAPIChecker::checkPostStmt(const CallExpr *CE, // allocated value symbol, since our diagnostics depend on the value // returned by the call. Ex: Data should only be freed if noErr was // returned during allocation.) - SymbolRef RetStatusSymbol = State->getSVal(CE).getAsSymbol(); + SymbolRef RetStatusSymbol = + State->getSVal(CE, C.getLocationContext()).getAsSymbol(); C.getSymbolManager().addSymbolDependency(V, RetStatusSymbol); // Track the allocated value in the checker state. @@ -481,7 +482,8 @@ void MacOSKeychainAPIChecker::checkPreStmt(const ReturnStmt *S, // Check if the value is escaping through the return. const ProgramState *state = C.getState(); - const MemRegion *V = state->getSVal(retExpr).getAsRegion(); + const MemRegion *V = + state->getSVal(retExpr, C.getLocationContext()).getAsRegion(); if (!V) return; state = state->remove<AllocatedData>(getSymbolForRegion(C, V)); diff --git a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp index f8c01047c38..9141656f0cb 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MacOSXAPIChecker.cpp @@ -57,7 +57,8 @@ void MacOSXAPIChecker::CheckDispatchOnce(CheckerContext &C, const CallExpr *CE, // Check if the first argument is stack allocated. If so, issue a warning // because that's likely to be bad news. const ProgramState *state = C.getState(); - const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion(); + const MemRegion *R = + state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion(); if (!R || !isa<StackSpaceRegion>(R->getMemorySpace())) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp index dcc7ab95dc0..ea42da40673 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MallocChecker.cpp @@ -100,7 +100,9 @@ private: static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE, const Expr *SizeEx, SVal Init, const ProgramState *state) { - return MallocMemAux(C, CE, state->getSVal(SizeEx), Init, state); + return MallocMemAux(C, CE, + state->getSVal(SizeEx, C.getLocationContext()), + Init, state); } static const ProgramState *MallocMemAux(CheckerContext &C, const CallExpr *CE, SVal SizeEx, SVal Init, @@ -230,7 +232,7 @@ const ProgramState *MallocChecker::MallocMemAux(CheckerContext &C, // Set the return value. SVal retVal = svalBuilder.getConjuredSymbolVal(NULL, CE, CE->getType(), Count); - state = state->BindExpr(CE, retVal); + state = state->BindExpr(CE, C.getLocationContext(), retVal); // Fill the region with the initialization value. state = state->bindDefault(retVal, Init); @@ -280,7 +282,7 @@ const ProgramState *MallocChecker::FreeMemAux(CheckerContext &C, unsigned Num, bool Hold) const { const Expr *ArgExpr = CE->getArg(Num); - SVal ArgVal = state->getSVal(ArgExpr); + SVal ArgVal = state->getSVal(ArgExpr, C.getLocationContext()); DefinedOrUnknownSVal location = cast<DefinedOrUnknownSVal>(ArgVal); @@ -501,8 +503,9 @@ void MallocChecker::ReportBadFree(CheckerContext &C, SVal ArgVal, void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); const Expr *arg0Expr = CE->getArg(0); + const LocationContext *LCtx = C.getLocationContext(); DefinedOrUnknownSVal arg0Val - = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr)); + = cast<DefinedOrUnknownSVal>(state->getSVal(arg0Expr, LCtx)); SValBuilder &svalBuilder = C.getSValBuilder(); @@ -516,7 +519,7 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { // Get the value of the size argument. DefinedOrUnknownSVal Arg1Val = - cast<DefinedOrUnknownSVal>(state->getSVal(Arg1)); + cast<DefinedOrUnknownSVal>(state->getSVal(Arg1, LCtx)); // Compare the size argument to 0. DefinedOrUnknownSVal SizeZero = @@ -548,7 +551,8 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { FreeMemAux(C, CE, stateSizeZero, 0, false)) { // Bind the return value to NULL because it is now free. - C.addTransition(stateFree->BindExpr(CE, svalBuilder.makeNull(), true)); + C.addTransition(stateFree->BindExpr(CE, LCtx, + svalBuilder.makeNull(), true)); } if (const ProgramState *stateSizeNotZero = stateNotEqual->assume(SizeZero,false)) @@ -565,9 +569,9 @@ void MallocChecker::ReallocMem(CheckerContext &C, const CallExpr *CE) const { void MallocChecker::CallocMem(CheckerContext &C, const CallExpr *CE) { const ProgramState *state = C.getState(); SValBuilder &svalBuilder = C.getSValBuilder(); - - SVal count = state->getSVal(CE->getArg(0)); - SVal elementSize = state->getSVal(CE->getArg(1)); + const LocationContext *LCtx = C.getLocationContext(); + SVal count = state->getSVal(CE->getArg(0), LCtx); + SVal elementSize = state->getSVal(CE->getArg(1), LCtx); SVal TotalSize = svalBuilder.evalBinOp(state, BO_Mul, count, elementSize, svalBuilder.getContext().getSizeType()); SVal zeroVal = svalBuilder.makeZeroVal(svalBuilder.getContext().CharTy); @@ -638,7 +642,7 @@ void MallocChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { const ProgramState *state = C.getState(); - SymbolRef Sym = state->getSVal(retExpr).getAsSymbol(); + SymbolRef Sym = state->getSVal(retExpr, C.getLocationContext()).getAsSymbol(); if (!Sym) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp index 81f1924b2c7..b831a822476 100644 --- a/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/NoReturnFunctionChecker.cpp @@ -42,7 +42,7 @@ void NoReturnFunctionChecker::checkPostStmt(const CallExpr *CE, bool BuildSinks = getFunctionExtInfo(Callee->getType()).getNoReturn(); if (!BuildSinks) { - SVal L = state->getSVal(Callee); + SVal L = state->getSVal(Callee, C.getLocationContext()); const FunctionDecl *FD = L.getAsFunctionDecl(); if (!FD) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp index 27d8fb5abbd..4089b346b80 100644 --- a/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/OSAtomicChecker.cpp @@ -36,9 +36,10 @@ private: } static StringRef getCalleeName(const ProgramState *State, - const CallExpr *CE) { + const CallExpr *CE, + const LocationContext *LCtx) { const Expr *Callee = CE->getCallee(); - SVal L = State->getSVal(Callee); + SVal L = State->getSVal(Callee, LCtx); const FunctionDecl *funDecl = L.getAsFunctionDecl(); if (!funDecl) return StringRef(); @@ -52,7 +53,8 @@ bool OSAtomicChecker::inlineCall(const CallExpr *CE, ExprEngine &Eng, ExplodedNode *Pred, ExplodedNodeSet &Dst) const { - StringRef FName = getCalleeName(Pred->getState(), CE); + StringRef FName = getCalleeName(Pred->getState(), + CE, Pred->getLocationContext()); if (FName.empty()) return false; @@ -103,8 +105,9 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE, // Load 'theValue'. const ProgramState *state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); ExplodedNodeSet Tmp; - SVal location = state->getSVal(theValueExpr); + SVal location = state->getSVal(theValueExpr, LCtx); // Here we should use the value type of the region as the load type, because // we are simulating the semantics of the function, not the semantics of // passing argument. So the type of theValue expr is not we are loading. @@ -135,9 +138,9 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE, // Use direct bindings from the environment since we are forcing a load // from a location that the Environment would typically not be used // to bind a value. - SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, true); + SVal theValueVal_untested = stateLoad->getSVal(theValueExpr, LCtx, true); - SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr); + SVal oldValueVal_untested = stateLoad->getSVal(oldValueExpr, LCtx); // FIXME: Issue an error. if (theValueVal_untested.isUndef() || oldValueVal_untested.isUndef()) { @@ -161,7 +164,7 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE, if (stateEqual) { // Perform the store. ExplodedNodeSet TmpStore; - SVal val = stateEqual->getSVal(newValueExpr); + SVal val = stateEqual->getSVal(newValueExpr, LCtx); // Handle implicit value casts. if (const TypedValueRegion *R = @@ -189,7 +192,8 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE, QualType T = CE->getType(); if (!T->isVoidType()) Res = Eng.getSValBuilder().makeTruthVal(true, T); - B.generateNode(CE, predNew, stateNew->BindExpr(CE, Res), false, this); + B.generateNode(CE, predNew, stateNew->BindExpr(CE, LCtx, Res), + false, this); } } @@ -201,7 +205,8 @@ bool OSAtomicChecker::evalOSAtomicCompareAndSwap(const CallExpr *CE, if (!T->isVoidType()) Res = Eng.getSValBuilder().makeTruthVal(false, CE->getType()); StmtNodeBuilder B(N, Dst, Eng.getBuilderContext()); - B.generateNode(CE, N, stateNotEqual->BindExpr(CE, Res), false, this); + B.generateNode(CE, N, stateNotEqual->BindExpr(CE, LCtx, Res), + false, this); } } diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp index 5db073c9cb1..06b138e4021 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCAtSyncChecker.cpp @@ -39,7 +39,7 @@ void ObjCAtSyncChecker::checkPreStmt(const ObjCAtSynchronizedStmt *S, const Expr *Ex = S->getSynchExpr(); const ProgramState *state = C.getState(); - SVal V = state->getSVal(Ex); + SVal V = state->getSVal(Ex, C.getLocationContext()); // Uninitialized value used for the mutex? if (isa<UndefinedVal>(V)) { diff --git a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp index 8b29a20dc62..a466b41d125 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ObjCSelfInitChecker.cpp @@ -156,7 +156,7 @@ static bool hasSelfFlag(SVal val, SelfFlagEnum flag, CheckerContext &C) { /// points to and is an object that did not come from the result of calling /// an initializer. static bool isInvalidSelf(const Expr *E, CheckerContext &C) { - SVal exprVal = C.getState()->getSVal(E); + SVal exprVal = C.getState()->getSVal(E, C.getLocationContext()); if (!hasSelfFlag(exprVal, SelfFlag_Self, C)) return false; // value did not come from 'self'. if (hasSelfFlag(exprVal, SelfFlag_InitRes, C)) @@ -206,7 +206,7 @@ void ObjCSelfInitChecker::checkPostObjCMessage(ObjCMessage msg, // value out when we return from this method. state = state->set<CalledInit>(true); - SVal V = state->getSVal(msg.getOriginExpr()); + SVal V = state->getSVal(msg.getOriginExpr(), C.getLocationContext()); addSelfFlag(state, V, SelfFlag_InitRes, C); return; } @@ -262,7 +262,7 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE, const ProgramState *state = C.getState(); for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { - SVal argV = state->getSVal(*I); + SVal argV = state->getSVal(*I, C.getLocationContext()); if (isSelfVar(argV, C)) { unsigned selfFlags = getSelfFlags(state->getSVal(cast<Loc>(argV)), C); C.addTransition(state->set<PreCallSelfFlags>(selfFlags)); @@ -278,9 +278,10 @@ void ObjCSelfInitChecker::checkPreStmt(const CallExpr *CE, void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end(); I != E; ++I) { - SVal argV = state->getSVal(*I); + SVal argV = state->getSVal(*I, LCtx); if (isSelfVar(argV, C)) { SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); state = state->remove<PreCallSelfFlags>(); @@ -289,7 +290,7 @@ void ObjCSelfInitChecker::checkPostStmt(const CallExpr *CE, } else if (hasSelfFlag(argV, SelfFlag_Self, C)) { SelfFlagEnum prevFlags = (SelfFlagEnum)state->get<PreCallSelfFlags>(); state = state->remove<PreCallSelfFlags>(); - addSelfFlag(state, state->getSVal(CE), prevFlags, C); + addSelfFlag(state, state->getSVal(CE, LCtx), prevFlags, C); return; } } diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp index 845ae4f0fcc..6adc4dc8601 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerArithChecker.cpp @@ -37,8 +37,9 @@ void PointerArithChecker::checkPreStmt(const BinaryOperator *B, return; const ProgramState *state = C.getState(); - SVal LV = state->getSVal(B->getLHS()); - SVal RV = state->getSVal(B->getRHS()); + const LocationContext *LCtx = C.getLocationContext(); + SVal LV = state->getSVal(B->getLHS(), LCtx); + SVal RV = state->getSVal(B->getRHS(), LCtx); const MemRegion *LR = LV.getAsRegion(); diff --git a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp index 5e5e3e3bfd1..51f57a20f3e 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PointerSubChecker.cpp @@ -40,8 +40,9 @@ void PointerSubChecker::checkPreStmt(const BinaryOperator *B, return; const ProgramState *state = C.getState(); - SVal LV = state->getSVal(B->getLHS()); - SVal RV = state->getSVal(B->getRHS()); + const LocationContext *LCtx = C.getLocationContext(); + SVal LV = state->getSVal(B->getLHS(), LCtx); + SVal RV = state->getSVal(B->getRHS(), LCtx); const MemRegion *LR = LV.getAsRegion(); const MemRegion *RR = RV.getAsRegion(); diff --git a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp index 45988f0a097..a3bbd258591 100644 --- a/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/PthreadLockChecker.cpp @@ -57,6 +57,7 @@ template <> struct ProgramStateTrait<LockSet> : void PthreadLockChecker::checkPostStmt(const CallExpr *CE, CheckerContext &C) const { const ProgramState *state = C.getState(); + const LocationContext *LCtx = C.getLocationContext(); StringRef FName = C.getCalleeName(CE); if (FName.empty()) return; @@ -67,24 +68,28 @@ void PthreadLockChecker::checkPostStmt(const CallExpr *CE, if (FName == "pthread_mutex_lock" || FName == "pthread_rwlock_rdlock" || FName == "pthread_rwlock_wrlock") - AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, PthreadSemantics); + AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), + false, PthreadSemantics); else if (FName == "lck_mtx_lock" || FName == "lck_rw_lock_exclusive" || FName == "lck_rw_lock_shared") - AcquireLock(C, CE, state->getSVal(CE->getArg(0)), false, XNUSemantics); + AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), + false, XNUSemantics); else if (FName == "pthread_mutex_trylock" || FName == "pthread_rwlock_tryrdlock" || FName == "pthread_rwlock_tryrwlock") - AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, PthreadSemantics); + AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), + true, PthreadSemantics); else if (FName == "lck_mtx_try_lock" || FName == "lck_rw_try_lock_exclusive" || FName == "lck_rw_try_lock_shared") - AcquireLock(C, CE, state->getSVal(CE->getArg(0)), true, XNUSemantics); + AcquireLock(C, CE, state->getSVal(CE->getArg(0), LCtx), + true, XNUSemantics); else if (FName == "pthread_mutex_unlock" || FName == "pthread_rwlock_unlock" || FName == "lck_mtx_unlock" || FName == "lck_rw_done") - ReleaseLock(C, CE, state->getSVal(CE->getArg(0))); + ReleaseLock(C, CE, state->getSVal(CE->getArg(0), LCtx)); } void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, @@ -97,7 +102,7 @@ void PthreadLockChecker::AcquireLock(CheckerContext &C, const CallExpr *CE, const ProgramState *state = C.getState(); - SVal X = state->getSVal(CE); + SVal X = state->getSVal(CE, C.getLocationContext()); if (X.isUnknownOrUndef()) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp index 24df0083f50..8ba1edbb414 100644 --- a/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/RetainCountChecker.cpp @@ -1312,7 +1312,7 @@ RetainSummaryManager::getInstanceMethodSummary(const ObjCMessage &msg, SVal receiverV; if (Receiver) { - receiverV = state->getSValAsScalarOrLoc(Receiver); + receiverV = state->getSValAsScalarOrLoc(Receiver, LC); // FIXME: Eventually replace the use of state->get<RefBindings> with // a generic API for reasoning about the Objective-C types of symbolic @@ -1841,6 +1841,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, // Check if the type state has changed. const ProgramState *PrevSt = PrevN->getState(); const ProgramState *CurrSt = N->getState(); + const LocationContext *LCtx = N->getLocationContext(); const RefVal* CurrT = CurrSt->get<RefBindings>(Sym); if (!CurrT) return NULL; @@ -1860,7 +1861,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, if (const CallExpr *CE = dyn_cast<CallExpr>(S)) { // Get the name of the callee (if it is available). - SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee()); + SVal X = CurrSt->getSValAsScalarOrLoc(CE->getCallee(), LCtx); if (const FunctionDecl *FD = X.getAsFunctionDecl()) os << "Call to function '" << *FD << '\''; else @@ -1920,7 +1921,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, // Retrieve the value of the argument. Is it the symbol // we are interested in? - if (CurrSt->getSValAsScalarOrLoc(*AI).getAsLocSymbol() != Sym) + if (CurrSt->getSValAsScalarOrLoc(*AI, LCtx).getAsLocSymbol() != Sym) continue; // We have an argument. Get the effect! @@ -1929,7 +1930,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, } else if (const ObjCMessageExpr *ME = dyn_cast<ObjCMessageExpr>(S)) { if (const Expr *receiver = ME->getInstanceReceiver()) - if (CurrSt->getSValAsScalarOrLoc(receiver).getAsLocSymbol() == Sym) { + if (CurrSt->getSValAsScalarOrLoc(receiver, LCtx) + .getAsLocSymbol() == Sym) { // The symbol we are tracking is the receiver. AEffects.push_back(Summ->getReceiverEffect()); } @@ -1957,7 +1959,8 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, if (contains(AEffects, MakeCollectable)) { // Get the name of the function. const Stmt *S = cast<StmtPoint>(N->getLocation()).getStmt(); - SVal X = CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee()); + SVal X = + CurrSt->getSValAsScalarOrLoc(cast<CallExpr>(S)->getCallee(), LCtx); const FunctionDecl *FD = X.getAsFunctionDecl(); if (GCEnabled) { @@ -2069,7 +2072,7 @@ PathDiagnosticPiece *CFRefReportVisitor::VisitNode(const ExplodedNode *N, for (Stmt::const_child_iterator I = S->child_begin(), E = S->child_end(); I!=E; ++I) if (const Expr *Exp = dyn_cast_or_null<Expr>(*I)) - if (CurrSt->getSValAsScalarOrLoc(Exp).getAsLocSymbol() == Sym) { + if (CurrSt->getSValAsScalarOrLoc(Exp, LCtx).getAsLocSymbol() == Sym) { P->addRange(Exp->getSourceRange()); break; } @@ -2505,7 +2508,8 @@ void RetainCountChecker::checkPostStmt(const BlockExpr *BE, const ProgramState *state = C.getState(); const BlockDataRegion *R = - cast<BlockDataRegion>(state->getSVal(BE).getAsRegion()); + cast<BlockDataRegion>(state->getSVal(BE, + C.getLocationContext()).getAsRegion()); BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), E = R->referenced_vars_end(); @@ -2555,7 +2559,7 @@ void RetainCountChecker::checkPostStmt(const CastExpr *CE, } const ProgramState *state = C.getState(); - SymbolRef Sym = state->getSVal(CE).getAsLocSymbol(); + SymbolRef Sym = state->getSVal(CE, C.getLocationContext()).getAsLocSymbol(); if (!Sym) return; const RefVal* T = state->get<RefBindings>(Sym); @@ -2579,7 +2583,7 @@ void RetainCountChecker::checkPostStmt(const CallExpr *CE, // Get the callee. const ProgramState *state = C.getState(); const Expr *Callee = CE->getCallee(); - SVal L = state->getSVal(Callee); + SVal L = state->getSVal(Callee, C.getLocationContext()); RetainSummaryManager &Summaries = getSummaryManager(C); const RetainSummary *Summ = 0; @@ -2599,7 +2603,7 @@ void RetainCountChecker::checkPostStmt(const CallExpr *CE, if (!Summ) Summ = Summaries.getDefaultSummary(); - checkSummary(*Summ, CallOrObjCMessage(CE, state), C); + checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C); } void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE, @@ -2616,7 +2620,7 @@ void RetainCountChecker::checkPostStmt(const CXXConstructExpr *CE, return; const ProgramState *state = C.getState(); - checkSummary(*Summ, CallOrObjCMessage(CE, state), C); + checkSummary(*Summ, CallOrObjCMessage(CE, state, C.getLocationContext()), C); } void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, @@ -2637,7 +2641,7 @@ void RetainCountChecker::checkPostObjCMessage(const ObjCMessage &Msg, if (!Summ) return; - checkSummary(*Summ, CallOrObjCMessage(Msg, state), C); + checkSummary(*Summ, CallOrObjCMessage(Msg, state, C.getLocationContext()), C); } /// GetReturnType - Used to get the return type of a message expression or @@ -2737,7 +2741,8 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, case RetEffect::OwnedAllocatedSymbol: case RetEffect::OwnedSymbol: { - SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr()).getAsSymbol(); + SymbolRef Sym = state->getSVal(CallOrMsg.getOriginExpr(), + C.getLocationContext()).getAsSymbol(); if (!Sym) break; @@ -2764,7 +2769,7 @@ void RetainCountChecker::checkSummary(const RetainSummary &Summ, case RetEffect::ARCNotOwnedSymbol: case RetEffect::NotOwnedSymbol: { const Expr *Ex = CallOrMsg.getOriginExpr(); - SymbolRef Sym = state->getSVal(Ex).getAsSymbol(); + SymbolRef Sym = state->getSVal(Ex, C.getLocationContext()).getAsSymbol(); if (!Sym) break; @@ -3030,14 +3035,15 @@ bool RetainCountChecker::evalCall(const CallExpr *CE, CheckerContext &C) const { return false; // Bind the return value. - SVal RetVal = state->getSVal(CE->getArg(0)); + const LocationContext *LCtx = C.getLocationContext(); + SVal RetVal = state->getSVal(CE->getArg(0), LCtx); if (RetVal.isUnknown()) { // If the receiver is unknown, conjure a return value. SValBuilder &SVB = C.getSValBuilder(); unsigned Count = C.getCurrentBlockCount(); SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count); } - state = state->BindExpr(CE, RetVal, false); + state = state->BindExpr(CE, LCtx, RetVal, false); // FIXME: This should not be necessary, but otherwise the argument seems to be // considered alive during the next statement. @@ -3072,7 +3078,8 @@ void RetainCountChecker::checkPreStmt(const ReturnStmt *S, return; const ProgramState *state = C.getState(); - SymbolRef Sym = state->getSValAsScalarOrLoc(RetE).getAsLocSymbol(); + SymbolRef Sym = + state->getSValAsScalarOrLoc(RetE, C.getLocationContext()).getAsLocSymbol(); if (!Sym) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp index e761bff8558..f176eecf34f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnPointerRangeChecker.cpp @@ -39,7 +39,7 @@ void ReturnPointerRangeChecker::checkPreStmt(const ReturnStmt *RS, if (!RetE) return; - SVal V = state->getSVal(RetE); + SVal V = state->getSVal(RetE, C.getLocationContext()); const MemRegion *R = V.getAsRegion(); const ElementRegion *ER = dyn_cast_or_null<ElementRegion>(R); diff --git a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp index e8c8d902a5e..e1316b56e78 100644 --- a/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/ReturnUndefChecker.cpp @@ -38,7 +38,7 @@ void ReturnUndefChecker::checkPreStmt(const ReturnStmt *RS, if (!RetE) return; - if (!C.getState()->getSVal(RetE).isUndef()) + if (!C.getState()->getSVal(RetE, C.getLocationContext()).isUndef()) return; ExplodedNode *N = C.generateSink(); diff --git a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp index 0d3059e01a7..8eda407f8ee 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StackAddrEscapeChecker.cpp @@ -119,7 +119,7 @@ void StackAddrEscapeChecker::checkPreStmt(const ReturnStmt *RS, if (!RetE) return; - SVal V = C.getState()->getSVal(RetE); + SVal V = C.getState()->getSVal(RetE, C.getLocationContext()); const MemRegion *R = V.getAsRegion(); if (!R || !R->hasStackStorage()) diff --git a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp index 2f96bbfeac6..c746c775ab6 100644 --- a/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/StreamChecker.cpp @@ -223,7 +223,7 @@ void StreamChecker::OpenFileAux(CheckerContext &C, const CallExpr *CE) const { SValBuilder &svalBuilder = C.getSValBuilder(); DefinedSVal RetVal = cast<DefinedSVal>(svalBuilder.getConjuredSymbolVal(0, CE, Count)); - state = state->BindExpr(CE, RetVal); + state = state->BindExpr(CE, C.getLocationContext(), RetVal); ConstraintManager &CM = C.getConstraintManager(); // Bifurcate the state into two: one with a valid FILE* pointer, the other @@ -251,22 +251,25 @@ void StreamChecker::Fclose(CheckerContext &C, const CallExpr *CE) const { void StreamChecker::Fread(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), + state, C)) return; } void StreamChecker::Fwrite(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(3)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(3), C.getLocationContext()), + state, C)) return; } void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!(state = CheckNullStream(state->getSVal(CE->getArg(0)), state, C))) + if (!(state = CheckNullStream(state->getSVal(CE->getArg(0), + C.getLocationContext()), state, C))) return; // Check the legality of the 'whence' argument of 'fseek'. - SVal Whence = state->getSVal(CE->getArg(2)); + SVal Whence = state->getSVal(CE->getArg(2), C.getLocationContext()); const nonloc::ConcreteInt *CI = dyn_cast<nonloc::ConcreteInt>(&Whence); if (!CI) @@ -289,49 +292,57 @@ void StreamChecker::Fseek(CheckerContext &C, const CallExpr *CE) const { void StreamChecker::Ftell(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Rewind(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Fgetpos(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Fsetpos(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Clearerr(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Feof(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Ferror(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } void StreamChecker::Fileno(CheckerContext &C, const CallExpr *CE) const { const ProgramState *state = C.getState(); - if (!CheckNullStream(state->getSVal(CE->getArg(0)), state, C)) + if (!CheckNullStream(state->getSVal(CE->getArg(0), C.getLocationContext()), + state, C)) return; } @@ -361,7 +372,8 @@ const ProgramState *StreamChecker::CheckNullStream(SVal SV, const ProgramState * const ProgramState *StreamChecker::CheckDoubleClose(const CallExpr *CE, const ProgramState *state, CheckerContext &C) const { - SymbolRef Sym = state->getSVal(CE->getArg(0)).getAsSymbol(); + SymbolRef Sym = + state->getSVal(CE->getArg(0), C.getLocationContext()).getAsSymbol(); if (!Sym) return state; @@ -442,7 +454,7 @@ void StreamChecker::checkPreStmt(const ReturnStmt *S, CheckerContext &C) const { return; const ProgramState *state = C.getState(); - SymbolRef Sym = state->getSVal(RetE).getAsSymbol(); + SymbolRef Sym = state->getSVal(RetE, C.getLocationContext()).getAsSymbol(); if (!Sym) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp index 415346f29c4..297beaeedcd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/TaintTesterChecker.cpp @@ -47,7 +47,7 @@ void TaintTesterChecker::checkPostStmt(const Expr *E, if (!State) return; - if (State->isTainted(E)) { + if (State->isTainted(E, C.getLocationContext())) { if (ExplodedNode *N = C.addTransition()) { initBugType(); BugReport *report = new BugReport(*BT, "tainted",N); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp index afb79b5d166..fc0b9c2ec6f 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefBranchChecker.cpp @@ -28,8 +28,10 @@ class UndefBranchChecker : public Checker<check::BranchCondition> { struct FindUndefExpr { const ProgramState *St; + const LocationContext *LCtx; - FindUndefExpr(const ProgramState *S) : St(S) {} + FindUndefExpr(const ProgramState *S, const LocationContext *L) + : St(S), LCtx(L) {} const Expr *FindExpr(const Expr *Ex) { if (!MatchesCriteria(Ex)) @@ -45,7 +47,9 @@ class UndefBranchChecker : public Checker<check::BranchCondition> { return Ex; } - bool MatchesCriteria(const Expr *Ex) { return St->getSVal(Ex).isUndef(); } + bool MatchesCriteria(const Expr *Ex) { + return St->getSVal(Ex, LCtx).isUndef(); + } }; public: @@ -56,7 +60,7 @@ public: void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, CheckerContext &Ctx) const { - SVal X = Ctx.getState()->getSVal(Condition); + SVal X = Ctx.getState()->getSVal(Condition, Ctx.getLocationContext()); if (X.isUndef()) { // Generate a sink node, which implicitly marks both outgoing branches as // infeasible. @@ -90,7 +94,7 @@ void UndefBranchChecker::checkBranchCondition(const Stmt *Condition, if (PS->getStmt() == Ex) St = PrevN->getState(); - FindUndefExpr FindIt(St); + FindUndefExpr FindIt(St, Ctx.getLocationContext()); Ex = FindIt.FindExpr(Ex); // Emit the bug report. diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp index 82c9fd4a86b..60f1f5b8e34 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefCapturedBlockVarChecker.cpp @@ -57,7 +57,8 @@ UndefCapturedBlockVarChecker::checkPostStmt(const BlockExpr *BE, const ProgramState *state = C.getState(); const BlockDataRegion *R = - cast<BlockDataRegion>(state->getSVal(BE).getAsRegion()); + cast<BlockDataRegion>(state->getSVal(BE, + C.getLocationContext()).getAsRegion()); BlockDataRegion::referenced_vars_iterator I = R->referenced_vars_begin(), E = R->referenced_vars_end(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp index 7ae966865c8..b074ff918e8 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefResultChecker.cpp @@ -36,7 +36,8 @@ public: void UndefResultChecker::checkPostStmt(const BinaryOperator *B, CheckerContext &C) const { const ProgramState *state = C.getState(); - if (state->getSVal(B).isUndef()) { + const LocationContext *LCtx = C.getLocationContext(); + if (state->getSVal(B, LCtx).isUndef()) { // Generate an error node. ExplodedNode *N = C.generateSink(); if (!N) @@ -50,11 +51,11 @@ void UndefResultChecker::checkPostStmt(const BinaryOperator *B, const Expr *Ex = NULL; bool isLeft = true; - if (state->getSVal(B->getLHS()).isUndef()) { + if (state->getSVal(B->getLHS(), LCtx).isUndef()) { Ex = B->getLHS()->IgnoreParenCasts(); isLeft = true; } - else if (state->getSVal(B->getRHS()).isUndef()) { + else if (state->getSVal(B->getRHS(), LCtx).isUndef()) { Ex = B->getRHS()->IgnoreParenCasts(); isLeft = false; } diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp index bb6831b7830..ee58a043cc0 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedArraySubscriptChecker.cpp @@ -34,7 +34,7 @@ public: void UndefinedArraySubscriptChecker::checkPreStmt(const ArraySubscriptExpr *A, CheckerContext &C) const { - if (C.getState()->getSVal(A->getIdx()).isUndef()) { + if (C.getState()->getSVal(A->getIdx(), C.getLocationContext()).isUndef()) { if (ExplodedNode *N = C.generateSink()) { if (!BT) BT.reset(new BuiltinBug("Array subscript is undefined")); diff --git a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp index 5ca4a9fe46d..bb9eeb1fa8c 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UndefinedAssignmentChecker.cpp @@ -55,7 +55,7 @@ void UndefinedAssignmentChecker::checkBind(SVal location, SVal val, if (const BinaryOperator *B = dyn_cast<BinaryOperator>(StoreE)) { if (B->isCompoundAssignmentOp()) { const ProgramState *state = C.getState(); - if (state->getSVal(B->getLHS()).isUndef()) { + if (state->getSVal(B->getLHS(), C.getLocationContext()).isUndef()) { str = "The left expression of the compound assignment is an " "uninitialized value. The computed value will also be garbage"; ex = B->getLHS(); diff --git a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp index 28ff6971a24..420acd5aacd 100644 --- a/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/UnixAPIChecker.cpp @@ -91,7 +91,7 @@ void UnixAPIChecker::CheckOpen(CheckerContext &C, const CallExpr *CE) const { // Now check if oflags has O_CREAT set. const Expr *oflagsEx = CE->getArg(1); - const SVal V = state->getSVal(oflagsEx); + const SVal V = state->getSVal(oflagsEx, C.getLocationContext()); if (!isa<NonLoc>(V)) { // The case where 'V' can be a location can only be due to a bad header, // so in this case bail out. @@ -149,7 +149,8 @@ void UnixAPIChecker::CheckPthreadOnce(CheckerContext &C, // Check if the first argument is stack allocated. If so, issue a warning // because that's likely to be bad news. const ProgramState *state = C.getState(); - const MemRegion *R = state->getSVal(CE->getArg(0)).getAsRegion(); + const MemRegion *R = + state->getSVal(CE->getArg(0), C.getLocationContext()).getAsRegion(); if (!R || !isa<StackSpaceRegion>(R->getMemorySpace())) return; @@ -229,7 +230,7 @@ void UnixAPIChecker::CheckCallocZero(CheckerContext &C, unsigned int i; for (i = 0; i < nArgs; i++) { const Expr *arg = CE->getArg(i); - SVal argVal = state->getSVal(arg); + SVal argVal = state->getSVal(arg, C.getLocationContext()); if (argVal.isUnknownOrUndef()) { if (i == 0) continue; @@ -265,7 +266,7 @@ void UnixAPIChecker::CheckMallocZero(CheckerContext &C, const ProgramState *state = C.getState(); const ProgramState *trueState = NULL, *falseState = NULL; const Expr *arg = CE->getArg(0); - SVal argVal = state->getSVal(arg); + SVal argVal = state->getSVal(arg, C.getLocationContext()); if (argVal.isUnknownOrUndef()) return; @@ -289,7 +290,7 @@ void UnixAPIChecker::CheckReallocZero(CheckerContext &C, const ProgramState *state = C.getState(); const ProgramState *trueState = NULL, *falseState = NULL; const Expr *arg = CE->getArg(1); - SVal argVal = state->getSVal(arg); + SVal argVal = state->getSVal(arg, C.getLocationContext()); if (argVal.isUnknownOrUndef()) return; diff --git a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp index 969a896b63b..0308bf5c11b 100644 --- a/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/VLASizeChecker.cpp @@ -50,7 +50,7 @@ void VLASizeChecker::checkPreStmt(const DeclStmt *DS, CheckerContext &C) const { // FIXME: Handle multi-dimensional VLAs. const Expr *SE = VLA->getSizeExpr(); const ProgramState *state = C.getState(); - SVal sizeV = state->getSVal(SE); + SVal sizeV = state->getSVal(SE, C.getLocationContext()); if (sizeV.isUndef()) { // Generate an error node. diff --git a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp index 8ef9c21913c..38be3895d4e 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporter.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporter.cpp @@ -343,7 +343,7 @@ static const VarDecl* GetMostRecentVarDeclBinding(const ExplodedNode *N, if (!DR) continue; - SVal Y = N->getState()->getSVal(DR); + SVal Y = N->getState()->getSVal(DR, N->getLocationContext()); if (X != Y) continue; diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 88f38a3e4b4..b27595a41b6 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -339,7 +339,7 @@ bugreporter::getTrackNullOrUndefValueVisitor(const ExplodedNode *N, } } - SVal V = state->getSValAsScalarOrLoc(S); + SVal V = state->getSValAsScalarOrLoc(S, N->getLocationContext()); // Uncomment this to find cases where we aren't properly getting the // base value that was dereferenced. @@ -389,7 +389,7 @@ PathDiagnosticPiece *NilReceiverBRVisitor::VisitNode(const ExplodedNode *N, if (!Receiver) return 0; const ProgramState *state = N->getState(); - const SVal &V = state->getSVal(Receiver); + const SVal &V = state->getSVal(Receiver, N->getLocationContext()); const DefinedOrUnknownSVal *DV = dyn_cast<DefinedOrUnknownSVal>(&V); if (!DV) return 0; @@ -428,7 +428,7 @@ void FindLastStoreBRVisitor::registerStatementVarDecls(BugReport &BR, StateMgr.getRegionManager().getVarRegion(VD, N->getLocationContext()); // What did we load? - SVal V = state->getSVal(S); + SVal V = state->getSVal(S, N->getLocationContext()); if (isa<loc::ConcreteInt>(V) || isa<nonloc::ConcreteInt>(V)) { // Register a new visitor with the BugReport. diff --git a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp index 5552a991d15..3737ca54672 100644 --- a/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp +++ b/clang/lib/StaticAnalyzer/Core/CheckerContext.cpp @@ -19,7 +19,7 @@ using namespace ento; const FunctionDecl *CheckerContext::getCalleeDecl(const CallExpr *CE) const { const ProgramState *State = getState(); const Expr *Callee = CE->getCallee(); - SVal L = State->getSVal(Callee); + SVal L = State->getSVal(Callee, Pred->getLocationContext()); return L.getAsFunctionDecl(); } diff --git a/clang/lib/StaticAnalyzer/Core/Environment.cpp b/clang/lib/StaticAnalyzer/Core/Environment.cpp index e1b982c08cf..f43c2adc649 100644 --- a/clang/lib/StaticAnalyzer/Core/Environment.cpp +++ b/clang/lib/StaticAnalyzer/Core/Environment.cpp @@ -19,7 +19,7 @@ using namespace clang; using namespace ento; -SVal Environment::lookupExpr(const Stmt *E) const { +SVal Environment::lookupExpr(const EnvironmentEntry &E) const { const SVal* X = ExprBindings.lookup(E); if (X) { SVal V = *X; @@ -28,17 +28,21 @@ SVal Environment::lookupExpr(const Stmt *E) const { return UnknownVal(); } -SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, - bool useOnlyDirectBindings) const { +SVal Environment::getSVal(const EnvironmentEntry &Entry, + SValBuilder& svalBuilder, + bool useOnlyDirectBindings) const { if (useOnlyDirectBindings) { // This branch is rarely taken, but can be exercised by // checkers that explicitly bind values to arbitrary // expressions. It is crucial that we do not ignore any // expression here, and do a direct lookup. - return lookupExpr(E); + return lookupExpr(Entry); } + const Stmt *E = Entry.getStmt(); + const LocationContext *LCtx = Entry.getLocationContext(); + for (;;) { if (const Expr *Ex = dyn_cast<Expr>(E)) E = Ex->IgnoreParens(); @@ -61,7 +65,7 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, return svalBuilder.makeIntVal(C->getValue(), C->getType()); } case Stmt::CXXBoolLiteralExprClass: { - const SVal *X = ExprBindings.lookup(E); + const SVal *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); if (X) return *X; else @@ -69,7 +73,7 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, } case Stmt::IntegerLiteralClass: { // In C++, this expression may have been bound to a temporary object. - SVal const *X = ExprBindings.lookup(E); + SVal const *X = ExprBindings.lookup(EnvironmentEntry(E, LCtx)); if (X) return *X; else @@ -93,32 +97,33 @@ SVal Environment::getSVal(const Stmt *E, SValBuilder& svalBuilder, }; break; } - return lookupExpr(E); + return lookupExpr(EnvironmentEntry(E, LCtx)); } -Environment EnvironmentManager::bindExpr(Environment Env, const Stmt *S, - SVal V, bool Invalidate) { - assert(S); - +Environment EnvironmentManager::bindExpr(Environment Env, + const EnvironmentEntry &E, + SVal V, + bool Invalidate) { if (V.isUnknown()) { if (Invalidate) - return Environment(F.remove(Env.ExprBindings, S)); + return Environment(F.remove(Env.ExprBindings, E)); else return Env; } - - return Environment(F.add(Env.ExprBindings, S, V)); + return Environment(F.add(Env.ExprBindings, E, V)); } -static inline const Stmt *MakeLocation(const Stmt *S) { - return (const Stmt*) (((uintptr_t) S) | 0x1); +static inline EnvironmentEntry MakeLocation(const EnvironmentEntry &E) { + const Stmt *S = E.getStmt(); + S = (const Stmt*) (((uintptr_t) S) | 0x1); + return EnvironmentEntry(S, E.getLocationContext()); } Environment EnvironmentManager::bindExprAndLocation(Environment Env, - const Stmt *S, + const EnvironmentEntry &E, SVal location, SVal V) { - return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(S), location), - S, V)); + return Environment(F.add(F.add(Env.ExprBindings, MakeLocation(E), location), + E, V)); } namespace { @@ -130,10 +135,11 @@ public: }; } // end anonymous namespace -// In addition to mapping from Stmt * - > SVals in the Environment, we also -// maintain a mapping from Stmt * -> SVals (locations) that were used during -// a load and store. -static inline bool IsLocation(const Stmt *S) { +// In addition to mapping from EnvironmentEntry - > SVals in the Environment, +// we also maintain a mapping from EnvironmentEntry -> SVals (locations) +// that were used during a load and store. +static inline bool IsLocation(const EnvironmentEntry &E) { + const Stmt *S = E.getStmt(); return (bool) (((uintptr_t) S) & 0x1); } @@ -154,12 +160,12 @@ EnvironmentManager::removeDeadBindings(Environment Env, // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); - SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations; + SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations; MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); - llvm::ImmutableMapRef<const Stmt*,SVal> + llvm::ImmutableMapRef<EnvironmentEntry,SVal> EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), F.getTreeFactory()); @@ -167,7 +173,7 @@ EnvironmentManager::removeDeadBindings(Environment Env, for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - const Stmt *BlkExpr = I.getKey(); + const EnvironmentEntry &BlkExpr = I.getKey(); // For recorded locations (used when evaluating loads and stores), we // consider them live only when their associated normal expression is // also live. @@ -179,7 +185,7 @@ EnvironmentManager::removeDeadBindings(Environment Env, } const SVal &X = I.getData(); - if (SymReaper.isLive(BlkExpr)) { + if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); @@ -204,13 +210,58 @@ EnvironmentManager::removeDeadBindings(Environment Env, // Go through he deferred locations and add them to the new environment if // the correspond Stmt* is in the map as well. - for (SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator + for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { - const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1); - if (EBMapRef.lookup(S)) - EBMapRef = EBMapRef.add(I->first, I->second); + const EnvironmentEntry &En = I->first; + const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1); + if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext()))) + EBMapRef = EBMapRef.add(En, I->second); } NewEnv.ExprBindings = EBMapRef.asImmutableMap(); return NewEnv; } + +void Environment::print(raw_ostream &Out, const char *NL, + const char *Sep) const { + printAux(Out, false, NL, Sep); + printAux(Out, true, NL, Sep); +} + +void Environment::printAux(raw_ostream &Out, bool printLocations, + const char *NL, + const char *Sep) const{ + + bool isFirst = true; + + for (Environment::iterator I = begin(), E = end(); I != E; ++I) { + const EnvironmentEntry &En = I.getKey(); + if (IsLocation(En)) { + if (!printLocations) + continue; + } + else { + if (printLocations) + continue; + } + + if (isFirst) { + Out << NL << NL + << (printLocations ? "Load/Store locations:" : "Expressions:") + << NL; + isFirst = false; + } else { + Out << NL; + } + + const Stmt *S = En.getStmt(); + if (printLocations) { + S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1)); + } + + Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") "; + LangOptions LO; // FIXME. + S->printPretty(Out, 0, PrintingPolicy(LO)); + Out << " : " << I.getData(); + } +} diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index f7022c6482c..2ab501a2677 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -366,7 +366,7 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init, const FieldDecl *FD = BMI->getAnyMember(); SVal FieldLoc = state->getLValue(FD, thisVal); - SVal InitVal = state->getSVal(BMI->getInit()); + SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext()); state = state->bindLoc(FieldLoc, InitVal); // Use a custom node building process. @@ -534,7 +534,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::GNUNullExprClass: { // GNU __null is a pointer-width integer, not an actual pointer. const ProgramState *state = Pred->getState(); - state = state->BindExpr(S, svalBuilder.makeIntValWithPtrWidth(0, false)); + state = state->BindExpr(S, Pred->getLocationContext(), + svalBuilder.makeIntValWithPtrWidth(0, false)); Bldr.generateNode(S, Pred, state); break; } @@ -553,7 +554,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, const ProgramState *state = Pred->getState(); QualType ty = cast<ImplicitValueInitExpr>(S)->getType(); SVal val = svalBuilder.makeZeroVal(ty); - Bldr.generateNode(S, Pred, state->BindExpr(S, val)); + Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(), + val)); break; } @@ -635,7 +637,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, else if (B->getOpcode() == BO_Comma) { const ProgramState *state = Pred->getState(); Bldr.generateNode(B, Pred, - state->BindExpr(B, state->getSVal(B->getRHS()))); + state->BindExpr(B, Pred->getLocationContext(), + state->getSVal(B->getRHS(), + Pred->getLocationContext()))); break; } @@ -850,7 +854,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, if (Expr *LastExpr = dyn_cast<Expr>(*SE->getSubStmt()->body_rbegin())) { const ProgramState *state = Pred->getState(); Bldr.generateNode(SE, Pred, - state->BindExpr(SE, state->getSVal(LastExpr))); + state->BindExpr(SE, Pred->getLocationContext(), + state->getSVal(LastExpr, + Pred->getLocationContext()))); } break; } @@ -858,7 +864,8 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::StringLiteralClass: { const ProgramState *state = Pred->getState(); SVal V = state->getLValue(cast<StringLiteral>(S)); - Bldr.generateNode(S, Pred, state->BindExpr(S, V)); + Bldr.generateNode(S, Pred, state->BindExpr(S, Pred->getLocationContext(), + V)); return; } @@ -881,11 +888,14 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, const ProgramState *state = Pred->getState(); const PseudoObjectExpr *PE = cast<PseudoObjectExpr>(S); if (const Expr *Result = PE->getResultExpr()) { - SVal V = state->getSVal(Result); - Bldr.generateNode(S, Pred, state->BindExpr(S, V)); + SVal V = state->getSVal(Result, Pred->getLocationContext()); + Bldr.generateNode(S, Pred, + state->BindExpr(S, Pred->getLocationContext(), V)); } else - Bldr.generateNode(S, Pred, state->BindExpr(S, UnknownVal())); + Bldr.generateNode(S, Pred, + state->BindExpr(S, Pred->getLocationContext(), + UnknownVal())); Bldr.addNodes(Dst); break; @@ -910,8 +920,9 @@ void ExprEngine::processCFGBlockEntrance(NodeBuilderWithSinks &nodeBuilder) { //===----------------------------------------------------------------------===// const ProgramState *ExprEngine::MarkBranch(const ProgramState *state, - const Stmt *Terminator, - bool branchTaken) { + const Stmt *Terminator, + const LocationContext *LCtx, + bool branchTaken) { switch (Terminator->getStmtClass()) { default: @@ -934,7 +945,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state, (Op == BO_LOr && !branchTaken) ? B->getRHS() : B->getLHS(); - return state->BindExpr(B, UndefinedVal(Ex)); + return state->BindExpr(B, LCtx, UndefinedVal(Ex)); } case Stmt::BinaryConditionalOperatorClass: @@ -952,7 +963,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state, else Ex = C->getFalseExpr(); - return state->BindExpr(C, UndefinedVal(Ex)); + return state->BindExpr(C, LCtx, UndefinedVal(Ex)); } case Stmt::ChooseExprClass: { // ?: @@ -960,7 +971,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state, const ChooseExpr *C = cast<ChooseExpr>(Terminator); const Expr *Ex = branchTaken ? C->getLHS() : C->getRHS(); - return state->BindExpr(C, UndefinedVal(Ex)); + return state->BindExpr(C, LCtx, UndefinedVal(Ex)); } } } @@ -973,6 +984,7 @@ const ProgramState *ExprEngine::MarkBranch(const ProgramState *state, static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr, const ProgramState *state, const Stmt *Condition, + const LocationContext *LCtx, ASTContext &Ctx) { const Expr *Ex = dyn_cast<Expr>(Condition); @@ -1003,7 +1015,7 @@ static SVal RecoverCastedSymbol(ProgramStateManager& StateMgr, if (!bitsInit || !T->isIntegerType() || Ctx.getTypeSize(T) > bits) return UnknownVal(); - return state->getSVal(Ex); + return state->getSVal(Ex, LCtx); } void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, @@ -1042,7 +1054,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, continue; const ProgramState *PrevState = Pred->getState(); - SVal X = PrevState->getSVal(Condition); + SVal X = PrevState->getSVal(Condition, Pred->getLocationContext()); if (X.isUnknownOrUndef()) { // Give it a chance to recover from unknown. @@ -1054,6 +1066,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, // underlying value and use that instead. SVal recovered = RecoverCastedSymbol(getStateManager(), PrevState, Condition, + Pred->getLocationContext(), getContext()); if (!recovered.isUnknown()) { @@ -1062,10 +1075,15 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, } } } + + const LocationContext *LCtx = PredI->getLocationContext(); + // If the condition is still unknown, give up. if (X.isUnknownOrUndef()) { - builder.generateNode(MarkBranch(PrevState, Term, true), true, PredI); - builder.generateNode(MarkBranch(PrevState, Term, false), false, PredI); + builder.generateNode(MarkBranch(PrevState, Term, LCtx, true), + true, PredI); + builder.generateNode(MarkBranch(PrevState, Term, LCtx, false), + false, PredI); continue; } @@ -1074,7 +1092,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, // Process the true branch. if (builder.isFeasible(true)) { if (const ProgramState *state = PrevState->assume(V, true)) - builder.generateNode(MarkBranch(state, Term, true), true, PredI); + builder.generateNode(MarkBranch(state, Term, LCtx, true), + true, PredI); else builder.markInfeasible(true); } @@ -1082,7 +1101,8 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, // Process the false branch. if (builder.isFeasible(false)) { if (const ProgramState *state = PrevState->assume(V, false)) - builder.generateNode(MarkBranch(state, Term, false), false, PredI); + builder.generateNode(MarkBranch(state, Term, LCtx, false), + false, PredI); else builder.markInfeasible(false); } @@ -1095,7 +1115,7 @@ void ExprEngine::processBranch(const Stmt *Condition, const Stmt *Term, void ExprEngine::processIndirectGoto(IndirectGotoNodeBuilder &builder) { const ProgramState *state = builder.getState(); - SVal V = state->getSVal(builder.getTarget()); + SVal V = state->getSVal(builder.getTarget(), builder.getLocationContext()); // Three possibilities: // @@ -1149,7 +1169,7 @@ void ExprEngine::processSwitch(SwitchNodeBuilder& builder) { typedef SwitchNodeBuilder::iterator iterator; const ProgramState *state = builder.getState(); const Expr *CondE = builder.getCondition(); - SVal CondV_untested = state->getSVal(CondE); + SVal CondV_untested = state->getSVal(CondE, builder.getLocationContext()); if (CondV_untested.isUndef()) { //ExplodedNode* N = builder.generateDefaultCaseNode(state, true); @@ -1256,6 +1276,7 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); const ProgramState *state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); if (const VarDecl *VD = dyn_cast<VarDecl>(D)) { assert(Ex->isLValue()); @@ -1270,19 +1291,19 @@ void ExprEngine::VisitCommonDeclRefExpr(const Expr *Ex, const NamedDecl *D, V = UnknownVal(); } - Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0, + Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0, ProgramPoint::PostLValueKind); return; } if (const EnumConstantDecl *ED = dyn_cast<EnumConstantDecl>(D)) { assert(!Ex->isLValue()); SVal V = svalBuilder.makeIntVal(ED->getInitVal()); - Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V)); + Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V)); return; } if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D)) { SVal V = svalBuilder.getFunctionPointer(FD); - Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, V), false, 0, + Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, V), false, 0, ProgramPoint::PostLValueKind); return; } @@ -1306,11 +1327,13 @@ void ExprEngine::VisitLvalArraySubscriptExpr(const ArraySubscriptExpr *A, for (ExplodedNodeSet::iterator it = checkerPreStmt.begin(), ei = checkerPreStmt.end(); it != ei; ++it) { + const LocationContext *LCtx = (*it)->getLocationContext(); const ProgramState *state = (*it)->getState(); - SVal V = state->getLValue(A->getType(), state->getSVal(Idx), - state->getSVal(Base)); + SVal V = state->getLValue(A->getType(), + state->getSVal(Idx, LCtx), + state->getSVal(Base, LCtx)); assert(A->isLValue()); - Bldr.generateNode(A, *it, state->BindExpr(A, V), + Bldr.generateNode(A, *it, state->BindExpr(A, LCtx, V), false, 0, ProgramPoint::PostLValueKind); } } @@ -1336,14 +1359,15 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, Expr *baseExpr = M->getBase()->IgnoreParens(); const ProgramState *state = Pred->getState(); - SVal baseExprVal = state->getSVal(baseExpr); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal baseExprVal = state->getSVal(baseExpr, Pred->getLocationContext()); if (isa<nonloc::LazyCompoundVal>(baseExprVal) || isa<nonloc::CompoundVal>(baseExprVal) || // FIXME: This can originate by conjuring a symbol for an unknown // temporary struct object, see test/Analysis/fields.c: // (p = getit()).x isa<nonloc::SymbolVal>(baseExprVal)) { - Bldr.generateNode(M, Pred, state->BindExpr(M, UnknownVal())); + Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, UnknownVal())); return; } @@ -1354,7 +1378,7 @@ void ExprEngine::VisitMemberExpr(const MemberExpr *M, ExplodedNode *Pred, // For all other cases, compute an lvalue. SVal L = state->getLValue(field, baseExprVal); if (M->isLValue()) - Bldr.generateNode(M, Pred, state->BindExpr(M, L), false, 0, + Bldr.generateNode(M, Pred, state->BindExpr(M, LCtx, L), false, 0, ProgramPoint::PostLValueKind); else { Bldr.takeNodes(Pred); @@ -1465,7 +1489,7 @@ void ExprEngine::evalLoad(ExplodedNodeSet &Dst, const Expr *Ex, // Perform the load from the referenced value. for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end() ; I!=E; ++I) { state = (*I)->getState(); - location = state->getSVal(Ex); + location = state->getSVal(Ex, (*I)->getLocationContext()); evalLoadCommon(Dst, Ex, *I, state, location, tag, LoadTy); } return; @@ -1493,17 +1517,19 @@ void ExprEngine::evalLoadCommon(ExplodedNodeSet &Dst, const Expr *Ex, // Proceed with the load. for (ExplodedNodeSet::iterator NI=Tmp.begin(), NE=Tmp.end(); NI!=NE; ++NI) { state = (*NI)->getState(); + const LocationContext *LCtx = (*NI)->getLocationContext(); if (location.isUnknown()) { // This is important. We must nuke the old binding. - Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, UnknownVal()), + Bldr.generateNode(Ex, *NI, state->BindExpr(Ex, LCtx, UnknownVal()), false, tag, ProgramPoint::PostLoadKind); } else { if (LoadTy.isNull()) LoadTy = Ex->getType(); SVal V = state->getSVal(cast<Loc>(location), LoadTy); - Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, location, V), + Bldr.generateNode(Ex, *NI, state->bindExprAndLocation(Ex, LCtx, + location, V), false, tag, ProgramPoint::PostLoadKind); } } @@ -1642,7 +1668,7 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, } const ProgramState *state = Pred->getState(); - SVal V = state->getSVal(Ex); + SVal V = state->getSVal(Ex, Pred->getLocationContext()); nonloc::SymbolVal *SEV = dyn_cast<nonloc::SymbolVal>(&V); if (SEV && SEV->isExpression()) { const std::pair<const ProgramPointTag *, const ProgramPointTag*> &tags = @@ -1651,14 +1677,14 @@ void ExprEngine::evalEagerlyAssume(ExplodedNodeSet &Dst, ExplodedNodeSet &Src, // First assume that the condition is true. if (const ProgramState *StateTrue = state->assume(*SEV, true)) { SVal Val = svalBuilder.makeIntVal(1U, Ex->getType()); - StateTrue = StateTrue->BindExpr(Ex, Val); + StateTrue = StateTrue->BindExpr(Ex, Pred->getLocationContext(), Val); Bldr.generateNode(Ex, Pred, StateTrue, false, tags.first); } // Next, assume that the condition is false. if (const ProgramState *StateFalse = state->assume(*SEV, false)) { SVal Val = svalBuilder.makeIntVal(0U, Ex->getType()); - StateFalse = StateFalse->BindExpr(Ex, Val); + StateFalse = StateFalse->BindExpr(Ex, Pred->getLocationContext(), Val); Bldr.generateNode(Ex, Pred, StateFalse, false, tags.second); } } @@ -1706,7 +1732,7 @@ void ExprEngine::VisitAsmStmtHelperInputs(const AsmStmt *A, for (AsmStmt::const_outputs_iterator OI = A->begin_outputs(), OE = A->end_outputs(); OI != OE; ++OI) { - SVal X = state->getSVal(*OI); + SVal X = state->getSVal(*OI, Pred->getLocationContext()); assert (!isa<NonLoc>(X)); // Should be an Lval, or unknown, undef. if (isa<Loc>(X)) @@ -1911,7 +1937,7 @@ struct DOTGraphTraits<ExplodedNode*> : const ProgramState *state = N->getState(); Out << "\\|StateID: " << (void*) state << " NodeID: " << (void*) N << "\\|"; - state->printDOT(Out, *N->getLocationContext()->getCFG()); + state->printDOT(Out); Out << "\\l"; diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp index 83bc39e1fde..b3c5802079a 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineC.cpp @@ -35,8 +35,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, it != ei; ++it) { const ProgramState *state = (*it)->getState(); - SVal LeftV = state->getSVal(LHS); - SVal RightV = state->getSVal(RHS); + const LocationContext *LCtx = (*it)->getLocationContext(); + SVal LeftV = state->getSVal(LHS, LCtx); + SVal RightV = state->getSVal(RHS, LCtx); BinaryOperator::Opcode Op = B->getOpcode(); @@ -50,7 +51,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // Simulate the effects of a "store": bind the value of the RHS // to the L-Value represented by the LHS. SVal ExprVal = B->isLValue() ? LeftV : RightV; - evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, ExprVal), LeftV, RightV); + evalStore(Tmp2, B, LHS, *it, state->BindExpr(B, LCtx, ExprVal), + LeftV, RightV); continue; } @@ -64,7 +66,7 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, continue; } - state = state->BindExpr(B, Result); + state = state->BindExpr(B, LCtx, Result); Bldr.generateNode(B, *it, state); continue; } @@ -96,7 +98,8 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, ++I) { state = (*I)->getState(); - SVal V = state->getSVal(LHS); + const LocationContext *LCtx = (*I)->getLocationContext(); + SVal V = state->getSVal(LHS, LCtx); // Get the computation type. QualType CTy = @@ -143,9 +146,9 @@ void ExprEngine::VisitBinaryOperator(const BinaryOperator* B, // In C++, assignment and compound assignment operators return an // lvalue. if (B->isLValue()) - state = state->BindExpr(B, location); + state = state->BindExpr(B, LCtx, location); else - state = state->BindExpr(B, Result); + state = state->BindExpr(B, LCtx, Result); evalStore(Tmp2, B, LHS, *I, state, location, LHSVal); } @@ -164,7 +167,10 @@ void ExprEngine::VisitBlockExpr(const BlockExpr *BE, ExplodedNode *Pred, ExplodedNodeSet Tmp; StmtNodeBuilder Bldr(Pred, Tmp, *currentBuilderContext); - Bldr.generateNode(BE, Pred, Pred->getState()->BindExpr(BE, V), false, 0, + Bldr.generateNode(BE, Pred, + Pred->getState()->BindExpr(BE, Pred->getLocationContext(), + V), + false, 0, ProgramPoint::PostLValueKind); // FIXME: Move all post/pre visits to ::Visit(). @@ -182,7 +188,8 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, I!=E; ++I) { ExplodedNode *subExprNode = *I; const ProgramState *state = subExprNode->getState(); - evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex)); + const LocationContext *LCtx = subExprNode->getLocationContext(); + evalLoad(Dst, CastE, subExprNode, state, state->getSVal(Ex, LCtx)); } return; } @@ -216,8 +223,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_FunctionToPointerDecay: { // Copy the SVal of Ex to CastE. const ProgramState *state = Pred->getState(); - SVal V = state->getSVal(Ex); - state = state->BindExpr(CastE, V); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal V = state->getSVal(Ex, LCtx); + state = state->BindExpr(CastE, LCtx, V); Bldr.generateNode(CastE, Pred, state); continue; } @@ -251,9 +259,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_ObjCObjectLValueCast: { // Delegate to SValBuilder to process. const ProgramState *state = Pred->getState(); - SVal V = state->getSVal(Ex); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal V = state->getSVal(Ex, LCtx); V = svalBuilder.evalCast(V, T, ExTy); - state = state->BindExpr(CastE, V); + state = state->BindExpr(CastE, LCtx, V); Bldr.generateNode(CastE, Pred, state); continue; } @@ -261,9 +270,10 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, case CK_UncheckedDerivedToBase: { // For DerivedToBase cast, delegate to the store manager. const ProgramState *state = Pred->getState(); - SVal val = state->getSVal(Ex); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal val = state->getSVal(Ex, LCtx); val = getStoreManager().evalDerivedToBase(val, T); - state = state->BindExpr(CastE, val); + state = state->BindExpr(CastE, LCtx, val); Bldr.generateNode(CastE, Pred, state); continue; } @@ -287,7 +297,9 @@ void ExprEngine::VisitCast(const CastExpr *CastE, const Expr *Ex, svalBuilder.getConjuredSymbolVal(NULL, CastE, resultType, currentBuilderContext->getCurrentBlockCount()); - const ProgramState *state = Pred->getState()->BindExpr(CastE, result); + const LocationContext *LCtx = Pred->getLocationContext(); + const ProgramState *state = Pred->getState()->BindExpr(CastE, LCtx, + result); Bldr.generateNode(CastE, Pred, state); continue; } @@ -304,14 +316,14 @@ void ExprEngine::VisitCompoundLiteralExpr(const CompoundLiteralExpr *CL, = cast<InitListExpr>(CL->getInitializer()->IgnoreParens()); const ProgramState *state = Pred->getState(); - SVal ILV = state->getSVal(ILE); + SVal ILV = state->getSVal(ILE, Pred->getLocationContext()); const LocationContext *LC = Pred->getLocationContext(); state = state->bindCompoundLiteral(CL, LC, ILV); if (CL->isLValue()) - B.generateNode(CL, Pred, state->BindExpr(CL, state->getLValue(CL, LC))); + B.generateNode(CL, Pred, state->BindExpr(CL, LC, state->getLValue(CL, LC))); else - B.generateNode(CL, Pred, state->BindExpr(CL, ILV)); + B.generateNode(CL, Pred, state->BindExpr(CL, LC, ILV)); } void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, @@ -345,7 +357,7 @@ void ExprEngine::VisitDeclStmt(const DeclStmt *DS, ExplodedNode *Pred, const LocationContext *LC = N->getLocationContext(); if (const Expr *InitEx = VD->getInit()) { - SVal InitVal = state->getSVal(InitEx); + SVal InitVal = state->getSVal(InitEx, Pred->getLocationContext()); // We bound the temp obj region to the CXXConstructExpr. Now recover // the lazy compound value when the variable is not a reference. @@ -379,18 +391,19 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); const ProgramState *state = Pred->getState(); - SVal X = state->getSVal(B); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal X = state->getSVal(B, LCtx); assert(X.isUndef()); const Expr *Ex = (const Expr*) cast<UndefinedVal>(X).getData(); assert(Ex); if (Ex == B->getRHS()) { - X = state->getSVal(Ex); + X = state->getSVal(Ex, LCtx); // Handle undefined values. if (X.isUndef()) { - Bldr.generateNode(B, Pred, state->BindExpr(B, X)); + Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X)); return; } @@ -404,11 +417,13 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, // the payoff is not likely to be large. Instead, we do eager evaluation. if (const ProgramState *newState = state->assume(XD, true)) Bldr.generateNode(B, Pred, - newState->BindExpr(B, svalBuilder.makeIntVal(1U, B->getType()))); + newState->BindExpr(B, LCtx, + svalBuilder.makeIntVal(1U, B->getType()))); if (const ProgramState *newState = state->assume(XD, false)) Bldr.generateNode(B, Pred, - newState->BindExpr(B, svalBuilder.makeIntVal(0U, B->getType()))); + newState->BindExpr(B, LCtx, + svalBuilder.makeIntVal(0U, B->getType()))); } else { // We took the LHS expression. Depending on whether we are '&&' or @@ -416,7 +431,7 @@ void ExprEngine::VisitLogicalExpr(const BinaryOperator* B, ExplodedNode *Pred, // the short-circuiting. X = svalBuilder.makeIntVal(B->getOpcode() == BO_LAnd ? 0U : 1U, B->getType()); - Bldr.generateNode(B, Pred, state->BindExpr(B, X)); + Bldr.generateNode(B, Pred, state->BindExpr(B, LCtx, X)); } } @@ -426,6 +441,7 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE, StmtNodeBuilder B(Pred, Dst, *currentBuilderContext); const ProgramState *state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); QualType T = getContext().getCanonicalType(IE->getType()); unsigned NumInitElements = IE->getNumInits(); @@ -436,24 +452,27 @@ void ExprEngine::VisitInitListExpr(const InitListExpr *IE, // e.g: static int* myArray[] = {}; if (NumInitElements == 0) { SVal V = svalBuilder.makeCompoundVal(T, vals); - B.generateNode(IE, Pred, state->BindExpr(IE, V)); + B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, V)); return; } for (InitListExpr::const_reverse_iterator it = IE->rbegin(), ei = IE->rend(); it != ei; ++it) { - vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it)), vals); + vals = getBasicVals().consVals(state->getSVal(cast<Expr>(*it), LCtx), + vals); } B.generateNode(IE, Pred, - state->BindExpr(IE, svalBuilder.makeCompoundVal(T, vals))); + state->BindExpr(IE, LCtx, + svalBuilder.makeCompoundVal(T, vals))); return; } if (Loc::isLocType(T) || T->isIntegerType()) { assert(IE->getNumInits() == 1); const Expr *initEx = IE->getInit(0); - B.generateNode(IE, Pred, state->BindExpr(IE, state->getSVal(initEx))); + B.generateNode(IE, Pred, state->BindExpr(IE, LCtx, + state->getSVal(initEx, LCtx))); return; } @@ -468,14 +487,15 @@ void ExprEngine::VisitGuardedExpr(const Expr *Ex, StmtNodeBuilder B(Pred, Dst, *currentBuilderContext); const ProgramState *state = Pred->getState(); - SVal X = state->getSVal(Ex); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal X = state->getSVal(Ex, LCtx); assert (X.isUndef()); const Expr *SE = (Expr*) cast<UndefinedVal>(X).getData(); assert(SE); - X = state->getSVal(SE); + X = state->getSVal(SE, LCtx); // Make sure that we invalidate the previous binding. - B.generateNode(Ex, Pred, state->BindExpr(Ex, X, true)); + B.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, X, true)); } void ExprEngine:: @@ -488,7 +508,9 @@ VisitOffsetOfExpr(const OffsetOfExpr *OOE, assert(OOE->getType()->isIntegerType()); assert(IV.isSigned() == OOE->getType()->isSignedIntegerOrEnumerationType()); SVal X = svalBuilder.makeIntVal(IV); - B.generateNode(OOE, Pred, Pred->getState()->BindExpr(OOE, X)); + B.generateNode(OOE, Pred, + Pred->getState()->BindExpr(OOE, Pred->getLocationContext(), + X)); } // FIXME: Handle the case where __builtin_offsetof is not a constant. } @@ -522,7 +544,8 @@ VisitUnaryExprOrTypeTraitExpr(const UnaryExprOrTypeTraitExpr *Ex, CharUnits amt = CharUnits::fromQuantity(Value.getZExtValue()); const ProgramState *state = Pred->getState(); - state = state->BindExpr(Ex, svalBuilder.makeIntVal(amt.getQuantity(), + state = state->BindExpr(Ex, Pred->getLocationContext(), + svalBuilder.makeIntVal(amt.getQuantity(), Ex->getType())); Bldr.generateNode(Ex, Pred, state); } @@ -555,7 +578,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // For all other types, UO_Real is an identity operation. assert (U->getType() == Ex->getType()); const ProgramState *state = (*I)->getState(); - Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex))); + const LocationContext *LCtx = (*I)->getLocationContext(); + Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, + state->getSVal(Ex, LCtx))); } break; @@ -576,8 +601,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, // For all other types, UO_Imag returns 0. const ProgramState *state = (*I)->getState(); + const LocationContext *LCtx = (*I)->getLocationContext(); SVal X = svalBuilder.makeZeroVal(Ex->getType()); - Bldr.generateNode(U, *I, state->BindExpr(U, X)); + Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, X)); } break; @@ -601,7 +627,9 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const ProgramState *state = (*I)->getState(); - Bldr.generateNode(U, *I, state->BindExpr(U, state->getSVal(Ex))); + const LocationContext *LCtx = (*I)->getLocationContext(); + Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, + state->getSVal(Ex, LCtx))); } break; @@ -617,12 +645,13 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, for (ExplodedNodeSet::iterator I=Tmp.begin(), E=Tmp.end(); I!=E; ++I) { const ProgramState *state = (*I)->getState(); + const LocationContext *LCtx = (*I)->getLocationContext(); // Get the value of the subexpression. - SVal V = state->getSVal(Ex); + SVal V = state->getSVal(Ex, LCtx); if (V.isUnknownOrUndef()) { - Bldr.generateNode(U, *I, state->BindExpr(U, V)); + Bldr.generateNode(U, *I, state->BindExpr(U, LCtx, V)); continue; } @@ -632,12 +661,12 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, case UO_Not: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, evalComplement(cast<NonLoc>(V))); + state = state->BindExpr(U, LCtx, evalComplement(cast<NonLoc>(V))); break; case UO_Minus: // FIXME: Do we need to handle promotions? - state = state->BindExpr(U, evalMinus(cast<NonLoc>(V))); + state = state->BindExpr(U, LCtx, evalMinus(cast<NonLoc>(V))); break; case UO_LNot: @@ -659,7 +688,7 @@ void ExprEngine::VisitUnaryOperator(const UnaryOperator* U, U->getType()); } - state = state->BindExpr(U, Result); + state = state->BindExpr(U, LCtx, Result); break; } @@ -681,9 +710,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, Visit(Ex, Pred, Tmp); for (ExplodedNodeSet::iterator I = Tmp.begin(), E = Tmp.end(); I!=E; ++I) { - + const LocationContext *LCtx = (*I)->getLocationContext(); const ProgramState *state = (*I)->getState(); - SVal loc = state->getSVal(Ex); + SVal loc = state->getSVal(Ex, LCtx); // Perform a load. ExplodedNodeSet Tmp2; @@ -694,11 +723,12 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, for (ExplodedNodeSet::iterator I2=Tmp2.begin(), E2=Tmp2.end();I2!=E2;++I2) { state = (*I2)->getState(); - SVal V2_untested = state->getSVal(Ex); + assert(LCtx == (*I2)->getLocationContext()); + SVal V2_untested = state->getSVal(Ex, LCtx); // Propagate unknown and undefined values. if (V2_untested.isUnknownOrUndef()) { - Bldr.generateNode(U, *I2, state->BindExpr(U, V2_untested)); + Bldr.generateNode(U, *I2, state->BindExpr(U, LCtx, V2_untested)); continue; } DefinedSVal V2 = cast<DefinedSVal>(V2_untested); @@ -749,9 +779,9 @@ void ExprEngine::VisitIncrementDecrementOperator(const UnaryOperator* U, // Since the lvalue-to-rvalue conversion is explicit in the AST, // we bind an l-value if the operator is prefix and an lvalue (in C++). if (U->isLValue()) - state = state->BindExpr(U, loc); + state = state->BindExpr(U, LCtx, loc); else - state = state->BindExpr(U, U->isPostfix() ? V2 : Result); + state = state->BindExpr(U, LCtx, U->isPostfix() ? V2 : Result); // Perform the store. Bldr.takeNodes(*I2); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 99752e5408d..f9e18fbc4a3 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -110,17 +110,17 @@ void ExprEngine::CreateCXXTemporaryObject(const MaterializeTemporaryExpr *ME, StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); const Expr *tempExpr = ME->GetTemporaryExpr()->IgnoreParens(); const ProgramState *state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); // Bind the temporary object to the value of the expression. Then bind // the expression to the location of the object. - SVal V = state->getSVal(tempExpr); + SVal V = state->getSVal(tempExpr, Pred->getLocationContext()); const MemRegion *R = - svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, - Pred->getLocationContext()); + svalBuilder.getRegionManager().getCXXTempObjectRegion(ME, LCtx); state = state->bindLoc(loc::MemRegionVal(R), V); - Bldr.generateNode(ME, Pred, state->BindExpr(ME, loc::MemRegionVal(R))); + Bldr.generateNode(ME, Pred, state->BindExpr(ME, LCtx, loc::MemRegionVal(R))); } void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, @@ -208,7 +208,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *E, const LocationContext *LC = Pred->getLocationContext(); const ProgramState *state = Pred->getState(); - state = invalidateArguments(state, CallOrObjCMessage(E, state), LC); + state = invalidateArguments(state, CallOrObjCMessage(E, state, LC), LC); Bldr.generateNode(E, Pred, state); } } @@ -256,7 +256,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, // FIXME: allocating an array requires simulating the constructors. // For now, just return a symbolicated region. const ProgramState *state = Pred->getState(); - state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); + state = state->BindExpr(CNE, Pred->getLocationContext(), + loc::MemRegionVal(EleReg)); Bldr.generateNode(CNE, Pred, state); return; } @@ -286,7 +287,7 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end(); ai != ae; ++ai) { - SVal val = state->getSVal(*ai); + SVal val = state->getSVal(*ai, (*I)->getLocationContext()); if (const MemRegion *region = val.getAsRegion()) regionsToInvalidate.push_back(region); } @@ -307,7 +308,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, CNE, blockCount, 0, 0); if (CNE->hasInitializer()) { - SVal V = state->getSVal(*CNE->constructor_arg_begin()); + SVal V = state->getSVal(*CNE->constructor_arg_begin(), + (*I)->getLocationContext()); state = state->bindLoc(loc::MemRegionVal(EleReg), V); } else { // Explicitly set to undefined, because currently we retrieve symbolic @@ -315,7 +317,8 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred, state = state->bindLoc(loc::MemRegionVal(EleReg), UndefinedVal()); } } - state = state->BindExpr(CNE, loc::MemRegionVal(EleReg)); + state = state->BindExpr(CNE, (*I)->getLocationContext(), + loc::MemRegionVal(EleReg)); Bldr.generateNode(CNE, *I, state); } } @@ -338,12 +341,13 @@ void ExprEngine::VisitCXXThisExpr(const CXXThisExpr *TE, ExplodedNode *Pred, StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext); // Get the this object region from StoreManager. + const LocationContext *LCtx = Pred->getLocationContext(); const MemRegion *R = svalBuilder.getRegionManager().getCXXThisRegion( getContext().getCanonicalType(TE->getType()), - Pred->getLocationContext()); + LCtx); const ProgramState *state = Pred->getState(); SVal V = state->getSVal(loc::MemRegionVal(R)); - Bldr.generateNode(TE, Pred, state->BindExpr(TE, V)); + Bldr.generateNode(TE, Pred, state->BindExpr(TE, LCtx, V)); } diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index faffee75fb2..3b508d28994 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -44,8 +44,9 @@ void ExprEngine::processCallExit(CallExitNodeBuilder &B) { // If the callee returns an expression, bind its value to CallExpr. const Stmt *ReturnedExpr = state->get<ReturnExpr>(); if (ReturnedExpr) { - SVal RetVal = state->getSVal(ReturnedExpr); - state = state->BindExpr(CE, RetVal); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal RetVal = state->getSVal(ReturnedExpr, LCtx); + state = state->BindExpr(CE, LCtx, RetVal); // Clear the return expr GDM. state = state->remove<ReturnExpr>(); } @@ -57,7 +58,7 @@ void ExprEngine::processCallExit(CallExitNodeBuilder &B) { SVal ThisV = state->getSVal(ThisR); // Always bind the region to the CXXConstructExpr. - state = state->BindExpr(CCE, ThisV); + state = state->BindExpr(CCE, Pred->getLocationContext(), ThisV); } B.generateNode(state); @@ -231,7 +232,7 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, // Get the callee. const Expr *Callee = CE->getCallee()->IgnoreParens(); const ProgramState *state = Pred->getState(); - SVal L = state->getSVal(Callee); + SVal L = state->getSVal(Callee, Pred->getLocationContext()); // Figure out the result type. We do this dance to handle references. QualType ResultTy; @@ -249,11 +250,12 @@ void ExprEngine::VisitCallExpr(const CallExpr *CE, ExplodedNode *Pred, SVal RetVal = SVB.getConjuredSymbolVal(0, CE, ResultTy, Count); // Generate a new state with the return value set. - state = state->BindExpr(CE, RetVal); + const LocationContext *LCtx = Pred->getLocationContext(); + state = state->BindExpr(CE, LCtx, RetVal); // Invalidate the arguments. - const LocationContext *LC = Pred->getLocationContext(); - state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state), LC); + state = Eng.invalidateArguments(state, CallOrObjCMessage(CE, state, LCtx), + LCtx); // And make the result node. Bldr.generateNode(CE, Pred, state); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp index a03a7b29e60..cb83d2f5609 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineObjC.cpp @@ -22,12 +22,13 @@ void ExprEngine::VisitLvalObjCIvarRefExpr(const ObjCIvarRefExpr *Ex, ExplodedNode *Pred, ExplodedNodeSet &Dst) { const ProgramState *state = Pred->getState(); - SVal baseVal = state->getSVal(Ex->getBase()); + const LocationContext *LCtx = Pred->getLocationContext(); + SVal baseVal = state->getSVal(Ex->getBase(), LCtx); SVal location = state->getLValue(Ex->getDecl(), baseVal); ExplodedNodeSet dstIvar; StmtNodeBuilder Bldr(Pred, dstIvar, *currentBuilderContext); - Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, location)); + Bldr.generateNode(Ex, Pred, state->BindExpr(Ex, LCtx, location)); // Perform the post-condition check of the ObjCIvarRefExpr and store // the created nodes in 'Dst'. @@ -80,7 +81,7 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, elementV = state->getLValue(elemD, Pred->getLocationContext()); } else { - elementV = state->getSVal(elem); + elementV = state->getSVal(elem, Pred->getLocationContext()); } ExplodedNodeSet dstLocation; @@ -92,14 +93,15 @@ void ExprEngine::VisitObjCForCollectionStmt(const ObjCForCollectionStmt *S, NE = dstLocation.end(); NI!=NE; ++NI) { Pred = *NI; const ProgramState *state = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); // Handle the case where the container still has elements. SVal TrueV = svalBuilder.makeTruthVal(1); - const ProgramState *hasElems = state->BindExpr(S, TrueV); + const ProgramState *hasElems = state->BindExpr(S, LCtx, TrueV); // Handle the case where the container has no elements. SVal FalseV = svalBuilder.makeTruthVal(0); - const ProgramState *noElems = state->BindExpr(S, FalseV); + const ProgramState *noElems = state->BindExpr(S, LCtx, FalseV); if (loc::MemRegionVal *MV = dyn_cast<loc::MemRegionVal>(&elementV)) if (const TypedValueRegion *R = @@ -146,7 +148,7 @@ void ExprEngine::VisitObjCMessage(const ObjCMessage &msg, if (const Expr *Receiver = msg.getInstanceReceiver()) { const ProgramState *state = Pred->getState(); - SVal recVal = state->getSVal(Receiver); + SVal recVal = state->getSVal(Receiver, Pred->getLocationContext()); if (!recVal.isUndef()) { // Bifurcate the state into nil and non-nil ones. DefinedOrUnknownSVal receiverVal = cast<DefinedOrUnknownSVal>(recVal); @@ -241,7 +243,7 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, // These methods return their receivers. const Expr *ReceiverE = msg.getInstanceReceiver(); if (ReceiverE) - ReturnValue = state->getSVal(ReceiverE); + ReturnValue = state->getSVal(ReceiverE, Pred->getLocationContext()); break; } } @@ -256,11 +258,11 @@ void ExprEngine::evalObjCMessage(StmtNodeBuilder &Bldr, } // Bind the return value. - state = state->BindExpr(currentStmt, ReturnValue); + const LocationContext *LCtx = Pred->getLocationContext(); + state = state->BindExpr(currentStmt, LCtx, ReturnValue); // Invalidate the arguments (and the receiver) - const LocationContext *LC = Pred->getLocationContext(); - state = invalidateArguments(state, CallOrObjCMessage(msg, state), LC); + state = invalidateArguments(state, CallOrObjCMessage(msg, state, LCtx), LCtx); // And create the new node. Bldr.generateNode(msg.getOriginExpr(), Pred, state, GenSink); diff --git a/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp index 1edc3769e7a..ac571a5ef67 100644 --- a/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp +++ b/clang/lib/StaticAnalyzer/Core/ObjCMessage.cpp @@ -125,7 +125,7 @@ QualType CallOrObjCMessage::getResultType(ASTContext &ctx) const { isLVal = FunctionCall->isLValue(); const Expr *Callee = FunctionCall->getCallee(); - if (const FunctionDecl *FD = State->getSVal(Callee).getAsFunctionDecl()) + if (const FunctionDecl *FD = State->getSVal(Callee, LCtx).getAsFunctionDecl()) resultTy = FD->getResultType(); else resultTy = FunctionCall->getType(); @@ -141,7 +141,7 @@ SVal CallOrObjCMessage::getFunctionCallee() const { assert(isFunctionCall()); assert(!isCXXCall()); const Expr *Fun = CallE.get<const CallExpr *>()->getCallee()->IgnoreParens(); - return State->getSVal(Fun); + return State->getSVal(Fun, LCtx); } SVal CallOrObjCMessage::getCXXCallee() const { @@ -155,7 +155,7 @@ SVal CallOrObjCMessage::getCXXCallee() const { if (!callee) return UnknownVal(); - return State->getSVal(callee); + return State->getSVal(callee, LCtx); } SVal diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 4b98ce8b0f7..8a287e9e169 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -239,9 +239,12 @@ SVal ProgramState::getSVal(Loc location, QualType T) const { return V; } -const ProgramState *ProgramState::BindExpr(const Stmt *S, SVal V, bool Invalidate) const{ - Environment NewEnv = getStateManager().EnvMgr.bindExpr(Env, S, V, - Invalidate); +const ProgramState *ProgramState::BindExpr(const Stmt *S, + const LocationContext *LCtx, + SVal V, bool Invalidate) const{ + Environment NewEnv = + getStateManager().EnvMgr.bindExpr(Env, EnvironmentEntry(S, LCtx), V, + Invalidate); if (NewEnv == Env) return this; @@ -250,10 +253,14 @@ const ProgramState *ProgramState::BindExpr(const Stmt *S, SVal V, bool Invalidat return getStateManager().getPersistentState(NewSt); } -const ProgramState *ProgramState::bindExprAndLocation(const Stmt *S, SVal location, - SVal V) const { +const ProgramState * +ProgramState::bindExprAndLocation(const Stmt *S, const LocationContext *LCtx, + SVal location, + SVal V) const { Environment NewEnv = - getStateManager().EnvMgr.bindExprAndLocation(Env, S, location, V); + getStateManager().EnvMgr.bindExprAndLocation(Env, + EnvironmentEntry(S, LCtx), + location, V); if (NewEnv == Env) return this; @@ -380,114 +387,28 @@ void ProgramState::setStore(const StoreRef &newStore) { // State pretty-printing. //===----------------------------------------------------------------------===// -static bool IsEnvLoc(const Stmt *S) { - // FIXME: This is a layering violation. Should be in environment. - return (bool) (((uintptr_t) S) & 0x1); -} - -void ProgramState::print(raw_ostream &Out, CFG *C, +void ProgramState::print(raw_ostream &Out, const char *NL, const char *Sep) const { // Print the store. ProgramStateManager &Mgr = getStateManager(); Mgr.getStoreManager().print(getStore(), Out, NL, Sep); - bool isFirst = true; - - // FIXME: All environment printing should be moved inside Environment. - if (C) { - // Print Subexpression bindings. - for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - if (C->isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey())) - continue; - - if (isFirst) { - Out << NL << NL << "Sub-Expressions:" << NL; - isFirst = false; - } else { - Out << NL; - } - Out << " (" << (void*) I.getKey() << ") "; - LangOptions LO; // FIXME. - I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); - Out << " : " << I.getData(); - } - - // Print block-expression bindings. - isFirst = true; - for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - if (!C->isBlkExpr(I.getKey())) - continue; - - if (isFirst) { - Out << NL << NL << "Block-level Expressions:" << NL; - isFirst = false; - } else { - Out << NL; - } - - Out << " (" << (void*) I.getKey() << ") "; - LangOptions LO; // FIXME. - I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); - Out << " : " << I.getData(); - } - } else { - // Print All bindings - no info to differentiate block from subexpressions. - for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - if (IsEnvLoc(I.getKey())) - continue; - - if (isFirst) { - Out << NL << NL << "Expressions:" << NL; - isFirst = false; - } else { - Out << NL; - } - - Out << " (" << (void*) I.getKey() << ") "; - LangOptions LO; // FIXME. - I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); - Out << " : " << I.getData(); - } - } - - // Print locations. - isFirst = true; - - for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { - if (!IsEnvLoc(I.getKey())) - continue; - - if (isFirst) { - Out << NL << NL << "Load/store locations:" << NL; - isFirst = false; - } else { - Out << NL; - } - - const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1)); - - Out << " (" << (void*) S << ") "; - LangOptions LO; // FIXME. - S->printPretty(Out, 0, PrintingPolicy(LO)); - Out << " : " << I.getData(); - } + // Print out the environment. + Env.print(Out, NL, Sep); + // Print out the constraints. Mgr.getConstraintManager().print(this, Out, NL, Sep); // Print checker-specific data. Mgr.getOwningEngine()->printState(Out, this, NL, Sep); } -void ProgramState::printDOT(raw_ostream &Out, CFG &C) const { - print(Out, &C, "\\l", "\\|"); -} - -void ProgramState::dump(CFG &C) const { - print(llvm::errs(), &C); +void ProgramState::printDOT(raw_ostream &Out) const { + print(Out, "\\l", "\\|"); } void ProgramState::dump() const { - print(llvm::errs(), 0); + print(llvm::errs()); } //===----------------------------------------------------------------------===// @@ -654,15 +575,16 @@ bool ProgramState::scanReachableSymbols(const MemRegion * const *I, } const ProgramState* ProgramState::addTaint(const Stmt *S, + const LocationContext *LCtx, TaintTagType Kind) const { if (const Expr *E = dyn_cast_or_null<Expr>(S)) S = E->IgnoreParens(); - SymbolRef Sym = getSVal(S).getAsSymbol(); + SymbolRef Sym = getSVal(S, LCtx).getAsSymbol(); if (Sym) return addTaint(Sym, Kind); - const MemRegion *R = getSVal(S).getAsRegion(); + const MemRegion *R = getSVal(S, LCtx).getAsRegion(); addTaint(R, Kind); // Cannot add taint, so just return the state. @@ -683,11 +605,12 @@ const ProgramState* ProgramState::addTaint(SymbolRef Sym, return NewState; } -bool ProgramState::isTainted(const Stmt *S, TaintTagType Kind) const { +bool ProgramState::isTainted(const Stmt *S, const LocationContext *LCtx, + TaintTagType Kind) const { if (const Expr *E = dyn_cast_or_null<Expr>(S)) S = E->IgnoreParens(); - SVal val = getSVal(S); + SVal val = getSVal(S, LCtx); return isTainted(val, Kind); } diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index a0d1bada247..fa4ff044493 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -1863,7 +1863,7 @@ StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state, // PI != PE because the actual number of arguments may be different than // the function declaration. for (; AI != AE && PI != PE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI); + SVal ArgVal = state->getSVal(*AI, frame); store = Bind(store.getStore(), svalBuilder.makeLoc(MRMgr.getVarRegion(*PI, frame)), ArgVal); } @@ -1874,7 +1874,7 @@ StoreRef RegionStoreManager::enterStackFrame(const ProgramState *state, // Copy the arg expression value to the arg variables. for (; AI != AE; ++AI, ++PI) { - SVal ArgVal = state->getSVal(*AI); + SVal ArgVal = state->getSVal(*AI, frame); store = Bind(store.getStore(), svalBuilder.makeLoc(MRMgr.getVarRegion(*PI,frame)), ArgVal); } diff --git a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp index d31dd06092d..bdb9ea74c21 100644 --- a/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp +++ b/clang/lib/StaticAnalyzer/Core/SymbolManager.cpp @@ -491,7 +491,16 @@ bool SymbolReaper::isLive(SymbolRef sym) { return isa<SymbolRegionValue>(sym); } -bool SymbolReaper::isLive(const Stmt *ExprVal) const { +bool +SymbolReaper::isLive(const Stmt *ExprVal, const LocationContext *ELCtx) const { + if (LCtx != ELCtx) { + // If the reaper's location context is a parent of the expression's + // location context, then the expression value is now "out of scope". + if (LCtx->isParentOf(ELCtx)) + return false; + return true; + } + return LCtx->getAnalysis<RelaxedLiveVariables>()->isLive(Loc, ExprVal); } |