@@ -104,6 +104,7 @@ static CXXMethodDecl *LookupSpecialMemberFromXValue(Sema &SemaRef,
104
104
OverloadCandidateSet::iterator Best;
105
105
switch (OCS.BestViableFunction (SemaRef, LookupLoc, Best)) {
106
106
case OR_Success:
107
+ case OR_Deleted:
107
108
return cast<CXXMethodDecl>(Best->Function );
108
109
default :
109
110
return nullptr ;
@@ -120,7 +121,8 @@ static bool hasSuitableConstructorForRelocation(Sema &SemaRef,
120
121
121
122
CXXMethodDecl *Decl =
122
123
LookupSpecialMemberFromXValue (SemaRef, D, /* Assign=*/ false );
123
- return Decl && Decl->isUserProvided () == AllowUserDefined;
124
+ return Decl && Decl->isUserProvided () == AllowUserDefined &&
125
+ !Decl->isDeleted ();
124
126
}
125
127
126
128
static bool hasSuitableMoveAssignmentOperatorForRelocation (
@@ -135,7 +137,8 @@ static bool hasSuitableMoveAssignmentOperatorForRelocation(
135
137
if (!Decl)
136
138
return false ;
137
139
138
- return Decl && Decl->isUserProvided () == AllowUserDefined;
140
+ return Decl && Decl->isUserProvided () == AllowUserDefined &&
141
+ !Decl->isDeleted ();
139
142
}
140
143
141
144
// [C++26][class.prop]
@@ -1940,6 +1943,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
1940
1943
return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
1941
1944
.Case (" is_trivially_relocatable" ,
1942
1945
TypeTrait::UTT_IsCppTriviallyRelocatable)
1946
+ .Case (" is_replaceable" , TypeTrait::UTT_IsReplaceable)
1943
1947
.Case (" is_trivially_copyable" , TypeTrait::UTT_IsTriviallyCopyable)
1944
1948
.Default (std::nullopt);
1945
1949
}
@@ -2005,35 +2009,8 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) {
2005
2009
return std::nullopt;
2006
2010
}
2007
2011
2008
- static void DiagnoseNonTriviallyRelocatableReason (Sema &SemaRef,
2009
- SourceLocation Loc,
2010
- const CXXRecordDecl *D) {
2011
- for (const CXXBaseSpecifier &B : D->bases ()) {
2012
- assert (B.getType ()->getAsCXXRecordDecl () && " invalid base?" );
2013
- if (B.isVirtual ())
2014
- SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2015
- << diag::TraitNotSatisfiedReason::VBase << B.getType ()
2016
- << B.getSourceRange ();
2017
- if (!SemaRef.IsCXXTriviallyRelocatableType (B.getType ()))
2018
- SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2019
- << diag::TraitNotSatisfiedReason::NTRBase << B.getType ()
2020
- << B.getSourceRange ();
2021
- }
2022
- for (const FieldDecl *Field : D->fields ()) {
2023
- if (!Field->getType ()->isReferenceType () &&
2024
- !SemaRef.IsCXXTriviallyRelocatableType (Field->getType ()))
2025
- SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2026
- << diag::TraitNotSatisfiedReason::NTRField << Field
2027
- << Field->getType () << Field->getSourceRange ();
2028
- }
2029
- if (D->hasDeletedDestructor ())
2030
- SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2031
- << diag::TraitNotSatisfiedReason::DeletedDtr << /* Deleted*/ 0
2032
- << D->getDestructor ()->getSourceRange ();
2033
-
2034
- if (D->hasAttr <TriviallyRelocatableAttr>())
2035
- return ;
2036
-
2012
+ static void DiagnoseNonDefaultMovable (Sema &SemaRef, SourceLocation Loc,
2013
+ const CXXRecordDecl *D) {
2037
2014
if (D->isUnion ()) {
2038
2015
auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) {
2039
2016
if (Has)
@@ -2074,6 +2051,37 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2074
2051
<< Dtr->getSourceRange ();
2075
2052
}
2076
2053
2054
+ static void DiagnoseNonTriviallyRelocatableReason (Sema &SemaRef,
2055
+ SourceLocation Loc,
2056
+ const CXXRecordDecl *D) {
2057
+ for (const CXXBaseSpecifier &B : D->bases ()) {
2058
+ assert (B.getType ()->getAsCXXRecordDecl () && " invalid base?" );
2059
+ if (B.isVirtual ())
2060
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2061
+ << diag::TraitNotSatisfiedReason::VBase << B.getType ()
2062
+ << B.getSourceRange ();
2063
+ if (!SemaRef.IsCXXTriviallyRelocatableType (B.getType ()))
2064
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2065
+ << diag::TraitNotSatisfiedReason::NTRBase << B.getType ()
2066
+ << B.getSourceRange ();
2067
+ }
2068
+ for (const FieldDecl *Field : D->fields ()) {
2069
+ if (!Field->getType ()->isReferenceType () &&
2070
+ !SemaRef.IsCXXTriviallyRelocatableType (Field->getType ()))
2071
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2072
+ << diag::TraitNotSatisfiedReason::NTRField << Field
2073
+ << Field->getType () << Field->getSourceRange ();
2074
+ }
2075
+ if (D->hasDeletedDestructor ())
2076
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2077
+ << diag::TraitNotSatisfiedReason::DeletedDtr << /* Deleted*/ 0
2078
+ << D->getDestructor ()->getSourceRange ();
2079
+
2080
+ if (D->hasAttr <TriviallyRelocatableAttr>())
2081
+ return ;
2082
+ DiagnoseNonDefaultMovable (SemaRef, Loc, D);
2083
+ }
2084
+
2077
2085
static void DiagnoseNonTriviallyRelocatableReason (Sema &SemaRef,
2078
2086
SourceLocation Loc,
2079
2087
QualType T) {
@@ -2102,6 +2110,92 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2102
2110
SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
2103
2111
}
2104
2112
2113
+ static void DiagnoseNonReplaceableReason (Sema &SemaRef, SourceLocation Loc,
2114
+ const CXXRecordDecl *D) {
2115
+ for (const CXXBaseSpecifier &B : D->bases ()) {
2116
+ assert (B.getType ()->getAsCXXRecordDecl () && " invalid base?" );
2117
+ if (!SemaRef.IsCXXReplaceableType (B.getType ()))
2118
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2119
+ << diag::TraitNotSatisfiedReason::NonReplaceableBase << B.getType ()
2120
+ << B.getSourceRange ();
2121
+ }
2122
+ for (const FieldDecl *Field : D->fields ()) {
2123
+ if (!SemaRef.IsCXXReplaceableType (Field->getType ()))
2124
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2125
+ << diag::TraitNotSatisfiedReason::NonReplaceableField << Field
2126
+ << Field->getType () << Field->getSourceRange ();
2127
+ }
2128
+ if (D->hasDeletedDestructor ())
2129
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2130
+ << diag::TraitNotSatisfiedReason::DeletedDtr << /* Deleted*/ 0
2131
+ << D->getDestructor ()->getSourceRange ();
2132
+
2133
+ if (!D->hasSimpleMoveConstructor () && !D->hasSimpleCopyConstructor ()) {
2134
+ const auto *Decl = cast<CXXConstructorDecl>(
2135
+ LookupSpecialMemberFromXValue (SemaRef, D, /* Assign=*/ false ));
2136
+ if (Decl && Decl->isDeleted ())
2137
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2138
+ << diag::TraitNotSatisfiedReason::DeletedCtr
2139
+ << Decl->isMoveConstructor () << Decl->getSourceRange ();
2140
+ }
2141
+ if (!D->hasSimpleMoveAssignment () && !D->hasSimpleCopyAssignment ()) {
2142
+ CXXMethodDecl *Decl =
2143
+ LookupSpecialMemberFromXValue (SemaRef, D, /* Assign=*/ true );
2144
+ if (Decl && Decl->isDeleted ())
2145
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2146
+ << diag::TraitNotSatisfiedReason::DeletedAssign
2147
+ << Decl->isMoveAssignmentOperator () << Decl->getSourceRange ();
2148
+ }
2149
+
2150
+ if (D->hasAttr <ReplaceableAttr>())
2151
+ return ;
2152
+ DiagnoseNonDefaultMovable (SemaRef, Loc, D);
2153
+ }
2154
+
2155
+ static void DiagnoseNonReplaceableReason (Sema &SemaRef, SourceLocation Loc,
2156
+ QualType T) {
2157
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait)
2158
+ << T << diag::TraitName::Replaceable;
2159
+
2160
+ if (T->isVariablyModifiedType ())
2161
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2162
+ << diag::TraitNotSatisfiedReason::VLA;
2163
+
2164
+ if (T->isReferenceType ())
2165
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2166
+ << diag::TraitNotSatisfiedReason::Ref;
2167
+ T = T.getNonReferenceType ();
2168
+
2169
+ if (T.isConstQualified ())
2170
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2171
+ << diag::TraitNotSatisfiedReason::Const;
2172
+
2173
+ if (T.isVolatileQualified ())
2174
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2175
+ << diag::TraitNotSatisfiedReason::Volatile;
2176
+
2177
+ bool IsArray = T->isArrayType ();
2178
+ T = SemaRef.getASTContext ().getBaseElementType (T.getUnqualifiedType ());
2179
+
2180
+ if (T->isScalarType ())
2181
+ return ;
2182
+
2183
+ const CXXRecordDecl *D = T->getAsCXXRecordDecl ();
2184
+ if (!D) {
2185
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2186
+ << diag::TraitNotSatisfiedReason::NotScalarOrClass << IsArray;
2187
+ return ;
2188
+ }
2189
+
2190
+ if (D->isInvalidDecl ())
2191
+ return ;
2192
+
2193
+ if (D->hasDefinition ())
2194
+ DiagnoseNonReplaceableReason (SemaRef, Loc, D);
2195
+
2196
+ SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
2197
+ }
2198
+
2105
2199
static void DiagnoseNonTriviallyCopyableReason (Sema &SemaRef,
2106
2200
SourceLocation Loc,
2107
2201
const CXXRecordDecl *D) {
@@ -2192,6 +2286,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
2192
2286
case UTT_IsCppTriviallyRelocatable:
2193
2287
DiagnoseNonTriviallyRelocatableReason (*this , E->getBeginLoc (), Args[0 ]);
2194
2288
break ;
2289
+ case UTT_IsReplaceable:
2290
+ DiagnoseNonReplaceableReason (*this , E->getBeginLoc (), Args[0 ]);
2291
+ break ;
2195
2292
case UTT_IsTriviallyCopyable:
2196
2293
DiagnoseNonTriviallyCopyableReason (*this , E->getBeginLoc (), Args[0 ]);
2197
2294
break ;
0 commit comments