brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 617d693 Raw
168 lines · c
1// RUN: %clang_analyze_cc1 -analyzer-checker=core.BitwiseShift \2// RUN:    -analyzer-config core.BitwiseShift:Pedantic=true \3// RUN:    -analyzer-output=text -verify=expected,c \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-config core.BitwiseShift:Pedantic=true \11// RUN:    -analyzer-output=text -verify=expected,cxx \12// RUN:    -triple x86_64-pc-linux-gnu -x c++ -std=c++14 %s \13// RUN:    -Wno-shift-count-negative -Wno-shift-negative-value \14// RUN:    -Wno-shift-count-overflow -Wno-shift-overflow \15// RUN:    -Wno-shift-sign-overflow16 17// This test file verifies the pedantic mode of the BitwiseShift checker, which18// also reports issues that are undefined behavior (according to the standard,19// under C and in C++ before C++20), but would be accepted by many compilers.20 21// TEST NEGATIVE LEFT OPERAND22//===----------------------------------------------------------------------===//23 24int negative_left_operand_literal(void) {25  return -2 << 2;26  // expected-warning@-1 {{Left operand is negative in left shift}}27  // expected-note@-2 {{The result of left shift is undefined because the left operand is negative}}28}29 30int negative_left_operand_symbolic(int left, int right) {31  // expected-note@+2 {{Assuming 'left' is < 0}}32  // expected-note@+1 {{Taking false branch}}33  if (left >= 0)34    return 0;35  return left >> right;36  // expected-warning@-1 {{Left operand is negative in right shift}}37  // expected-note@-2 {{The result of right shift is undefined because the left operand is negative}}38}39 40int negative_left_operand_compound(short arg) {41  // expected-note@+2 {{Assuming 'arg' is < 0}}42  // expected-note@+1 {{Taking false branch}}43  if (arg >= 0)44    return 0;45  return (arg - 3) << 2;46  // expected-warning@-1 {{Left operand is negative in left shift}}47  // expected-note@-2 {{The result of left shift is undefined because the left operand is negative}}48}49 50int double_negative(void) {51  // In this case we still report that the right operand is negative, because52  // that's the more "serious" issue:53  return -2 >> -2;54  // expected-warning@-1 {{Right operand is negative in right shift}}55  // expected-note@-2 {{The result of right shift is undefined because the right operand is negative}}56}57 58int single_unknown_negative(int arg) {59  // In this case just one of the operands will be negative, so we end up60  // reporting the left operand after assuming that the right operand is61  // positive.62  // expected-note@+2 {{Assuming 'arg' is not equal to 0}}63  // expected-note@+1 {{Taking false branch}}64  if (!arg)65    return 0;66  // We're first checking the right operand, record that it must be positive,67  // then report that then the left argument must be negative.68  return -arg << arg;69  // expected-warning@-1 {{Left operand is negative in left shift}}70  // expected-note@-2 {{The result of left shift is undefined because the left operand is negative}}71}72 73void shift_negative_by_zero(int c) {74  // This seems to be innocent, but the standard (before C++20) clearly implies75  // that this is UB, so we should report it in pedantic mode.76  c = (-1) << 0;77  // expected-warning@-1 {{Left operand is negative in left shift}}78  // expected-note@-2 {{The result of left shift is undefined because the left operand is negative}}79}80 81// TEST OVERFLOW OF CONCRETE SIGNED LEFT OPERAND82//===----------------------------------------------------------------------===//83// (the most complex and least important part of the checker)84 85int concrete_overflow_literal(void) {86  // 27 in binary is 11011 (5 bits), when shifted by 28 bits it becomes87  // 1_10110000_00000000_00000000_0000000088  return 27 << 28;89  // expected-warning@-1 {{The shift '27 << 28' overflows the capacity of 'int'}}90  // cxx-note@-2 {{The shift '27 << 28' is undefined because 'int' can hold only 32 bits (including the sign bit), so 1 bit overflows}}91  // c-note@-3 {{The shift '27 << 28' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so 2 bits overflow}}92}93 94int concrete_overflow_symbolic(int arg) {95  // 29 in binary is 11101 (5 bits), when shifted by 29 bits it becomes96  // 11_10100000_00000000_00000000_0000000097 98  // expected-note@+2 {{Assuming 'arg' is equal to 29}}99  // expected-note@+1 {{Taking false branch}}100  if (arg != 29)101    return 0;102  return arg << arg;103  // expected-warning@-1 {{The shift '29 << 29' overflows the capacity of 'int'}}104  // cxx-note@-2 {{The shift '29 << 29' is undefined because 'int' can hold only 32 bits (including the sign bit), so 2 bits overflow}}105  // c-note@-3 {{The shift '29 << 29' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so 3 bits overflow}}106}107 108int concrete_overflow_language_difference(void) {109  // 21 in binary is 10101 (5 bits), when shifted by 27 bits it becomes110  // 10101000_00000000_00000000_00000000111  // This does not overflow the 32-bit capacity of int, but reaches the sign112  // bit, which is undefined under C (but accepted in C++ even before C++20).113  return 21 << 27;114  // c-warning@-1 {{The shift '21 << 27' overflows the capacity of 'int'}}115  // c-note@-2 {{The shift '21 << 27' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so 1 bit overflows}}116}117 118int concrete_overflow_int_min(void) {119  // Another case that's undefined in C but valid in all C++ versions.120  // Note the "represented by 1 bit" special case121  return 1 << 31;122  // c-warning@-1 {{The shift '1 << 31' overflows the capacity of 'int'}}123  // c-note@-2 {{The shift '1 << 31' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so 1 bit overflows}}124}125 126int concrete_overflow_vague(int arg) {127  // expected-note@+2 {{Assuming 'arg' is > 25}}128  // expected-note@+1 {{Taking false branch}}129  if (arg <= 25)130    return 0;131  return 1024 << arg;132    // expected-warning@-1 {{Left shift of '1024' overflows the capacity of 'int'}}133  // cxx-note@-2 {{Left shift of '1024' is undefined because 'int' can hold only 32 bits (including the sign bit), so some bits overflow}}134  // c-note@-3 {{Left shift of '1024' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so some bits overflow}}135}136 137int concrete_overflow_vague_only_c(int arg) {138  // A third case that's undefined in C but valid in all C++ versions.139 140  // c-note@+2 {{Assuming 'arg' is > 20}}141  // c-note@+1 {{Taking false branch}}142  if (arg <= 20)143    return 0;144  return 1024 << arg;145  // c-warning@-1 {{Left shift of '1024' overflows the capacity of 'int'}}146  // c-note@-2 {{Left shift of '1024' is undefined because 'int' can hold only 31 bits (excluding the sign bit), so some bits overflow}}147}148 149int concrete_overflow_vague_left(int arg) {150  // This kind of overflow check only handles concrete values on the LHS. With151  // some effort it would be possible to report errors in cases like this; but152  // it's probably a waste of time especially considering that overflows of153  // left shifts became well-defined in C++20.154 155  if (arg <= 1024)156    return 0;157  return arg << 25; // no-warning158}159 160int concrete_overflow_shift_zero(void) {161  // This is legal, even in C.162  // The relevant rule (as paraphrased on cppreference.com) is:163  // "For signed LHS with nonnegative values, the value of LHS << RHS is164  // LHS * 2^RHS if it is representable in the promoted type of lhs, otherwise165  // the behavior is undefined."166  return 0 << 31; // no-warning167}168