diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/SValVisitor.h @@ -141,6 +141,7 @@ using SValVisitor::Visit; using SymExprVisitor::Visit; using MemRegionVisitor::Visit; + using Base = FullSValVisitor; }; } // end namespace ento diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp @@ -412,6 +412,15 @@ SymbolRef symLHS = LHS.getAsSymbol(); SymbolRef symRHS = RHS.getAsSymbol(); + // FIXME This should be done in getAsSymbol. But then getAsSymbol should be + // the member function of SValBuilder (?) + if (symRHS) + if (auto RLocAsInt = RHS.getAs()) { + auto FromTy = symRHS->getType(); + auto ToTy = RLocAsInt->getType(this->Context); + symRHS = this->getSymbolManager().getCastSymbol(symRHS, FromTy, ToTy); + } + // TODO: When the Max Complexity is reached, we should conjure a symbol // instead of generating an Unknown value and propagate the taint info to it. const unsigned MaxComp = AnOpts.MaxSymbolComplexity; @@ -459,23 +468,14 @@ return evalBinOpLN(state, op, *LV, rhs.castAs(), type); } - if (const Optional RV = rhs.getAs()) { - const auto IsCommutative = [](BinaryOperatorKind Op) { - return Op == BO_Mul || Op == BO_Add || Op == BO_And || Op == BO_Xor || - Op == BO_Or; - }; + if (Optional RV = rhs.getAs()) { + // Support pointer arithmetic where the addend is on the left + // and the pointer on the right. - if (IsCommutative(op)) { - // Swap operands. - return evalBinOpLN(state, op, *RV, lhs.castAs(), type); - } + assert(op == BO_Add); - // If the right operand is a concrete int location then we have nothing - // better but to treat it as a simple nonloc. - if (auto RV = rhs.getAs()) { - const nonloc::ConcreteInt RhsAsLoc = makeIntVal(RV->getValue()); - return evalBinOpNN(state, op, lhs.castAs(), RhsAsLoc, type); - } + // Commute the operands. + return evalBinOpLN(state, op, *RV, lhs.castAs(), type); } return evalBinOpNN(state, op, lhs.castAs(), rhs.castAs(), diff --git a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp --- a/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp +++ b/clang/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp @@ -1204,7 +1204,23 @@ return SVB.makeSymbolVal(S); } - // TODO: Support SymbolCast. + SVal VisitSymbolCast(const SymbolCast *Cast) { + SVal Castee = Visit(Cast->getOperand()); + const auto &Context = SVB.getContext(); + QualType CastTy = Cast->getType(); + + // Cast a pointer to an integral type. + if (Castee.getAs() && !Loc::isLocType(CastTy)) { + const unsigned BitWidth = Context.getIntWidth(CastTy); + if (Castee.getAsSymbol()) + return SVB.makeLocAsInteger(Castee.castAs(), BitWidth); + if (auto X = Castee.getAs()) + return SVB.makeIntVal(X->getValue()); + // FIXME other cases? + } + + return Base::VisitSymbolCast(Cast); + } SVal VisitSymIntExpr(const SymIntExpr *S) { auto I = Cached.find(S);