| 1 | // RUN: %clang_tysan -O0 %s -o %t && %run %t >%t.out.0 2>&1 |
| 2 | // RUN: FileCheck %s < %t.out.0 |
| 3 | // RUN: %clang_tysan -O2 %s -o %t && %run %t >%t.out 2>&1 |
| 4 | // RUN: FileCheck %s < %t.out |
| 5 | |
| 6 | #include <stdio.h> |
| 7 | |
| 8 | // There's no type-based-aliasing violation here: the memcpy is implemented |
| 9 | // using only char* or unsigned char* (both of which may alias anything). |
| 10 | // CHECK-NOT: ERROR: TypeSanitizer: type-aliasing-violation |
| 11 | |
| 12 | void my_memcpy_uchar(void *dest, void *src, int n) { |
| 13 | unsigned char *p = dest, *q = src, *end = p + n; |
| 14 | while (p < end) |
| 15 | *p++ = *q++; |
| 16 | } |
| 17 | |
| 18 | void my_memcpy_char(void *dest, void *src, int n) { |
| 19 | char *p = dest, *q = src, *end = p + n; |
| 20 | while (p < end) |
| 21 | *p++ = *q++; |
| 22 | } |
| 23 | |
| 24 | void test_uchar() { |
| 25 | struct S { |
| 26 | short x; |
| 27 | short *r; |
| 28 | } s = {10, &s.x}, s2; |
| 29 | my_memcpy_uchar(dest: &s2, src: &s, n: sizeof(struct S)); |
| 30 | printf(format: "%d\n" , *(s2.r)); |
| 31 | } |
| 32 | |
| 33 | void test_char() { |
| 34 | struct S { |
| 35 | short x; |
| 36 | short *r; |
| 37 | } s = {10, &s.x}, s2; |
| 38 | my_memcpy_char(dest: &s2, src: &s, n: sizeof(struct S)); |
| 39 | printf(format: "%d\n" , *(s2.r)); |
| 40 | } |
| 41 | |
| 42 | int main() { |
| 43 | test_uchar(); |
| 44 | test_char(); |
| 45 | } |
| 46 | |