| // NOTE: Assertions have been autogenerated by utils/update_cc_test_checks.py |
| // RUN: %clang_cc1 -x c++ -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s |
| // RUN: %clang_cc1 -x c++ -fsanitize=pointer-overflow -fno-sanitize-recover=pointer-overflow -emit-llvm %s -o - -triple x86_64-linux-gnu | FileCheck %s |
| |
| #include <stdint.h> |
| |
| struct S { |
| int x, y; |
| }; |
| |
| // CHECK-LABEL: @_Z23get_offset_of_y_naivelyv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr null, i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_naively() { |
| return ((uintptr_t)(&(((S *)nullptr)->y))); |
| } |
| |
| struct Empty {}; |
| |
| struct T { |
| int a; |
| S s; |
| [[no_unique_address]] Empty e1; |
| int b; |
| [[no_unique_address]] Empty e2; |
| }; |
| |
| // CHECK-LABEL: @_Z30get_offset_of_y_naively_nestedv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr getelementptr ([[STRUCT_T:%.*]], ptr null, i32 0, i32 1), i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_naively_nested() { |
| return ((uintptr_t)(&(((T *)nullptr)->s.y))); |
| } |
| |
| // CHECK-LABEL: @_Z42get_offset_of_y_naively_nested_with_parensv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr getelementptr ([[STRUCT_T:%.*]], ptr null, i32 0, i32 1), i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_naively_nested_with_parens() { |
| return ((uintptr_t)(&((((T *)nullptr)->s).y))); |
| } |
| |
| // CHECK-LABEL: @_Z26get_offset_of_zero_storagev( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr (i8, ptr null, i64 16) to i64) |
| // |
| uintptr_t get_offset_of_zero_storage() { |
| return ((uintptr_t)(&(((T *)nullptr)->e2))); |
| } |
| |
| namespace std { typedef decltype(__nullptr) nullptr_t; } |
| // CHECK-LABEL: @_Z29get_offset_of_y_integral_zerov( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr null, i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_integral_zero() { |
| return ((uintptr_t)(&(((S *)0)->y))); |
| } |
| |
| // CHECK-LABEL: @_Z37get_offset_of_y_integral_zero_voidptrv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr null, i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_integral_zero_voidptr() { |
| return ((uintptr_t)(&(((S *)(void*)0)->y))); |
| } |
| |
| // CHECK-LABEL: @_Z25get_offset_of_y_nullptr_tv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr ([[STRUCT_S:%.*]], ptr null, i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_nullptr_t() { |
| return ((uintptr_t)(&(((S *)std::nullptr_t{})->y))); |
| } |
| |
| // CHECK-LABEL: @_Z32get_offset_of_y_nullptr_constantv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: [[NULL:%.*]] = alloca ptr, align 8 |
| // CHECK-NEXT: store ptr null, ptr [[NULL]], align 8 |
| // CHECK-NEXT: ret i64 ptrtoint (ptr getelementptr inbounds nuw ([[STRUCT_S:%.*]], ptr null, i32 0, i32 1) to i64) |
| // |
| uintptr_t get_offset_of_y_nullptr_constant() { |
| constexpr void *null = nullptr; |
| return ((uintptr_t)(&(((S *)null)->y))); |
| } |
| |
| // CHECK-LABEL: @_Z27get_offset_of_y_via_builtinv( |
| // CHECK-NEXT: entry: |
| // CHECK-NEXT: ret i64 4 |
| // |
| uintptr_t get_offset_of_y_via_builtin() { |
| return __builtin_offsetof(S, y); |
| } |