|
| 1 | +// RUN: %clang_analyze_cc1 -analyzer-checker=core %s \ |
| 2 | +// RUN: -triple x86_64-pc-linux-gnu -verify |
| 3 | + |
| 4 | +#define BINOP(OP) [](auto x, auto y) { return x OP y; } |
| 5 | + |
| 6 | +template <typename BinOp> |
| 7 | +void nonloc_OP_loc(int *p, BinOp op) { |
| 8 | + long p_as_integer = (long)p; |
| 9 | + if (op(12, p_as_integer) != 11) |
| 10 | + return; |
| 11 | + |
| 12 | + // Perfectly constrain 'p', thus 'p_as_integer', and trigger a simplification |
| 13 | + // of the previously recorded constraint. |
| 14 | + if (p) { |
| 15 | + // no-crash |
| 16 | + } |
| 17 | + if (p == (int *)0x404) { |
| 18 | + // no-crash |
| 19 | + } |
| 20 | +} |
| 21 | + |
| 22 | +// Same as before, but the operands are swapped. |
| 23 | +template <typename BinOp> |
| 24 | +void loc_OP_nonloc(int *p, BinOp op) { |
| 25 | + long p_as_integer = (long)p; |
| 26 | + if (op(p_as_integer, 12) != 11) |
| 27 | + return; |
| 28 | + |
| 29 | + if (p) { |
| 30 | + // no-crash |
| 31 | + } |
| 32 | + if (p == (int *)0x404) { |
| 33 | + // no-crash |
| 34 | + } |
| 35 | +} |
| 36 | + |
| 37 | +void instantiate_tests_for_nonloc_OP_loc(int *p) { |
| 38 | + // Multiplicative and additive operators: |
| 39 | + nonloc_OP_loc(p, BINOP(*)); |
| 40 | + nonloc_OP_loc(p, BINOP(/)); // no-crash |
| 41 | + nonloc_OP_loc(p, BINOP(%)); // no-crash |
| 42 | + nonloc_OP_loc(p, BINOP(+)); |
| 43 | + nonloc_OP_loc(p, BINOP(-)); // no-crash |
| 44 | + |
| 45 | + // Bitwise operators: |
| 46 | + // expected-warning@+2 {{The result of the left shift is undefined due to shifting by '1028', which is greater or equal to the width of type 'int' [core.UndefinedBinaryOperatorResult]}} |
| 47 | + // expected-warning@+2 {{The result of the right shift is undefined due to shifting by '1028', which is greater or equal to the width of type 'int' [core.UndefinedBinaryOperatorResult]}} |
| 48 | + nonloc_OP_loc(p, BINOP(<<)); // no-crash |
| 49 | + nonloc_OP_loc(p, BINOP(>>)); // no-crash |
| 50 | + nonloc_OP_loc(p, BINOP(&)); |
| 51 | + nonloc_OP_loc(p, BINOP(^)); |
| 52 | + nonloc_OP_loc(p, BINOP(|)); |
| 53 | +} |
| 54 | + |
| 55 | +void instantiate_tests_for_loc_OP_nonloc(int *p) { |
| 56 | + // Multiplicative and additive operators: |
| 57 | + loc_OP_nonloc(p, BINOP(*)); |
| 58 | + loc_OP_nonloc(p, BINOP(/)); |
| 59 | + loc_OP_nonloc(p, BINOP(%)); |
| 60 | + loc_OP_nonloc(p, BINOP(+)); |
| 61 | + loc_OP_nonloc(p, BINOP(-)); |
| 62 | + |
| 63 | + // Bitwise operators: |
| 64 | + loc_OP_nonloc(p, BINOP(<<)); |
| 65 | + loc_OP_nonloc(p, BINOP(>>)); |
| 66 | + loc_OP_nonloc(p, BINOP(&)); |
| 67 | + loc_OP_nonloc(p, BINOP(^)); |
| 68 | + loc_OP_nonloc(p, BINOP(|)); |
| 69 | +} |
| 70 | + |
| 71 | +// from: nullptr.cpp |
| 72 | +void zoo1backwards() { |
| 73 | + char **p = nullptr; |
| 74 | + // expected-warning@+1 {{Dereference of null pointer [core.NullDereference]}} |
| 75 | + *(0 + p) = nullptr; // warn |
| 76 | + **(0 + p) = 'a'; // no-warning: this should be unreachable |
| 77 | +} |
0 commit comments