32#include "llvm/ADT/APFloat.h"
40class ConversionChecker :
public Checker<check::PreStmt<ImplicitCastExpr>> {
45 mutable std::unique_ptr<BugType> BT;
53 const char Msg[])
const;
60 if (
Cast->getType()->isBooleanType())
64 if (
Cast->getExprLoc().isMacroID())
68 const ParentMap &PM =
C.getLocationContext()->getParentMap();
73 if (isa<ExplicitCastExpr>(
Parent))
76 bool LossOfSign =
false;
77 bool LossOfPrecision =
false;
80 if (
const auto *B = dyn_cast<BinaryOperator>(
Parent)) {
82 if (Opc == BO_Assign) {
83 if (!
Cast->IgnoreParenImpCasts()->isEvaluatable(
C.getASTContext())) {
84 LossOfSign = isLossOfSign(Cast,
C);
85 LossOfPrecision = isLossOfPrecision(Cast,
Cast->getType(),
C);
87 }
else if (Opc == BO_AddAssign || Opc == BO_SubAssign) {
89 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(),
C);
90 }
else if (Opc == BO_MulAssign) {
91 LossOfSign = isLossOfSign(Cast,
C);
92 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(),
C);
93 }
else if (Opc == BO_DivAssign || Opc == BO_RemAssign) {
94 LossOfSign = isLossOfSign(Cast,
C);
96 }
else if (Opc == BO_AndAssign) {
97 LossOfSign = isLossOfSign(Cast,
C);
99 }
else if (Opc == BO_OrAssign || Opc == BO_XorAssign) {
100 LossOfSign = isLossOfSign(Cast,
C);
101 LossOfPrecision = isLossOfPrecision(Cast, B->getLHS()->getType(),
C);
102 }
else if (B->isRelationalOp() || B->isMultiplicativeOp()) {
103 LossOfSign = isLossOfSign(Cast,
C);
105 }
else if (isa<DeclStmt, ReturnStmt>(
Parent)) {
106 if (!
Cast->IgnoreParenImpCasts()->isEvaluatable(
C.getASTContext())) {
107 LossOfSign = isLossOfSign(Cast,
C);
108 LossOfPrecision = isLossOfPrecision(Cast,
Cast->getType(),
C);
111 LossOfSign = isLossOfSign(Cast,
C);
112 LossOfPrecision = isLossOfPrecision(Cast,
Cast->getType(),
C);
115 if (LossOfSign || LossOfPrecision) {
121 reportBug(N, Cast,
C,
"Loss of sign in implicit conversion");
123 reportBug(N, Cast,
C,
"Loss of precision in implicit conversion");
130 BT.reset(
new BugType(
this,
"Conversion"));
133 auto R = std::make_unique<PathSensitiveBugReport>(*BT, Msg, N);
135 C.emitReport(std::move(R));
142 if (
Cast->isEvaluatable(
C.getASTContext()))
145 QualType SubType =
Cast->IgnoreParenImpCasts()->getType();
152 const auto &AC =
C.getASTContext();
156 unsigned RepresentsUntilExp;
159 const llvm::fltSemantics &
Sema = AC.getFloatTypeSemantics(DestType);
160 RepresentsUntilExp = llvm::APFloat::semanticsPrecision(
Sema);
162 RepresentsUntilExp = AC.getIntWidth(DestType);
163 if (RepresentsUntilExp == 1) {
168 RepresentsUntilExp--;
171 if (RepresentsUntilExp >=
sizeof(
unsigned long long) *
CHAR_BIT) {
176 unsigned CorrectedSrcWidth = AC.getIntWidth(SubType);
180 if (RepresentsUntilExp >= CorrectedSrcWidth) {
185 unsigned long long MaxVal = 1ULL << RepresentsUntilExp;
190 return C.isGreaterOrEqual(
Cast->getSubExpr(), MaxVal);
197 QualType SubType =
Cast->IgnoreParenImpCasts()->getType();
202 return C.isNegative(
Cast->getSubExpr());
209bool ento::shouldRegisterConversionChecker(
const CheckerManager &mgr) {
This represents one expression.
ImplicitCastExpr - Allows us to explicitly represent implicit type conversions, which have no direct ...
Stmt * getParent(Stmt *) const
A (possibly-)qualified type.
Sema - This implements semantic analysis and AST building for C.
Stmt - This represents one statement.
bool isSignedIntegerType() const
Return true if this is an integer type that is signed, according to C99 6.2.5p4 [char,...
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
bool isFloatingType() const
CHECKER * registerChecker(AT &&... Args)
Used to register checkers.
bool trackExpressionValue(const ExplodedNode *N, const Expr *E, PathSensitiveBugReport &R, TrackingOptions Opts={})
Attempts to add visitors to track expression value back to its point of origin.
bool Cast(InterpState &S, CodePtr OpPC)