[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-29 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr closed 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-27 Thread Erich Keane via cfe-commits

https://github.com/erichkeane approved this pull request.


https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/65901

>From 5dc457a45bdf8366a5f8e5d7df7bcf3383120ecd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Sun, 10 Sep 2023 17:02:22 +0200
Subject: [PATCH] [clang][Interp] Three-way comparisons

---
 clang/lib/AST/Interp/Boolean.h   |  6 +++
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 23 ++
 clang/lib/AST/Interp/Floating.h  |  6 +++
 clang/lib/AST/Interp/Integral.h  |  7 +++
 clang/lib/AST/Interp/Interp.h| 29 +
 clang/lib/AST/Interp/InterpBuiltin.cpp   | 17 
 clang/lib/AST/Interp/Opcodes.td  |  5 +++
 clang/lib/AST/Interp/Pointer.h   | 13 ++
 clang/test/AST/Interp/cxx20.cpp  | 54 
 9 files changed, 160 insertions(+)

diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 6f0fe26ace68807..c3ed3d61f76ca1c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -84,6 +84,12 @@ class Boolean final {
   Boolean truncate(unsigned TruncBits) const { return *this; }
 
   void print(llvm::raw_ostream ) const { OS << (V ? "true" : "false"); }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index e813d4fa651ceaf..a09e2a007b912c9 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::{strong,weak,partial}_ordering (which is a class, so 
doesn't
+  // have a PrimType).
+  if (!T) {
+if (DiscardResult)
+  return true;
+const ComparisonCategoryInfo *CmpInfo =
+Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
+assert(CmpInfo);
+
+// We need a temporary variable holding our return value.
+if (!Initializing) {
+  std::optional ResultIndex = this->allocateLocal(BO, false);
+  if (!this->emitGetPtrLocal(*ResultIndex, BO))
+return false;
+}
+
+if (!visit(LHS) || !visit(RHS))
+  return false;
+
+return this->emitCMP3(*LT, CmpInfo, BO);
+  }
+
   if (!LT || !RT || !T)
 return this->bail(BO);
 
diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index 9a8fd34ec934893..a22b3fa79f3992f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -76,6 +76,12 @@ class Floating final {
 F.toString(Buffer);
 OS << Buffer;
   }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
 
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 72285cabcbbf8ce..0295a9c3b5c898c 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -128,6 +128,13 @@ template  class Integral final 
{
 return Compare(V, RHS.V);
   }
 
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+OS << V;
+return NameStr;
+  }
+
   unsigned countLeadingZeros() const {
 if constexpr (!Signed)
   return llvm::countl_zero(V);
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8453856e526a6b2..dd37150b63f6db0 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -112,6 +112,11 @@ bool CheckCtorCall(InterpState , CodePtr OpPC, const 
Pointer );
 bool CheckPotentialReinterpretCast(InterpState , CodePtr OpPC,
const Pointer );
 
+/// Sets the given integral value to the pointer, which is of
+/// a std::{weak,partial,strong}_ordering type.
+bool SetThreeWayComparisonField(InterpState , CodePtr OpPC,
+const Pointer , const APSInt );
+
 /// Checks if the shift operation is legal.
 template 
 bool CheckShift(InterpState , CodePtr OpPC, const LT , const RT ,
@@ -781,6 +786,30 @@ bool EQ(InterpState , CodePtr OpPC) {
   });
 }
 
+template ::T>
+bool CMP3(InterpState , CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) 
{
+  const T  = S.Stk.pop();
+  const T  = S.Stk.pop();
+  const Pointer  = S.Stk.peek();
+
+  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
+  if (CmpResult == ComparisonCategoryResult::Unordered) {
+// This should only happen with pointers.
+const 

[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr resolved 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Timm Baeder via cfe-commits


@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a

tbaederr wrote:

Right, I wrote that comment for the first test case I had. Updated it, thanks.

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/65901

>From 0c61a3cd0d02e70bc1cedf048e73af50caf65bd5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Sun, 10 Sep 2023 17:02:22 +0200
Subject: [PATCH] [clang][Interp] Three-way comparisons

---
 clang/lib/AST/Interp/Boolean.h   |  6 +++
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 23 ++
 clang/lib/AST/Interp/Floating.h  |  6 +++
 clang/lib/AST/Interp/Integral.h  |  7 +++
 clang/lib/AST/Interp/Interp.h| 29 +
 clang/lib/AST/Interp/InterpBuiltin.cpp   | 17 
 clang/lib/AST/Interp/Opcodes.td  |  5 +++
 clang/lib/AST/Interp/Pointer.h   | 13 ++
 clang/test/AST/Interp/cxx20.cpp  | 54 
 9 files changed, 160 insertions(+)

diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 6f0fe26ace68807..c3ed3d61f76ca1c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -84,6 +84,12 @@ class Boolean final {
   Boolean truncate(unsigned TruncBits) const { return *this; }
 
   void print(llvm::raw_ostream ) const { OS << (V ? "true" : "false"); }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index e813d4fa651ceaf..f18b969805b373e 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::{strong,weak,partial}_ordering (which is class, so doesn't
+  // have a PrimType).
+  if (!T) {
+if (DiscardResult)
+  return true;
+const ComparisonCategoryInfo *CmpInfo =
+Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
+assert(CmpInfo);
+
+// We need a temporary variable holding our return value.
+if (!Initializing) {
+  std::optional ResultIndex = this->allocateLocal(BO, false);
+  if (!this->emitGetPtrLocal(*ResultIndex, BO))
+return false;
+}
+
+if (!visit(LHS) || !visit(RHS))
+  return false;
+
+return this->emitCMP3(*LT, CmpInfo, BO);
+  }
+
   if (!LT || !RT || !T)
 return this->bail(BO);
 
diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index 9a8fd34ec934893..a22b3fa79f3992f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -76,6 +76,12 @@ class Floating final {
 F.toString(Buffer);
 OS << Buffer;
   }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
 
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 72285cabcbbf8ce..0295a9c3b5c898c 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -128,6 +128,13 @@ template  class Integral final 
{
 return Compare(V, RHS.V);
   }
 
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+OS << V;
+return NameStr;
+  }
+
   unsigned countLeadingZeros() const {
 if constexpr (!Signed)
   return llvm::countl_zero(V);
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8453856e526a6b2..dd37150b63f6db0 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -112,6 +112,11 @@ bool CheckCtorCall(InterpState , CodePtr OpPC, const 
Pointer );
 bool CheckPotentialReinterpretCast(InterpState , CodePtr OpPC,
const Pointer );
 
+/// Sets the given integral value to the pointer, which is of
+/// a std::{weak,partial,strong}_ordering type.
+bool SetThreeWayComparisonField(InterpState , CodePtr OpPC,
+const Pointer , const APSInt );
+
 /// Checks if the shift operation is legal.
 template 
 bool CheckShift(InterpState , CodePtr OpPC, const LT , const RT ,
@@ -781,6 +786,30 @@ bool EQ(InterpState , CodePtr OpPC) {
   });
 }
 
+template ::T>
+bool CMP3(InterpState , CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) 
{
+  const T  = S.Stk.pop();
+  const T  = S.Stk.pop();
+  const Pointer  = S.Stk.peek();
+
+  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
+  if (CmpResult == ComparisonCategoryResult::Unordered) {
+// This should only happen with pointers.
+const 

[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Erich Keane via cfe-commits

https://github.com/erichkeane edited 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Erich Keane via cfe-commits


@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a

erichkeane wrote:

So this isn't really true, see the rules here: 
https://en.cppreference.com/w/cpp/language/default_comparisons

It can end up returning a `std::weak_ordering` or `std::partial_ordering` as 
well.  The rest here is true, but I wanted to make sure you know, since these 
have slightly different semantics that I don't see handled here?

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Erich Keane via cfe-commits


@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a

erichkeane wrote:

I already put that up, but I see lower you refer to all 3, so this is just a 
request to modify that comment as necessary.

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-26 Thread Erich Keane via cfe-commits

https://github.com/erichkeane commented:

This has been sitting a while, else I wouldn't feel comfortable reviewing (as I 
haven't been keeping up on these as much as I should have).  However, I saw 1 
issue with the comment I think, else I'm OK with this.  So if you can fix that, 
I'll approve.

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-25 Thread Timm Baeder via cfe-commits

tbaederr wrote:

Ping

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-18 Thread Timm Baeder via cfe-commits

tbaederr wrote:

Ping

https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-15 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr updated 
https://github.com/llvm/llvm-project/pull/65901

>From 1b76f3b46359c7a688bc5cefc15254253fb57e64 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Sun, 10 Sep 2023 17:02:22 +0200
Subject: [PATCH] [clang][Interp] Three-way comparisons

---
 clang/lib/AST/Interp/Boolean.h   |  6 +++
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 23 ++
 clang/lib/AST/Interp/Floating.h  |  6 +++
 clang/lib/AST/Interp/Integral.h  |  7 +++
 clang/lib/AST/Interp/Interp.h| 29 +
 clang/lib/AST/Interp/InterpBuiltin.cpp   | 17 
 clang/lib/AST/Interp/Opcodes.td  |  5 +++
 clang/lib/AST/Interp/Pointer.h   | 13 ++
 clang/test/AST/Interp/cxx20.cpp  | 54 
 9 files changed, 160 insertions(+)

diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 6f0fe26ace68807..c3ed3d61f76ca1c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -84,6 +84,12 @@ class Boolean final {
   Boolean truncate(unsigned TruncBits) const { return *this; }
 
   void print(llvm::raw_ostream ) const { OS << (V ? "true" : "false"); }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 823bef7a8c19e11..a33dfee0b229ac6 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -253,6 +253,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 return this->delegate(RHS);
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a
+  // PrimType).
+  if (!T) {
+if (DiscardResult)
+  return true;
+const ComparisonCategoryInfo *CmpInfo =
+Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
+assert(CmpInfo);
+
+// We need a temporary variable holding our return value.
+if (!Initializing) {
+  std::optional ResultIndex = this->allocateLocal(BO, false);
+  if (!this->emitGetPtrLocal(*ResultIndex, BO))
+return false;
+}
+
+if (!visit(LHS) || !visit(RHS))
+  return false;
+
+return this->emitCMP3(*LT, CmpInfo, BO);
+  }
+
   if (!LT || !RT || !T)
 return this->bail(BO);
 
diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index 9a8fd34ec934893..a22b3fa79f3992f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -76,6 +76,12 @@ class Floating final {
 F.toString(Buffer);
 OS << Buffer;
   }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
 
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 72285cabcbbf8ce..0295a9c3b5c898c 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -128,6 +128,13 @@ template  class Integral final 
{
 return Compare(V, RHS.V);
   }
 
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+OS << V;
+return NameStr;
+  }
+
   unsigned countLeadingZeros() const {
 if constexpr (!Signed)
   return llvm::countl_zero(V);
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 8453856e526a6b2..dd37150b63f6db0 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -112,6 +112,11 @@ bool CheckCtorCall(InterpState , CodePtr OpPC, const 
Pointer );
 bool CheckPotentialReinterpretCast(InterpState , CodePtr OpPC,
const Pointer );
 
+/// Sets the given integral value to the pointer, which is of
+/// a std::{weak,partial,strong}_ordering type.
+bool SetThreeWayComparisonField(InterpState , CodePtr OpPC,
+const Pointer , const APSInt );
+
 /// Checks if the shift operation is legal.
 template 
 bool CheckShift(InterpState , CodePtr OpPC, const LT , const RT ,
@@ -781,6 +786,30 @@ bool EQ(InterpState , CodePtr OpPC) {
   });
 }
 
+template ::T>
+bool CMP3(InterpState , CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) 
{
+  const T  = S.Stk.pop();
+  const T  = S.Stk.pop();
+  const Pointer  = S.Stk.peek();
+
+  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
+  if (CmpResult == ComparisonCategoryResult::Unordered) {
+// This should only happen with pointers.
+const SourceInfo  = 

[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread via cfe-commits

llvmbot wrote:

@llvm/pr-subscribers-clang


Changes

None
--
Full diff: https://github.com/llvm/llvm-project/pull/65901.diff

9 Files Affected:

- (modified) clang/lib/AST/Interp/Boolean.h (+6) 
- (modified) clang/lib/AST/Interp/ByteCodeExprGen.cpp (+23) 
- (modified) clang/lib/AST/Interp/Floating.h (+6) 
- (modified) clang/lib/AST/Interp/Integral.h (+7) 
- (modified) clang/lib/AST/Interp/Interp.h (+29) 
- (modified) clang/lib/AST/Interp/InterpBuiltin.cpp (+17) 
- (modified) clang/lib/AST/Interp/Opcodes.td (+5) 
- (modified) clang/lib/AST/Interp/Pointer.h (+13) 
- (modified) clang/test/AST/Interp/cxx20.cpp (+54) 



diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 6f0fe26ace68807..c3ed3d61f76ca1c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -84,6 +84,12 @@ class Boolean final {
   Boolean truncate(unsigned TruncBits) const { return *this; }
 
   void print(llvm::raw_ostream ) const { OS << (V ? "true" : "false"); }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6a492c4c907cde0..47e070285aebd67 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -261,6 +261,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 : this->visit(RHS));
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a
+  // PrimType).
+  if (!T) {
+if (DiscardResult)
+  return true;
+const ComparisonCategoryInfo *CmpInfo =
+Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
+assert(CmpInfo);
+
+// We need a temporary variable holding our return value.
+if (!Initializing) {
+  std::optional ResultIndex = this->allocateLocal(BO, false);
+  if (!this->emitGetPtrLocal(*ResultIndex, BO))
+return false;
+}
+
+if (!visit(LHS) || !visit(RHS))
+  return false;
+
+return this->emitCMP3(*LT, CmpInfo, BO);
+  }
+
   if (!LT || !RT || !T)
 return this->bail(BO);
 
diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index 9a8fd34ec934893..a22b3fa79f3992f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -76,6 +76,12 @@ class Floating final {
 F.toString(Buffer);
 OS << Buffer;
   }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
 
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 72285cabcbbf8ce..0295a9c3b5c898c 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -128,6 +128,13 @@ template  class Integral final 
{
 return Compare(V, RHS.V);
   }
 
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+OS << V;
+return NameStr;
+  }
+
   unsigned countLeadingZeros() const {
 if constexpr (!Signed)
   return llvm::countl_zero(V);
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 5006f72fe7237f5..14f23e84386d0fd 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -112,6 +112,11 @@ bool CheckCtorCall(InterpState , CodePtr OpPC, const 
Pointer );
 bool CheckPotentialReinterpretCast(InterpState , CodePtr OpPC,
const Pointer );
 
+/// Sets the given integral value to the pointer, which is of
+/// a std::{weak,partial,strong}_ordering type.
+bool SetThreeWayComparisonField(InterpState , CodePtr OpPC,
+const Pointer , const APSInt );
+
 /// Checks if the shift operation is legal.
 template 
 bool CheckShift(InterpState , CodePtr OpPC, const LT , const RT ,
@@ -773,6 +778,30 @@ bool EQ(InterpState , CodePtr OpPC) {
   });
 }
 
+template ::T>
+bool CMP3(InterpState , CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) 
{
+  const T  = S.Stk.pop();
+  const T  = S.Stk.pop();
+  const Pointer  = S.Stk.peek();
+
+  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
+  if (CmpResult == ComparisonCategoryResult::Unordered) {
+// This should only happen with pointers.
+const SourceInfo  = S.Current->getSource(OpPC);
+S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
+<< LHS.toDiagnosticString(S.getCtx())
+<< RHS.toDiagnosticString(S.getCtx());
+

[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread via cfe-commits

https://github.com/llvmbot labeled 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread via cfe-commits

https://github.com/llvmbot labeled 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr review_requested 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr review_requested 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr review_requested 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr review_requested 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr created 
https://github.com/llvm/llvm-project/pull/65901:

None

>From a8503c150e80df7c505eb0f82941f2fcebe8a97e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Timm=20B=C3=A4der?= 
Date: Sun, 10 Sep 2023 17:02:22 +0200
Subject: [PATCH] [clang][Interp] Three-way comparisons

---
 clang/lib/AST/Interp/Boolean.h   |  6 +++
 clang/lib/AST/Interp/ByteCodeExprGen.cpp | 23 ++
 clang/lib/AST/Interp/Floating.h  |  6 +++
 clang/lib/AST/Interp/Integral.h  |  7 +++
 clang/lib/AST/Interp/Interp.h| 29 +
 clang/lib/AST/Interp/InterpBuiltin.cpp   | 17 
 clang/lib/AST/Interp/Opcodes.td  |  5 +++
 clang/lib/AST/Interp/Pointer.h   | 13 ++
 clang/test/AST/Interp/cxx20.cpp  | 54 
 9 files changed, 160 insertions(+)

diff --git a/clang/lib/AST/Interp/Boolean.h b/clang/lib/AST/Interp/Boolean.h
index 6f0fe26ace68807..c3ed3d61f76ca1c 100644
--- a/clang/lib/AST/Interp/Boolean.h
+++ b/clang/lib/AST/Interp/Boolean.h
@@ -84,6 +84,12 @@ class Boolean final {
   Boolean truncate(unsigned TruncBits) const { return *this; }
 
   void print(llvm::raw_ostream ) const { OS << (V ? "true" : "false"); }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   static Boolean min(unsigned NumBits) { return Boolean(false); }
   static Boolean max(unsigned NumBits) { return Boolean(true); }
diff --git a/clang/lib/AST/Interp/ByteCodeExprGen.cpp 
b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
index 6a492c4c907cde0..47e070285aebd67 100644
--- a/clang/lib/AST/Interp/ByteCodeExprGen.cpp
+++ b/clang/lib/AST/Interp/ByteCodeExprGen.cpp
@@ -261,6 +261,29 @@ bool ByteCodeExprGen::VisitBinaryOperator(const 
BinaryOperator *BO) {
 : this->visit(RHS));
   }
 
+  // Special case for C++'s three-way/spaceship operator <=>, which
+  // returns a std::strong_ordering (which is class, so doesn't have a
+  // PrimType).
+  if (!T) {
+if (DiscardResult)
+  return true;
+const ComparisonCategoryInfo *CmpInfo =
+Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
+assert(CmpInfo);
+
+// We need a temporary variable holding our return value.
+if (!Initializing) {
+  std::optional ResultIndex = this->allocateLocal(BO, false);
+  if (!this->emitGetPtrLocal(*ResultIndex, BO))
+return false;
+}
+
+if (!visit(LHS) || !visit(RHS))
+  return false;
+
+return this->emitCMP3(*LT, CmpInfo, BO);
+  }
+
   if (!LT || !RT || !T)
 return this->bail(BO);
 
diff --git a/clang/lib/AST/Interp/Floating.h b/clang/lib/AST/Interp/Floating.h
index 9a8fd34ec934893..a22b3fa79f3992f 100644
--- a/clang/lib/AST/Interp/Floating.h
+++ b/clang/lib/AST/Interp/Floating.h
@@ -76,6 +76,12 @@ class Floating final {
 F.toString(Buffer);
 OS << Buffer;
   }
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+print(OS);
+return NameStr;
+  }
 
   unsigned bitWidth() const { return F.semanticsSizeInBits(F.getSemantics()); }
 
diff --git a/clang/lib/AST/Interp/Integral.h b/clang/lib/AST/Interp/Integral.h
index 72285cabcbbf8ce..0295a9c3b5c898c 100644
--- a/clang/lib/AST/Interp/Integral.h
+++ b/clang/lib/AST/Interp/Integral.h
@@ -128,6 +128,13 @@ template  class Integral final 
{
 return Compare(V, RHS.V);
   }
 
+  std::string toDiagnosticString(const ASTContext ) const {
+std::string NameStr;
+llvm::raw_string_ostream OS(NameStr);
+OS << V;
+return NameStr;
+  }
+
   unsigned countLeadingZeros() const {
 if constexpr (!Signed)
   return llvm::countl_zero(V);
diff --git a/clang/lib/AST/Interp/Interp.h b/clang/lib/AST/Interp/Interp.h
index 5006f72fe7237f5..14f23e84386d0fd 100644
--- a/clang/lib/AST/Interp/Interp.h
+++ b/clang/lib/AST/Interp/Interp.h
@@ -112,6 +112,11 @@ bool CheckCtorCall(InterpState , CodePtr OpPC, const 
Pointer );
 bool CheckPotentialReinterpretCast(InterpState , CodePtr OpPC,
const Pointer );
 
+/// Sets the given integral value to the pointer, which is of
+/// a std::{weak,partial,strong}_ordering type.
+bool SetThreeWayComparisonField(InterpState , CodePtr OpPC,
+const Pointer , const APSInt );
+
 /// Checks if the shift operation is legal.
 template 
 bool CheckShift(InterpState , CodePtr OpPC, const LT , const RT ,
@@ -773,6 +778,30 @@ bool EQ(InterpState , CodePtr OpPC) {
   });
 }
 
+template ::T>
+bool CMP3(InterpState , CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) 
{
+  const T  = S.Stk.pop();
+  const T  = S.Stk.pop();
+  const Pointer  = S.Stk.peek();
+
+  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
+  if (CmpResult == ComparisonCategoryResult::Unordered) {
+// This should only happen with pointers.
+

[clang] [clang][Interp] Three-way comparisons (PR #65901)

2023-09-10 Thread Timm Baeder via cfe-commits

https://github.com/tbaederr review_requested 
https://github.com/llvm/llvm-project/pull/65901
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits