Skip to content

Commit 17fb77d

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

File tree

9 files changed

+52
-20
lines changed

9 files changed

+52
-20
lines changed

clang/lib/Sema/SemaExpr.cpp

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11444,9 +11444,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1144411444
llvm::APSInt Right = RHSResult.Val.getInt();
1144511445

1144611446
if (Right.isNegative()) {
11447-
S.DiagRuntimeBehavior(Loc, RHS.get(),
11448-
S.PDiag(diag::warn_shift_negative)
11449-
<< RHS.get()->getSourceRange());
11447+
if (S.ExprEvalContexts.back().isConstantEvaluated())
11448+
S.Diag(Loc, diag::warn_shift_negative) << RHS.get()->getSourceRange();
11449+
else
11450+
S.DiagRuntimeBehavior(Loc, RHS.get(),
11451+
S.PDiag(diag::warn_shift_negative)
11452+
<< RHS.get()->getSourceRange());
1145011453
return;
1145111454
}
1145211455

@@ -11460,9 +11463,14 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1146011463
}
1146111464
llvm::APInt LeftBits(Right.getBitWidth(), LeftSize);
1146211465
if (Right.uge(LeftBits)) {
11463-
S.DiagRuntimeBehavior(Loc, RHS.get(),
11464-
S.PDiag(diag::warn_shift_gt_typewidth)
11465-
<< RHS.get()->getSourceRange());
11466+
if (S.ExprEvalContexts.back().isConstantEvaluated()
11467+
&& !S.getLangOpts().CPlusPlus11)
11468+
S.Diag(Loc, diag::warn_shift_gt_typewidth)
11469+
<< RHS.get()->getSourceRange();
11470+
else
11471+
S.DiagRuntimeBehavior(Loc, RHS.get(),
11472+
S.PDiag(diag::warn_shift_gt_typewidth)
11473+
<< RHS.get()->getSourceRange());
1146611474
return;
1146711475
}
1146811476

@@ -11493,9 +11501,12 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1149311501
// If LHS does not have a non-negative value then, the
1149411502
// behavior is undefined before C++2a. Warn about it.
1149511503
if (Left.isNegative()) {
11496-
S.DiagRuntimeBehavior(Loc, LHS.get(),
11497-
S.PDiag(diag::warn_shift_lhs_negative)
11498-
<< LHS.get()->getSourceRange());
11504+
if (S.ExprEvalContexts.back().isConstantEvaluated())
11505+
S.Diag(Loc, diag::warn_shift_lhs_negative) << LHS.get()->getSourceRange();
11506+
else
11507+
S.DiagRuntimeBehavior(Loc, LHS.get(),
11508+
S.PDiag(diag::warn_shift_lhs_negative)
11509+
<< LHS.get()->getSourceRange());
1149911510
return;
1150011511
}
1150111512

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"); /* Undefined behavior since C99 */
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)