[C++2a] Implement operator<=> CodeGen and ExprConstant
Summary:
This patch tackles long hanging fruit for the builtin operator<=> expressions. It is currently needs some cleanup before landing, but I want to get some initial feedback.
The main changes are:
* Lookup, build, and store the required standard library types and expressions in `ASTContext`. By storing them in ASTContext we don't need to store (and duplicate) the required expressions in the BinaryOperator AST nodes.
* Implement [expr.spaceship] checking, including diagnosing narrowing conversions.
* Implement `ExprConstant` for builtin spaceship operators.
* Implement builitin operator<=> support in `CodeGenAgg`. Initially I emitted the required comparisons using `ScalarExprEmitter::VisitBinaryOperator`, but this caused the operand expressions to be emitted once for every required cmp.
* Implement [builtin.over] with modifications to support the intent of P0946R0. See the note on `BuiltinOperatorOverloadBuilder::addThreeWayArithmeticOverloads` for more information about the workaround.
Reviewers: rsmith, aaron.ballman, majnemer, rnk, compnerd, rjmccall
Reviewed By: rjmccall
Subscribers: rjmccall, rsmith, aaron.ballman, junbuml, mgorny, cfe-commits
Differential Revision: https://reviews.llvm.org/D45476
llvm-svn: 331677
diff --git a/clang/test/SemaCXX/std-compare-cxx2a.cpp b/clang/test/SemaCXX/std-compare-cxx2a.cpp
new file mode 100644
index 0000000..3aa625a
--- /dev/null
+++ b/clang/test/SemaCXX/std-compare-cxx2a.cpp
@@ -0,0 +1,65 @@
+// Test diagnostics for ill-formed STL <compare> headers.
+
+// RUN: %clang_cc1 -triple x86_64-apple-darwin -fcxx-exceptions -fsyntax-only -pedantic -verify -Wsign-compare -std=c++2a %s
+
+void compare_not_found_test() {
+ // expected-error@+1 {{cannot deduce return type of 'operator<=>' because type partial_ordering was not found; include <compare>}}
+ (void)(0.0 <=> 42.123);
+}
+
+namespace std {
+inline namespace __1 {
+struct partial_ordering; // expected-note {{forward declaration}}
+}
+} // namespace std
+
+auto compare_incomplete_test() {
+ // expected-error@+1 {{incomplete type 'std::partial_ordering' where a complete type is required}}
+ return (-1.2 <=> 123.0);
+}
+
+namespace std {
+inline namespace __1 {
+struct partial_ordering {
+ unsigned value;
+};
+} // namespace __1
+} // namespace std
+
+auto missing_member_test() {
+ // expected-error@+1 {{standard library implementation of 'std::partial_ordering' is not supported; member 'equivalent' is missing}}
+ return (1.0 <=> 1.0);
+}
+
+namespace std {
+inline namespace __1 {
+struct strong_ordering {
+ long long value;
+ static const strong_ordering equivalent; // expected-note {{declared here}}
+};
+} // namespace __1
+} // namespace std
+
+auto test_non_constexpr_var() {
+ // expected-error@+1 {{standard library implementation of 'std::strong_ordering' is not supported; member 'equivalent' does not have expected form}}
+ return (1 <=> 0);
+}
+
+namespace std {
+inline namespace __1 {
+struct strong_equality {
+ char value = 0;
+ constexpr strong_equality() = default;
+ // non-trivial
+ constexpr strong_equality(strong_equality const &other) : value(other.value) {}
+};
+} // namespace __1
+} // namespace std
+
+struct Class {};
+using MemPtr = void (Class::*)(int);
+
+auto test_non_trivial(MemPtr LHS, MemPtr RHS) {
+ // expected-error@+1 {{standard library implementation of 'std::strong_equality' is not supported; the type is not trivially copyable}}
+ return LHS <=> RHS;
+}