Hi,
I have a new check i'd like to get reviewed. It warns on dangerous long casts.
e.g
int a = 105000;
int b = 25000;
long l = a*b; // possible truncation before conversion from 'int' to 'long'
//Anders
Index: include/clang/Basic/DiagnosticSemaKinds.td
===================================================================
--- include/clang/Basic/DiagnosticSemaKinds.td (revision 221872)
+++ include/clang/Basic/DiagnosticSemaKinds.td (working copy)
@@ -2472,6 +2472,9 @@
def warn_impcast_integer_precision : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<Conversion>, DefaultIgnore;
+def warn_impcast_trunc : Warning<
+ "possible truncation before conversion from %0 to %1">,
+ InGroup<Conversion>, DefaultIgnore;
def warn_impcast_integer_64_32 : Warning<
"implicit conversion loses integer precision: %0 to %1">,
InGroup<Shorten64To32>, DefaultIgnore;
Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp (revision 221872)
+++ lib/Sema/SemaChecking.cpp (working copy)
@@ -6408,6 +6408,14 @@
return DiagnoseImpCast(S, E, T, CC, DiagID);
}
+ if (SourceRange.Width < TargetRange.Width) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E))
+ if (Bop->getOpcode() == BO_Mul || Bop->getOpcode() == BO_Shl)
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_trunc);
+ if (UnaryOperator *Uop = dyn_cast<UnaryOperator>(E))
+ if (Uop->getOpcode() == UO_Not)
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_trunc);
+ }
// Diagnose conversions between different enumeration types.
// In C, we pretend that the type of an EnumConstantDecl is its enumeration
// type, to give us better diagnostics.
@@ -6436,6 +6444,39 @@
return;
}
+void CheckExplicitConversion(Sema &S, Expr *E, QualType T,
+ SourceLocation CC, bool *ICContext = nullptr) {
+ if (E->isTypeDependent() || E->isValueDependent())
+ return;
+
+ if (CC.isInvalid())
+ return;
+
+ const Type *Source = S.Context.getCanonicalType(E->getType()).getTypePtr();
+ const Type *Target = S.Context.getCanonicalType(T).getTypePtr();
+
+ if (Source == Target)
+ return;
+
+ if (Target->isDependentType())
+ return;
+
+ if (!Source->isIntegerType() || !Target->isIntegerType())
+ return;
+
+ IntRange SourceRange = GetExprRange(S.Context, E);
+ IntRange TargetRange = IntRange::forTargetOfCanonicalType(S.Context, Target);
+
+ if (SourceRange.Width < TargetRange.Width) {
+ if (BinaryOperator *Bop = dyn_cast<BinaryOperator>(E))
+ if (Bop->getOpcode() == BO_Mul || Bop->getOpcode() == BO_Shl)
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_trunc);
+ if (UnaryOperator *Uop = dyn_cast<UnaryOperator>(E))
+ if (Uop->getOpcode() == UO_Not)
+ return DiagnoseImpCast(S, E, T, CC, diag::warn_impcast_trunc);
+ }
+}
+
void CheckConditionalOperator(Sema &S, ConditionalOperator *E,
SourceLocation CC, QualType T);
@@ -6518,6 +6559,11 @@
if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(E))
return AnalyzeImplicitConversions(S, OVE->getSourceExpr(), CC);
+ // Check explicit conversions for CStyle castings.
+ if (CStyleCastExpr *CStyleExpr = dyn_cast<CStyleCastExpr>(E)) {
+ CheckExplicitConversion(S, CStyleExpr->getSubExpr()->IgnoreParenImpCasts(), T, CC);
+ }
+
// Skip past explicit casts.
if (isa<ExplicitCastExpr>(E)) {
E = cast<ExplicitCastExpr>(E)->getSubExpr()->IgnoreParenImpCasts();
Index: test/Sema/conversion.c
===================================================================
--- test/Sema/conversion.c (revision 221872)
+++ test/Sema/conversion.c (working copy)
@@ -429,3 +429,13 @@
ushort16 crCbScale = pairedConstants.s4; // expected-warning {{implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to 'ushort16'}}
ushort16 brBias = pairedConstants.s6; // expected-warning {{implicit conversion loses integer precision: 'uint32_t' (aka 'unsigned int') to 'ushort16'}}
}
+
+void test28(int a, int b) {
+ long l = a * b; // expected-warning {{possible truncation before conversion from 'int' to 'long'}}
+ l = (long)a * b;
+}
+
+void test29(unsigned int n) {
+ long a = (long) (n << 8); // expected-warning {{possible truncation before conversion from 'unsigned int' to 'long'}}
+ a = (long) n << 8;
+}
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits