32#include "llvm/ADT/APFloat.h"
40class ConversionChecker :
public Checker<check::PreStmt<ImplicitCastExpr>> {
45 const BugType BT{
this,
"Conversion"};
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 auto R = std::make_unique<PathSensitiveBugReport>(BT, Msg, N);
132 C.emitReport(std::move(R));
139 if (
Cast->isEvaluatable(
C.getASTContext()))
142 QualType SubType =
Cast->IgnoreParenImpCasts()->getType();
149 const auto &AC =
C.getASTContext();
153 unsigned RepresentsUntilExp;
156 const llvm::fltSemantics &
Sema = AC.getFloatTypeSemantics(DestType);
157 RepresentsUntilExp = llvm::APFloat::semanticsPrecision(
Sema);
159 RepresentsUntilExp = AC.getIntWidth(DestType);
160 if (RepresentsUntilExp == 1) {
165 RepresentsUntilExp--;
168 if (RepresentsUntilExp >=
sizeof(
unsigned long long) *
CHAR_BIT) {
173 unsigned CorrectedSrcWidth = AC.getIntWidth(SubType);
177 if (RepresentsUntilExp >= CorrectedSrcWidth) {
182 unsigned long long MaxVal = 1ULL << RepresentsUntilExp;
187 return C.isGreaterOrEqual(
Cast->getSubExpr(), MaxVal);
194 QualType SubType =
Cast->IgnoreParenImpCasts()->getType();
199 return C.isNegative(
Cast->getSubExpr());
206bool 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)
The JSON file list parser is used to communicate input to InstallAPI.