@@ -7368,279 +7368,6 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
73687368 CheckMismatchedTypeAwareAllocators(OO_Array_New, OO_Array_Delete);
73697369}
73707370
7371- static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
7372- const CXXRecordDecl *RD,
7373- bool Assign) {
7374- RD = RD->getDefinition();
7375- SourceLocation LookupLoc = RD->getLocation();
7376-
7377- CanQualType CanTy = SemaRef.getASTContext().getCanonicalType(
7378- SemaRef.getASTContext().getTagDeclType(RD));
7379- DeclarationName Name;
7380- Expr *Arg = nullptr;
7381- unsigned NumArgs;
7382-
7383- QualType ArgType = CanTy;
7384- ExprValueKind VK = clang::VK_XValue;
7385-
7386- if (Assign)
7387- Name =
7388- SemaRef.getASTContext().DeclarationNames.getCXXOperatorName(OO_Equal);
7389- else
7390- Name =
7391- SemaRef.getASTContext().DeclarationNames.getCXXConstructorName(CanTy);
7392-
7393- OpaqueValueExpr FakeArg(LookupLoc, ArgType, VK);
7394- NumArgs = 1;
7395- Arg = &FakeArg;
7396-
7397- // Create the object argument
7398- QualType ThisTy = CanTy;
7399- Expr::Classification Classification =
7400- OpaqueValueExpr(LookupLoc, ThisTy, VK_LValue)
7401- .Classify(SemaRef.getASTContext());
7402-
7403- // Now we perform lookup on the name we computed earlier and do overload
7404- // resolution. Lookup is only performed directly into the class since there
7405- // will always be a (possibly implicit) declaration to shadow any others.
7406- OverloadCandidateSet OCS(LookupLoc, OverloadCandidateSet::CSK_Normal);
7407- DeclContext::lookup_result R = RD->lookup(Name);
7408-
7409- if (R.empty())
7410- return nullptr;
7411-
7412- // Copy the candidates as our processing of them may load new declarations
7413- // from an external source and invalidate lookup_result.
7414- SmallVector<NamedDecl *, 8> Candidates(R.begin(), R.end());
7415-
7416- for (NamedDecl *CandDecl : Candidates) {
7417- if (CandDecl->isInvalidDecl())
7418- continue;
7419-
7420- DeclAccessPair Cand = DeclAccessPair::make(CandDecl, clang::AS_none);
7421- auto CtorInfo = getConstructorInfo(Cand);
7422- if (CXXMethodDecl *M = dyn_cast<CXXMethodDecl>(Cand->getUnderlyingDecl())) {
7423- if (Assign)
7424- SemaRef.AddMethodCandidate(M, Cand, const_cast<CXXRecordDecl *>(RD),
7425- ThisTy, Classification,
7426- llvm::ArrayRef(&Arg, NumArgs), OCS, true);
7427- else {
7428- assert(CtorInfo);
7429- SemaRef.AddOverloadCandidate(CtorInfo.Constructor, CtorInfo.FoundDecl,
7430- llvm::ArrayRef(&Arg, NumArgs), OCS,
7431- /*SuppressUserConversions*/ true);
7432- }
7433- } else if (FunctionTemplateDecl *Tmpl =
7434- dyn_cast<FunctionTemplateDecl>(Cand->getUnderlyingDecl())) {
7435- if (Assign)
7436- SemaRef.AddMethodTemplateCandidate(
7437- Tmpl, Cand, const_cast<CXXRecordDecl *>(RD), nullptr, ThisTy,
7438- Classification, llvm::ArrayRef(&Arg, NumArgs), OCS, true);
7439- else {
7440- assert(CtorInfo);
7441- SemaRef.AddTemplateOverloadCandidate(
7442- CtorInfo.ConstructorTmpl, CtorInfo.FoundDecl, nullptr,
7443- llvm::ArrayRef(&Arg, NumArgs), OCS, true);
7444- }
7445- }
7446- }
7447-
7448- OverloadCandidateSet::iterator Best;
7449- switch (OCS.BestViableFunction(SemaRef, LookupLoc, Best)) {
7450- case OR_Success:
7451- return cast<CXXMethodDecl>(Best->Function);
7452- default:
7453- return nullptr;
7454- }
7455- }
7456-
7457- static bool hasSuitableConstructorForRelocation(Sema &SemaRef,
7458- const CXXRecordDecl *D,
7459- bool AllowUserDefined) {
7460- assert(D->hasDefinition() && !D->isInvalidDecl());
7461-
7462- if (D->hasSimpleMoveConstructor() || D->hasSimpleCopyConstructor())
7463- return true;
7464-
7465- CXXMethodDecl *Decl =
7466- LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false);
7467- return Decl && Decl->isUserProvided() == AllowUserDefined;
7468- }
7469-
7470- static bool hasSuitableMoveAssignmentOperatorForRelocation(
7471- Sema &SemaRef, const CXXRecordDecl *D, bool AllowUserDefined) {
7472- assert(D->hasDefinition() && !D->isInvalidDecl());
7473-
7474- if (D->hasSimpleMoveAssignment() || D->hasSimpleCopyAssignment())
7475- return true;
7476-
7477- CXXMethodDecl *Decl =
7478- LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true);
7479- if (!Decl)
7480- return false;
7481-
7482- return Decl && Decl->isUserProvided() == AllowUserDefined;
7483- }
7484-
7485- // [C++26][class.prop]
7486- // A class C is default-movable if
7487- // - overload resolution for direct-initializing an object of type C
7488- // from an xvalue of type C selects a constructor that is a direct member of C
7489- // and is neither user-provided nor deleted,
7490- // - overload resolution for assigning to an lvalue of type C from an xvalue of
7491- // type C selects an assignment operator function that is a direct member of C
7492- // and is neither user-provided nor deleted, and C has a destructor that is
7493- // neither user-provided nor deleted.
7494- static bool IsDefaultMovable(Sema &SemaRef, const CXXRecordDecl *D) {
7495- if (!hasSuitableConstructorForRelocation(SemaRef, D,
7496- /*AllowUserDefined=*/false))
7497- return false;
7498-
7499- if (!hasSuitableMoveAssignmentOperatorForRelocation(
7500- SemaRef, D, /*AllowUserDefined=*/false))
7501- return false;
7502-
7503- CXXDestructorDecl *Dtr = D->getDestructor();
7504-
7505- if (!Dtr)
7506- return true;
7507-
7508- if (Dtr->isUserProvided() && (!Dtr->isDefaulted() || Dtr->isDeleted()))
7509- return false;
7510-
7511- return !Dtr->isDeleted();
7512- }
7513-
7514- // [C++26][class.prop]
7515- // A class is eligible for trivial relocation unless it...
7516- static bool IsEligibleForTrivialRelocation(Sema &SemaRef,
7517- const CXXRecordDecl *D) {
7518-
7519- for (const CXXBaseSpecifier &B : D->bases()) {
7520- const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
7521- if (!BaseDecl)
7522- continue;
7523- // ... has any virtual base classes
7524- // ... has a base class that is not a trivially relocatable class
7525- if (B.isVirtual() || (!BaseDecl->isDependentType() &&
7526- !SemaRef.IsCXXTriviallyRelocatableType(B.getType())))
7527- return false;
7528- }
7529-
7530- for (const FieldDecl *Field : D->fields()) {
7531- if (Field->getType()->isDependentType())
7532- continue;
7533- if (Field->getType()->isReferenceType())
7534- continue;
7535- // ... has a non-static data member of an object type that is not
7536- // of a trivially relocatable type
7537- if (!SemaRef.IsCXXTriviallyRelocatableType(Field->getType()))
7538- return false;
7539- }
7540- return !D->hasDeletedDestructor();
7541- }
7542-
7543- // [C++26][class.prop]
7544- // A class C is eligible for replacement unless
7545- static bool IsEligibleForReplacement(Sema &SemaRef, const CXXRecordDecl *D) {
7546-
7547- for (const CXXBaseSpecifier &B : D->bases()) {
7548- const auto *BaseDecl = B.getType()->getAsCXXRecordDecl();
7549- if (!BaseDecl)
7550- continue;
7551- // it has a base class that is not a replaceable class
7552- if (!BaseDecl->isDependentType() &&
7553- !SemaRef.IsCXXReplaceableType(B.getType()))
7554- return false;
7555- }
7556-
7557- for (const FieldDecl *Field : D->fields()) {
7558- if (Field->getType()->isDependentType())
7559- continue;
7560-
7561- // it has a non-static data member that is not of a replaceable type,
7562- if (!SemaRef.IsCXXReplaceableType(Field->getType()))
7563- return false;
7564- }
7565- return !D->hasDeletedDestructor();
7566- }
7567-
7568- ASTContext::CXXRecordDeclRelocationInfo
7569- Sema::CheckCXX2CRelocatableAndReplaceable(const CXXRecordDecl *D) {
7570- ASTContext::CXXRecordDeclRelocationInfo Info{false, false};
7571-
7572- if (!getLangOpts().CPlusPlus || D->isInvalidDecl())
7573- return Info;
7574-
7575- assert(D->hasDefinition());
7576-
7577- // This is part of "eligible for replacement", however we defer it
7578- // to avoid extraneous computations.
7579- auto HasSuitableSMP = [&] {
7580- return hasSuitableConstructorForRelocation(*this, D,
7581- /*AllowUserDefined=*/true) &&
7582- hasSuitableMoveAssignmentOperatorForRelocation(
7583- *this, D, /*AllowUserDefined=*/true);
7584- };
7585-
7586- auto IsUnion = [&, Is = std::optional<bool>{}]() mutable {
7587- if (!Is.has_value())
7588- Is = D->isUnion() && !D->hasUserDeclaredCopyConstructor() &&
7589- !D->hasUserDeclaredCopyAssignment() &&
7590- !D->hasUserDeclaredMoveOperation() &&
7591- !D->hasUserDeclaredDestructor();
7592- return *Is;
7593- };
7594-
7595- auto IsDefaultMovable = [&, Is = std::optional<bool>{}]() mutable {
7596- if (!Is.has_value())
7597- Is = ::IsDefaultMovable(*this, D);
7598- return *Is;
7599- };
7600-
7601- Info.IsRelocatable = [&] {
7602- if (D->isDependentType())
7603- return false;
7604-
7605- // if it is eligible for trivial relocation
7606- if (!IsEligibleForTrivialRelocation(*this, D))
7607- return false;
7608-
7609- // has the trivially_relocatable_if_eligible class-property-specifier,
7610- if (D->hasAttr<TriviallyRelocatableAttr>())
7611- return true;
7612-
7613- // is a union with no user-declared special member functions, or
7614- if (IsUnion())
7615- return true;
7616-
7617- // is default-movable.
7618- return IsDefaultMovable();
7619- }();
7620-
7621- Info.IsReplaceable = [&] {
7622- if (D->isDependentType())
7623- return false;
7624-
7625- // A class C is a replaceable class if it is eligible for replacement
7626- if (!IsEligibleForReplacement(*this, D))
7627- return false;
7628-
7629- // has the replaceable_if_eligible class-property-specifier
7630- if (D->hasAttr<ReplaceableAttr>())
7631- return HasSuitableSMP();
7632-
7633- // is a union with no user-declared special member functions, or
7634- if (IsUnion())
7635- return HasSuitableSMP();
7636-
7637- // is default-movable.
7638- return IsDefaultMovable();
7639- }();
7640-
7641- return Info;
7642- }
7643-
76447371/// Look up the special member function that would be called by a special
76457372/// member function for a subobject of class type.
76467373///
0 commit comments