@@ -980,15 +980,19 @@ SVal SValBuilder::evalCastSubKind(nonloc::SymbolVal V, QualType CastTy,
980
980
} else {
981
981
// Symbol to integer, float.
982
982
QualType T = Context.getCanonicalType (SE->getType ());
983
- // If types are the same or both are integers, ignore the cast.
984
- // FIXME: Remove this hack when we support symbolic truncation/extension.
985
- // HACK: If both castTy and T are integers, ignore the cast. This is
986
- // not a permanent solution. Eventually we want to precisely handle
987
- // extension/truncation of symbolic integers. This prevents us from losing
988
- // precision when we assign 'x = y' and 'y' is symbolic and x and y are
989
- // different integer types.
990
- if (haveSameType (T, CastTy))
991
- return V;
983
+
984
+ // Produce SymbolCast if CastTy and T are different integers.
985
+ // NOTE: In the end the type of SymbolCast shall be equal to CastTy.
986
+ if (T->isIntegralOrEnumerationType () &&
987
+ CastTy->isIntegralOrEnumerationType ()) {
988
+ AnalyzerOptions &Opts =
989
+ StateMgr.getOwningEngine ().getAnalysisManager ().getAnalyzerOptions ();
990
+ // If appropriate option is disabled, ignore the cast.
991
+ // NOTE: ShouldSupportSymbolicIntegerCasts is `false` by default.
992
+ if (!Opts.ShouldSupportSymbolicIntegerCasts )
993
+ return V;
994
+ return simplifySymbolCast (V, CastTy);
995
+ }
992
996
if (!Loc::isLocType (CastTy))
993
997
if (!IsUnknownOriginalType || !CastTy->isFloatingType () ||
994
998
T->isFloatingType ())
@@ -1004,3 +1008,75 @@ SVal SValBuilder::evalCastSubKind(nonloc::PointerToMember V, QualType CastTy,
1004
1008
// Member pointer to whatever.
1005
1009
return V;
1006
1010
}
1011
+
1012
+ SVal clang::ento::SValBuilder::simplifySymbolCast (nonloc::SymbolVal V,
1013
+ QualType CastTy) {
1014
+ // We use seven conditions to recognize a simplification case.
1015
+ // For the clarity let `CastTy` be `C`, SE->getType() - `T`, root type - `R`,
1016
+ // prefix `u` for unsigned, `s` for signed, no prefix - any sign:
1017
+ // E.g. (char)(short)(uint x)
1018
+ // ( sC )( sT )( uR x)
1019
+ //
1020
+ // C === R (the same type)
1021
+ // (char)(char x) -> (char x)
1022
+ // (long)(long x) -> (long x)
1023
+ // Note: Comparisons operators below are for bit width.
1024
+ // C == T
1025
+ // (short)(short)(int x) -> (short)(int x)
1026
+ // (int)(long)(char x) -> (int)(char x) (sizeof(long) == sizeof(int))
1027
+ // (long)(ullong)(char x) -> (long)(char x) (sizeof(long) == sizeof(ullong))
1028
+ // C < T
1029
+ // (short)(int)(char x) -> (short)(char x)
1030
+ // (char)(int)(short x) -> (char)(short x)
1031
+ // (short)(int)(short x) -> (short x)
1032
+ // C > T > uR
1033
+ // (int)(short)(uchar x) -> (int)(uchar x)
1034
+ // (uint)(short)(uchar x) -> (uint)(uchar x)
1035
+ // (int)(ushort)(uchar x) -> (int)(uchar x)
1036
+ // C > sT > sR
1037
+ // (int)(short)(char x) -> (int)(char x)
1038
+ // (uint)(short)(char x) -> (uint)(char x)
1039
+ // C > sT == sR
1040
+ // (int)(char)(char x) -> (int)(char x)
1041
+ // (uint)(short)(short x) -> (uint)(short x)
1042
+ // C > uT == uR
1043
+ // (int)(uchar)(uchar x) -> (int)(uchar x)
1044
+ // (uint)(ushort)(ushort x) -> (uint)(ushort x)
1045
+ // (llong)(ulong)(uint x) -> (llong)(uint x) (sizeof(ulong) == sizeof(uint))
1046
+
1047
+ SymbolRef SE = V.getSymbol ();
1048
+ QualType T = Context.getCanonicalType (SE->getType ());
1049
+
1050
+ if (T == CastTy)
1051
+ return V;
1052
+
1053
+ if (!isa<SymbolCast>(SE))
1054
+ return makeNonLoc (SE, T, CastTy);
1055
+
1056
+ SymbolRef RootSym = cast<SymbolCast>(SE)->getOperand ();
1057
+ QualType RT = RootSym->getType ().getCanonicalType ();
1058
+
1059
+ BasicValueFactory &BVF = getBasicValueFactory ();
1060
+ APSIntType CTy = BVF.getAPSIntType (CastTy);
1061
+ APSIntType TTy = BVF.getAPSIntType (T);
1062
+
1063
+ const auto WC = CTy.getBitWidth ();
1064
+ const auto WT = TTy.getBitWidth ();
1065
+
1066
+ if (WC <= WT) {
1067
+ const bool isSameType = (RT == CastTy);
1068
+ if (isSameType)
1069
+ return nonloc::SymbolVal (RootSym);
1070
+ return makeNonLoc (RootSym, RT, CastTy);
1071
+ }
1072
+
1073
+ APSIntType RTy = BVF.getAPSIntType (RT);
1074
+ const auto WR = RTy.getBitWidth ();
1075
+ const bool UT = TTy.isUnsigned ();
1076
+ const bool UR = RTy.isUnsigned ();
1077
+
1078
+ if (((WT > WR) && (UR || !UT)) || ((WT == WR) && (UT == UR)))
1079
+ return makeNonLoc (RootSym, RT, CastTy);
1080
+
1081
+ return makeNonLoc (SE, T, CastTy);
1082
+ }
0 commit comments