Skip to content

Commit 9502d1b

Browse files
authored
[Clang][NFC] Move the type trait logic to a separate file. (#141245)
Just to try to keep the size of SemaExprCXX.cpp in check. As discussed in #141238
1 parent cd7104e commit 9502d1b

File tree

4 files changed

+1920
-1895
lines changed

4 files changed

+1920
-1895
lines changed

clang/lib/Sema/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ add_clang_library(clangSema
9696
SemaTemplateInstantiateDecl.cpp
9797
SemaTemplateVariadic.cpp
9898
SemaType.cpp
99+
SemaTypeTraits.cpp
99100
SemaWasm.cpp
100101
SemaX86.cpp
101102
TypeLocBuilder.cpp

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 0 additions & 273 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)