@@ -2014,6 +2014,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
2014
2014
.Case (" is_aggregate" , TypeTrait::UTT_IsAggregate)
2015
2015
.Case (" is_constructible" , TypeTrait::TT_IsConstructible)
2016
2016
.Case (" is_final" , TypeTrait::UTT_IsFinal)
2017
+ .Case (" is_abstract" , TypeTrait::UTT_IsAbstract)
2017
2018
.Default (std::nullopt );
2018
2019
}
2019
2020
@@ -2774,6 +2775,75 @@ static void DiagnoseNonAggregateReason(Sema &SemaRef, SourceLocation Loc,
2774
2775
DiagnoseNonAggregateReason (SemaRef, Loc, D);
2775
2776
}
2776
2777
2778
+ static void DiagnoseNonAbstractReason (Sema &SemaRef, SourceLocation Loc,
2779
+ const CXXRecordDecl *D) {
2780
+ // If this type has any abstract base classes, their respective virtual
2781
+ // functions must have been overridden.
2782
+ for (const CXXBaseSpecifier &B : D->bases ()) {
2783
+ if (B.getType ()->castAsCXXRecordDecl ()->isAbstract ()) {
2784
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2785
+ << diag::TraitNotSatisfiedReason::OverridesAllPureVirtual
2786
+ << B.getType () << B.getSourceRange ();
2787
+ }
2788
+ }
2789
+ }
2790
+
2791
+ static void DiagnoseNonAbstractReason (Sema &SemaRef, SourceLocation Loc,
2792
+ QualType T) {
2793
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait)
2794
+ << T << diag::TraitName::Abstract;
2795
+
2796
+ if (T->isReferenceType ()) {
2797
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2798
+ << diag::TraitNotSatisfiedReason::Ref;
2799
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2800
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2801
+ return ;
2802
+ }
2803
+
2804
+ if (T->isUnionType ()) {
2805
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2806
+ << diag::TraitNotSatisfiedReason::UnionType;
2807
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2808
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2809
+ return ;
2810
+ }
2811
+
2812
+ if (SemaRef.Context .getAsArrayType (T)) {
2813
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2814
+ << diag::TraitNotSatisfiedReason::ArrayType;
2815
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2816
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2817
+ return ;
2818
+ }
2819
+
2820
+ if (T->isFunctionType ()) {
2821
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2822
+ << diag::TraitNotSatisfiedReason::FunctionType;
2823
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2824
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2825
+ return ;
2826
+ }
2827
+
2828
+ if (T->isPointerType ()) {
2829
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2830
+ << diag::TraitNotSatisfiedReason::PointerType;
2831
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2832
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2833
+ return ;
2834
+ }
2835
+
2836
+ if (!T->isStructureOrClassType ()) {
2837
+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2838
+ << diag::TraitNotSatisfiedReason::NotStructOrClass;
2839
+ return ;
2840
+ }
2841
+
2842
+ const CXXRecordDecl *D = T->getAsCXXRecordDecl ();
2843
+ if (D->hasDefinition ())
2844
+ DiagnoseNonAbstractReason (SemaRef, Loc, D);
2845
+ }
2846
+
2777
2847
void Sema::DiagnoseTypeTraitDetails (const Expr *E) {
2778
2848
E = E->IgnoreParenImpCasts ();
2779
2849
if (E->containsErrors ())
@@ -2818,6 +2888,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
2818
2888
DiagnoseIsFinalReason (*this , E->getBeginLoc (), QT); // unsatisfied
2819
2889
break ;
2820
2890
}
2891
+ case UTT_IsAbstract:
2892
+ DiagnoseNonAbstractReason (*this , E->getBeginLoc (), Args[0 ]);
2893
+ break ;
2821
2894
default :
2822
2895
break ;
2823
2896
}
0 commit comments