summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
diff options
context:
space:
mode:
authorPierre Gousseau <pierregousseau14@gmail.com>2016-01-12 10:07:56 +0000
committerPierre Gousseau <pierregousseau14@gmail.com>2016-01-12 10:07:56 +0000
commite961b445ada499e233b8dbca58065d1372c32e88 (patch)
tree0f3fd22843dfe3696b1913f975f5409a9b7bf17f /clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
parentea8e8e9f97b22e6490898f495f24fd979b677dd0 (diff)
downloadbcm5719-llvm-e961b445ada499e233b8dbca58065d1372c32e88.tar.gz
bcm5719-llvm-e961b445ada499e233b8dbca58065d1372c32e88.zip
[analyzer] Evaluate integral casts as cast symbols if truncations are detected.
The current workaround for truncations not being modelled is that the evaluation of integer to integer casts are simply bypassed and so the original symbol is used as the new casted symbol (cf SimpleSValBuilder::evalCastFromNonLoc). This lead to the issue described in PR25078, as the RangeConstraintManager associates ranges with symbols. The new evalIntegralCast method added by this patch wont bypass the cast if it finds the range of the symbol to be greater than the maximum value of the target type. The fix to RangeSet::pin mentioned in the initial review will be committed separately. Differential Revision: http://reviews.llvm.org/D12901 llvm-svn: 257464
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/SValBuilder.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/SValBuilder.cpp39
1 files changed, 39 insertions, 0 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
index cdae04068e1..d74e3539510 100644
--- a/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
+++ b/clang/lib/StaticAnalyzer/Core/SValBuilder.cpp
@@ -423,6 +423,45 @@ static bool shouldBeModeledWithNoOp(ASTContext &Context, QualType ToTy,
return true;
}
+// Handles casts of type CK_IntegralCast.
+// At the moment, this function will redirect to evalCast, except when the range
+// of the original value is known to be greater than the max of the target type.
+SVal SValBuilder::evalIntegralCast(ProgramStateRef state, SVal val,
+ QualType castTy, QualType originalTy) {
+
+ // No truncations if target type is big enough.
+ if (getContext().getTypeSize(castTy) >= getContext().getTypeSize(originalTy))
+ return evalCast(val, castTy, originalTy);
+
+ const SymExpr *se = val.getAsSymbolicExpression();
+ if (!se) // Let evalCast handle non symbolic expressions.
+ return evalCast(val, castTy, originalTy);
+
+ // Find the maximum value of the target type.
+ APSIntType ToType(getContext().getTypeSize(castTy),
+ castTy->isUnsignedIntegerType());
+ llvm::APSInt ToTypeMax = ToType.getMaxValue();
+ NonLoc ToTypeMaxVal =
+ makeIntVal(ToTypeMax.isUnsigned() ? ToTypeMax.getZExtValue()
+ : ToTypeMax.getSExtValue(),
+ castTy)
+ .castAs<NonLoc>();
+ // Check the range of the symbol being casted against the maximum value of the
+ // target type.
+ NonLoc FromVal = val.castAs<NonLoc>();
+ QualType CmpTy = getConditionType();
+ NonLoc CompVal =
+ evalBinOpNN(state, BO_LT, FromVal, ToTypeMaxVal, CmpTy).castAs<NonLoc>();
+ ProgramStateRef IsNotTruncated, IsTruncated;
+ std::tie(IsNotTruncated, IsTruncated) = state->assume(CompVal);
+ if (!IsNotTruncated && IsTruncated) {
+ // Symbol is truncated so we evaluate it as a cast.
+ NonLoc CastVal = makeNonLoc(se, originalTy, castTy);
+ return CastVal;
+ }
+ return evalCast(val, castTy, originalTy);
+}
+
// FIXME: should rewrite according to the cast kind.
SVal SValBuilder::evalCast(SVal val, QualType castTy, QualType originalTy) {
castTy = Context.getCanonicalType(castTy);
OpenPOWER on IntegriCloud