[clang] [clang] Emit bad shift warnings (PR #70307)

Budimir Aranđelović via cfe-commits cfe-commits at lists.llvm.org
Wed Jun 12 01:23:15 PDT 2024


https://github.com/budimirarandjelovicsyrmia updated https://github.com/llvm/llvm-project/pull/70307

>From 550bdebeb5ee3e305495407063a7d33c640a333c Mon Sep 17 00:00:00 2001
From: budimirarandjelovicsyrmia <budimir.arandjelovic at syrmia.com>
Date: Thu, 26 Oct 2023 10:39:52 +0200
Subject: [PATCH] [clang] Emit bad shift warnings

---
 clang/lib/AST/ExprConstant.cpp         |  7 +++++++
 clang/lib/Sema/SemaExpr.cpp            | 17 +++++++++++++----
 clang/test/AST/Interp/shifts.cpp       |  4 +---
 clang/test/C/drs/dr0xx.c               |  2 +-
 clang/test/Sema/shift-count-negative.c | 10 ++++++++++
 clang/test/Sema/shift-count-overflow.c |  7 +++++++
 clang/test/Sema/shift-negative-value.c | 10 ++++++++++
 clang/test/Sema/vla-2.c                |  6 ++++--
 clang/test/SemaCXX/shift.cpp           |  1 -
 9 files changed, 53 insertions(+), 11 deletions(-)
 create mode 100644 clang/test/Sema/shift-count-negative.c
 create mode 100644 clang/test/Sema/shift-count-overflow.c
 create mode 100644 clang/test/Sema/shift-negative-value.c

diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 78cfecbec9fd3..8b26ba30c2bbd 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -2816,6 +2816,9 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
       else if (LHS.countLeadingZeros() < SA)
         Info.CCEDiag(E, diag::note_constexpr_lshift_discards);
     }
+    if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
+        Info.getLangOpts().CPlusPlus)
+      return false;
     Result = LHS << SA;
     return true;
   }
@@ -2839,6 +2842,10 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
     if (SA != RHS)
       Info.CCEDiag(E, diag::note_constexpr_large_shift)
         << RHS << E->getType() << LHS.getBitWidth();
+
+    if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
+        Info.getLangOpts().CPlusPlus)
+      return false;
     Result = LHS >> SA;
     return true;
   }
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 94f52004cf6c2..70afced7a32e7 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -11446,7 +11446,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
   if (Right.isNegative()) {
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_negative)
-                            << RHS.get()->getSourceRange());
+                              << RHS.get()->getSourceRange());
     return;
   }
 
@@ -11462,7 +11462,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
   if (Right.uge(LeftBits)) {
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_gt_typewidth)
-                            << RHS.get()->getSourceRange());
+                              << RHS.get()->getSourceRange());
     return;
   }
 
@@ -11495,7 +11495,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
   if (Left.isNegative()) {
     S.DiagRuntimeBehavior(Loc, LHS.get(),
                           S.PDiag(diag::warn_shift_lhs_negative)
-                            << LHS.get()->getSourceRange());
+                              << LHS.get()->getSourceRange());
     return;
   }
 
@@ -17322,11 +17322,20 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
   // Circumvent ICE checking in C++11 to avoid evaluating the expression twice
   // in the non-ICE case.
   if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
+    SmallVector<PartialDiagnosticAt, 8> Notes;
     if (Result)
-      *Result = E->EvaluateKnownConstIntCheckOverflow(Context);
+      *Result = E->EvaluateKnownConstIntCheckOverflow(Context, &Notes);
     if (!isa<ConstantExpr>(E))
       E = Result ? ConstantExpr::Create(Context, E, APValue(*Result))
                  : ConstantExpr::Create(Context, E);
+
+    if (Notes.size() && !Diagnoser.Suppress) {
+      Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange();
+      for (const PartialDiagnosticAt &Note : Notes)
+        Diag(Note.first, Note.second);
+      return ExprError();
+    }
+
     return E;
   }
 
diff --git a/clang/test/AST/Interp/shifts.cpp b/clang/test/AST/Interp/shifts.cpp
index b1df7b85cc9f2..b2b2cb60f4a61 100644
--- a/clang/test/AST/Interp/shifts.cpp
+++ b/clang/test/AST/Interp/shifts.cpp
@@ -33,9 +33,7 @@ namespace shifts {
                            // FIXME: 'implicit conversion' warning missing in the new interpreter. \
                            // cxx17-warning {{shift count >= width of type}} \
                            // ref-warning {{shift count >= width of type}} \
-                           // ref-warning {{implicit conversion}} \
-                           // ref-cxx17-warning {{shift count >= width of type}} \
-                           // ref-cxx17-warning {{implicit conversion}}
+                           // ref-cxx17-warning {{shift count >= width of type}}
     c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} \
                            // cxx17-warning {{shift count >= width of type}} \
                            // ref-warning {{shift count >= width of type}} \
diff --git a/clang/test/C/drs/dr0xx.c b/clang/test/C/drs/dr0xx.c
index 6a3717f0729b6..6611b2b65264f 100644
--- a/clang/test/C/drs/dr0xx.c
+++ b/clang/test/C/drs/dr0xx.c
@@ -426,7 +426,7 @@ void dr081(void) {
   /* Demonstrate that we don't crash when left shifting a signed value; that's
    * implementation defined behavior.
    */
- _Static_assert(-1 << 1 == -2, "fail"); /* Didn't shift a zero into the "sign bit". */
+ _Static_assert(-1 << 1 == -2, "fail"); /* Undefined behavior since C99 */
  _Static_assert(1 << 3 == 1u << 3u, "fail"); /* Shift of a positive signed value does sensible things. */
 }
 
diff --git a/clang/test/Sema/shift-count-negative.c b/clang/test/Sema/shift-count-negative.c
new file mode 100644
index 0000000000000..34d51294b43d4
--- /dev/null
+++ b/clang/test/Sema/shift-count-negative.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wshift-count-negative %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wall %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wshift-count-negative %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wall %s
+
+enum shiftof {
+    X = (1<<-29) // c-error {{expression is not an integer constant expression}}
+                 // cpp-error at -1 {{expression is not an integral constant expression}}
+                 // expected-note at -2 {{negative shift count -29}}
+};
diff --git a/clang/test/Sema/shift-count-overflow.c b/clang/test/Sema/shift-count-overflow.c
new file mode 100644
index 0000000000000..77dd4b3c6a401
--- /dev/null
+++ b/clang/test/Sema/shift-count-overflow.c
@@ -0,0 +1,7 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wshift-count-overflow %s
+// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
+
+enum shiftof {
+    X = (1<<32) // expected-error {{expression is not an integer constant expression}}
+                // expected-note at -1 {{shift count 32 >= width of type 'int'}}
+};
diff --git a/clang/test/Sema/shift-negative-value.c b/clang/test/Sema/shift-negative-value.c
new file mode 100644
index 0000000000000..0394c00e00d0f
--- /dev/null
+++ b/clang/test/Sema/shift-negative-value.c
@@ -0,0 +1,10 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wshift-negative-value %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wall %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wshift-negative-value %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wall %s
+
+enum shiftof {
+    X = (-1<<29) // c-error {{expression is not an integer constant expression}}
+                 // cpp-error at -1 {{expression is not an integral constant expression}}
+                 // expected-note at -2 {{left shift of negative value -1}}
+};
diff --git a/clang/test/Sema/vla-2.c b/clang/test/Sema/vla-2.c
index 316931f270607..577407e15b479 100644
--- a/clang/test/Sema/vla-2.c
+++ b/clang/test/Sema/vla-2.c
@@ -4,11 +4,13 @@
 // a different codepath when we have already emitted an error.)
 
 int PotentiallyEvaluatedSizeofWarn(int n) {
-  return (int)sizeof *(0 << 32,(int(*)[n])0); // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}}
+  return (int)sizeof *(0 << 32,(int(*)[n])0); /* expected-warning {{shift count >= width of type}}
+                                                 expected-warning {{left operand of comma operator has no effect}} */
 }
 
 void PotentiallyEvaluatedTypeofWarn(int n) {
-  __typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}}
+  __typeof(*(0 << 32,(int(*)[n])0)) x; /* expected-warning {{shift count >= width of type}}
+                                          expected-warning {{left operand of comma operator has no effect}} */
   (void)x;
 }
 
diff --git a/clang/test/SemaCXX/shift.cpp b/clang/test/SemaCXX/shift.cpp
index 89a98791d3eba..c3249b124e926 100644
--- a/clang/test/SemaCXX/shift.cpp
+++ b/clang/test/SemaCXX/shift.cpp
@@ -22,7 +22,6 @@ void test() {
   c = 1 << -1; // expected-warning {{shift count is negative}}
   c = 1 >> -1; // expected-warning {{shift count is negative}}
   c = 1 << (unsigned)-1; // expected-warning {{shift count >= width of type}}
-                         // expected-warning at -1 {{implicit conversion}}
   c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}}
   c = 1 << c;
   c <<= 0;



More information about the cfe-commits mailing list