llvm/clang/test/Analysis/bitwise-shift-common.c

// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \
// RUN:    -analyzer-checker=debug.ExprInspection \
// RUN:    -analyzer-output=text -verify \
// RUN:    -triple x86_64-pc-linux-gnu -x c %s \
// RUN:    -Wno-shift-count-negative -Wno-shift-negative-value \
// RUN:    -Wno-shift-count-overflow -Wno-shift-overflow \
// RUN:    -Wno-shift-sign-overflow
//
// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \
// RUN:    -analyzer-checker=debug.ExprInspection \
// RUN:    -analyzer-config core.BitwiseShift:Pedantic=true \
// RUN:    -analyzer-output=text -verify \
// RUN:    -triple x86_64-pc-linux-gnu -x c++ -std=c++20 %s \
// RUN:    -Wno-shift-count-negative -Wno-shift-negative-value \
// RUN:    -Wno-shift-count-overflow -Wno-shift-overflow \
// RUN:    -Wno-shift-sign-overflow
//
// This test file verifies the default behavior of the BitwiseShift checker,
// which reports the serious logical defects, but doesn't warn on code that's
// legal under C++20 (or later) and widely accepted (but theoretically
// undefined) in other compilation modes.

// TEST NEGATIVE RIGHT OPERAND
//===----------------------------------------------------------------------===//

int negative_right_operand_literal(void) {
  return 2 << -2;
  // expected-warning@-1 {{Right operand is negative in left shift}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}
}

int negative_right_operand_symbolic(int left, int right) {
  // expected-note@+2 {{Assuming 'right' is < 0}}
  // expected-note@+1 {{Taking false branch}}
  if (right >= 0)
    return 0;
  return left >> right;
  // expected-warning@-1 {{Right operand is negative in right shift}}
  // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
}

int negative_right_operand_compound(short arg) {
  // expected-note@+2 {{Assuming 'arg' is < 2}}
  // expected-note@+1 {{Taking false branch}}
  if (arg >= 2 )
    return 0;
  return 2 << (arg - 1 - 1 - 1);
  // expected-warning@-1 {{Right operand is negative in left shift}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}
}

// TEST TOO LARGE RIGHT OPERAND
//===----------------------------------------------------------------------===//

int too_large_right_operand_literal(void) {
  return 2 << 32;
  // expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}
}

int too_large_right_operand_exact_symbolic(int arg) {
  // expected-note@+4 {{Assuming 'arg' is > 33}}
  // expected-note@+3 {{Left side of '||' is false}}
  // expected-note@+2 {{Assuming 'arg' is < 35}}
  // expected-note@+1 {{Taking false branch}}
  if (arg <= 33 || arg >= 35)
    return 0;
  return 3 << arg;
  // expected-warning@-1 {{Left shift by '34' overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand '34' is not smaller than 32, the capacity of 'int'}}
}

int too_large_right_operand_exact_symbolic_2(char arg) {
  // expected-note@+2 {{Assuming the condition is false}}
  // expected-note@+1 {{Taking false branch}}
  if (arg != ' ')
    return 0;
  return 3 << arg;
  // expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}
}

int too_large_right_operand_symbolic(int left, int right) {
  // expected-note@+2 {{Assuming 'right' is > 31}}
  // expected-note@+1 {{Taking false branch}}
  if (right <= 31)
    return 0;
  return left >> right;
  // expected-warning@-1 {{Right shift overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of right shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}
}

void clang_analyzer_value(int);
int too_large_right_operand_compound(unsigned short arg) {
  // Note: this would be valid code with an 'unsigned int' because
  // unsigned addition is allowed to overflow.
  clang_analyzer_value(32+arg);
  // expected-warning@-1 {{32s:{ [-2147483648, 2147483647] }}
  // expected-note@-2 {{32s:{ [-2147483648, 2147483647] }}
  return 1 << (32 + arg);
  // expected-warning@-1 {{Left shift overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}
  // FIXME: this message should be
  //     {{The result of left shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}
  // but for some reason neither the new logic, nor debug.ExprInspection and
  // clang_analyzer_value reports this range information.
}

// TEST STATE UPDATES
//===----------------------------------------------------------------------===//

void state_update(char a, int *p) {
  // NOTE: with 'int a' this would not produce a bug report because the engine
  // would not rule out an overflow.
  *p += 1 << a;
  // expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}
  *p += 1 << (a + 32);
  // expected-warning@-1 {{Left shift overflows the capacity of 'int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}
}

void state_update_2(char a, int *p) {
  *p += 1234 >> (a + 32);
  // expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}
  *p += 1234 >> a;
  // expected-warning@-1 {{Right operand is negative in right shift}}
  // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
}

// TEST EXPRESSION TRACKING
//===----------------------------------------------------------------------===//
// Expression tracking a "generic" tool that's used by many other checkers,
// so this is just a minimal test to see that it's activated.

void setValue(unsigned *p, unsigned newval) {
  *p = newval;
  // expected-note@-1 {{The value 33 is assigned to 'right'}}
}

int expression_tracked_back(void) {
  unsigned left = 115; // expected-note {{'left' initialized to 115}}
  unsigned right;
  setValue(&right, 33);
  // expected-note@-1 {{Calling 'setValue'}}
  // expected-note@-2 {{Passing the value 33 via 2nd parameter 'newval'}}
  // expected-note@-3 {{Returning from 'setValue'}}

  return left << right;
  // expected-warning@-1 {{Left shift by '33' overflows the capacity of 'unsigned int'}}
  // expected-note@-2 {{The result of left shift is undefined because the right operand '33' is not smaller than 32, the capacity of 'unsigned int'}}
}

// TEST PERMISSIVENESS
//===----------------------------------------------------------------------===//

int allow_overflows_and_negative_operands(void) {
  // These are all legal under C++20 and many compilers accept them under
  // earlier standards as well.
  int int_min = 1 << 31; // no-warning
  int this_overflows = 1027 << 30; // no-warning
  return (-2 << 5) + (-3 >> 4); // no-warning
}

int double_negative(void) {
  return -2 >> -2;
  // expected-warning@-1 {{Right operand is negative in right shift}}
  // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}
}