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
4 // A trivial struct large enough so it is not passed in registers on ARM64.
14 // Make sure noalias is added to indirect arguments with trivially copyable types
15 // if -fpass-by-value-is-noalias is provided.
17 // WITH_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr noalias noundef %arg)
18 // NO_NOALIAS: define{{.*}} void @_Z4take3Foo(ptr noundef %arg)
23 // NonTrivial is not trivially-copyable, because it has a non-trivial copy
33 NonTrivial(const NonTrivial
&Other
) {
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.
41 // WITH_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr noundef %arg)
42 // NO_NOALIAS: define{{.*}} void @_Z4take10NonTrivial(ptr noundef %arg)
43 void take(NonTrivial arg
) {}
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).
47 A(A
**where
) : data
{"hello world 1"} {
48 *where
= this; //Escaped pointer 1 (proposed UB?)
51 A() : data
{"hello world 2"} {}
57 // WITH_NOALIAS: define{{.*}} void @_Z4take1A(ptr noalias noundef %arg)
58 // NO_NOALIAS: define{{.*}} void @_Z4take1A(ptr noundef %arg)
61 // WITH_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr noalias sret(%struct.A) align 1 %agg.result, ptr noundef %where)
62 // NO_NOALIAS: define{{.*}} void @_Z7CreateAPP1A(ptr noalias sret(%struct.A) align 1 %agg.result, ptr noundef %where)
63 A
CreateA(A
**where
) {
65 *where
= &justlikethis
; //Escaped pointer 2 (should also be UB, then)
69 // elsewhere, perhaps compiled by a smarter compiler that doesn't make a copy here
72 take(CreateA(&p
)); // 2