| // RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple %itanium_abi_triple | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-ITANIUM |
| // RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple i686-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS |
| // RUN: %clang_cc1 -std=c++1z %s -emit-llvm -o - -triple x86_64-windows | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-WINDOWS |
| |
| struct B; |
| struct A { |
| A(); |
| A(const A&); |
| |
| void operator[](B b); |
| |
| int a_member_f(B); |
| }; |
| struct B { |
| B(); |
| ~B(); |
| }; |
| |
| struct C { |
| operator int *(); |
| A *operator->(); |
| void operator->*(A); |
| friend void operator->*(C, B); |
| |
| friend void operator<<(C, B); |
| friend void operator>>(C, B); |
| void operator<<(A); |
| void operator>>(A); |
| |
| void operator=(A); |
| void operator+=(A); |
| friend void operator+=(C, B); |
| |
| void operator,(A); |
| friend void operator,(C, B); |
| |
| void operator&&(A); |
| void operator||(A); |
| friend void operator&&(C, B); |
| friend void operator||(C, B); |
| }; |
| |
| A make_a(); |
| A *make_a_ptr(); |
| int A::*make_mem_ptr_a(); |
| void (A::*make_mem_fn_ptr_a())(); |
| B make_b(); |
| C make_c(); |
| void side_effect(); |
| |
| void callee(A); |
| void (*get_f())(A); |
| |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}postfix_before_args{{.*}}( |
| void postfix_before_args() { |
| // CHECK: call {{.*}}@{{.*}}get_f{{.*}}( |
| // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( |
| // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"( |
| // CHECK: call {{.*}}%{{.*}}( |
| get_f()(A{}); |
| |
| // CHECK: call {{.*}}@{{.*}}side_effect{{.*}}( |
| // CHECK-ITANIUM: call {{.*}}@_ZN1AC1Ev( |
| // CHECK-WINDOWS: call {{.*}}@"??0A@@Q{{AE|EAA}}@XZ"( |
| // CHECK: call {{.*}}@{{.*}}callee{{.*}}( |
| (side_effect(), callee)(A{}); |
| // CHECK: } |
| } |
| |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}dot_lhs_before_rhs{{.*}}( |
| void dot_lhs_before_rhs() { |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( |
| make_a().a_member_f(make_b()); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( |
| make_a_ptr()->a_member_f(make_b()); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}a_member_f{{.*}}( |
| make_c()->a_member_f(make_b()); |
| // CHECK: } |
| } |
| |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}array_lhs_before_rhs{{.*}}( |
| void array_lhs_before_rhs() { |
| int (&get_arr())[10]; |
| extern int get_index(); |
| |
| // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( |
| get_arr()[get_index()] = 0; |
| |
| // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}get_arr{{.*}}( |
| get_index()[get_arr()] = 0; |
| |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| // CHECK: call |
| make_a()[make_b()]; |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( |
| // CHECK: call |
| make_c()[get_index()] = 0; |
| |
| // CHECK: call {{.*}}@{{.*}}get_index{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call |
| get_index()[make_c()] = 0; |
| // CHECK: } |
| } |
| |
| |
| void *operator new(decltype(sizeof(0)), C); |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}alloc_before_init{{.*}}( |
| void alloc_before_init() { |
| struct Q { Q(A) {} }; |
| // CHECK-ITANIUM: call {{.*}}@_Znw{{.*}}( |
| // CHECK-WINDOWS: call {{.*}}@"??2@YAP{{EAX_K|AXI}}@Z"( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| delete new Q(make_a()); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| new (make_c()) Q(make_a()); |
| // CHECK: } |
| } |
| |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}dotstar_lhs_before_rhs{{.*}}( |
| int dotstar_lhs_before_rhs() { |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}( |
| int a = make_a().*make_mem_ptr_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_mem_ptr_a{{.*}}( |
| int b = make_a_ptr()->*make_mem_ptr_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c()->*make_a(); |
| |
| // FIXME: For MS ABI, the order of destruction of parameters here will not be |
| // reverse construction order (parameters are destroyed left-to-right in the |
| // callee). That sadly seems unavoidable; the rules are not implementable as |
| // specified. If we changed parameter destruction order for these functions |
| // to right-to-left, we could make the destruction order match for all cases |
| // other than indirect calls, but we can't completely avoid the problem. |
| // |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c()->*make_b(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}( |
| // CHECK: call |
| (make_a().*make_mem_fn_ptr_a())(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a_ptr{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_mem_fn_ptr_a{{.*}}( |
| // CHECK: call |
| (make_a_ptr()->*make_mem_fn_ptr_a())(); |
| |
| return a + b; |
| // CHECK: } |
| } |
| |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}assign_rhs_before_lhs{{.*}}( |
| void assign_rhs_before_lhs() { |
| extern int &lhs_ref(), rhs(); |
| |
| // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( |
| lhs_ref() = rhs(); |
| |
| // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( |
| lhs_ref() += rhs(); |
| |
| // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}lhs_ref{{.*}}( |
| lhs_ref() %= rhs(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| make_c() = make_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| make_c() += make_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| make_c() += make_b(); |
| // CHECK: } |
| } |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}shift_lhs_before_rhs{{.*}}( |
| void shift_lhs_before_rhs() { |
| extern int lhs(), rhs(); |
| |
| // CHECK: call {{.*}}@{{.*}}lhs{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( |
| (void)(lhs() << rhs()); |
| |
| // CHECK: call {{.*}}@{{.*}}lhs{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}rhs{{.*}}( |
| (void)(lhs() >> rhs()); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c() << make_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c() >> make_a(); |
| |
| // FIXME: This is not correct for Windows ABIs, see above. |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c() << make_b(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c() >> make_b(); |
| // CHECK: } |
| } |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}comma_lhs_before_rhs{{.*}}( |
| void comma_lhs_before_rhs() { |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c() , make_a(); |
| |
| // FIXME: This is not correct for Windows ABIs, see above. |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c() , make_b(); |
| } |
| |
| // CHECK-LABEL: define {{.*}}@{{.*}}andor_lhs_before_rhs{{.*}}( |
| void andor_lhs_before_rhs() { |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c() && make_a(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_a{{.*}}( |
| make_c() || make_a(); |
| |
| // FIXME: This is not correct for Windows ABIs, see above. |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c() && make_b(); |
| |
| // CHECK: call {{.*}}@{{.*}}make_c{{.*}}( |
| // CHECK: call {{.*}}@{{.*}}make_b{{.*}}( |
| make_c() || make_b(); |
| } |