169 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \2// RUN: -analyzer-checker=debug.ExprInspection \3// RUN: -analyzer-output=text -verify \4// RUN: -triple x86_64-pc-linux-gnu -x c %s \5// RUN: -Wno-shift-count-negative -Wno-shift-negative-value \6// RUN: -Wno-shift-count-overflow -Wno-shift-overflow \7// RUN: -Wno-shift-sign-overflow8//9// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \10// RUN: -analyzer-checker=debug.ExprInspection \11// RUN: -analyzer-config core.BitwiseShift:Pedantic=true \12// RUN: -analyzer-output=text -verify \13// RUN: -triple x86_64-pc-linux-gnu -x c++ -std=c++20 %s \14// RUN: -Wno-shift-count-negative -Wno-shift-negative-value \15// RUN: -Wno-shift-count-overflow -Wno-shift-overflow \16// RUN: -Wno-shift-sign-overflow17//18// This test file verifies the default behavior of the BitwiseShift checker,19// which reports the serious logical defects, but doesn't warn on code that's20// legal under C++20 (or later) and widely accepted (but theoretically21// undefined) in other compilation modes.22 23// TEST NEGATIVE RIGHT OPERAND24//===----------------------------------------------------------------------===//25 26int negative_right_operand_literal(void) {27 return 2 << -2;28 // expected-warning@-1 {{Right operand is negative in left shift}}29 // expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}30}31 32int negative_right_operand_symbolic(int left, int right) {33 // expected-note@+2 {{Assuming 'right' is < 0}}34 // expected-note@+1 {{Taking false branch}}35 if (right >= 0)36 return 0;37 return left >> right;38 // expected-warning@-1 {{Right operand is negative in right shift}}39 // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}40}41 42int negative_right_operand_compound(short arg) {43 // expected-note@+2 {{Assuming 'arg' is < 2}}44 // expected-note@+1 {{Taking false branch}}45 if (arg >= 2 )46 return 0;47 return 2 << (arg - 1 - 1 - 1);48 // expected-warning@-1 {{Right operand is negative in left shift}}49 // expected-note@-2 {{The result of left shift is undefined because the right operand is negative}}50}51 52// TEST TOO LARGE RIGHT OPERAND53//===----------------------------------------------------------------------===//54 55int too_large_right_operand_literal(void) {56 return 2 << 32;57 // expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}58 // expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}59}60 61int too_large_right_operand_exact_symbolic(int arg) {62 // expected-note@+4 {{Assuming 'arg' is > 33}}63 // expected-note@+3 {{Left side of '||' is false}}64 // expected-note@+2 {{Assuming 'arg' is < 35}}65 // expected-note@+1 {{Taking false branch}}66 if (arg <= 33 || arg >= 35)67 return 0;68 return 3 << arg;69 // expected-warning@-1 {{Left shift by '34' overflows the capacity of 'int'}}70 // expected-note@-2 {{The result of left shift is undefined because the right operand '34' is not smaller than 32, the capacity of 'int'}}71}72 73int too_large_right_operand_exact_symbolic_2(char arg) {74 // expected-note@+2 {{Assuming the condition is false}}75 // expected-note@+1 {{Taking false branch}}76 if (arg != ' ')77 return 0;78 return 3 << arg;79 // expected-warning@-1 {{Left shift by '32' overflows the capacity of 'int'}}80 // expected-note@-2 {{The result of left shift is undefined because the right operand '32' is not smaller than 32, the capacity of 'int'}}81}82 83int too_large_right_operand_symbolic(int left, int right) {84 // expected-note@+2 {{Assuming 'right' is > 31}}85 // expected-note@+1 {{Taking false branch}}86 if (right <= 31)87 return 0;88 return left >> right;89 // expected-warning@-1 {{Right shift overflows the capacity of 'int'}}90 // expected-note@-2 {{The result of right shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}91}92 93void clang_analyzer_value(int);94int too_large_right_operand_compound(unsigned short arg) {95 // Note: this would be valid code with an 'unsigned int' because96 // unsigned addition is allowed to overflow.97 clang_analyzer_value(32+arg);98 // expected-warning@-1 {{32s:{ [-2147483648, 2147483647] }}99 // expected-note@-2 {{32s:{ [-2147483648, 2147483647] }}100 return 1 << (32 + arg);101 // expected-warning@-1 {{Left shift overflows the capacity of 'int'}}102 // expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}103 // FIXME: this message should be104 // {{The result of left shift is undefined because the right operand is >= 32, not smaller than 32, the capacity of 'int'}}105 // but for some reason neither the new logic, nor debug.ExprInspection and106 // clang_analyzer_value reports this range information.107}108 109// TEST STATE UPDATES110//===----------------------------------------------------------------------===//111 112void state_update(char a, int *p) {113 // NOTE: with 'int a' this would not produce a bug report because the engine114 // would not rule out an overflow.115 *p += 1 << a;116 // expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}117 *p += 1 << (a + 32);118 // expected-warning@-1 {{Left shift overflows the capacity of 'int'}}119 // expected-note@-2 {{The result of left shift is undefined because the right operand is not smaller than 32, the capacity of 'int'}}120}121 122void state_update_2(char a, int *p) {123 *p += 1234 >> (a + 32);124 // expected-note@-1 {{Assuming right operand of bit shift is non-negative but less than 32}}125 *p += 1234 >> a;126 // expected-warning@-1 {{Right operand is negative in right shift}}127 // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}128}129 130// TEST EXPRESSION TRACKING131//===----------------------------------------------------------------------===//132// Expression tracking a "generic" tool that's used by many other checkers,133// so this is just a minimal test to see that it's activated.134 135void setValue(unsigned *p, unsigned newval) {136 *p = newval;137 // expected-note@-1 {{The value 33 is assigned to 'right'}}138}139 140int expression_tracked_back(void) {141 unsigned left = 115; // expected-note {{'left' initialized to 115}}142 unsigned right;143 setValue(&right, 33);144 // expected-note@-1 {{Calling 'setValue'}}145 // expected-note@-2 {{Passing the value 33 via 2nd parameter 'newval'}}146 // expected-note@-3 {{Returning from 'setValue'}}147 148 return left << right;149 // expected-warning@-1 {{Left shift by '33' overflows the capacity of 'unsigned int'}}150 // 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'}}151}152 153// TEST PERMISSIVENESS154//===----------------------------------------------------------------------===//155 156int allow_overflows_and_negative_operands(void) {157 // These are all legal under C++20 and many compilers accept them under158 // earlier standards as well.159 int int_min = 1 << 31; // no-warning160 int this_overflows = 1027 << 30; // no-warning161 return (-2 << 5) + (-3 >> 4); // no-warning162}163 164int double_negative(void) {165 return -2 >> -2;166 // expected-warning@-1 {{Right operand is negative in right shift}}167 // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}168}169