@@ -7368,279 +7368,6 @@ void Sema::CheckCompletedCXXClass(Scope *S, CXXRecordDecl *Record) {
7368
7368
CheckMismatchedTypeAwareAllocators(OO_Array_New, OO_Array_Delete);
7369
7369
}
7370
7370
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
-
7644
7371
/// Look up the special member function that would be called by a special
7645
7372
/// member function for a subobject of class type.
7646
7373
///
0 commit comments