| // 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}} |
| } |