forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			272 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			272 lines
		
	
	
		
			7.5 KiB
		
	
	
	
		
			C++
		
	
	
	
| // 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();
 | |
| }
 |