@@ -1958,6 +1958,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
19581958 .Case (" is_replaceable" , TypeTrait::UTT_IsReplaceable)
19591959 .Case (" is_trivially_copyable" , TypeTrait::UTT_IsTriviallyCopyable)
19601960 .Case (" is_assignable" , TypeTrait::BTT_IsAssignable)
1961+ .Case (" is_empty" , TypeTrait::UTT_IsEmpty)
19611962 .Default (std::nullopt );
19621963}
19631964
@@ -2313,6 +2314,74 @@ static void DiagnoseNonAssignableReason(Sema &SemaRef, SourceLocation Loc,
23132314 SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
23142315}
23152316
2317+ static void DiagnoseIsEmptyReason (Sema &S, SourceLocation Loc,
2318+ const CXXRecordDecl *D) {
2319+ // Non-static data members (ignore zero-width bit‐fields).
2320+ for (const auto *Field : D->fields ()) {
2321+ if (Field->isZeroLengthBitField ())
2322+ continue ;
2323+ if (Field->isBitField ()) {
2324+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2325+ << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field
2326+ << Field->getSourceRange ();
2327+ continue ;
2328+ }
2329+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2330+ << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
2331+ << Field->getType () << Field->getSourceRange ();
2332+ }
2333+
2334+ // Virtual functions.
2335+ for (const auto *M : D->methods ()) {
2336+ if (M->isVirtual ()) {
2337+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2338+ << diag::TraitNotSatisfiedReason::VirtualFunction << M
2339+ << M->getSourceRange ();
2340+ break ;
2341+ }
2342+ }
2343+
2344+ // Virtual bases and non-empty bases.
2345+ for (const auto &B : D->bases ()) {
2346+ const auto *BR = B.getType ()->getAsCXXRecordDecl ();
2347+ if (!BR || BR->isInvalidDecl ())
2348+ continue ;
2349+ if (B.isVirtual ()) {
2350+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2351+ << diag::TraitNotSatisfiedReason::VBase << B.getType ()
2352+ << B.getSourceRange ();
2353+ }
2354+ if (!BR->isEmpty ()) {
2355+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2356+ << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType ()
2357+ << B.getSourceRange ();
2358+ }
2359+ }
2360+ }
2361+
2362+ static void DiagnoseIsEmptyReason (Sema &S, SourceLocation Loc, QualType T) {
2363+ // Emit primary "not empty" diagnostic.
2364+ S.Diag (Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;
2365+
2366+ // While diagnosing is_empty<T>, we want to look at the actual type, not a
2367+ // reference or an array of it. So we need to massage the QualType param to
2368+ // strip refs and arrays.
2369+ if (T->isReferenceType ())
2370+ S.Diag (Loc, diag::note_unsatisfied_trait_reason)
2371+ << diag::TraitNotSatisfiedReason::Ref;
2372+ T = T.getNonReferenceType ();
2373+
2374+ if (auto *AT = S.Context .getAsArrayType (T))
2375+ T = AT->getElementType ();
2376+
2377+ if (auto *D = T->getAsCXXRecordDecl ()) {
2378+ if (D->hasDefinition ()) {
2379+ DiagnoseIsEmptyReason (S, Loc, D);
2380+ S.Diag (D->getLocation (), diag::note_defined_here) << D;
2381+ }
2382+ }
2383+ }
2384+
23162385void Sema::DiagnoseTypeTraitDetails (const Expr *E) {
23172386 E = E->IgnoreParenImpCasts ();
23182387 if (E->containsErrors ())
@@ -2336,6 +2405,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
23362405 case BTT_IsAssignable:
23372406 DiagnoseNonAssignableReason (*this , E->getBeginLoc (), Args[0 ], Args[1 ]);
23382407 break ;
2408+ case UTT_IsEmpty:
2409+ DiagnoseIsEmptyReason (*this , E->getBeginLoc (), Args[0 ]);
2410+ break ;
23392411 default :
23402412 break ;
23412413 }
0 commit comments