| // RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple %itanium_abi_triple | FileCheck %s --check-prefixes=CHECK,ITANIUM |
| // RUN: %clang_cc1 -std=c++2a -emit-llvm %s -o - -triple x86_64-pc-win32 2>&1 | FileCheck %s --check-prefixes=CHECK,MSABI |
| |
| namespace std { |
| struct strong_ordering { |
| int n; |
| constexpr operator int() const { return n; } |
| static const strong_ordering less, equal, greater; |
| }; |
| constexpr strong_ordering strong_ordering::less = {-1}; |
| constexpr strong_ordering strong_ordering::equal = {0}; |
| constexpr strong_ordering strong_ordering::greater = {1}; |
| } |
| |
| struct Primary { |
| virtual void f(); |
| std::strong_ordering operator<=>(const Primary&) const = default; |
| }; |
| struct X { |
| virtual struct Y &operator=(Y&&); |
| virtual struct Y &operator=(const Y&); |
| std::strong_ordering operator<=>(const X&) const = default; |
| }; |
| // The vtable for Y should contain the following entries in order: |
| // - Primary::f |
| // - Y::operator<=> |
| // - Y::operator=(const Y&) (implicit) |
| // - Y::operator=(Y&&) (implicit) |
| // - Y::operator==(const Y&) const (implicit) |
| // See: |
| // https://github.com/itanium-cxx-abi/cxx-abi/issues/83 for assignment operator |
| // https://github.com/itanium-cxx-abi/cxx-abi/issues/88 for equality comparison |
| // FIXME: What rule does MSVC use? |
| struct Y : Primary, X { |
| virtual std::strong_ordering operator<=>(const Y&) const = default; |
| }; |
| Y y; |
| // ITANIUM: @_ZTV1Y = {{.*}}constant {{.*}} null, {{.*}} @_ZTI1Y {{.*}} @_ZN7Primary1fEv {{.*}} @_ZNK1YssERKS_ {{.*}} @_ZN1YaSERKS_ {{.*}} @_ZN1YaSEOS_ {{.*}} @_ZNK1YeqERKS_ {{.*}} -[[POINTERSIZE:4|8]] |
| // ITANIUM-SAME: @_ZTI1Y {{.*}} @_ZThn[[POINTERSIZE]]_N1YaSERKS_ |
| |
| struct A { |
| void operator<=>(int); |
| }; |
| |
| // ITANIUM: define {{.*}}@_ZN1AssEi( |
| // MSABI: define {{.*}}@"??__MA@@QEAAXH@Z"( |
| void A::operator<=>(int) {} |
| |
| // ITANIUM: define {{.*}}@_Zssi1A( |
| // MSABI: define {{.*}}@"??__M@YAXHUA@@@Z"( |
| void operator<=>(int, A) {} |
| |
| int operator<=>(A, A); |
| |
| // ITANIUM: define {{.*}}_Z1f1A( |
| // MSABI: define {{.*}}@"?f@@YAHUA@@@Z"( |
| int f(A a) { |
| // ITANIUM: %[[RET:.*]] = call {{.*}}_Zss1AS_( |
| // ITANIUM: ret i32 %[[RET]] |
| // MSABI: %[[RET:.*]] = call {{.*}}"??__M@YAHUA@@0@Z"( |
| // MSABI: ret i32 %[[RET]] |
| return a <=> a; |
| } |
| |
| // CHECK-LABEL: define {{.*}}builtin_cmp |
| void builtin_cmp(int a) { |
| // CHECK: icmp slt |
| // CHECK: select |
| // CHECK: icmp eq |
| // CHECK: select |
| a <=> a; |
| } |