|  | // 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(); | 
|  | } |