Skip to content

Commit c9b85c8

Browse files
[clang] Emit bad shift warnings
1 parent 6daa983 commit c9b85c8

File tree

10 files changed

+52
-23
lines changed

10 files changed

+52
-23
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2803,9 +2803,10 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
28032803
// C++11 [expr.shift]p1: Shift width must be less than the bit width of
28042804
// the shifted type.
28052805
unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
2806-
if (SA != RHS) {
2806+
if (SA != RHS && Info.getLangOpts().CPlusPlus11) {
28072807
Info.CCEDiag(E, diag::note_constexpr_large_shift)
2808-
<< RHS << E->getType() << LHS.getBitWidth();
2808+
<< RHS << E->getType() << LHS.getBitWidth();
2809+
return false;
28092810
} else if (LHS.isSigned() && !Info.getLangOpts().CPlusPlus20) {
28102811
// C++11 [expr.shift]p2: A signed left shift must have a non-negative
28112812
// operand, and must not overflow the corresponding unsigned type.
@@ -2836,9 +2837,11 @@ static bool handleIntIntBinOp(EvalInfo &Info, const Expr *E, const APSInt &LHS,
28362837
// C++11 [expr.shift]p1: Shift width must be less than the bit width of the
28372838
// shifted type.
28382839
unsigned SA = (unsigned) RHS.getLimitedValue(LHS.getBitWidth()-1);
2839-
if (SA != RHS)
2840+
if (SA != RHS && Info.getLangOpts().CPlusPlus11) {
28402841
Info.CCEDiag(E, diag::note_constexpr_large_shift)
2841-
<< RHS << E->getType() << LHS.getBitWidth();
2842+
<< RHS << E->getType() << LHS.getBitWidth();
2843+
return false;
2844+
}
28422845
Result = LHS >> SA;
28432846
return true;
28442847
}

clang/lib/Sema/SemaExpr.cpp

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11428,7 +11428,7 @@ static bool isScopedEnumerationType(QualType T) {
1142811428
return false;
1142911429
}
1143011430

11431-
static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
11431+
static void DiagnoseBadShiftValues(Sema &S, ExprResult &LHS, ExprResult &RHS,
1143211432
SourceLocation Loc, BinaryOperatorKind Opc,
1143311433
QualType LHSType) {
1143411434
// OpenCL 6.3j: shift values are effectively % word size of LHS (more defined),
@@ -11460,9 +11460,11 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1146011460
}
1146111461
llvm::APInt LeftBits(Right.getBitWidth(), LeftSize);
1146211462
if (Right.uge(LeftBits)) {
11463-
S.DiagRuntimeBehavior(Loc, RHS.get(),
11464-
S.PDiag(diag::warn_shift_gt_typewidth)
11465-
<< RHS.get()->getSourceRange());
11463+
if (!S.getLangOpts().CPlusPlus11) {
11464+
S.DiagRuntimeBehavior(Loc, RHS.get(),
11465+
S.PDiag(diag::warn_shift_gt_typewidth)
11466+
<< RHS.get()->getSourceRange());
11467+
}
1146611468
return;
1146711469
}
1146811470

@@ -11523,9 +11525,9 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1152311525
}
1152411526

1152511527
S.Diag(Loc, diag::warn_shift_result_gt_typewidth)
11526-
<< HexResult.str() << Result.getMinSignedBits() << LHSType
11527-
<< Left.getBitWidth() << LHS.get()->getSourceRange()
11528-
<< RHS.get()->getSourceRange();
11528+
<< HexResult.str() << Result.getMinSignedBits() << LHSType
11529+
<< Left.getBitWidth() << LHS.get()->getSourceRange()
11530+
<< RHS.get()->getSourceRange();
1152911531
}
1153011532

1153111533
/// Return the resulting type when a vector is shifted
@@ -19959,7 +19961,10 @@ bool Sema::DiagRuntimeBehavior(SourceLocation Loc, ArrayRef<const Stmt*> Stmts,
1995919961
case ExpressionEvaluationContext::ConstantEvaluated:
1996019962
case ExpressionEvaluationContext::ImmediateFunctionContext:
1996119963
// Relevant diagnostics should be produced by constant evaluation.
19962-
break;
19964+
19965+
// Solution below works for warnings detected in
19966+
// Sema::DiagnoseBadShiftValues()
19967+
return DiagIfReachable(Loc, Stmts, PD);
1996319968

1996419969
case ExpressionEvaluationContext::PotentiallyEvaluated:
1996519970
case ExpressionEvaluationContext::PotentiallyEvaluatedIfUsed:

clang/test/AST/Interp/shifts.cpp

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,10 @@ namespace shifts {
3333
// FIXME: 'implicit conversion' warning missing in the new interpreter. \
3434
// cxx17-warning {{shift count >= width of type}} \
3535
// ref-warning {{shift count >= width of type}} \
36-
// ref-warning {{implicit conversion}} \
37-
// ref-cxx17-warning {{shift count >= width of type}} \
38-
// ref-cxx17-warning {{implicit conversion}}
36+
// ref-cxx17-warning {{shift count >= width of type}}
3937
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}} \
4038
// cxx17-warning {{shift count >= width of type}} \
41-
// ref-warning {{shift count >= width of type}} \
42-
// ref-cxx17-warning {{shift count >= width of type}}
39+
// ref-warning {{shift count >= width of type}}
4340
c = 1 << c;
4441
c <<= 0;
4542
c >>= 0;

clang/test/C/drs/dr0xx.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ void dr081(void) {
426426
/* Demonstrate that we don't crash when left shifting a signed value; that's
427427
* implementation defined behavior.
428428
*/
429-
_Static_assert(-1 << 1 == -2, "fail"); /* Didn't shift a zero into the "sign bit". */
429+
_Static_assert(-1 << 1 == -2, "fail"); /* expected-warning {{shifting a negative signed value is undefined}} */
430430
_Static_assert(1 << 3 == 1u << 3u, "fail"); /* Shift of a positive signed value does sensible things. */
431431
}
432432

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wshift-count-negative %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
3+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wshift-count-negative %s
4+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
5+
6+
enum shiftof {
7+
X = (1<<-29) //expected-warning {{shift count is negative}}
8+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// RUN: %clang_cc1 -fsyntax-only -verify -Wshift-count-overflow %s
2+
// RUN: %clang_cc1 -fsyntax-only -verify -Wall %s
3+
4+
enum shiftof {
5+
X = (1<<32) // expected-warning {{shift count >= width of type}}
6+
};
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wshift-negative-value %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only -verify -Wall %s
3+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wshift-negative-value %s
4+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify -Wall %s
5+
6+
enum shiftof {
7+
X = (-1<<29) //expected-warning {{shifting a negative signed value is undefined}}
8+
};

clang/test/Sema/vla-2.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,17 @@
44
// a different codepath when we have already emitted an error.)
55

66
int PotentiallyEvaluatedSizeofWarn(int n) {
7-
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}}
7+
return (int)sizeof *(0 << 32,(int(*)[n])0); /* expected-warning {{shift count >= width of type}}
8+
expected-warning {{left operand of comma operator has no effect}} */
89
}
910

1011
void PotentiallyEvaluatedTypeofWarn(int n) {
11-
__typeof(*(0 << 32,(int(*)[n])0)) x; // expected-warning {{left operand of comma operator has no effect}} expected-warning {{shift count >= width of type}}
12+
__typeof(*(0 << 32,(int(*)[n])0)) x; /* expected-warning {{shift count >= width of type}}
13+
expected-warning {{left operand of comma operator has no effect}} */
1214
(void)x;
1315
}
1416

1517
void PotentiallyEvaluatedArrayBoundWarn(int n) {
16-
(void)*(int(*)[(0 << 32,n)])0; // expected-warning {{left operand of comma operator has no effect}}
18+
(void)*(int(*)[(0 << 32,n)])0; /* expected-warning {{shift count >= width of type}}
19+
expected-warning {{left operand of comma operator has no effect}} */
1720
}

clang/test/SemaCXX/cxx2a-explicit-bool.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ namespace special_cases
2121
template<int a>
2222
struct A {
2323
// expected-note@-1+ {{candidate constructor}}
24-
explicit(1 << a)
24+
explicit(1 << a) // expected-warning {{shift count is negative}}
2525
// expected-note@-1 {{negative shift count -1}}
2626
// expected-error@-2 {{explicit specifier argument is not a constant expression}}
2727
A(int);

clang/test/SemaCXX/shift.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ void test() {
2222
c = 1 << -1; // expected-warning {{shift count is negative}}
2323
c = 1 >> -1; // expected-warning {{shift count is negative}}
2424
c = 1 << (unsigned)-1; // expected-warning {{shift count >= width of type}}
25-
// expected-warning@-1 {{implicit conversion}}
2625
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}}
2726
c = 1 << c;
2827
c <<= 0;

0 commit comments

Comments
 (0)