From 5e21db7130f81fdcb219c31bba8a25153ce47ab8 Mon Sep 17 00:00:00 2001 From: Jordan Rose Date: Thu, 16 Jan 2014 18:02:23 +0000 Subject: [PATCH] [analyzer] Shitfing a constant value by its bit width is undefined. Citation: C++11 [expr.shift]p1 (and the equivalent text in C11). This fixes PR18073, but the right thing to do (as noted in the FIXME) is to have a real checker for too-large shifts. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@199405 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/BasicValueFactory.cpp | 4 ++-- test/Analysis/bitwise-ops.c | 20 ++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp index a6c400f370..8f93cee626 100644 --- a/lib/StaticAnalyzer/Core/BasicValueFactory.cpp +++ b/lib/StaticAnalyzer/Core/BasicValueFactory.cpp @@ -177,7 +177,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, uint64_t Amt = V2.getZExtValue(); - if (Amt > V1.getBitWidth()) + if (Amt >= V1.getBitWidth()) return NULL; return &getValue( V1.operator<<( (unsigned) Amt )); @@ -195,7 +195,7 @@ BasicValueFactory::evalAPSInt(BinaryOperator::Opcode Op, uint64_t Amt = V2.getZExtValue(); - if (Amt > V1.getBitWidth()) + if (Amt >= V1.getBitWidth()) return NULL; return &getValue( V1.operator>>( (unsigned) Amt )); diff --git a/test/Analysis/bitwise-ops.c b/test/Analysis/bitwise-ops.c index bf282eca27..01daf42296 100644 --- a/test/Analysis/bitwise-ops.c +++ b/test/Analysis/bitwise-ops.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s +// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -triple x86_64-apple-darwin13 -Wno-shift-count-overflow -verify %s void clang_analyzer_eval(int); #define CHECK(expr) if (!(expr)) return; clang_analyzer_eval(expr) @@ -11,4 +11,22 @@ void testPersistentConstraints(int x, int y) { // False positives due to SValBuilder giving up on certain kinds of exprs. CHECK(1 - x); // expected-warning{{UNKNOWN}} CHECK(x & y); // expected-warning{{UNKNOWN}} +} + +int testConstantShifts_PR18073(int which) { + // FIXME: We should have a checker that actually specifically checks bitwise + // shifts against the width of the LHS's /static/ type, rather than just + // having BasicValueFactory return "undefined" when dealing with two constant + // operands. + switch (which) { + case 1: + return 0ULL << 63; // no-warning + case 2: + return 0ULL << 64; // expected-warning{{The result of the '<<' expression is undefined}} + case 3: + return 0ULL << 65; // expected-warning{{The result of the '<<' expression is undefined}} + + default: + return 0; + } } \ No newline at end of file -- 2.40.0