chestnykh updated this revision to Diff 487174.
chestnykh retitled this revision from "[Clang] Add warnings on bad shifts 
inside enums." to "[Clang] Fix warnings on bad shifts.".

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141192/new/

https://reviews.llvm.org/D141192

Files:
  clang/lib/AST/ExprConstant.cpp
  clang/lib/Sema/SemaExpr.cpp
  clang/test/AST/Interp/shifts.cpp
  clang/test/C/drs/dr0xx.c
  clang/test/Sema/shift-count-negative.c
  clang/test/Sema/shift-count-overflow.c
  clang/test/Sema/shift-negative-value.c
  clang/test/Sema/vla-2.c
  clang/test/SemaCXX/cxx2a-explicit-bool.cpp

Index: clang/test/SemaCXX/cxx2a-explicit-bool.cpp
===================================================================
--- clang/test/SemaCXX/cxx2a-explicit-bool.cpp
+++ clang/test/SemaCXX/cxx2a-explicit-bool.cpp
@@ -21,7 +21,7 @@
 template<int a>
 struct A {
 // expected-note@-1+ {{candidate constructor}}
-  explicit(1 << a)
+  explicit(1 << a) // expected-warning {{shift count is negative}}
 // expected-note@-1 {{negative shift count -1}}
 // expected-error@-2 {{explicit specifier argument is not a constant expression}}
   A(int);
Index: clang/test/Sema/vla-2.c
===================================================================
--- clang/test/Sema/vla-2.c
+++ clang/test/Sema/vla-2.c
@@ -4,14 +4,17 @@
 // 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;
 }
 
 void PotentiallyEvaluatedArrayBoundWarn(int n) {
-  (void)*(int(*)[(0 << 32,n)])0; // expected-warning {{left operand of comma operator has no effect}}
+  (void)*(int(*)[(0 << 32,n)])0; /* expected-warning {{shift count >= width of type}}
+                                    expected-warning {{left operand of comma operator has no effect}} */
 }
Index: clang/test/Sema/shift-negative-value.c
===================================================================
--- /dev/null
+++ clang/test/Sema/shift-negative-value.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wshift-negative-value %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wshift-negative-value %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
+
+enum shiftof {
+    X = (-1<<29) //expected-warning {{shifting a negative signed value is undefined}}
+};
+
Index: clang/test/Sema/shift-count-overflow.c
===================================================================
--- /dev/null
+++ clang/test/Sema/shift-count-overflow.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wshift-count-overflow %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wshift-count-overflow %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
+
+enum shiftof {
+    X = (1<<32) //expected-warning {{shift count >= width of type}}
+};
+
Index: clang/test/Sema/shift-count-negative.c
===================================================================
--- /dev/null
+++ clang/test/Sema/shift-count-negative.c
@@ -0,0 +1,9 @@
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wshift-count-negative %s
+// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wshift-count-negative %s
+// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
+
+enum shiftof {
+    X = (1<<-29) //expected-warning {{shift count is negative}}
+};
+
Index: clang/test/C/drs/dr0xx.c
===================================================================
--- clang/test/C/drs/dr0xx.c
+++ clang/test/C/drs/dr0xx.c
@@ -426,7 +426,7 @@
   /* 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");  /* expected-warning {{shifting a negative signed value is undefined}} */
  _Static_assert(1 << 3 == 1u << 3u, "fail"); /* Shift of a positive signed value does sensible things. */
 }
 
Index: clang/test/AST/Interp/shifts.cpp
===================================================================
--- clang/test/AST/Interp/shifts.cpp
+++ clang/test/AST/Interp/shifts.cpp
@@ -33,9 +33,7 @@
                            // 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}} \
Index: clang/lib/Sema/SemaExpr.cpp
===================================================================
--- clang/lib/Sema/SemaExpr.cpp
+++ clang/lib/Sema/SemaExpr.cpp
@@ -11659,26 +11659,35 @@
   return false;
 }
 
-static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
-                                   SourceLocation Loc, BinaryOperatorKind Opc,
-                                   QualType LHSType) {
+enum BadShiftValueKind {
+  BSV_Ok,
+  BSV_ShiftIsNegative,
+  BSV_ShiftLHSIsNegative,
+  BSV_ShiftSizeGTTypeWidth,
+};
+
+static BadShiftValueKind DiagnoseBadShiftValues(Sema &S, ExprResult &LHS,
+                                                ExprResult &RHS,
+                                                SourceLocation Loc,
+                                                BinaryOperatorKind Opc,
+                                                QualType LHSType) {
   // OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
   // so skip remaining warnings as we don't want to modify values within Sema.
   if (S.getLangOpts().OpenCL)
-    return;
+    return BSV_Ok;
 
   // Check right/shifter operand
   Expr::EvalResult RHSResult;
   if (RHS.get()->isValueDependent() ||
       !RHS.get()->EvaluateAsInt(RHSResult, S.Context))
-    return;
+    return BSV_Ok;
   llvm::APSInt Right = RHSResult.Val.getInt();
 
   if (Right.isNegative()) {
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_negative)
                             << RHS.get()->getSourceRange());
-    return;
+    return BSV_ShiftIsNegative;
   }
 
   QualType LHSExprType = LHS.get()->getType();
@@ -11694,12 +11703,12 @@
     S.DiagRuntimeBehavior(Loc, RHS.get(),
                           S.PDiag(diag::warn_shift_gt_typewidth)
                             << RHS.get()->getSourceRange());
-    return;
+    return BSV_ShiftSizeGTTypeWidth;
   }
 
   // FIXME: We probably need to handle fixed point types specially here.
   if (Opc != BO_Shl || LHSExprType->isFixedPointType())
-    return;
+    return BSV_Ok;
 
   // When left shifting an ICE which is signed, we can check for overflow which
   // according to C++ standards prior to C++2a has undefined behavior
@@ -11711,7 +11720,7 @@
   if (LHS.get()->isValueDependent() ||
       LHSType->hasUnsignedIntegerRepresentation() ||
       !LHS.get()->EvaluateAsInt(LHSResult, S.Context))
-    return;
+    return BSV_Ok;
   llvm::APSInt Left = LHSResult.Val.getInt();
 
   // Don't warn if signed overflow is defined, then all the rest of the
@@ -11719,7 +11728,7 @@
   // Also don't warn in C++20 mode (and newer), as signed left shifts
   // always wrap and never overflow.
   if (S.getLangOpts().isSignedOverflowDefined() || S.getLangOpts().CPlusPlus20)
-    return;
+    return BSV_Ok;
 
   // If LHS does not have a non-negative value then, the
   // behavior is undefined before C++2a. Warn about it.
@@ -11727,13 +11736,13 @@
     S.DiagRuntimeBehavior(Loc, LHS.get(),
                           S.PDiag(diag::warn_shift_lhs_negative)
                             << LHS.get()->getSourceRange());
-    return;
+    return BSV_ShiftLHSIsNegative;
   }
 
   llvm::APInt ResultBits =
       static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
   if (LeftBits.uge(ResultBits))
-    return;
+    return BSV_Ok;
   llvm::APSInt Result = Left.extend(ResultBits.getLimitedValue());
   Result = Result.shl(Right);
 
@@ -11750,13 +11759,17 @@
     S.Diag(Loc, diag::warn_shift_result_sets_sign_bit)
         << HexResult << LHSType
         << LHS.get()->getSourceRange() << RHS.get()->getSourceRange();
-    return;
+
+    // We return BSV_Ok because we already done diag.
+    return BSV_Ok;
   }
 
   S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
     << HexResult.str() << Result.getMinSignedBits() << LHSType
     << Left.getBitWidth() << LHS.get()->getSourceRange()
     << RHS.get()->getSourceRange();
+
+  return BSV_Ok;
 }
 
 /// Return the resulting type when a vector is shifted
@@ -12004,7 +12017,27 @@
       isScopedEnumerationType(RHSType)) {
     return InvalidOperands(Loc, LHS, RHS);
   }
-  DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType);
+
+  BadShiftValueKind BSVKind =
+      DiagnoseBadShiftValues(*this, LHS, RHS, Loc, Opc, LHSType);
+  ExpressionEvaluationContext Context = ExprEvalContexts.back().Context;
+  if (Context == ExpressionEvaluationContext::ConstantEvaluated ||
+      Context == ExpressionEvaluationContext::ImmediateFunctionContext) {
+    switch (BSVKind) {
+    case BSV_ShiftSizeGTTypeWidth:
+      if (!getLangOpts().CPlusPlus11)
+        Diag(Loc, diag::warn_shift_gt_typewidth) << RHS.get()->getSourceRange();
+      break;
+    case BSV_ShiftIsNegative:
+      Diag(Loc, diag::warn_shift_negative) << RHS.get()->getSourceRange();
+      break;
+    case BSV_ShiftLHSIsNegative:
+      Diag(Loc, diag::warn_shift_lhs_negative) << RHS.get()->getSourceRange();
+      break;
+    default:
+      break;
+    }
+  }
 
   // "The type of the result is that of the promoted left operand."
   return LHSType;
Index: clang/lib/AST/ExprConstant.cpp
===================================================================
--- clang/lib/AST/ExprConstant.cpp
+++ clang/lib/AST/ExprConstant.cpp
@@ -2799,8 +2799,11 @@
     // the shifted type.
     unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
     if (SA != RHS) {
-      Info.CCEDiag(E, diag::note_constexpr_large_shift)
-        << RHS << E->getType() << LHS.getBitWidth();
+      if (Info.getLangOpts().CPlusPlus11) {
+        Info.CCEDiag(E, diag::note_constexpr_large_shift)
+            << RHS << E->getType() << LHS.getBitWidth();
+        return false;
+      }
     } else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus20) {
       // C++11 [expr.shift]p2: A signed left shift must have a non-negative
       // operand, and must not overflow the corresponding unsigned type.
@@ -2831,9 +2834,13 @@
     // C++11 [expr.shift]p1: Shift width must be less than the bit width of the
     // shifted type.
     unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
-    if (SA != RHS)
-      Info.CCEDiag(E, diag::note_constexpr_large_shift)
-        << RHS << E->getType() << LHS.getBitWidth();
+    if (SA != RHS) {
+      if (Info.getLangOpts().CPlusPlus11) {
+        Info.CCEDiag(E, diag::note_constexpr_large_shift)
+            << RHS << E->getType() << LHS.getBitWidth();
+        return false;
+      }
+    }
     Result = LHS >> SA;
     return true;
   }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to