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; } 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(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/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/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/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/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 + +enum shiftof { + X = (1<<32) // expected-warning {{shift count >= width of type}} +}; + + + 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/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/SemaCXX/cxx2a-explicit-bool.cpp =================================================================== --- clang/test/SemaCXX/cxx2a-explicit-bool.cpp +++ clang/test/SemaCXX/cxx2a-explicit-bool.cpp @@ -21,7 +21,7 @@ template 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/SemaCXX/shift.cpp =================================================================== --- clang/test/SemaCXX/shift.cpp +++ clang/test/SemaCXX/shift.cpp @@ -22,7 +22,6 @@ 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@-1 {{implicit conversion}} c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} c = 1 << c; c <<= 0;