[PATCH] D18654: In C++11 it is undefined to shift into the sign bit

Filipe Cabecinhas via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 31 10:14:20 PDT 2016


filcab created this revision.
filcab added reviewers: rsmith, samsonov.
filcab added a subscriber: cfe-commits.

Clang was using C++14 rules for shifts into the sign bit with any C++
standard. Now it has the C++ <14 special case (same as C).

Using this C++11 standard draft as reference (before CWG 1457):
https://github.com/cplusplus/draft/blob/672675e01528fba6ca02f5340eee747566ebdca8/papers/N3376.pdf

http://reviews.llvm.org/D18654

Files:
  lib/CodeGen/CGExprScalar.cpp
  test/CodeGen/cxx-signed-shift-overflow.cpp
  test/CodeGenCXX/catch-undef-behavior.cpp

Index: test/CodeGenCXX/catch-undef-behavior.cpp
===================================================================
--- test/CodeGenCXX/catch-undef-behavior.cpp
+++ test/CodeGenCXX/catch-undef-behavior.cpp
@@ -137,11 +137,7 @@
   // CHECK-NEXT: %[[SHIFTED_OUT_WIDTH:.*]] = sub nuw nsw i32 31, %[[RHS]]
   // CHECK-NEXT: %[[SHIFTED_OUT:.*]] = lshr i32 %[[LHS:.*]], %[[SHIFTED_OUT_WIDTH]]
 
-  // This is present for C++11 but not for C: C++ core issue 1457 allows a '1'
-  // to be shifted into the sign bit, but not out of it.
-  // CHECK-NEXT: %[[SHIFTED_OUT_NOT_SIGN:.*]] = lshr i32 %[[SHIFTED_OUT]], 1
-
-  // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT_NOT_SIGN]], 0
+  // CHECK-NEXT: %[[NO_OVERFLOW:.*]] = icmp eq i32 %[[SHIFTED_OUT]], 0
   // CHECK-NEXT: br label %[[CONT_BB]]
 
   // CHECK:      [[CONT_BB]]:
Index: test/CodeGen/cxx-signed-shift-overflow.cpp
===================================================================
--- /dev/null
+++ test/CodeGen/cxx-signed-shift-overflow.cpp
@@ -0,0 +1,13 @@
+// RUN: %clang_cc1 -std=c++11 -triple x86_64-apple-darwin10 -fsanitize=shift-base %s -emit-llvm -o - | FileCheck %s -check-prefix=CXX11 -check-prefix=BOTH
+// RUN: %clang_cc1 -std=c++14 -triple x86_64-apple-darwin10 -fsanitize=shift-base %s -emit-llvm -o - | FileCheck %s -check-prefix=CXX14 -check-prefix=BOTH
+
+int shiftoverflow(int b, int e) {
+  // BOTH-LABEL: shiftoverflow
+  // CXX14-LABEL: check:
+  // CXX14: %shl.check = lshr
+  // CXX14: lshr i{{[^ ]*}} %shl.check, 1
+  // CXX11-LABEL: check:
+  // CXX11: %shl.check = lshr
+  // CXX11-NOT: lshr i{{[^ ]*}} %shl.check, 1
+  return b << e;
+}
Index: lib/CodeGen/CGExprScalar.cpp
===================================================================
--- lib/CodeGen/CGExprScalar.cpp
+++ lib/CodeGen/CGExprScalar.cpp
@@ -2746,11 +2746,12 @@
                            Builder.CreateSub(WidthMinusOne, RHS, "shl.zeros",
                                              /*NUW*/true, /*NSW*/true),
                            "shl.check");
-      if (CGF.getLangOpts().CPlusPlus) {
-        // In C99, we are not permitted to shift a 1 bit into the sign bit.
-        // Under C++11's rules, shifting a 1 bit into the sign bit is
-        // OK, but shifting a 1 bit out of it is not. (C89 and C++03 don't
-        // define signed left shifts, so we use the C99 and C++11 rules there).
+      if (CGF.getLangOpts().CPlusPlus && CGF.getLangOpts().CPlusPlus14) {
+        // In C99 and C++11, we are not permitted to shift a 1 bit into the sign
+        // bit.
+        // Under C++14's rules, shifting a 1 bit into the sign bit is OK, but
+        // shifting a 1 bit out of it is not. (C89 and C++03 don't define signed
+        // left shifts, so we use the C99 and C++11 rules there).
         llvm::Value *One = llvm::ConstantInt::get(BitsShiftedOff->getType(), 1);
         BitsShiftedOff = Builder.CreateLShr(BitsShiftedOff, One);
       }


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D18654.52233.patch
Type: text/x-patch
Size: 2930 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160331/48ccab12/attachment.bin>


More information about the cfe-commits mailing list