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 %arg)
18 // NO_NOALIAS: define{{.*}} void @_Z4take3Foo(%struct.Foo* %arg)
take(Foo 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
NonTrivialNonTrivial33 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* %arg)
42 // NO_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(%struct.NonTrivial* %arg)
take(NonTrivial 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 {
AA47 A(A **where) : data{"hello world 1"} {
48 *where = this; //Escaped pointer 1 (proposed UB?)
49 }
50
AA51 A() : data{"hello world 2"} {}
52
53 char data[32];
54 };
55 A *p;
56
57 // WITH_NOALIAS: define{{.*}} void @_Z4take1A(%struct.A* noalias %arg)
58 // NO_NOALIAS: define{{.*}} void @_Z4take1A(%struct.A* %arg)
take(A 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** %where)
62 // NO_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(%struct.A* noalias sret(%struct.A) align 1 %agg.result, %struct.A** %where)
CreateA(A ** 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
test()70 void test() {
71 take({&p}); // 1
72 take(CreateA(&p)); // 2
73 }
74