[clang] [clang] Implement the __builtin_type_order intrinsic for P2830R10 Constexpr Type Ordering (PR #216462)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Aug 15 00:16:34 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-clang-modules
Author: Matthias Wippich (Tsche)
<details>
<summary>Changes</summary>
This patch implements a __builtin_type_order intrinsic to support the implementation of [P2830R10](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2830r10.html) Constexpr Type Ordering.
The `__builtin_type_order` builtin returns a `std::strong_ordering` to match GCC's behavior. Similar to GCC, we establish a total order over all types by doing lexicographical comparisons over the mangled type names. This may yield different orderings with different ABIs.
Resolves https://github.com/llvm/llvm-project/issues/146838
---
Patch is 36.91 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/216462.diff
37 Files Affected:
- (modified) clang/docs/LanguageExtensions.md (+3)
- (modified) clang/docs/ReleaseNotes.md (+3)
- (modified) clang/include/clang/AST/ASTNodeTraverser.h (+5)
- (modified) clang/include/clang/AST/ComputeDependence.h (+2)
- (modified) clang/include/clang/AST/ExprCXX.h (+43)
- (modified) clang/include/clang/AST/RecursiveASTVisitor.h (+5)
- (modified) clang/include/clang/AST/StmtDataCollectors.td (+6)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+1-1)
- (modified) clang/include/clang/Basic/StmtNodes.td (+1)
- (modified) clang/include/clang/Basic/TokenKinds.def (+1)
- (modified) clang/include/clang/Parse/Parser.h (+3)
- (modified) clang/include/clang/Sema/Sema.h (+9)
- (modified) clang/include/clang/Serialization/ASTBitCodes.h (+1)
- (modified) clang/lib/AST/ASTImporter.cpp (+18-1)
- (modified) clang/lib/AST/ASTStructuralEquivalence.cpp (+8)
- (modified) clang/lib/AST/ComputeDependence.cpp (+8)
- (modified) clang/lib/AST/Expr.cpp (+1)
- (modified) clang/lib/AST/ExprClassification.cpp (+1)
- (modified) clang/lib/AST/ExprConstant.cpp (+1)
- (modified) clang/lib/AST/ItaniumMangle.cpp (+1)
- (modified) clang/lib/AST/StmtPrinter.cpp (+8)
- (modified) clang/lib/AST/StmtProfile.cpp (+6)
- (modified) clang/lib/Parse/ParseExpr.cpp (+4)
- (modified) clang/lib/Parse/ParseExprCXX.cpp (+33)
- (modified) clang/lib/Sema/SemaExceptionSpec.cpp (+1)
- (modified) clang/lib/Sema/SemaTypeTraits.cpp (+66)
- (modified) clang/lib/Sema/TreeTransform.h (+33-2)
- (modified) clang/lib/Serialization/ASTReaderStmt.cpp (+13)
- (modified) clang/lib/Serialization/ASTWriter.cpp (+1)
- (modified) clang/lib/Serialization/ASTWriterStmt.cpp (+8)
- (modified) clang/lib/StaticAnalyzer/Core/ExprEngine.cpp (+1)
- (added) clang/test/AST/builtin-type-order.cpp (+35)
- (added) clang/test/PCH/builtin-type-order.cpp (+31)
- (added) clang/test/Parser/builtin_type_order.cpp (+14)
- (added) clang/test/SemaCXX/builtin-type-order.cpp (+82)
- (modified) clang/tools/libclang/CIndex.cpp (+6)
- (modified) clang/tools/libclang/CXCursor.cpp (+1)
``````````diff
diff --git a/clang/docs/LanguageExtensions.md b/clang/docs/LanguageExtensions.md
index 85586174e9190..6080f70ec8311 100644
--- a/clang/docs/LanguageExtensions.md
+++ b/clang/docs/LanguageExtensions.md
@@ -2058,6 +2058,9 @@ The following type trait primitives are supported by Clang. Those traits marked
- `__builtin_lt_synthesizes_from_spaceship`, `__builtin_gt_synthesizes_from_spaceship`,
`__builtin_le_synthesizes_from_spaceship`, `__builtin_ge_synthesizes_from_spaceship` (Clang):
These builtins can be used to determine whether the corresponding operator is synthesized from a spaceship operator.
+- `__builtin_type_order` (C++): Returns `std::strong_ordering::less` if `T` precedes `U` in an
+ implementation-defined total ordering of all types, `std::strong_ordering::greater` if `U` precedes `T`,
+ and `std::strong_ordering::equal` if they are the same type.
In addition, the following expression traits are supported:
diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 9a19bb2f2d5c7..6ac9e3678ade1 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -125,6 +125,9 @@ features cannot lower the translation-unit ABI level;
#### C++2c Feature Support
+- Added `__builtin_type_order` for compatibility with GCC as part of the
+ implementation of [P2830R10](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p2830r10.html) (Constexpr Type Ordering).
+
- Clang now supports [P3533R2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2025/p3533r2.html) (constexpr virtual inheritance).
#### C++23 Feature Support
diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h
index a8a73c5b72d33..14fcbf3656752 100644
--- a/clang/include/clang/AST/ASTNodeTraverser.h
+++ b/clang/include/clang/AST/ASTNodeTraverser.h
@@ -934,6 +934,11 @@ class ASTNodeTraverser
Visit(A->getType());
}
+ void VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *E) {
+ Visit(E->getLhsType());
+ Visit(E->getRhsType());
+ }
+
void VisitLambdaExpr(const LambdaExpr *Node) {
if (Traversal == TK_IgnoreUnlessSpelledInSource) {
for (unsigned I = 0, N = Node->capture_size(); I != N; ++I) {
diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h
index 3a3c86842501a..c78cf273dc17e 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -83,6 +83,7 @@ class CXXDependentScopeMemberExpr;
class MaterializeTemporaryExpr;
class CXXFoldExpr;
class CXXParenListInitExpr;
+class BuiltinTypeOrderExpr;
class TypeTraitExpr;
class ConceptSpecializationExpr;
class SYCLUniqueStableNameExpr;
@@ -178,6 +179,7 @@ ExprDependence computeDependence(CXXDependentScopeMemberExpr *E);
ExprDependence computeDependence(MaterializeTemporaryExpr *E);
ExprDependence computeDependence(CXXFoldExpr *E);
ExprDependence computeDependence(CXXParenListInitExpr *E);
+ExprDependence computeDependence(BuiltinTypeOrderExpr *E);
ExprDependence computeDependence(TypeTraitExpr *E);
ExprDependence computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent);
diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h
index d3d3b9c6d6326..9b56fa5515f7f 100644
--- a/clang/include/clang/AST/ExprCXX.h
+++ b/clang/include/clang/AST/ExprCXX.h
@@ -2886,6 +2886,49 @@ class CXXPseudoDestructorExpr : public Expr {
}
};
+/// Represents a C++26 __builtin_type_order(T, U) expression. Used to implement
+/// std::type_order.
+class BuiltinTypeOrderExpr final : public Expr {
+ friend class ASTStmtReader;
+
+ SourceLocation Loc;
+ SourceLocation RParenLoc;
+ TypeSourceInfo *Lhs;
+ TypeSourceInfo *Rhs;
+
+public:
+ BuiltinTypeOrderExpr(QualType T, SourceLocation Loc, TypeSourceInfo *LHS,
+ TypeSourceInfo *RHS, SourceLocation RParenLoc)
+ : Expr(BuiltinTypeOrderExprClass, T, VK_PRValue, OK_Ordinary), Loc(Loc),
+ RParenLoc(RParenLoc), Lhs(LHS), Rhs(RHS) {
+ setDependence(computeDependence(this));
+ }
+
+ explicit BuiltinTypeOrderExpr(EmptyShell Empty)
+ : Expr(BuiltinTypeOrderExprClass, Empty) {}
+
+ TypeSourceInfo *getLhsTypeInfo() const { return Lhs; }
+ TypeSourceInfo *getRhsTypeInfo() const { return Rhs; }
+
+ QualType getLhsType() const { return getLhsTypeInfo()->getType(); }
+ QualType getRhsType() const { return getRhsTypeInfo()->getType(); }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return Loc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RParenLoc; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == BuiltinTypeOrderExprClass;
+ }
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ const_child_range children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+};
+
/// A type trait used in the implementation of various C++11 and
/// Library TR1 trait templates.
///
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 617990b82edca..2ee34d4675865 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2865,6 +2865,11 @@ DEF_TRAVERSE_STMT(TypeTraitExpr, {
TRY_TO(TraverseTypeLoc(S->getArg(I)->getTypeLoc()));
})
+DEF_TRAVERSE_STMT(BuiltinTypeOrderExpr, {
+ TRY_TO(TraverseTypeLoc(S->getLhsTypeInfo()->getTypeLoc()));
+ TRY_TO(TraverseTypeLoc(S->getRhsTypeInfo()->getTypeLoc()));
+})
+
DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, {
TRY_TO(TraverseTypeLoc(S->getQueriedTypeSourceInfo()->getTypeLoc()));
})
diff --git a/clang/include/clang/AST/StmtDataCollectors.td b/clang/include/clang/AST/StmtDataCollectors.td
index abf4b5f34d349..8b8c9da988579 100644
--- a/clang/include/clang/AST/StmtDataCollectors.td
+++ b/clang/include/clang/AST/StmtDataCollectors.td
@@ -37,6 +37,12 @@ class TypeTraitExpr {
addData(S->getArg(i)->getType());
}];
}
+class BuiltinTypeOrderExpr {
+ code Code = [{
+ addData(S->getLhsType());
+ addData(S->getRhsType());
+ }];
+}
//--- Calls --------------------------------------------------------------//
class CallExpr {
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b314c17ad27bd..9356416eed302 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -13354,7 +13354,7 @@ def warn_invalid_default_version_priority
// three-way comparison operator diagnostics
def err_implied_comparison_category_type_not_found : Error<
- "cannot %select{use builtin operator '<=>'|default 'operator<=>'}1 "
+ "cannot %select{use builtin operator '<=>'|default 'operator<=>'|retrieve type order}1 "
"because type '%0' was not found; include <compare>">;
def err_spaceship_argument_narrowing : Error<
"argument to 'operator<=>' "
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 6df244d7a8c90..0c0f82f944ceb 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -150,6 +150,7 @@ def CXXStdInitializerListExpr : StmtNode<Expr>;
def CXXNewExpr : StmtNode<Expr>;
def CXXDeleteExpr : StmtNode<Expr>;
def CXXPseudoDestructorExpr : StmtNode<Expr>;
+def BuiltinTypeOrderExpr : StmtNode<Expr>;
def TypeTraitExpr : StmtNode<Expr>;
def ArrayTypeTraitExpr : StmtNode<Expr>;
def ExpressionTraitExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Basic/TokenKinds.def b/clang/include/clang/Basic/TokenKinds.def
index dc9c7d8109467..38995aca639a5 100644
--- a/clang/include/clang/Basic/TokenKinds.def
+++ b/clang/include/clang/Basic/TokenKinds.def
@@ -469,6 +469,7 @@ KEYWORD(__builtin_FUNCSIG , KEYMS)
KEYWORD(__builtin_LINE , KEYALL)
KEYWORD(__builtin_COLUMN , KEYALL)
KEYWORD(__builtin_source_location , KEYCXX)
+KEYWORD(__builtin_type_order , KEYCXX)
KEYWORD(__builtin_va_arg , KEYALL)
KEYWORD(__extension__ , KEYALL)
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 163aa483a84e3..feb39ecb5ca55 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -5195,6 +5195,9 @@ class Parser : public CodeCompletionHandler {
///
ExprResult ParseTypeTrait();
+ /// Parse __builtin_type_order(T, U), used to implement C++26 std::type_order.
+ ExprResult ParseBuiltinTypeOrder();
+
//===--------------------------------------------------------------------===//
// Embarcadero: Arary and Expression Traits
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index d931e70cb2342..ecccc1d985924 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -5335,6 +5335,8 @@ class Sema final : public SemaBase {
/// typically only applies to 'std::strong_ordering', due to the implicit
/// fallback return value.
DefaultedOperator,
+ /// The '__builtin_type_order' builtin needed 'std::strong_ordering'.
+ BuiltinTypeOrder,
};
/// Lookup the specified comparison category types in the standard
@@ -8723,6 +8725,13 @@ class Sema final : public SemaBase {
bool CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N);
+ ExprResult ActOnBuiltinTypeOrder(SourceLocation KWLoc, ParsedType LhsTy,
+ ParsedType RhsTy, SourceLocation RParenLoc);
+ ExprResult BuildBuiltinTypeOrderExpr(SourceLocation KWLoc,
+ TypeSourceInfo *LhsT,
+ TypeSourceInfo *RhsT,
+ SourceLocation RParenLoc);
+
/// Parsed one of the type trait support pseudo-functions.
ExprResult ActOnTypeTrait(TypeTrait Kind, SourceLocation KWLoc,
ArrayRef<ParsedType> Args,
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index b582cbdadc070..191918df5e5e7 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1938,6 +1938,7 @@ enum StmtCode {
EXPR_OPAQUE_VALUE, // OpaqueValueExpr
EXPR_BINARY_CONDITIONAL_OPERATOR, // BinaryConditionalOperator
+ EXPR_BUILTIN_TYPE_ORDER, // BuiltinTypeOrderExpr
EXPR_TYPE_TRAIT, // TypeTraitExpr
EXPR_ARRAY_TYPE_TRAIT, // ArrayTypeTraitIntExpr
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index 5be9ce780aec5..a8c03b1eb768c 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -696,7 +696,9 @@ namespace clang {
ExpectedStmt VisitArrayInitIndexExpr(ArrayInitIndexExpr *E);
ExpectedStmt VisitCXXDefaultInitExpr(CXXDefaultInitExpr *E);
ExpectedStmt VisitCXXNamedCastExpr(CXXNamedCastExpr *E);
- ExpectedStmt VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+ ExpectedStmt
+ VisitSubstNonTypeTemplateParmExpr(SubstNonTypeTemplateParmExpr *E);
+ ExpectedStmt VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E);
ExpectedStmt VisitTypeTraitExpr(TypeTraitExpr *E);
ExpectedStmt VisitCXXTypeidExpr(CXXTypeidExpr *E);
ExpectedStmt VisitCXXFoldExpr(CXXFoldExpr *E);
@@ -9157,6 +9159,21 @@ ExpectedStmt ASTNodeImporter::VisitSubstNonTypeTemplateParmExpr(
ToParamType, E->getIndex(), E->getPackIndex(), E->getFinal());
}
+ExpectedStmt
+ASTNodeImporter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) {
+ Error Err = Error::success();
+ auto ToType = importChecked(Err, E->getType());
+ auto ToBeginLoc = importChecked(Err, E->getBeginLoc());
+ auto ToEndLoc = importChecked(Err, E->getEndLoc());
+ auto *ToLhs = importChecked(Err, E->getLhsTypeInfo());
+ auto *ToRhs = importChecked(Err, E->getRhsTypeInfo());
+ if (Err)
+ return std::move(Err);
+
+ return new (Importer.getToContext())
+ BuiltinTypeOrderExpr(ToType, ToBeginLoc, ToLhs, ToRhs, ToEndLoc);
+}
+
ExpectedStmt ASTNodeImporter::VisitTypeTraitExpr(TypeTraitExpr *E) {
Error Err = Error::success();
auto ToType = importChecked(Err, E->getType());
diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp
index d8bbfbe5dac72..7cbcdc1bf8495 100644
--- a/clang/lib/AST/ASTStructuralEquivalence.cpp
+++ b/clang/lib/AST/ASTStructuralEquivalence.cpp
@@ -351,6 +351,14 @@ class StmtComparer {
return true;
}
+ bool IsStmtEquivalent(const BuiltinTypeOrderExpr *E1,
+ const BuiltinTypeOrderExpr *E2) {
+ return IsStructurallyEquivalent(Context, E1->getLhsType(),
+ E2->getLhsType()) &&
+ IsStructurallyEquivalent(Context, E1->getRhsType(),
+ E2->getRhsType());
+ }
+
bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1,
const CXXDependentScopeMemberExpr *E2) {
if (!IsStructurallyEquivalent(Context, E1->getMember(), E2->getMember())) {
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index 7e6bd69711c5b..40ab05f7f8ebc 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -931,6 +931,14 @@ ExprDependence clang::computeDependence(TypeTraitExpr *E) {
return D;
}
+ExprDependence clang::computeDependence(BuiltinTypeOrderExpr *E) {
+ ExprDependence D = ExprDependence::None;
+ for (TypeSourceInfo *Arg : {E->getLhsTypeInfo(), E->getRhsTypeInfo()})
+ D |= toExprDependenceAsWritten(Arg->getType()->getDependence()) &
+ ~ExprDependence::Type;
+ return D;
+}
+
ExprDependence clang::computeDependence(ConceptSpecializationExpr *E,
bool ValueDependent) {
auto TA = TemplateArgumentDependence::None;
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 5d7ee4710481c..55a5d8214e5da 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3747,6 +3747,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case CXXNullPtrLiteralExprClass:
case CXXThisExprClass:
case CXXScalarValueInitExprClass:
+ case BuiltinTypeOrderExprClass:
case TypeTraitExprClass:
case ArrayTypeTraitExprClass:
case ExpressionTraitExprClass:
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index ef071cdef66b6..37d799e329df0 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -192,6 +192,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::FloatingLiteralClass:
case Expr::CXXNoexceptExprClass:
case Expr::CXXScalarValueInitExprClass:
+ case Expr::BuiltinTypeOrderExprClass:
case Expr::TypeTraitExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 480d5119a5363..47df253ddfef4 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -22441,6 +22441,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ObjCBoolLiteralExprClass:
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXScalarValueInitExprClass:
+ case Expr::BuiltinTypeOrderExprClass:
case Expr::TypeTraitExprClass:
case Expr::ConceptSpecializationExprClass:
case Expr::RequiresExprClass:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index f6c4ca1ae6ba8..126c1b67452c5 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -5056,6 +5056,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity,
case Expr::StmtExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::ExpressionTraitExprClass:
+ case Expr::BuiltinTypeOrderExprClass:
case Expr::VAArgExprClass:
case Expr::CUDAKernelCallExprClass:
case Expr::AsTypeExprClass:
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index eeb377c794e05..5f220b26936b1 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -2708,6 +2708,14 @@ void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) {
OS << ")";
}
+void StmtPrinter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) {
+ OS << "__builtin_type_order(";
+ E->getLhsType().print(OS, Policy);
+ OS << ", ";
+ E->getRhsType().print(OS, Policy);
+ OS << ')';
+}
+
void StmtPrinter::VisitArrayTypeTraitExpr(ArrayTypeTraitExpr *E) {
OS << getTraitSpelling(E->getTrait()) << '(';
E->getQueriedType().print(OS, Policy);
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 45c962aa27553..7baf7443b02f6 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -2320,6 +2320,12 @@ void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) {
VisitType(S->getArg(I)->getType());
}
+void StmtProfiler::VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *S) {
+ VisitExpr(S);
+ VisitType(S->getLhsType());
+ VisitType(S->getRhsType());
+}
+
void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) {
VisitExpr(S);
ID.AddInteger(S->getTrait());
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 87cd7a01451cf..a84de3a72170c 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -1523,6 +1523,10 @@ Parser::ParseCastExpression(CastParseKind ParseKind, bool isAddressOfOperand,
break;
}
+ case tok::kw___builtin_type_order:
+ Res = ParseBuiltinTypeOrder();
+ break;
+
#define TYPE_TRAIT(N,Spelling,K) \
case tok::kw_##Spelling:
#include "clang/Basic/TokenKinds.def"
diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp
index f9a0dcc7d53af..57e4f2096a9d9 100644
--- a/clang/lib/Parse/ParseExprCXX.cpp
+++ b/clang/lib/Parse/ParseExprCXX.cpp
@@ -3490,6 +3490,39 @@ static ExpressionTrait ExpressionTraitFromTokKind(tok::TokenKind kind) {
}
}
+ExprResult Parser::ParseBuiltinTypeOrder() {
+ SourceLocation Loc = ConsumeToken();
+
+ BalancedDelimiterTracker Parens(*this, tok::l_paren);
+ if (Parens.expectAndConsume())
+ return ExprError();
+
+ TypeResult LHS = ParseTypeName(/*SourceRange=*/nullptr,
+ DeclaratorContext::TemplateTypeArg);
+ if (LHS.isInvalid()) {
+ Parens.skipToEnd();
+ return ExprError();
+ }
+
+ if (ExpectAndConsume(tok::comma)) {
+ Parens.skipToEnd();
+ return ExprError();
+ }
+
+ TypeResult RHS = ParseTypeName(/*SourceRange=*/nullptr,
+ DeclaratorContext::TemplateTypeArg);
+ if (RHS.isInvalid()) {
+ Parens.skipToEnd();
+ return ExprError();
+ }
+
+ if (Parens.consumeClose())
+ return ExprError();
+
+ return Actions.ActOnBuiltinTypeOrder(Loc, LHS.get(), RHS.get(),
+ Parens.getCloseLocation());
+}
+
ExprResult Parser::ParseTypeTrait() {
tok::TokenKind Kind = Tok.getKind();
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index d41137ddc85d5..213aa6701fdb0 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1390,6 +1390,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Expr::AddrLabelExprClass:
case Expr::ArrayTypeTraitExprClass:
case Expr::AtomicExprClass:
+ case Expr::BuiltinTypeOrderExprClass:
case Expr::TypeTraitExprClass:
case Expr::CXXBoolLiteralExprClass:
case Expr::CXXNoexceptExprClass:
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp
index 53ab235f3654a..78e6d8d76b114 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -10,7 +10,9 @@
//
//===----------------------------------------------------------------------===//
+#include "clang/AST/ComparisonCategories.h"
#include "clang/AST/DeclCXX.h"
+#include "clang/AST/Mangle.h"
#include "clang/AST/TemplateBase.h"
#include "clang/AST/Type.h"
#include "clang/Basic/BuiltinTraits.h"
@@ -25,6 +27,9 @@
#include "clang/Sema/Sema.h"
#include "clang/Sema/SemaHLSL.h"
#include "llvm/ADT/STLExtras.h"
+#inc...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/216462
More information about the cfe-commits
mailing list