1 // RUN: %clang_cc1 -triple=x86_64-linux-gnu -emit-llvm -o - -std=c++17 %s | FileCheck %s --implicit-check-not=@_ZSt4move 2 3 namespace std { 4 template<typename T> constexpr T &&move(T &val) { return static_cast<T&&>(val); } 5 template<typename T> constexpr T &&move_if_noexcept(T &val); 6 template<typename T> constexpr T &&forward(T &val); 7 template<typename T> constexpr const T &as_const(T &val); 8 9 // Not the builtin. 10 template<typename T, typename U> T move(U source, U source_end, T dest); 11 } 12 13 class T {}; 14 extern "C" void take(T &&); 15 extern "C" void take_lval(const T &); 16 17 T a; 18 19 // Check emission of a constant-evaluated call. 20 // CHECK-DAG: @move_a = constant ptr @a 21 T &&move_a = std::move(a); 22 // CHECK-DAG: @move_if_noexcept_a = constant ptr @a 23 T &&move_if_noexcept_a = std::move_if_noexcept(a); 24 // CHECK-DAG: @forward_a = constant ptr @a 25 T &forward_a = std::forward<T&>(a); 26 27 // Check emission of a non-constant call. 28 // CHECK-LABEL: define {{.*}} void @test 29 extern "C" void test(T &t) { 30 // CHECK: store ptr %{{.*}}, ptr %[[T_REF:[^,]*]] 31 // CHECK: %0 = load ptr, ptr %[[T_REF]] 32 // CHECK: call void @take(ptr {{.*}} %0) 33 take(std::move(t)); 34 // CHECK: %1 = load ptr, ptr %[[T_REF]] 35 // CHECK: call void @take(ptr {{.*}} %1) 36 take(std::move_if_noexcept(t)); 37 // CHECK: %2 = load ptr, ptr %[[T_REF]] 38 // CHECK: call void @take(ptr {{.*}} %2) 39 take(std::forward<T&&>(t)); 40 // CHECK: %3 = load ptr, ptr %[[T_REF]] 41 // CHECK: call void @take_lval(ptr {{.*}} %3) 42 take_lval(std::as_const<T&&>(t)); 43 44 // CHECK: call {{.*}} @_ZSt4moveI1TS0_ET_T0_S2_S1_ 45 std::move(t, t, t); 46 } 47 48 // CHECK: declare {{.*}} @_ZSt4moveI1TS0_ET_T0_S2_S1_ 49 50 // Check that we instantiate and emit if the address is taken. 51 // CHECK-LABEL: define {{.*}} @use_address 52 extern "C" void *use_address() { 53 // CHECK: ret {{.*}} @_ZSt4moveIiEOT_RS0_ 54 return (void*)&std::move<int>; 55 } 56 57 // CHECK: define {{.*}} ptr @_ZSt4moveIiEOT_RS0_(ptr 58 59 extern "C" void take_const_int_rref(const int &&); 60 // CHECK-LABEL: define {{.*}} @move_const_int( 61 extern "C" void move_const_int() { 62 // CHECK: store i32 5, ptr %[[N_ADDR:[^,]*]] 63 const int n = 5; 64 // CHECK: call {{.*}} @take_const_int_rref(ptr {{.*}} %[[N_ADDR]]) 65 take_const_int_rref(std::move(n)); 66 } 67