@@ -5129,6 +5129,83 @@ static bool HasNoThrowOperator(const RecordType *RT, OverloadedOperatorKind Op,
5129
5129
return false ;
5130
5130
}
5131
5131
5132
+ static bool HasNonDeletedDefaultedEqualityComparison (Sema &S,
5133
+ const CXXRecordDecl *Decl,
5134
+ SourceLocation KeyLoc) {
5135
+ if (Decl->isUnion ())
5136
+ return false ;
5137
+ if (Decl->isLambda ())
5138
+ return Decl->isCapturelessLambda ();
5139
+
5140
+ {
5141
+ EnterExpressionEvaluationContext UnevaluatedContext (
5142
+ S, Sema::ExpressionEvaluationContext::Unevaluated);
5143
+ Sema::SFINAETrap SFINAE (S, /* AccessCheckingSFINAE=*/ true );
5144
+ Sema::ContextRAII TUContext (S, S.Context .getTranslationUnitDecl ());
5145
+
5146
+ // const ClassT& obj;
5147
+ OpaqueValueExpr Operand (
5148
+ {}, Decl->getTypeForDecl ()->getCanonicalTypeUnqualified ().withConst (),
5149
+ ExprValueKind::VK_LValue);
5150
+ UnresolvedSet<16 > Functions;
5151
+ // obj == obj;
5152
+ S.LookupBinOp (S.TUScope , {}, BinaryOperatorKind::BO_EQ, Functions);
5153
+
5154
+ auto Result = S.CreateOverloadedBinOp (KeyLoc, BinaryOperatorKind::BO_EQ,
5155
+ Functions, &Operand, &Operand);
5156
+ if (Result.isInvalid () || SFINAE.hasErrorOccurred ())
5157
+ return false ;
5158
+
5159
+ const auto *CallExpr = dyn_cast<CXXOperatorCallExpr>(Result.get ());
5160
+ if (!CallExpr)
5161
+ return false ;
5162
+ const auto *Callee = CallExpr->getDirectCallee ();
5163
+ auto ParamT = Callee->getParamDecl (0 )->getType ();
5164
+ if (!Callee->isDefaulted ())
5165
+ return false ;
5166
+ if (!ParamT->isReferenceType () && !Decl->isTriviallyCopyable ())
5167
+ return false ;
5168
+ if (ParamT.getNonReferenceType ()->getUnqualifiedDesugaredType () !=
5169
+ Decl->getTypeForDecl ())
5170
+ return false ;
5171
+ }
5172
+
5173
+ return llvm::all_of (Decl->bases (),
5174
+ [&](const CXXBaseSpecifier &BS) {
5175
+ if (const auto *RD = BS.getType ()->getAsCXXRecordDecl ())
5176
+ return HasNonDeletedDefaultedEqualityComparison (
5177
+ S, RD, KeyLoc);
5178
+ return true ;
5179
+ }) &&
5180
+ llvm::all_of (Decl->fields (), [&](const FieldDecl *FD) {
5181
+ auto Type = FD->getType ();
5182
+ if (Type->isArrayType ())
5183
+ Type = Type->getBaseElementTypeUnsafe ()
5184
+ ->getCanonicalTypeUnqualified ();
5185
+
5186
+ if (Type->isReferenceType () || Type->isEnumeralType ())
5187
+ return false ;
5188
+ if (const auto *RD = Type->getAsCXXRecordDecl ())
5189
+ return HasNonDeletedDefaultedEqualityComparison (S, RD, KeyLoc);
5190
+ return true ;
5191
+ });
5192
+ }
5193
+
5194
+ static bool isTriviallyEqualityComparableType (Sema &S, QualType Type, SourceLocation KeyLoc) {
5195
+ QualType CanonicalType = Type.getCanonicalType ();
5196
+ if (CanonicalType->isIncompleteType () || CanonicalType->isDependentType () ||
5197
+ CanonicalType->isEnumeralType () || CanonicalType->isArrayType ())
5198
+ return false ;
5199
+
5200
+ if (const auto *RD = CanonicalType->getAsCXXRecordDecl ()) {
5201
+ if (!HasNonDeletedDefaultedEqualityComparison (S, RD, KeyLoc))
5202
+ return false ;
5203
+ }
5204
+
5205
+ return S.getASTContext ().hasUniqueObjectRepresentations (
5206
+ CanonicalType, /* CheckIfTriviallyCopyable=*/ false );
5207
+ }
5208
+
5132
5209
static bool EvaluateUnaryTypeTrait (Sema &Self, TypeTrait UTT,
5133
5210
SourceLocation KeyLoc,
5134
5211
TypeSourceInfo *TInfo) {
@@ -5561,7 +5638,7 @@ static bool EvaluateUnaryTypeTrait(Sema &Self, TypeTrait UTT,
5561
5638
Self.Diag (KeyLoc, diag::err_builtin_pass_in_regs_non_class) << T;
5562
5639
return false ;
5563
5640
case UTT_IsTriviallyEqualityComparable:
5564
- return T. isTriviallyEqualityComparableType (C );
5641
+ return isTriviallyEqualityComparableType (Self, T, KeyLoc );
5565
5642
}
5566
5643
}
5567
5644
0 commit comments