1 // RUN: %clang_cc1 -fpass-by-value-is-noalias -triple arm64-apple-iphoneos -emit-llvm -disable-llvm-optzns %s -o - 2>&1 | FileCheck --check-prefix=WITH_NOALIAS %s 2 // RUN: %clang_cc1 -triple arm64-apple-iphoneos -emit-llvm -disable-llvm-optzns %s -o - 2>&1 | FileCheck --check-prefix=NO_NOALIAS %s 3 4 // A trivial struct large enough so it is not passed in registers on ARM64. 5 struct Foo { 6 int a; 7 int b; 8 int c; 9 int d; 10 int e; 11 int f; 12 }; 13 14 // Make sure noalias is added to indirect arguments with trivially copyable types 15 // if -fpass-by-value-is-noalias is provided. 16 17 // WITH_NOALIAS: define{{.*}} void @_Z4take3Foo(%struct.Foo* noalias noundef %arg) 18 // NO_NOALIAS: define{{.*}} void @_Z4take3Foo(%struct.Foo* noundef %arg) 19 void take(Foo arg) {} 20 21 int G; 22 23 // NonTrivial is not trivially-copyable, because it has a non-trivial copy 24 // constructor. 25 struct NonTrivial { 26 int a; 27 int b; 28 int c; 29 int d; 30 int e; 31 int f; 32 33 NonTrivial(const NonTrivial &Other) { 34 a = G + 10 + Other.a; 35 } 36 }; 37 38 // Make sure noalias is not added to indirect arguments that are not trivially 39 // copyable even if -fpass-by-value-is-noalias is provided. 40 41 // WITH_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(%struct.NonTrivial* noundef %arg) 42 // NO_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(%struct.NonTrivial* noundef %arg) 43 void take(NonTrivial arg) {} 44 45 // Escape examples. Pointers to the objects passed to take() may escape, depending on whether a temporary copy is created or not (e.g. due to NRVO). 46 struct A { 47 A(A **where) : data{"hello world 1"} { 48 *where = this; //Escaped pointer 1 (proposed UB?) 49 } 50 51 A() : data{"hello world 2"} {} 52 53 char data[32]; 54 }; 55 A *p; 56 57 // WITH_NOALIAS: define{{.*}} void @_Z4take1A(%struct.A* noalias noundef %arg) 58 // NO_NOALIAS: define{{.*}} void @_Z4take1A(%struct.A* noundef %arg) 59 void take(A arg) {} 60 61 // WITH_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(%struct.A* noalias sret(%struct.A) align 1 %agg.result, %struct.A** noundef %where) 62 // NO_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(%struct.A* noalias sret(%struct.A) align 1 %agg.result, %struct.A** noundef %where) 63 A CreateA(A **where) { 64 A justlikethis; 65 *where = &justlikethis; //Escaped pointer 2 (should also be UB, then) 66 return justlikethis; 67 } 68 69 // elsewhere, perhaps compiled by a smarter compiler that doesn't make a copy here 70 void test() { 71 take({&p}); // 1 72 take(CreateA(&p)); // 2 73 } 74