https://github.com/Tsche updated https://github.com/llvm/llvm-project/pull/216462
>From c6ee0d5a900f11bcc7f0f81a13f867518928a4df Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Sat, 15 Aug 2026 09:02:00 +0200 Subject: [PATCH 1/2] [clang] Implement the __builtin_type_order intrinsic for P2830R10 Constexpr Type Ordering --- clang/docs/LanguageExtensions.md | 3 + clang/docs/ReleaseNotes.md | 3 + clang/include/clang/AST/ASTNodeTraverser.h | 5 ++ clang/include/clang/AST/ComputeDependence.h | 2 + clang/include/clang/AST/ExprCXX.h | 43 ++++++++++ clang/include/clang/AST/RecursiveASTVisitor.h | 5 ++ clang/include/clang/AST/StmtDataCollectors.td | 6 ++ .../clang/Basic/DiagnosticSemaKinds.td | 2 +- clang/include/clang/Basic/StmtNodes.td | 1 + clang/include/clang/Basic/TokenKinds.def | 1 + clang/include/clang/Parse/Parser.h | 3 + clang/include/clang/Sema/Sema.h | 9 ++ .../include/clang/Serialization/ASTBitCodes.h | 1 + clang/lib/AST/ASTImporter.cpp | 19 ++++- clang/lib/AST/ASTStructuralEquivalence.cpp | 8 ++ clang/lib/AST/ComputeDependence.cpp | 8 ++ clang/lib/AST/Expr.cpp | 1 + clang/lib/AST/ExprClassification.cpp | 1 + clang/lib/AST/ExprConstant.cpp | 1 + clang/lib/AST/ItaniumMangle.cpp | 1 + clang/lib/AST/StmtPrinter.cpp | 8 ++ clang/lib/AST/StmtProfile.cpp | 6 ++ clang/lib/Parse/ParseExpr.cpp | 4 + clang/lib/Parse/ParseExprCXX.cpp | 33 ++++++++ clang/lib/Sema/SemaExceptionSpec.cpp | 1 + clang/lib/Sema/SemaTypeTraits.cpp | 66 +++++++++++++++ clang/lib/Sema/TreeTransform.h | 35 +++++++- clang/lib/Serialization/ASTReaderStmt.cpp | 13 +++ clang/lib/Serialization/ASTWriter.cpp | 1 + clang/lib/Serialization/ASTWriterStmt.cpp | 8 ++ clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 + clang/test/AST/builtin-type-order.cpp | 35 ++++++++ clang/test/PCH/builtin-type-order.cpp | 31 +++++++ clang/test/Parser/builtin_type_order.cpp | 14 ++++ clang/test/SemaCXX/builtin-type-order.cpp | 82 +++++++++++++++++++ clang/tools/libclang/CIndex.cpp | 6 ++ clang/tools/libclang/CXCursor.cpp | 1 + 37 files changed, 464 insertions(+), 4 deletions(-) create mode 100644 clang/test/AST/builtin-type-order.cpp create mode 100644 clang/test/PCH/builtin-type-order.cpp create mode 100644 clang/test/Parser/builtin_type_order.cpp create mode 100644 clang/test/SemaCXX/builtin-type-order.cpp 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" +#include "llvm/ADT/SmallString.h" +#include "llvm/Support/raw_ostream.h" +#include <memory> using namespace clang; @@ -1463,6 +1468,67 @@ bool Sema::CheckTypeTraitArity(unsigned Arity, SourceLocation Loc, size_t N) { return true; } +static ComparisonCategoryResult EvaluateTypeOrder(Sema &S, QualType LHS, + QualType RHS) { + if (S.Context.hasSameType(LHS, RHS)) + return ComparisonCategoryResult::Equal; + + std::unique_ptr<MangleContext> MC(S.Context.createMangleContext()); + SmallString<64> LhsName, RhsName; + { + llvm::raw_svector_ostream LhsOut(LhsName), RhsOut(RhsName); + MC->mangleCanonicalTypeName(LHS, LhsOut); + MC->mangleCanonicalTypeName(RHS, RhsOut); + } + + int Result = LhsName.compare(RhsName); + return Result == 0 ? ComparisonCategoryResult::Equal + : Result > 0 ? ComparisonCategoryResult::Greater + : ComparisonCategoryResult::Less; +} + +ExprResult Sema::ActOnBuiltinTypeOrder(SourceLocation KWLoc, ParsedType LhsTy, + ParsedType RhsTy, + SourceLocation RParenLoc) { + SmallVector<TypeSourceInfo *, 2> Args; + for (auto ArgT : {LhsTy, RhsTy}) { + TypeSourceInfo *TInfo; + QualType T = GetTypeFromParser(ArgT, &TInfo); + if (!TInfo) + TInfo = Context.getTrivialTypeSourceInfo(T, KWLoc); + + Args.push_back(TInfo); + } + return BuildBuiltinTypeOrderExpr(KWLoc, Args[0], Args[1], RParenLoc); +} + +ExprResult Sema::BuildBuiltinTypeOrderExpr(SourceLocation KWLoc, + TypeSourceInfo *LhsT, + TypeSourceInfo *RhsT, + SourceLocation RParenLoc) { + QualType StrongOrdering = + CheckComparisonCategoryType(ComparisonCategoryType::StrongOrdering, KWLoc, + ComparisonCategoryUsage::BuiltinTypeOrder); + if (StrongOrdering.isNull()) + return ExprError(); + + QualType LHS = LhsT->getType(); + QualType RHS = RhsT->getType(); + if (LHS->isDependentType() || RHS->isDependentType()) + return new (Context) + BuiltinTypeOrderExpr(StrongOrdering, KWLoc, LhsT, RhsT, RParenLoc); + + ComparisonCategoryResult Result = EvaluateTypeOrder(*this, LHS, RHS); + VarDecl *ResultVD = Context.CompCategories.getInfoForType(StrongOrdering) + .getValueInfo(Result) + ->VD; + Expr *ResultExpr = + BuildDeclRefExpr(ResultVD, ResultVD->getType(), VK_LValue, KWLoc); + return PerformCopyInitialization( + InitializedEntity::InitializeTemporary(StrongOrdering), KWLoc, + ResultExpr); +} + enum class TypeTraitReturnType { Bool, SizeT, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index e6abb3ad577c6..035a76c1612de 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -3567,6 +3567,17 @@ class TreeTransform { Operand); } + /// Build a new type ordering expression. + /// + /// By default, performs semantic analysis to build the new expression. + /// Subclasses may override this routine to provide different behavior. + ExprResult RebuildBuiltinTypeOrderExpr(SourceLocation StartLoc, + TypeSourceInfo *LhsT, + TypeSourceInfo *RhsT, + SourceLocation RParenLoc) { + return getSema().BuildBuiltinTypeOrderExpr(StartLoc, LhsT, RhsT, RParenLoc); + } + /// Build a new type trait expression. /// /// By default, performs semantic analysis to build the new expression. @@ -15485,9 +15496,29 @@ TreeTransform<Derived>::TransformUnresolvedLookupExpr(UnresolvedLookupExpr *Old, Old->requiresADL(), &TransArgs); } -template<typename Derived> +template <typename Derived> ExprResult -TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { +TreeTransform<Derived>::TransformBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { + SmallVector<TypeSourceInfo *, 2> Args; + bool ArgChanged = false; + for (TypeSourceInfo *From : {E->getLhsTypeInfo(), E->getRhsTypeInfo()}) { + TypeSourceInfo *To = getDerived().TransformType(From); + if (!To) + return ExprError(); + + Args.push_back(To); + ArgChanged |= To != From; + } + + if (!getDerived().AlwaysRebuild() && !ArgChanged) + return E; + + return getDerived().RebuildBuiltinTypeOrderExpr(E->getBeginLoc(), Args[0], + Args[1], E->getEndLoc()); +} + +template <typename Derived> +ExprResult TreeTransform<Derived>::TransformTypeTraitExpr(TypeTraitExpr *E) { bool ArgChanged = false; SmallVector<TypeSourceInfo *, 4> Args; for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I) { diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 1afde95b05290..2b53f447a29af 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2225,6 +2225,15 @@ void ASTStmtReader::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { E->NamingClass = readDeclAs<CXXRecordDecl>(); } +void ASTStmtReader::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { + VisitExpr(E); + SourceRange Range = readSourceRange(); + E->Loc = Range.getBegin(); + E->RParenLoc = Range.getEnd(); + E->Lhs = readTypeSourceInfo(); + E->Rhs = readTypeSourceInfo(); +} + void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { VisitExpr(E); E->TypeTraitExprBits.IsBooleanTypeTrait = Record.readInt(); @@ -4452,6 +4461,10 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { break; } + case EXPR_BUILTIN_TYPE_ORDER: + S = new (Context) BuiltinTypeOrderExpr(Empty); + break; + case EXPR_TYPE_TRAIT: S = TypeTraitExpr::CreateDeserialized( Context, Record[ASTStmtReader::NumExprFields], diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp index f34b2ff182bc8..1c7df49705658 100644 --- a/clang/lib/Serialization/ASTWriter.cpp +++ b/clang/lib/Serialization/ASTWriter.cpp @@ -866,6 +866,7 @@ static void AddStmtsExprs(llvm::BitstreamWriter &Stream, RECORD(EXPR_CXX_NOEXCEPT); RECORD(EXPR_OPAQUE_VALUE); RECORD(EXPR_BINARY_CONDITIONAL_OPERATOR); + RECORD(EXPR_BUILTIN_TYPE_ORDER); RECORD(EXPR_TYPE_TRAIT); RECORD(EXPR_ARRAY_TYPE_TRAIT); RECORD(EXPR_PACK_EXPANSION); diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 3854eabd62a46..780359f58ed34 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2244,6 +2244,14 @@ void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { } } +void ASTStmtWriter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { + VisitExpr(E); + Record.AddSourceRange(E->getSourceRange()); + Record.AddTypeSourceInfo(E->getLhsTypeInfo()); + Record.AddTypeSourceInfo(E->getRhsTypeInfo()); + Code = serialization::EXPR_BUILTIN_TYPE_ORDER; +} + void ASTStmtWriter::VisitTypeTraitExpr(TypeTraitExpr *E) { VisitExpr(E); Record.push_back(E->TypeTraitExprBits.IsBooleanTypeTrait); diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 328ed5b23dd83..64ff7766ba9a4 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -1699,6 +1699,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::DependentScopeDeclRefExprClass: case Stmt::ArrayTypeTraitExprClass: case Stmt::ExpressionTraitExprClass: + case Stmt::BuiltinTypeOrderExprClass: case Stmt::UnresolvedLookupExprClass: case Stmt::UnresolvedMemberExprClass: case Stmt::RecoveryExprClass: diff --git a/clang/test/AST/builtin-type-order.cpp b/clang/test/AST/builtin-type-order.cpp new file mode 100644 index 0000000000000..7b2447e647273 --- /dev/null +++ b/clang/test/AST/builtin-type-order.cpp @@ -0,0 +1,35 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -ast-print %s | FileCheck %s --check-prefix=PRINT +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -ast-dump -ast-dump-filter=dependent_order %s | FileCheck %s --check-prefix=AST + +namespace std { +enum class __order : signed char { less = -1, equal = 0, greater = 1 }; + +struct strong_ordering { + __order value; + + constexpr explicit strong_ordering(__order value) : value(value) {} + + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering greater; +}; + +inline constexpr strong_ordering strong_ordering::less(__order::less); +inline constexpr strong_ordering strong_ordering::equal(__order::equal); +inline constexpr strong_ordering strong_ordering::greater(__order::greater); +} // namespace std + +template <class T, class U> +constexpr std::strong_ordering dependent_order() { + return __builtin_type_order(T, U); +} + +// PRINT: template <class T, class U> constexpr std::strong_ordering dependent_order() +// PRINT: return __builtin_type_order(T, U); + +// AST-LABEL: FunctionTemplateDecl {{.*}} dependent_order +// AST: BuiltinTypeOrderExpr {{.*}} 'std::strong_ordering' +// AST-NEXT: |-TemplateTypeParmType {{.*}} 'T' dependent +// AST-NEXT: | `-TemplateTypeParm {{.*}} 'T' +// AST-NEXT: `-TemplateTypeParmType {{.*}} 'U' dependent +// AST-NEXT: `-TemplateTypeParm {{.*}} 'U' diff --git a/clang/test/PCH/builtin-type-order.cpp b/clang/test/PCH/builtin-type-order.cpp new file mode 100644 index 0000000000000..f948028bb494f --- /dev/null +++ b/clang/test/PCH/builtin-type-order.cpp @@ -0,0 +1,31 @@ +// RUN: %clang_cc1 -std=c++20 -emit-pch -o %t %s +// RUN: %clang_cc1 -std=c++20 -include-pch %t -DTEST %s -verify +// RUN: %clang_cc1 -std=c++20 -include-pch %t -DTEST %s -verify -fexperimental-new-constant-interpreter + +#ifndef TEST +namespace std { +enum class __order : signed char { less = -1, equal = 0, greater = 1 }; + +struct strong_ordering { + __order value; + + constexpr explicit strong_ordering(__order value) : value(value) {} + + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering greater; +}; + +inline constexpr strong_ordering strong_ordering::less(__order::less); +inline constexpr strong_ordering strong_ordering::equal(__order::equal); +inline constexpr strong_ordering strong_ordering::greater(__order::greater); +} // namespace std + +template <class T, class U> +constexpr auto type_order = __builtin_type_order(T, U); +#else +static_assert(type_order<int, int>.value == std::__order::equal); +static_assert(type_order<int, long>.value != std::__order::equal); + +// expected-no-diagnostics +#endif diff --git a/clang/test/Parser/builtin_type_order.cpp b/clang/test/Parser/builtin_type_order.cpp new file mode 100644 index 0000000000000..293a6b930681b --- /dev/null +++ b/clang/test/Parser/builtin_type_order.cpp @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -fsyntax-only -verify %s + +template <typename... T> +void syntax_errors() { + (void)__builtin_type_order(int); // expected-error {{expected ','}} + (void)__builtin_type_order(T...); // expected-error {{expected ','}} + + (void)__builtin_type_order(int, long, char); + // expected-error@-1 {{expected ')'}} \ + // expected-note@-1 {{to match this '('}} + (void)__builtin_type_order(int, T...); + // expected-error@-1 {{expected ')'}} \ + // expected-note@-1 {{to match this '('}} +} diff --git a/clang/test/SemaCXX/builtin-type-order.cpp b/clang/test/SemaCXX/builtin-type-order.cpp new file mode 100644 index 0000000000000..2de69008b9e23 --- /dev/null +++ b/clang/test/SemaCXX/builtin-type-order.cpp @@ -0,0 +1,82 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fsyntax-only -verify -DITANIUM %s +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -std=c++20 -fsyntax-only -verify -DITANIUM -fexperimental-new-constant-interpreter %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++20 -fsyntax-only -verify -DMICROSOFT %s +// RUN: %clang_cc1 -triple x86_64-pc-windows-msvc -std=c++20 -fsyntax-only -verify -DMICROSOFT -fexperimental-new-constant-interpreter %s + +constexpr auto missing = __builtin_type_order(int, long); +// expected-error@-1 {{cannot retrieve type order because type 'std::strong_ordering' was not found; include <compare>}} + +namespace std { + struct strong_ordering { + enum __order { LT = -1, EQ = 0, GT = 1 }; + __order value; + + constexpr explicit strong_ordering(__order value) : value(value) {} + constexpr bool operator==(strong_ordering const& other) const { + return value == other.value; + } + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering greater; +}; + +inline constexpr strong_ordering strong_ordering::less(__order::LT); +inline constexpr strong_ordering strong_ordering::equal(__order::EQ); +inline constexpr strong_ordering strong_ordering::greater(__order::GT); +} // namespace std + +static_assert(__is_same(decltype(__builtin_type_order(int, long)), + std::strong_ordering)); + +static_assert(__builtin_type_order(int, int) == std::strong_ordering::equal); +static_assert(__builtin_type_order(int, int const) != std::strong_ordering::equal); +static_assert(__builtin_type_order(void(*)(int), void(*)(int)) == std::strong_ordering::equal); + +static_assert(__builtin_type_order(void*, void const volatile*) != std::strong_ordering::equal); +static_assert(__builtin_type_order(int, long) != std::strong_ordering::equal); +static_assert(__builtin_type_order(int, long).value == + -__builtin_type_order(long, int).value); + +using int_alias = int; +static_assert(__builtin_type_order(int, int_alias) == + std::strong_ordering::equal); + +struct incomplete; +static_assert(__builtin_type_order(incomplete, incomplete) == + std::strong_ordering::equal); +static_assert(__builtin_type_order(int incomplete::*, char incomplete::*) != std::strong_ordering::equal); +static_assert(__builtin_type_order(void (incomplete::*)(), void (incomplete::*)() const) != std::strong_ordering::equal); + +struct A {}; +struct B {}; +static_assert(__builtin_type_order(A, B) == std::strong_ordering::less); +static_assert(__builtin_type_order(B, A) == std::strong_ordering::greater); +static_assert(__builtin_type_order(void(*)(A), void(*)(B)) == std::strong_ordering::less); +static_assert(__builtin_type_order(A[1], B[1]) == std::strong_ordering::less); + +#ifdef ITANIUM +static_assert(__builtin_type_order(A, int) == std::strong_ordering::less); +#endif +#ifdef MICROSOFT +static_assert(__builtin_type_order(A, int) == std::strong_ordering::greater); +#endif + +template <class T> struct C; +static_assert(__builtin_type_order(C<A>, C<B>) == std::strong_ordering::less); +static_assert(__builtin_type_order(C<B>, C<A>) == std::strong_ordering::greater); + + +template <class T, class U> +constexpr std::strong_ordering dependent_order() { + return __builtin_type_order(T, U); +} +static_assert(dependent_order<int, int>() == std::strong_ordering::equal); +static_assert(dependent_order<const int, const int>() == + std::strong_ordering::equal); + +template <class T> +constexpr bool dependent_constant_expression() { + static_assert(__builtin_type_order(T, T) == std::strong_ordering::equal); + return true; +} +static_assert(dependent_constant_expression<int>()); diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e485e6e2e5547..e798e691374b1 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -2128,6 +2128,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>, void VisitStmt(const Stmt *S); void VisitSwitchStmt(const SwitchStmt *S); void VisitWhileStmt(const WhileStmt *W); + void VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *E); void VisitTypeTraitExpr(const TypeTraitExpr *E); void VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E); void VisitExpressionTraitExpr(const ExpressionTraitExpr *E); @@ -3271,6 +3272,11 @@ void EnqueueVisitor::VisitTypeTraitExpr(const TypeTraitExpr *E) { AddTypeLoc(E->getArg(I - 1)); } +void EnqueueVisitor::VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *E) { + AddTypeLoc(E->getRhsTypeInfo()); + AddTypeLoc(E->getLhsTypeInfo()); +} + void EnqueueVisitor::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { AddTypeLoc(E->getQueriedTypeSourceInfo()); } diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp index e27964d0ad6e1..421630c764ebc 100644 --- a/clang/tools/libclang/CXCursor.cpp +++ b/clang/tools/libclang/CXCursor.cpp @@ -304,6 +304,7 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent, case Stmt::AsTypeExprClass: case Stmt::AtomicExprClass: case Stmt::BinaryConditionalOperatorClass: + case Stmt::BuiltinTypeOrderExprClass: case Stmt::TypeTraitExprClass: case Stmt::CoawaitExprClass: case Stmt::DependentCoawaitExprClass: >From 6272eb44e77795475dee3225c95728f3c0597f7e Mon Sep 17 00:00:00 2001 From: Matthias Wippich <[email protected]> Date: Mon, 17 Aug 2026 02:12:07 +0200 Subject: [PATCH 2/2] rename Lhs/Rhs to LHS/RHS, break up nested conditional expression --- clang/include/clang/AST/ASTNodeTraverser.h | 4 ++-- clang/include/clang/AST/ExprCXX.h | 14 +++++++------- clang/include/clang/AST/RecursiveASTVisitor.h | 4 ++-- clang/include/clang/AST/StmtDataCollectors.td | 4 ++-- clang/lib/AST/ASTImporter.cpp | 4 ++-- clang/lib/AST/ASTStructuralEquivalence.cpp | 8 ++++---- clang/lib/AST/ComputeDependence.cpp | 2 +- clang/lib/AST/StmtPrinter.cpp | 4 ++-- clang/lib/AST/StmtProfile.cpp | 4 ++-- clang/lib/Sema/SemaTypeTraits.cpp | 7 ++++--- clang/lib/Sema/TreeTransform.h | 2 +- clang/lib/Serialization/ASTReaderStmt.cpp | 4 ++-- clang/lib/Serialization/ASTWriterStmt.cpp | 4 ++-- clang/tools/libclang/CIndex.cpp | 4 ++-- 14 files changed, 35 insertions(+), 34 deletions(-) diff --git a/clang/include/clang/AST/ASTNodeTraverser.h b/clang/include/clang/AST/ASTNodeTraverser.h index 14fcbf3656752..e7c02bdae2d74 100644 --- a/clang/include/clang/AST/ASTNodeTraverser.h +++ b/clang/include/clang/AST/ASTNodeTraverser.h @@ -935,8 +935,8 @@ class ASTNodeTraverser } void VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *E) { - Visit(E->getLhsType()); - Visit(E->getRhsType()); + Visit(E->getLHSType()); + Visit(E->getRHSType()); } void VisitLambdaExpr(const LambdaExpr *Node) { diff --git a/clang/include/clang/AST/ExprCXX.h b/clang/include/clang/AST/ExprCXX.h index 9b56fa5515f7f..a8ad7065e60bb 100644 --- a/clang/include/clang/AST/ExprCXX.h +++ b/clang/include/clang/AST/ExprCXX.h @@ -2893,25 +2893,25 @@ class BuiltinTypeOrderExpr final : public Expr { SourceLocation Loc; SourceLocation RParenLoc; - TypeSourceInfo *Lhs; - TypeSourceInfo *Rhs; + 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) { + 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; } + TypeSourceInfo *getLHSTypeInfo() const { return LHS; } + TypeSourceInfo *getRHSTypeInfo() const { return RHS; } - QualType getLhsType() const { return getLhsTypeInfo()->getType(); } - QualType getRhsType() const { return getRhsTypeInfo()->getType(); } + 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; } diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h index 2ee34d4675865..e204da9ca3899 100644 --- a/clang/include/clang/AST/RecursiveASTVisitor.h +++ b/clang/include/clang/AST/RecursiveASTVisitor.h @@ -2866,8 +2866,8 @@ DEF_TRAVERSE_STMT(TypeTraitExpr, { }) DEF_TRAVERSE_STMT(BuiltinTypeOrderExpr, { - TRY_TO(TraverseTypeLoc(S->getLhsTypeInfo()->getTypeLoc())); - TRY_TO(TraverseTypeLoc(S->getRhsTypeInfo()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(S->getLHSTypeInfo()->getTypeLoc())); + TRY_TO(TraverseTypeLoc(S->getRHSTypeInfo()->getTypeLoc())); }) DEF_TRAVERSE_STMT(ArrayTypeTraitExpr, { diff --git a/clang/include/clang/AST/StmtDataCollectors.td b/clang/include/clang/AST/StmtDataCollectors.td index 8b8c9da988579..7863cca48d079 100644 --- a/clang/include/clang/AST/StmtDataCollectors.td +++ b/clang/include/clang/AST/StmtDataCollectors.td @@ -39,8 +39,8 @@ class TypeTraitExpr { } class BuiltinTypeOrderExpr { code Code = [{ - addData(S->getLhsType()); - addData(S->getRhsType()); + addData(S->getLHSType()); + addData(S->getRHSType()); }]; } diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index a8c03b1eb768c..e85f0c49e8807 100644 --- a/clang/lib/AST/ASTImporter.cpp +++ b/clang/lib/AST/ASTImporter.cpp @@ -9165,8 +9165,8 @@ ASTNodeImporter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { 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()); + auto *ToLhs = importChecked(Err, E->getLHSTypeInfo()); + auto *ToRhs = importChecked(Err, E->getRHSTypeInfo()); if (Err) return std::move(Err); diff --git a/clang/lib/AST/ASTStructuralEquivalence.cpp b/clang/lib/AST/ASTStructuralEquivalence.cpp index 7cbcdc1bf8495..e9292792bc823 100644 --- a/clang/lib/AST/ASTStructuralEquivalence.cpp +++ b/clang/lib/AST/ASTStructuralEquivalence.cpp @@ -353,10 +353,10 @@ class StmtComparer { bool IsStmtEquivalent(const BuiltinTypeOrderExpr *E1, const BuiltinTypeOrderExpr *E2) { - return IsStructurallyEquivalent(Context, E1->getLhsType(), - E2->getLhsType()) && - IsStructurallyEquivalent(Context, E1->getRhsType(), - E2->getRhsType()); + return IsStructurallyEquivalent(Context, E1->getLHSType(), + E2->getLHSType()) && + IsStructurallyEquivalent(Context, E1->getRHSType(), + E2->getRHSType()); } bool IsStmtEquivalent(const CXXDependentScopeMemberExpr *E1, diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp index 40ab05f7f8ebc..8e14387641030 100644 --- a/clang/lib/AST/ComputeDependence.cpp +++ b/clang/lib/AST/ComputeDependence.cpp @@ -933,7 +933,7 @@ ExprDependence clang::computeDependence(TypeTraitExpr *E) { ExprDependence clang::computeDependence(BuiltinTypeOrderExpr *E) { ExprDependence D = ExprDependence::None; - for (TypeSourceInfo *Arg : {E->getLhsTypeInfo(), E->getRhsTypeInfo()}) + for (TypeSourceInfo *Arg : {E->getLHSTypeInfo(), E->getRHSTypeInfo()}) D |= toExprDependenceAsWritten(Arg->getType()->getDependence()) & ~ExprDependence::Type; return D; diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 5f220b26936b1..44acfc28113c4 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -2710,9 +2710,9 @@ void StmtPrinter::VisitTypeTraitExpr(TypeTraitExpr *E) { void StmtPrinter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { OS << "__builtin_type_order("; - E->getLhsType().print(OS, Policy); + E->getLHSType().print(OS, Policy); OS << ", "; - E->getRhsType().print(OS, Policy); + E->getRHSType().print(OS, Policy); OS << ')'; } diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index 7baf7443b02f6..d2ff5f6742321 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -2322,8 +2322,8 @@ void StmtProfiler::VisitTypeTraitExpr(const TypeTraitExpr *S) { void StmtProfiler::VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *S) { VisitExpr(S); - VisitType(S->getLhsType()); - VisitType(S->getRhsType()); + VisitType(S->getLHSType()); + VisitType(S->getRHSType()); } void StmtProfiler::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *S) { diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 78e6d8d76b114..898e7ce71a311 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -1482,9 +1482,10 @@ static ComparisonCategoryResult EvaluateTypeOrder(Sema &S, QualType LHS, } int Result = LhsName.compare(RhsName); - return Result == 0 ? ComparisonCategoryResult::Equal - : Result > 0 ? ComparisonCategoryResult::Greater - : ComparisonCategoryResult::Less; + if (Result == 0) + return ComparisonCategoryResult::Equal; + return Result > 0 ? ComparisonCategoryResult::Greater + : ComparisonCategoryResult::Less; } ExprResult Sema::ActOnBuiltinTypeOrder(SourceLocation KWLoc, ParsedType LhsTy, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 035a76c1612de..aa630a55fa965 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -15501,7 +15501,7 @@ ExprResult TreeTransform<Derived>::TransformBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { SmallVector<TypeSourceInfo *, 2> Args; bool ArgChanged = false; - for (TypeSourceInfo *From : {E->getLhsTypeInfo(), E->getRhsTypeInfo()}) { + for (TypeSourceInfo *From : {E->getLHSTypeInfo(), E->getRHSTypeInfo()}) { TypeSourceInfo *To = getDerived().TransformType(From); if (!To) return ExprError(); diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index 2b53f447a29af..09572ffef827b 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -2230,8 +2230,8 @@ void ASTStmtReader::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { SourceRange Range = readSourceRange(); E->Loc = Range.getBegin(); E->RParenLoc = Range.getEnd(); - E->Lhs = readTypeSourceInfo(); - E->Rhs = readTypeSourceInfo(); + E->LHS = readTypeSourceInfo(); + E->RHS = readTypeSourceInfo(); } void ASTStmtReader::VisitTypeTraitExpr(TypeTraitExpr *E) { diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 780359f58ed34..1983e7fef73a9 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -2247,8 +2247,8 @@ void ASTStmtWriter::VisitUnresolvedLookupExpr(UnresolvedLookupExpr *E) { void ASTStmtWriter::VisitBuiltinTypeOrderExpr(BuiltinTypeOrderExpr *E) { VisitExpr(E); Record.AddSourceRange(E->getSourceRange()); - Record.AddTypeSourceInfo(E->getLhsTypeInfo()); - Record.AddTypeSourceInfo(E->getRhsTypeInfo()); + Record.AddTypeSourceInfo(E->getLHSTypeInfo()); + Record.AddTypeSourceInfo(E->getRHSTypeInfo()); Code = serialization::EXPR_BUILTIN_TYPE_ORDER; } diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp index e798e691374b1..e424bf412adc8 100644 --- a/clang/tools/libclang/CIndex.cpp +++ b/clang/tools/libclang/CIndex.cpp @@ -3273,8 +3273,8 @@ void EnqueueVisitor::VisitTypeTraitExpr(const TypeTraitExpr *E) { } void EnqueueVisitor::VisitBuiltinTypeOrderExpr(const BuiltinTypeOrderExpr *E) { - AddTypeLoc(E->getRhsTypeInfo()); - AddTypeLoc(E->getLhsTypeInfo()); + AddTypeLoc(E->getRHSTypeInfo()); + AddTypeLoc(E->getLHSTypeInfo()); } void EnqueueVisitor::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
