summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorDavide Italiano <davide@freebsd.org>2015-07-06 18:02:09 +0000
committerDavide Italiano <davide@freebsd.org>2015-07-06 18:02:09 +0000
commitbf0f7757e24264bb6e211e30f60a75f272b0a90d (patch)
tree7e32d8cc052765a1eea8d89cb7bb42ce4abc0227 /clang
parent183f53fd2213006589847fe40567720296e68717 (diff)
downloadbcm5719-llvm-bf0f7757e24264bb6e211e30f60a75f272b0a90d.tar.gz
bcm5719-llvm-bf0f7757e24264bb6e211e30f60a75f272b0a90d.zip
[Sema] Warn when shifting a negative value.
Example: % ./clang -Wshift-negative-value emit.c emit.c:3:14: warning: shifting a negative signed value is undefined [-Wshift-negative-value] int a = -1 << 3; ~~ ^ 1 warning generated. PR: 24026 Differential Revision: http://reviews.llvm.org/D10938 Reviewed by: rsmith llvm-svn: 241478
Diffstat (limited to 'clang')
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td2
-rw-r--r--clang/lib/Sema/SemaExpr.cpp14
-rw-r--r--clang/test/CXX/expr/expr.const/p2-0x.cpp2
-rw-r--r--clang/test/Sema/shift.c5
4 files changed, 18 insertions, 5 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 750219483c6..39b602c5514 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -4740,6 +4740,8 @@ def warn_division_by_zero : Warning<"division by zero is undefined">,
InGroup<DivZero>;
def warn_remainder_by_zero : Warning<"remainder by zero is undefined">,
InGroup<DivZero>;
+def warn_shift_lhs_negative : Warning<"shifting a negative signed value is undefined">,
+ InGroup<DiagGroup<"shift-negative-value">>;
def warn_shift_negative : Warning<"shift count is negative">,
InGroup<DiagGroup<"shift-count-negative">>;
def warn_shift_gt_typewidth : Warning<"shift count >= width of type">,
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c023c8523a3..01a4d488057 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -7937,9 +7937,19 @@ static void DiagnoseBadShiftValues(Sema& S, ExprResult &LHS, ExprResult &RHS,
// representable in the result type, so never warn for those.
llvm::APSInt Left;
if (LHS.get()->isValueDependent() ||
- !LHS.get()->isIntegerConstantExpr(Left, S.Context) ||
- LHSType->hasUnsignedIntegerRepresentation())
+ LHSType->hasUnsignedIntegerRepresentation() ||
+ !LHS.get()->EvaluateAsInt(Left, S.Context))
return;
+
+ // If LHS does not have a signed type and non-negative value
+ // then, the behavior is undefined. Warn about it.
+ if (Left.isNegative()) {
+ S.DiagRuntimeBehavior(Loc, LHS.get(),
+ S.PDiag(diag::warn_shift_lhs_negative)
+ << LHS.get()->getSourceRange());
+ return;
+ }
+
llvm::APInt ResultBits =
static_cast<llvm::APInt&>(Right) + Left.getMinSignedBits();
if (LeftBits.uge(ResultBits))
diff --git a/clang/test/CXX/expr/expr.const/p2-0x.cpp b/clang/test/CXX/expr/expr.const/p2-0x.cpp
index d027c7a388b..2adefd928af 100644
--- a/clang/test/CXX/expr/expr.const/p2-0x.cpp
+++ b/clang/test/CXX/expr/expr.const/p2-0x.cpp
@@ -157,7 +157,7 @@ namespace UndefinedBehavior {
constexpr int shl_unsigned_negative = unsigned(-3) << 1; // ok
constexpr int shl_unsigned_into_sign = 1u << 31; // ok
constexpr int shl_unsigned_overflow = 1024u << 31; // ok
- constexpr int shl_signed_negative = (-3) << 1; // expected-error {{constant expression}} expected-note {{left shift of negative value -3}}
+ constexpr int shl_signed_negative = (-3) << 1; // expected-warning {{shifting a negative signed value is undefined}} // expected-error {{constant expression}} expected-note {{left shift of negative value -3}}
constexpr int shl_signed_ok = 1 << 30; // ok
constexpr int shl_signed_into_sign = 1 << 31; // ok (DR1457)
constexpr int shl_signed_into_sign_2 = 0x7fffffff << 1; // ok (DR1457)
diff --git a/clang/test/Sema/shift.c b/clang/test/Sema/shift.c
index d3555448851..07c5fe5280e 100644
--- a/clang/test/Sema/shift.c
+++ b/clang/test/Sema/shift.c
@@ -39,7 +39,8 @@ void test() {
i = 1 << (WORD_BIT - 2);
i = 2 << (WORD_BIT - 1); // expected-warning {{bits to represent, but 'int' only has}}
i = 1 << (WORD_BIT - 1); // expected-warning {{sets the sign bit of the shift expression}}
- i = -1 << (WORD_BIT - 1);
+ i = -1 << (WORD_BIT - 1); // expected-warning {{shifting a negative signed value is undefined}}
+ i = -1 << 0; // expected-warning {{shifting a negative signed value is undefined}}
i = 0 << (WORD_BIT - 1);
i = (char)1 << (WORD_BIT - 2);
@@ -48,7 +49,7 @@ void test() {
u = 5U << (WORD_BIT - 1);
long long int lli;
- lli = INT_MIN << 2; // expected-warning {{bits to represent, but 'int' only has}}
+ lli = INT_MIN << 2; // expected-warning {{shifting a negative signed value is undefined}}
lli = 1LL << (sizeof(long long) * CHAR_BIT - 2);
}
OpenPOWER on IntegriCloud