32 #include "llvm/ADT/APFloat.h" 36 using namespace clang;
40 class ConversionChecker :
public Checker<check::PreStmt<ImplicitCastExpr>> {
45 mutable std::unique_ptr<BuiltinBug> BT;
48 CheckerContext &C)
const;
52 void reportBug(ExplodedNode *N, CheckerContext &C,
const char Msg[])
const;
57 CheckerContext &C)
const {
68 const ParentMap &PM = C.getLocationContext()->getParentMap();
73 bool LossOfSign =
false;
74 bool LossOfPrecision =
false;
77 if (
const auto *B = dyn_cast<BinaryOperator>(Parent)) {
79 if (Opc == BO_Assign) {
80 LossOfSign = isLossOfSign(Cast, C);
81 LossOfPrecision = isLossOfPrecision(Cast, Cast->
getType(), C);
82 }
else if (Opc == BO_AddAssign || Opc == BO_SubAssign) {
84 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->
getType(), C);
85 }
else if (Opc == BO_MulAssign) {
86 LossOfSign = isLossOfSign(Cast, C);
87 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->
getType(), C);
88 }
else if (Opc == BO_DivAssign || Opc == BO_RemAssign) {
89 LossOfSign = isLossOfSign(Cast, C);
91 }
else if (Opc == BO_AndAssign) {
92 LossOfSign = isLossOfSign(Cast, C);
94 }
else if (Opc == BO_OrAssign || Opc == BO_XorAssign) {
95 LossOfSign = isLossOfSign(Cast, C);
96 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->
getType(), C);
97 }
else if (B->isRelationalOp() || B->isMultiplicativeOp()) {
98 LossOfSign = isLossOfSign(Cast, C);
100 }
else if (isa<DeclStmt>(Parent)) {
101 LossOfSign = isLossOfSign(Cast, C);
102 LossOfPrecision = isLossOfPrecision(Cast, Cast->
getType(), C);
105 if (LossOfSign || LossOfPrecision) {
107 ExplodedNode *N = C.generateNonFatalErrorNode(C.getState());
111 reportBug(N, C,
"Loss of sign in implicit conversion");
113 reportBug(N, C,
"Loss of precision in implicit conversion");
117 void ConversionChecker::reportBug(ExplodedNode *N, CheckerContext &C,
118 const char Msg[])
const {
121 new BuiltinBug(
this,
"Conversion",
"Possible loss of sign/precision."));
124 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
125 C.emitReport(std::move(R));
130 CheckerContext &C)
const {
142 const auto &AC = C.getASTContext();
146 unsigned RepresentsUntilExp;
149 const llvm::fltSemantics &
Sema = AC.getFloatTypeSemantics(DestType);
150 RepresentsUntilExp = llvm::APFloat::semanticsPrecision(Sema);
152 RepresentsUntilExp = AC.getIntWidth(DestType);
153 if (RepresentsUntilExp == 1) {
158 RepresentsUntilExp--;
161 if (RepresentsUntilExp >=
sizeof(
unsigned long long) *
CHAR_BIT) {
166 unsigned CorrectedSrcWidth = AC.getIntWidth(SubType);
170 if (RepresentsUntilExp >= CorrectedSrcWidth) {
175 unsigned long long MaxVal = 1ULL << RepresentsUntilExp;
180 return C.isGreaterOrEqual(Cast->
getSubExpr(), MaxVal);
185 CheckerContext &C)
const {
195 void ento::registerConversionChecker(CheckerManager &mgr) {
196 mgr.registerChecker<ConversionChecker>();
199 bool ento::shouldRegisterConversionChecker(
const LangOptions &LO) {
bool Cast(InterpState &S, CodePtr OpPC)
A (possibly-)qualified type.
Stmt - This represents one statement.
Stmt * getParent(Stmt *) const
bool isUnsignedIntegerType() const
Return true if this is an integer type that is unsigned, according to C99 6.2.5p6 [which returns true...
Keeps track of the various options that can be enabled, which controls the dialect of C or C++ that i...
Sema - This implements semantic analysis and AST building for C.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char, signed char, short, int, long..], or an enum decl which has a signed representation.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Dataflow Directional Tag Classes.
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isEvaluatable(const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects) const
isEvaluatable - Call EvaluateAsRValue to see if this expression can be constant folded without side-e...
bool isFloatingType() const