[PATCH] Add a truncation warning for values under a bitwise or

Sam Panzer espanz at gmail.com
Thu Feb 14 11:25:54 PST 2013


  Added the new test according to Dmitri's suggestion.

http://llvm-reviews.chandlerc.com/D405

CHANGE SINCE LAST DIFF
  http://llvm-reviews.chandlerc.com/D405?vs=975&id=983#toc

Files:
  lib/Sema/SemaChecking.cpp
  test/Sema/constant-conversion.c

Index: lib/Sema/SemaChecking.cpp
===================================================================
--- lib/Sema/SemaChecking.cpp
+++ lib/Sema/SemaChecking.cpp
@@ -4778,6 +4778,18 @@
   }
 }
 
+// Determine if E is a bitwise or expression with a constant on either side.
+static bool IsBitwiseOrWithConstant(Sema &S, llvm::APSInt &Value, Expr *E) {
+  E = E->IgnoreImpCasts();
+  if (const BinaryOperator *BO = dyn_cast<BinaryOperator>(E)) {
+    if (BO->getOpcode() != BO_Or)
+      return false;
+    return BO->getLHS()->isIntegerConstantExpr(Value, S.Context) ||
+      BO->getRHS()->isIntegerConstantExpr(Value, S.Context);
+  }
+  return false;
+}
+
 void CheckImplicitConversion(Sema &S, Expr *E, QualType T,
                              SourceLocation CC, bool *ICContext = 0) {
   if (E->isTypeDependent() || E->isValueDependent()) return;
@@ -4962,9 +4974,12 @@
 
   if (SourceRange.Width > TargetRange.Width) {
     // If the source is a constant, use a default-on diagnostic.
+    // Also use a default-on diagnostic if the source is bitwise-or'ed with
+    // a constant.
     // TODO: this should happen for bitfield stores, too.
     llvm::APSInt Value(32);
-    if (E->isIntegerConstantExpr(Value, S.Context)) {
+    if (E->isIntegerConstantExpr(Value, S.Context) ||
+        IsBitwiseOrWithConstant(S, Value, E)) {
       if (S.SourceMgr.isInSystemMacro(CC))
         return;
 
@@ -5114,6 +5129,19 @@
   if (E->getType() != T)
     CheckImplicitConversion(S, E, T, CC);
 
+  // For CompoundAssignmentOperators, check the conversion from the computed
+  // LHS type to the type of the assignee.
+  if (CompoundAssignOperator *CAO = dyn_cast<CompoundAssignOperator>(E)) {
+    QualType LHST = CAO->getComputationLHSType();
+    // This CheckImplicitConversion would trigger on NULLs, though their
+    // warnings should be trigger elsewhere. We filter those out here.
+    if (CAO->getOpcode() == BO_OrAssign && LHST != T &&
+        CAO->getRHS()->isNullPointerConstant(S.Context,
+                                             Expr::NPC_ValueDependentIsNotNull)
+        != Expr::NPCK_GNUNull)
+      CheckImplicitConversion(S, CAO->getRHS(), T, CC);
+  }
+
   // Now continue drilling into this expression.
 
   // Skip past explicit casts.
@@ -5128,7 +5156,7 @@
       return AnalyzeComparison(S, BO);
 
     // And with simple assignments.
-    if (BO->getOpcode() == BO_Assign)
+    if (BO->getOpcode() == BO_Assign || BO->getOpcode() == BO_OrAssign)
       return AnalyzeAssignment(S, BO);
   }
 
Index: test/Sema/constant-conversion.c
===================================================================
--- test/Sema/constant-conversion.c
+++ test/Sema/constant-conversion.c
@@ -66,17 +66,31 @@
 	struct {
 		unsigned int twoBits1:2;
 		unsigned int twoBits2:2;
-		unsigned int reserved:28;
+		unsigned int twoBits3:2;
+		unsigned int reserved:26;
 	} f;
 
 	f.twoBits1 = ~1; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -2 to 2}}
 	f.twoBits2 = ~2; // expected-warning {{implicit truncation from 'int' to bitfield changes value from -3 to 1}}
 	f.twoBits1 &= ~1; // no-warning
 	f.twoBits2 &= ~2; // no-warning
+	f.twoBits3 |= 4; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 4 to 0}}
+	f.twoBits3 |= 1; // no-warning
 }
 
 void test8() {
   enum E { A, B, C };
   struct { enum E x : 1; } f;
   f.x = C; // expected-warning {{implicit truncation from 'int' to bitfield changes value from 2 to 0}}
 }
+
+void test9() {
+  unsigned char x = 0;
+  unsigned char y = 0;
+	x = y | 0x1ff; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}}
+	x = y | 0xff; // no-warning
+	x = 0x1ff | y; // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}}
+	x = 0xff | y; // no-warning
+	x = (y | 0x1ff); // expected-warning {{implicit conversion from 'int' to 'unsigned char' changes value from 511 to 255}}
+	x = (y | 0xff); // no-warning
+}
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D405.3.patch
Type: text/x-patch
Size: 4030 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20130214/cd2d0def/attachment.bin>


More information about the cfe-commits mailing list