Skip to content

[Clang][NFC] Move the type trait logic to a separate file. #141245

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 23, 2025

Conversation

cor3ntin
Copy link
Contributor

Just to try to keep the size of SemaExprCXX.cpp in check.

As discussed in #141238

Just to try to keep the size of SemaExprCXX.cpp in check.

As discussed in llvm#141238
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels May 23, 2025
@cor3ntin cor3ntin requested a review from erichkeane May 23, 2025 15:46
@llvmbot
Copy link
Member

llvmbot commented May 23, 2025

@llvm/pr-subscribers-clang

Author: cor3ntin (cor3ntin)

Changes

Just to try to keep the size of SemaExprCXX.cpp in check.

As discussed in #141238


Patch is 147.71 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141245.diff

4 Files Affected:

  • (modified) clang/lib/Sema/CMakeLists.txt (+1)
  • (modified) clang/lib/Sema/SemaDeclCXX.cpp (-273)
  • (modified) clang/lib/Sema/SemaExprCXX.cpp (-1621)
  • (added) clang/lib/Sema/SemaTypeTraits.cpp (+1919)
diff --git a/clang/lib/Sema/CMakeLists.txt b/clang/lib/Sema/CMakeLists.txt
index 4b87004e4b8ea..51e0ee10b080b 100644
--- a/clang/lib/Sema/CMakeLists.txt
+++ b/clang/lib/Sema/CMakeLists.txt
@@ -96,6 +96,7 @@ add_clang_library(clangSema
   SemaTemplateInstantiateDecl.cpp
   SemaTemplateVariadic.cpp
   SemaType.cpp
+  SemaTypeTraits.cpp
   SemaWasm.cpp
   SemaX86.cpp
   TypeLocBuilder.cpp
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index fe92191b6a687..ead53a995dff1 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -7368,279 +7368,6 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
   CheckMismatchedTypeAwareAllocators(OO_Array_New, OO_Array_Delete);
 }
 
-static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
-                                                    const CXXRecordDecl *RD,
-                                                    bool Assign) {
-  RD = RD->getDefinition();
-  SourceLocation LookupLoc = RD->getLocation();
-
-  CanQualType CanTy = SemaRef.getASTContext().getCanonicalType(
-      SemaRef.getASTContext().getTagDeclType(RD));
-  DeclarationName Name;
-  Expr *Arg = nullptr;
-  unsigned NumArgs;
-
-  QualType ArgType = CanTy;
-  ExprValueKind VK = clang::VK_XValue;
-
-  if (Assign)
-    Name =
-        SemaRef.getASTContext().DeclarationNames.getCXXOperatorName(OO_Equal);
-  else
-    Name =
-        SemaRef.getASTContext().DeclarationNames.getCXXConstructorName(CanTy);
-
-  OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK);
-  NumArgs = 1;
-  Arg = &FakeArg;
-
-  // Create the object argument
-  QualType ThisTy = CanTy;
-  Expr::Classification Classification =
-      OpaqueValueExpr(LookupLoc, ThisTy, VK_LValue)
-          .Classify(SemaRef.getASTContext());
-
-  // Now we perform lookup on the name we computed earlier and do overload
-  // resolution. Lookup is only performed directly into the class since there
-  // will always be a (possibly implicit) declaration to shadow any others.
-  OverloadCandidateSet OCS(LookupLoc, OverloadCandidateSet::CSK_Normal);
-  DeclContext::lookup_result R = RD->lookup(Name);
-
-  if (R.empty())
-    return nullptr;
-
-  // Copy the candidates as our processing of them may load new declarations
-  // from an external source and invalidate lookup_result.
-  SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
-
-  for (NamedDecl *CandDecl : Candidates) {
-    if (CandDecl->isInvalidDecl())
-      continue;
-
-    DeclAccessPair Cand = DeclAccessPair::make(CandDecl, clang::AS_none);
-    auto CtorInfo = getConstructorInfo(Cand);
-    if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) {
-      if (Assign)
-        SemaRef.AddMethodCandidate(M, Cand, const_cast<CXXRecordDecl *>(RD),
-                                   ThisTy, Classification,
-                                   llvm::ArrayRef(&Arg, NumArgs), OCS, true);
-      else {
-        assert(CtorInfo);
-        SemaRef.AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
-                                     llvm::ArrayRef(&Arg, NumArgs), OCS,
-                                     /*SuppressUserConversions*/ true);
-      }
-    } else if (FunctionTemplateDecl *Tmpl =
-                   dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) {
-      if (Assign)
-        SemaRef.AddMethodTemplateCandidate(
-            Tmpl, Cand, const_cast<CXXRecordDecl *>(RD), nullptr, ThisTy,
-            Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true);
-      else {
-        assert(CtorInfo);
-        SemaRef.AddTemplateOverloadCandidate(
-            CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,
-            llvm::ArrayRef(&Arg, NumArgs), OCS, true);
-      }
-    }
-  }
-
-  OverloadCandidateSet::iterator Best;
-  switch (OCS.BestViableFunction(SemaRef, LookupLoc, Best)) {
-  case OR_Success:
-    return cast<CXXMethodDecl>(Best->Function);
-  default:
-    return nullptr;
-  }
-}
-
-static bool hasSuitableConstructorForRelocation(Sema &SemaRef,
-                                                const CXXRecordDecl *D,
-                                                bool AllowUserDefined) {
-  assert(D->hasDefinition() && !D->isInvalidDecl());
-
-  if (D->hasSimpleMoveConstructor() || D->hasSimpleCopyConstructor())
-    return true;
-
-  CXXMethodDecl *Decl =
-      LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false);
-  return Decl && Decl->isUserProvided() == AllowUserDefined;
-}
-
-static bool hasSuitableMoveAssignmentOperatorForRelocation(
-    Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined) {
-  assert(D->hasDefinition() && !D->isInvalidDecl());
-
-  if (D->hasSimpleMoveAssignment() || D->hasSimpleCopyAssignment())
-    return true;
-
-  CXXMethodDecl *Decl =
-      LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true);
-  if (!Decl)
-    return false;
-
-  return Decl && Decl->isUserProvided() == AllowUserDefined;
-}
-
-// [C++26][class.prop]
-// A class C is default-movable if
-// - overload resolution for direct-initializing an object of type C
-// from an xvalue of type C selects a constructor that is a direct member of C
-// and is neither user-provided nor deleted,
-// - overload resolution for assigning to an lvalue of type C from an xvalue of
-// type C selects an assignment operator function that is a direct member of C
-// and is neither user-provided nor deleted, and C has a destructor that is
-// neither user-provided nor deleted.
-static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D) {
-  if (!hasSuitableConstructorForRelocation(SemaRef, D,
-                                           /*AllowUserDefined=*/false))
-    return false;
-
-  if (!hasSuitableMoveAssignmentOperatorForRelocation(
-          SemaRef, D, /*AllowUserDefined=*/false))
-    return false;
-
-  CXXDestructorDecl *Dtr = D->getDestructor();
-
-  if (!Dtr)
-    return true;
-
-  if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))
-    return false;
-
-  return !Dtr->isDeleted();
-}
-
-// [C++26][class.prop]
-// A class is eligible for trivial relocation unless it...
-static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
-                                           const CXXRecordDecl *D) {
-
-  for (const CXXBaseSpecifier &B : D->bases()) {
-    const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
-    if (!BaseDecl)
-      continue;
-    // ... has any virtual base classes
-    // ... has a base class that is not a trivially relocatable class
-    if (B.isVirtual() || (!BaseDecl->isDependentType() &&
-                          !SemaRef.IsCXXTriviallyRelocatableType(B.getType())))
-      return false;
-  }
-
-  for (const FieldDecl *Field : D->fields()) {
-    if (Field->getType()->isDependentType())
-      continue;
-    if (Field->getType()->isReferenceType())
-      continue;
-    // ... has a non-static data member of an object type that is not
-    // of a trivially relocatable type
-    if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))
-      return false;
-  }
-  return !D->hasDeletedDestructor();
-}
-
-// [C++26][class.prop]
-// A class C is eligible for replacement unless
-static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) {
-
-  for (const CXXBaseSpecifier &B : D->bases()) {
-    const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
-    if (!BaseDecl)
-      continue;
-    // it has a base class that is not a replaceable class
-    if (!BaseDecl->isDependentType() &&
-        !SemaRef.IsCXXReplaceableType(B.getType()))
-      return false;
-  }
-
-  for (const FieldDecl *Field : D->fields()) {
-    if (Field->getType()->isDependentType())
-      continue;
-
-    // it has a non-static data member that is not of a replaceable type,
-    if (!SemaRef.IsCXXReplaceableType(Field->getType()))
-      return false;
-  }
-  return !D->hasDeletedDestructor();
-}
-
-ASTContext::CXXRecordDeclRelocationInfo
-Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
-  ASTContext::CXXRecordDeclRelocationInfo Info{false, false};
-
-  if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
-    return Info;
-
-  assert(D->hasDefinition());
-
-  // This is part of "eligible for replacement", however we defer it
-  // to avoid extraneous computations.
-  auto HasSuitableSMP = [&] {
-    return hasSuitableConstructorForRelocation(*this, D,
-                                               /*AllowUserDefined=*/true) &&
-           hasSuitableMoveAssignmentOperatorForRelocation(
-               *this, D, /*AllowUserDefined=*/true);
-  };
-
-  auto IsUnion = [&, Is = std::optional<bool>{}]() mutable {
-    if (!Is.has_value())
-      Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
-           !D->hasUserDeclaredCopyAssignment() &&
-           !D->hasUserDeclaredMoveOperation() &&
-           !D->hasUserDeclaredDestructor();
-    return *Is;
-  };
-
-  auto IsDefaultMovable = [&, Is = std::optional<bool>{}]() mutable {
-    if (!Is.has_value())
-      Is = ::IsDefaultMovable(*this, D);
-    return *Is;
-  };
-
-  Info.IsRelocatable = [&] {
-    if (D->isDependentType())
-      return false;
-
-    // if it is eligible for trivial relocation
-    if (!IsEligibleForTrivialRelocation(*this, D))
-      return false;
-
-    // has the trivially_relocatable_if_eligible class-property-specifier,
-    if (D->hasAttr<TriviallyRelocatableAttr>())
-      return true;
-
-    // is a union with no user-declared special member functions, or
-    if (IsUnion())
-      return true;
-
-    // is default-movable.
-    return IsDefaultMovable();
-  }();
-
-  Info.IsReplaceable = [&] {
-    if (D->isDependentType())
-      return false;
-
-    // A class C is a replaceable class if it is eligible for replacement
-    if (!IsEligibleForReplacement(*this, D))
-      return false;
-
-    // has the replaceable_if_eligible class-property-specifier
-    if (D->hasAttr<ReplaceableAttr>())
-      return HasSuitableSMP();
-
-    // is a union with no user-declared special member functions, or
-    if (IsUnion())
-      return HasSuitableSMP();
-
-    // is default-movable.
-    return IsDefaultMovable();
-  }();
-
-  return Info;
-}
-
 /// Look up the special member function that would be called by a special
 /// member function for a subobject of class type.
 ///
diff --git a/clang/lib/Sema/SemaExprCXX.cpp b/clang/lib/Sema/SemaExprCXX.cpp
index b53877c40668d..63cf324ddb1f9 100644
--- a/clang/lib/Sema/SemaExprCXX.cpp
+++ b/clang/lib/Sema/SemaExprCXX.cpp
@@ -30,7 +30,6 @@
 #include "clang/Basic/PartialDiagnostic.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Basic/TokenKinds.h"
-#include "clang/Basic/TypeTraits.h"
 #include "clang/Lex/Preprocessor.h"
 #include "clang/Sema/DeclSpec.h"
 #include "clang/Sema/EnterExpressionEvaluationContext.h"
@@ -49,7 +48,6 @@
 #include "clang/Sema/TemplateDeduction.h"
 #include "llvm/ADT/APInt.h"
 #include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/TypeSize.h"
@@ -5294,1625 +5292,6 @@ Sema::PerformImplicitConversion(Expr *From, QualType ToType,
   return From;
 }
 
-/// Checks that type T is not a VLA.
-///
-/// @returns @c true if @p T is VLA and a diagnostic was emitted,
-/// @c false otherwise.
-static bool DiagnoseVLAInCXXTypeTrait(Sema &S, const TypeSourceInfo *T,
-                                      clang::tok::TokenKind TypeTraitID) {
-  if (!T->getType()->isVariableArrayType())
-    return false;
-
-  S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_vla_unsupported)
-      << 1 << TypeTraitID;
-  return true;
-}
-
-/// Checks that type T is not an atomic type (_Atomic).
-///
-/// @returns @c true if @p T is VLA and a diagnostic was emitted,
-/// @c false otherwise.
-static bool DiagnoseAtomicInCXXTypeTrait(Sema &S, const TypeSourceInfo *T,
-                                         clang::tok::TokenKind TypeTraitID) {
-  if (!T->getType()->isAtomicType())
-    return false;
-
-  S.Diag(T->getTypeLoc().getBeginLoc(), diag::err_atomic_unsupported)
-      << TypeTraitID;
-  return true;
-}
-
-/// Check the completeness of a type in a unary type trait.
-///
-/// If the particular type trait requires a complete type, tries to complete
-/// it. If completing the type fails, a diagnostic is emitted and false
-/// returned. If completing the type succeeds or no completion was required,
-/// returns true.
-static bool CheckUnaryTypeTraitTypeCompleteness(Sema &S, TypeTrait UTT,
-                                                SourceLocation Loc,
-                                                QualType ArgTy) {
-  // C++0x [meta.unary.prop]p3:
-  //   For all of the class templates X declared in this Clause, instantiating
-  //   that template with a template argument that is a class template
-  //   specialization may result in the implicit instantiation of the template
-  //   argument if and only if the semantics of X require that the argument
-  //   must be a complete type.
-  // We apply this rule to all the type trait expressions used to implement
-  // these class templates. We also try to follow any GCC documented behavior
-  // in these expressions to ensure portability of standard libraries.
-  switch (UTT) {
-  default: llvm_unreachable("not a UTT");
-    // is_complete_type somewhat obviously cannot require a complete type.
-  case UTT_IsCompleteType:
-    // Fall-through
-
-    // These traits are modeled on the type predicates in C++0x
-    // [meta.unary.cat] and [meta.unary.comp]. They are not specified as
-    // requiring a complete type, as whether or not they return true cannot be
-    // impacted by the completeness of the type.
-  case UTT_IsVoid:
-  case UTT_IsIntegral:
-  case UTT_IsFloatingPoint:
-  case UTT_IsArray:
-  case UTT_IsBoundedArray:
-  case UTT_IsPointer:
-  case UTT_IsLvalueReference:
-  case UTT_IsRvalueReference:
-  case UTT_IsMemberFunctionPointer:
-  case UTT_IsMemberObjectPointer:
-  case UTT_IsEnum:
-  case UTT_IsScopedEnum:
-  case UTT_IsUnion:
-  case UTT_IsClass:
-  case UTT_IsFunction:
-  case UTT_IsReference:
-  case UTT_IsArithmetic:
-  case UTT_IsFundamental:
-  case UTT_IsObject:
-  case UTT_IsScalar:
-  case UTT_IsCompound:
-  case UTT_IsMemberPointer:
-  case UTT_IsTypedResourceElementCompatible:
-    // Fall-through
-
-    // These traits are modeled on type predicates in C++0x [meta.unary.prop]
-    // which requires some of its traits to have the complete type. However,
-    // the completeness of the type cannot impact these traits' semantics, and
-    // so they don't require it. This matches the comments on these traits in
-    // Table 49.
-  case UTT_IsConst:
-  case UTT_IsVolatile:
-  case UTT_IsSigned:
-  case UTT_IsUnboundedArray:
-  case UTT_IsUnsigned:
-
-  // This type trait always returns false, checking the type is moot.
-  case UTT_IsInterfaceClass:
-    return true;
-
-  // We diagnose incomplete class types later.
-  case UTT_StructuredBindingSize:
-    return true;
-
-  // C++14 [meta.unary.prop]:
-  //   If T is a non-union class type, T shall be a complete type.
-  case UTT_IsEmpty:
-  case UTT_IsPolymorphic:
-  case UTT_IsAbstract:
-    if (const auto *RD = ArgTy->getAsCXXRecordDecl())
-      if (!RD->isUnion())
-        return !S.RequireCompleteType(
-            Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
-    return true;
-
-  // C++14 [meta.unary.prop]:
-  //   If T is a class type, T shall be a complete type.
-  case UTT_IsFinal:
-  case UTT_IsSealed:
-    if (ArgTy->getAsCXXRecordDecl())
-      return !S.RequireCompleteType(
-          Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
-    return true;
-
-  // LWG3823: T shall be an array type, a complete type, or cv void.
-  case UTT_IsAggregate:
-  case UTT_IsImplicitLifetime:
-    if (ArgTy->isArrayType() || ArgTy->isVoidType())
-      return true;
-
-    return !S.RequireCompleteType(
-        Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
-
-  // has_unique_object_representations<T>
-  // remove_all_extents_t<T> shall be a complete type or cv void (LWG4113).
-  case UTT_HasUniqueObjectRepresentations:
-    ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
-    if (ArgTy->isVoidType())
-      return true;
-    return !S.RequireCompleteType(
-        Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
-
-  // C++1z [meta.unary.prop]:
-  //   remove_all_extents_t<T> shall be a complete type or cv void.
-  case UTT_IsTrivial:
-  case UTT_IsTriviallyCopyable:
-  case UTT_IsStandardLayout:
-  case UTT_IsPOD:
-  case UTT_IsLiteral:
-  case UTT_IsBitwiseCloneable:
-  // By analogy, is_trivially_relocatable and is_trivially_equality_comparable
-  // impose the same constraints.
-  case UTT_IsTriviallyRelocatable:
-  case UTT_IsTriviallyEqualityComparable:
-  case UTT_IsCppTriviallyRelocatable:
-  case UTT_IsReplaceable:
-  case UTT_CanPassInRegs:
-  // Per the GCC type traits documentation, T shall be a complete type, cv void,
-  // or an array of unknown bound. But GCC actually imposes the same constraints
-  // as above.
-  case UTT_HasNothrowAssign:
-  case UTT_HasNothrowMoveAssign:
-  case UTT_HasNothrowConstructor:
-  case UTT_HasNothrowCopy:
-  case UTT_HasTrivialAssign:
-  case UTT_HasTrivialMoveAssign:
-  case UTT_HasTrivialDefaultConstructor:
-  case UTT_HasTrivialMoveConstructor:
-  case UTT_HasTrivialCopy:
-  case UTT_HasTrivialDestructor:
-  case UTT_HasVirtualDestructor:
-    ArgTy = QualType(ArgTy->getBaseElementTypeUnsafe(), 0);
-    [[fallthrough]];
-  // C++1z [meta.unary.prop]:
-  //   T shall be a complete type, cv void, or an array of unknown bound.
-  case UTT_IsDestructible:
-  case UTT_IsNothrowDestructible:
-  case UTT_IsTriviallyDestructible:
-  case UTT_IsIntangibleType:
-    if (ArgTy->isIncompleteArrayType() || ArgTy->isVoidType())
-      return true;
-
-    return !S.RequireCompleteType(
-        Loc, ArgTy, diag::err_incomplete_type_used_in_type_trait_expr);
-  }
-}
-
-static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
-                               Sema &Self, SourceLocation KeyLoc, ASTContext &C,
-                               bool (CXXRecordDecl::*HasTrivial)() const,
-                               bool (CXXRecordDecl::*HasNonTrivial)() const,
-                               bool (CXXMethodDecl::*IsDesiredOp)() const)
-{
-  CXXRecordDecl *RD = cast<CXXRecordDecl>(RT->getDecl());
-  if ((RD->*HasTrivial)() && !(RD->*HasNonTrivial)())
-    return true;
-
-  DeclarationName Name = C.DeclarationNames.getCXXOperatorName(Op);
-  DeclarationNameInfo NameInfo(Name, KeyLoc);
-  LookupResult Res(Self, NameInfo, Sema::LookupOrdinaryName);
-  if (Self.LookupQualifiedName(Res, RD)) {
-    bool FoundOperator = false;
-    Res.suppressDiagnostics();
-    for (LookupResult::iterator Op = Res.begin(), OpEnd = Res.end();
-         Op != OpEnd; ++Op) {
-      if (isa<FunctionTemplateDecl>(*Op))
-        continue;
-
-      CXXMethodDecl *Operator = cast<CXXMethodDecl>(*Op);
-      if((Operator->*IsDesiredOp)()) {
-        FoundOperator = true;
-        auto *CPT = Operator->getType()->castAs<FunctionProtoType>();
-        CPT = Self.ResolveExceptionSpec(KeyLoc, CPT);
-        if (!CPT || !CPT->isNothrow())
-          return false;
-      }
-    }
-    return FoundOperator;
-  }
-  return false;
-}
-
-static bool HasNonDeletedDefaultedEqualityComparison(Sema &S,
-                                                     const CXXRecordDecl *Decl,
-                                                     SourceLocation KeyLoc) {
-  if (Decl->isUnion())
-    return false;
-  if (Decl->isLambda())
-    return Decl->isCapturelessLambda();
-
-  {
-    EnterExpressionEvaluationContext UnevaluatedContext(
-        S, Sema::ExpressionEvaluationContext::Unevaluated);
-    Sema::SFINAETrap SFINAE(S, /*ForValidityCheck=*/true);
-    Sema::ContextRAII TUContext(S, S.Context.getTranslationUnitDecl());
-
-    // const ClassT& obj;
-    OpaqueValueExpr Operand(
-        KeyLoc,
-        Decl->getTypeForDecl()->getCanonicalTypeUnqualified().withConst(),
-        ExprValueKind::VK_LValue);
-    UnresolvedSet<16> Functions;
-    // obj == obj;
-    S.LookupBinOp(S.TUScope, {}, BinaryOperatorKind::BO_EQ, Functions);
-
-    auto Result = S.CreateOverloadedBinOp(KeyLoc, BinaryOperatorKind::BO...
[truncated]

Copy link

github-actions bot commented May 23, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

Copy link
Collaborator

@erichkeane erichkeane left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a copy&paste refactor that makes a lot of sense. Thanks!

@cor3ntin cor3ntin merged commit 9502d1b into llvm:main May 23, 2025
10 of 11 checks passed
@cor3ntin cor3ntin deleted the corentin/split-sema branch May 23, 2025 16:22
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
Just to try to keep the size of SemaExprCXX.cpp in check.

As discussed in llvm#141238
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants