Skip to content

Commit a66ca21

Browse files
[clang] Emit bad shift warnings
1 parent a46a2c2 commit a66ca21

File tree

13 files changed

+73
-20
lines changed

13 files changed

+73
-20
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,6 +2858,9 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
28582858
else if (LHS.countl_zero() < SA)
28592859
Info.CCEDiag(E, diag::note_constexpr_lshift_discards);
28602860
}
2861+
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
2862+
Info.getLangOpts().CPlusPlus)
2863+
return false;
28612864
Result = LHS << SA;
28622865
return true;
28632866
}
@@ -2881,6 +2884,10 @@ static bool handleIntIntBinOp(EvalInfo &Info, const BinaryOperator *E,
28812884
if (SA != RHS)
28822885
Info.CCEDiag(E, diag::note_constexpr_large_shift)
28832886
<< RHS << E->getType() << LHS.getBitWidth();
2887+
2888+
if (Info.EvalStatus.Diag && !Info.EvalStatus.Diag->empty() &&
2889+
Info.getLangOpts().CPlusPlus)
2890+
return false;
28842891
Result = LHS >> SA;
28852892
return true;
28862893
}

clang/lib/Sema/SemaExpr.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11256,7 +11256,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1125611256
if (Right.isNegative()) {
1125711257
S.DiagRuntimeBehavior(Loc, RHS.get(),
1125811258
S.PDiag(diag::warn_shift_negative)
11259-
<< RHS.get()->getSourceRange());
11259+
<< RHS.get()->getSourceRange());
1126011260
return;
1126111261
}
1126211262

@@ -11271,7 +11271,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1127111271
if (Right.uge(LeftSize)) {
1127211272
S.DiagRuntimeBehavior(Loc, RHS.get(),
1127311273
S.PDiag(diag::warn_shift_gt_typewidth)
11274-
<< RHS.get()->getSourceRange());
11274+
<< RHS.get()->getSourceRange());
1127511275
return;
1127611276
}
1127711277

@@ -11304,7 +11304,7 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
1130411304
if (Left.isNegative()) {
1130511305
S.DiagRuntimeBehavior(Loc, LHS.get(),
1130611306
S.PDiag(diag::warn_shift_lhs_negative)
11307-
<< LHS.get()->getSourceRange());
11307+
<< LHS.get()->getSourceRange());
1130811308
return;
1130911309
}
1131011310

@@ -17138,11 +17138,20 @@ Sema::VerifyIntegerConstantExpression(Expr *E, llvm::APSInt *Result,
1713817138
// Circumvent ICE checking in C++11 to avoid evaluating the expression twice
1713917139
// in the non-ICE case.
1714017140
if (!getLangOpts().CPlusPlus11 && E->isIntegerConstantExpr(Context)) {
17141+
SmallVector<PartialDiagnosticAt, 8> Notes;
1714117142
if (Result)
17142-
*Result = E->EvaluateKnownConstIntCheckOverflow(Context);
17143+
*Result = E->EvaluateKnownConstIntCheckOverflow(Context, &Notes);
1714317144
if (!isa<ConstantExpr>(E))
1714417145
E = Result ? ConstantExpr::Create(Context, E, APValue(*Result))
1714517146
: ConstantExpr::Create(Context, E);
17147+
17148+
if (Notes.size() && !Diagnoser.Suppress) {
17149+
Diagnoser.diagnoseNotICE(*this, DiagLoc) << E->getSourceRange();
17150+
for (const PartialDiagnosticAt &Note : Notes)
17151+
Diag(Note.first, Note.second);
17152+
return ExprError();
17153+
}
17154+
1714617155
return E;
1714717156
}
1714817157

clang/test/C/drs/dr0xx.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -430,7 +430,8 @@ void dr081(void) {
430430
/* Demonstrate that we don't crash when left shifting a signed value; that's
431431
* implementation defined behavior.
432432
*/
433-
_Static_assert(-1 << 1 == -2, "fail"); /* Didn't shift a zero into the "sign bit". */
433+
_Static_assert(-1 << 1 == -2, "fail"); /* c89only-error {{static assertion expression is not an integral constant expression}}
434+
c89only-note {{left shift of negative value -1}} */
434435
_Static_assert(1 << 3 == 1u << 3u, "fail"); /* Shift of a positive signed value does sensible things. */
435436
}
436437

clang/test/C/drs/dr2xx.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -277,7 +277,9 @@ void dr258(void) {
277277
void dr261(void) {
278278
/* This is still an integer constant expression despite the overflow. */
279279
enum e1 {
280-
ex1 = __INT_MAX__ + 1 /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}} */
280+
ex1 = __INT_MAX__ + 1 /* expected-warning {{overflow in expression; result is -2'147'483'648 with type 'int'}}
281+
c89only-error {{expression is not an integer constant expression}}
282+
c89only-note {{value 2147483648 is outside the range of representable values of type 'int'}} */
281283
};
282284

283285
/* This is not an integer constant expression, because of the comma operator,

clang/test/Sema/builtins.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,10 @@ void test17(void) {
171171
#define OPT(...) (__builtin_constant_p(__VA_ARGS__) && strlen(__VA_ARGS__) < 4)
172172
// FIXME: These are incorrectly treated as ICEs because strlen is treated as
173173
// a builtin.
174-
ASSERT(OPT("abc"));
175-
ASSERT(!OPT("abcd"));
174+
ASSERT(OPT("abc")); // expected-error {{expression is not an integer constant expression}}
175+
// expected-note@-1 {{subexpression not valid in a constant expression}}
176+
ASSERT(!OPT("abcd")); // expected-error {{expression is not an integer constant expression}}
177+
// expected-note@-1 {{subexpression not valid in a constant expression}}
176178
// In these cases, the strlen is non-constant, but the __builtin_constant_p
177179
// is 0: the array size is not an ICE but is foldable.
178180
ASSERT(!OPT(test17_c));

clang/test/Sema/code_align.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,9 +97,10 @@ void foo1(int A)
9797
for(int I=0; I<256; ++I) { bar(I); }
9898

9999
#ifdef __SIZEOF_INT128__
100-
// cpp-local-error@+3{{expression is not an integral constant expression}}
101-
// cpp-local-note@+2{{left shift of negative value -1311768467294899680}}
102-
// c-local-error@+1{{'code_align' attribute requires an integer argument which is a constant power of two between 1 and 4096 inclusive; provided argument was -(__int128_t)1311768467294899680ULL << 64}}
100+
// cpp-local-error@+4{{expression is not an integral constant expression}}
101+
// cpp-local-note@+3{{left shift of negative value -1311768467294899680}}
102+
// c-local-error+2{{expression is not an integer constant expression}}
103+
// c-local-note+1{{left shift of negative value -1311768467294899680}}
103104
[[clang::code_align(-(__int128_t)0x1234567890abcde0ULL << 64)]]
104105
for(int I=0; I<256; ++I) { bar(I); }
105106
#endif

clang/test/Sema/constant-builtins-2.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -265,17 +265,17 @@ char clz52[__builtin_clzg((unsigned __int128)0x1) == BITSIZE(__int128) - 1 ? 1 :
265265
char clz53[__builtin_clzg((unsigned __int128)0x1, 42) == BITSIZE(__int128) - 1 ? 1 : -1];
266266
char clz54[__builtin_clzg((unsigned __int128)0xf) == BITSIZE(__int128) - 4 ? 1 : -1];
267267
char clz55[__builtin_clzg((unsigned __int128)0xf, 42) == BITSIZE(__int128) - 4 ? 1 : -1];
268-
char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1];
269-
char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1];
268+
char clz56[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1))) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
269+
char clz57[__builtin_clzg((unsigned __int128)(1 << (BITSIZE(__int128) - 1)), 42) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
270270
#endif
271271
int clz58 = __builtin_clzg((unsigned _BitInt(128))0); // expected-error {{not a compile-time constant}}
272272
char clz59[__builtin_clzg((unsigned _BitInt(128))0, 42) == 42 ? 1 : -1];
273273
char clz60[__builtin_clzg((unsigned _BitInt(128))0x1) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
274274
char clz61[__builtin_clzg((unsigned _BitInt(128))0x1, 42) == BITSIZE(_BitInt(128)) - 1 ? 1 : -1];
275275
char clz62[__builtin_clzg((unsigned _BitInt(128))0xf) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
276276
char clz63[__builtin_clzg((unsigned _BitInt(128))0xf, 42) == BITSIZE(_BitInt(128)) - 4 ? 1 : -1];
277-
char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1];
278-
char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1];
277+
char clz64[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1))) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
278+
char clz65[__builtin_clzg((unsigned _BitInt(128))(1 << (BITSIZE(_BitInt(128)) - 1)), 42) == 0 ? 1 : -1]; // expected-warning {{variable length array folded to constant array as an extension}}
279279

280280
char ctz1[__builtin_ctz(1) == 0 ? 1 : -1];
281281
char ctz2[__builtin_ctz(8) == 3 ? 1 : -1];
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wshift-count-negative %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wall %s
3+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wshift-count-negative %s
4+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wall %s
5+
6+
enum shiftof {
7+
X = (1<<-29) // c-error {{expression is not an integer constant expression}}
8+
// cpp-error@-1 {{expression is not an integral constant expression}}
9+
// expected-note@-2 {{negative shift count -29}}
10+
};
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
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-error {{expression is not an integer constant expression}}
6+
// expected-note@-1 {{shift count 32 >= width of type 'int'}}
7+
};
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wshift-negative-value %s
2+
// RUN: %clang_cc1 -x c -fsyntax-only -verify=expected,c -Wall %s
3+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wshift-negative-value %s
4+
// RUN: %clang_cc1 -x c++ -fsyntax-only -verify=expected,cpp -Wall %s
5+
6+
enum shiftof {
7+
X = (-1<<29) // c-error {{expression is not an integer constant expression}}
8+
// cpp-error@-1 {{expression is not an integral constant expression}}
9+
// expected-note@-2 {{left shift of negative value -1}}
10+
};

clang/test/Sema/vla-2.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,13 @@
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

clang/test/SemaCXX/enum.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ void PR8089() {
9898

9999
// This is accepted as a GNU extension. In C++98, there was no provision for
100100
// expressions with UB to be non-constant.
101-
enum { overflow = 123456 * 234567 };
101+
enum { overflow = 123456 * 234567 }; /* expected-error {{expression is not an integral constant expression}}
102+
expected-note {{value 28958703552 is outside the range of representable values of type 'int}} */
102103
#if __cplusplus >= 201103L
103104
// expected-warning@-2 {{not an integral constant expression}}
104105
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}
@@ -107,7 +108,8 @@ enum { overflow = 123456 * 234567 };
107108
#endif
108109

109110
// FIXME: This is not consistent with the above case.
110-
enum NoFold : int { overflow2 = 123456 * 234567 };
111+
enum NoFold : int { overflow2 = 123456 * 234567 }; /* expected-error {{expression is not an integral constant expression}}
112+
expected-note {{value 28958703552 is outside the range of representable values of type 'int}} */
111113
#if __cplusplus >= 201103L
112114
// expected-error@-2 {{enumerator value is not a constant expression}}
113115
// expected-note@-3 {{value 28958703552 is outside the range of representable values}}

clang/test/SemaCXX/shift.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ 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}}
25+
// cxx17-warning {{implicit conversion from 'int' to 'char' changes value from -2147483648 to 0}}
2626
c = 1 >> (unsigned)-1; // expected-warning {{shift count >= width of type}}
2727
c = 1 << c;
2828
c <<= 0;

0 commit comments

Comments
 (0)