SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &RHS, QualType resultTy) { bool isIdempotent = false; // Check for a few special cases with known reductions first. switch (op) { default: // We can't reduce this case; just treat it normally. break; case BO_Mul: // a*0 and a*1 if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS == 1) isIdempotent = true; break; case BO_Div: // a/0 and a/1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) isIdempotent = true; break; case BO_Rem: // a%0 and a%1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) return makeIntVal(0, resultTy); break; case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_Xor: // a+0, a-0, a<<0, a>>0, a^0 if (RHS == 0) isIdempotent = true; break; case BO_And: // a&0 and a&(~0) if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS.isAllOnesValue()) isIdempotent = true; break; case BO_Or: // a|0 and a|(~0) if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnesValue()) { const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); return nonloc::ConcreteInt(Result); } break; } // Idempotent ops (like a*1) can still change the type of an expression. // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the // dirty work. if (isIdempotent) return evalCastFromNonLoc(nonloc::SymbolVal(LHS), resultTy); // If we reach this point, the expression cannot be simplified. // Make a SymbolVal for the entire expression, after converting the RHS. const llvm::APSInt *ConvertedRHS = &RHS; if (BinaryOperator::isComparisonOp(op)) { // We're looking for a type big enough to compare the symbolic value // with the given constant. // FIXME: This is an approximation of Sema::UsualArithmeticConversions. ASTContext &Ctx = getContext(); QualType SymbolType = LHS->getType(); uint64_t ValWidth = RHS.getBitWidth(); uint64_t TypeWidth = Ctx.getTypeSize(SymbolType); if (ValWidth < TypeWidth) { // If the value is too small, extend it. ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } else if (ValWidth == TypeWidth) { // If the value is signed but the symbol is unsigned, do the comparison // in unsigned space. [C99 6.3.1.8] // (For the opposite case, the value is already unsigned.) if (RHS.isSigned() && !SymbolType->isSignedIntegerOrEnumerationType()) ConvertedRHS = &BasicVals.Convert(SymbolType, RHS); } } else ConvertedRHS = &BasicVals.Convert(resultTy, RHS); return makeNonLoc(LHS, op, *ConvertedRHS, resultTy); }
SVal SimpleSValBuilder::MakeSymIntVal(const SymExpr *LHS, BinaryOperator::Opcode op, const llvm::APSInt &RHS, QualType resultTy) { bool isIdempotent = false; // Check for a few special cases with known reductions first. switch (op) { default: // We can't reduce this case; just treat it normally. break; case BO_Mul: // a*0 and a*1 if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS == 1) isIdempotent = true; break; case BO_Div: // a/0 and a/1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) isIdempotent = true; break; case BO_Rem: // a%0 and a%1 if (RHS == 0) // This is also handled elsewhere. return UndefinedVal(); else if (RHS == 1) return makeIntVal(0, resultTy); break; case BO_Add: case BO_Sub: case BO_Shl: case BO_Shr: case BO_Xor: // a+0, a-0, a<<0, a>>0, a^0 if (RHS == 0) isIdempotent = true; break; case BO_And: // a&0 and a&(~0) if (RHS == 0) return makeIntVal(0, resultTy); else if (RHS.isAllOnesValue()) isIdempotent = true; break; case BO_Or: // a|0 and a|(~0) if (RHS == 0) isIdempotent = true; else if (RHS.isAllOnesValue()) { const llvm::APSInt &Result = BasicVals.Convert(resultTy, RHS); return nonloc::ConcreteInt(Result); } break; } // Idempotent ops (like a*1) can still change the type of an expression. // Wrap the LHS up in a NonLoc again and let evalCastFromNonLoc do the // dirty work. if (isIdempotent) { if (SymbolRef LHSSym = dyn_cast<SymbolData>(LHS)) return evalCastFromNonLoc(nonloc::SymbolVal(LHSSym), resultTy); return evalCastFromNonLoc(nonloc::SymExprVal(LHS), resultTy); } // If we reach this point, the expression cannot be simplified. // Make a SymExprVal for the entire thing. return makeNonLoc(LHS, op, RHS, resultTy); }