1111// ===----------------------------------------------------------------------===//
1212
1313#include " clang/AST/DeclCXX.h"
14+ #include " clang/AST/Type.h"
1415#include " clang/Basic/DiagnosticParse.h"
1516#include " clang/Basic/DiagnosticSema.h"
17+ #include " clang/Basic/TypeTraits.h"
1618#include " clang/Sema/EnterExpressionEvaluationContext.h"
1719#include " clang/Sema/Initialization.h"
1820#include " clang/Sema/Lookup.h"
@@ -1938,6 +1940,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
19381940 return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
19391941 .Case (" is_trivially_relocatable" ,
19401942 TypeTrait::UTT_IsCppTriviallyRelocatable)
1943+ .Case (" is_trivially_copyable" , TypeTrait::UTT_IsTriviallyCopyable)
19411944 .Default (std::nullopt );
19421945}
19431946
@@ -2013,15 +2016,15 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
20132016 << B.getSourceRange ();
20142017 if (!SemaRef.IsCXXTriviallyRelocatableType (B.getType ()))
20152018 SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2016- << diag::TraitNotSatisfiedReason::NRBase << B.getType ()
2019+ << diag::TraitNotSatisfiedReason::NTRBase << B.getType ()
20172020 << B.getSourceRange ();
20182021 }
20192022 for (const FieldDecl *Field : D->fields ()) {
20202023 if (!Field->getType ()->isReferenceType () &&
20212024 !SemaRef.IsCXXTriviallyRelocatableType (Field->getType ()))
20222025 SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2023- << diag::TraitNotSatisfiedReason::NRField << Field << Field-> getType ()
2024- << Field->getSourceRange ();
2026+ << diag::TraitNotSatisfiedReason::NTRField << Field
2027+ << Field->getType () << Field-> getSourceRange ();
20252028 }
20262029 if (D->hasDeletedDestructor ())
20272030 SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
@@ -2099,6 +2102,82 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
20992102 SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
21002103}
21012104
2105+ static void DiagnoseNonTriviallyCopyableReason (Sema &SemaRef,
2106+ SourceLocation Loc,
2107+ const CXXRecordDecl *D) {
2108+ for (const CXXBaseSpecifier &B : D->bases ()) {
2109+ assert (B.getType ()->getAsCXXRecordDecl () && " invalid base?" );
2110+ if (B.isVirtual ())
2111+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2112+ << diag::TraitNotSatisfiedReason::VBase << B.getType ()
2113+ << B.getSourceRange ();
2114+ if (!B.getType ().isTriviallyCopyableType (D->getASTContext ())) {
2115+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2116+ << diag::TraitNotSatisfiedReason::NTCBase << B.getType ()
2117+ << B.getSourceRange ();
2118+ }
2119+ }
2120+ for (const FieldDecl *Field : D->fields ()) {
2121+ if (!Field->getType ().isTriviallyCopyableType (Field->getASTContext ()))
2122+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2123+ << diag::TraitNotSatisfiedReason::NTCField << Field
2124+ << Field->getType () << Field->getSourceRange ();
2125+ }
2126+ CXXDestructorDecl *Dtr = D->getDestructor ();
2127+ if (D->hasDeletedDestructor () || (Dtr && !Dtr->isTrivial ()))
2128+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2129+ << diag::TraitNotSatisfiedReason::DeletedDtr
2130+ << !D->hasDeletedDestructor () << D->getDestructor ()->getSourceRange ();
2131+
2132+ for (const CXXMethodDecl *Method : D->methods ()) {
2133+ if (Method->isTrivial () || !Method->isUserProvided ()) {
2134+ continue ;
2135+ }
2136+ auto SpecialMemberKind =
2137+ SemaRef.getDefaultedFunctionKind (Method).asSpecialMember ();
2138+ switch (SpecialMemberKind) {
2139+ case CXXSpecialMemberKind::CopyConstructor:
2140+ case CXXSpecialMemberKind::MoveConstructor:
2141+ case CXXSpecialMemberKind::CopyAssignment:
2142+ case CXXSpecialMemberKind::MoveAssignment: {
2143+ bool IsAssignment =
2144+ SpecialMemberKind == CXXSpecialMemberKind::CopyAssignment ||
2145+ SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;
2146+ bool IsMove =
2147+ SpecialMemberKind == CXXSpecialMemberKind::MoveConstructor ||
2148+ SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment;
2149+
2150+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2151+ << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign
2152+ : diag::TraitNotSatisfiedReason::UserProvidedCtr)
2153+ << IsMove << Method->getSourceRange ();
2154+ break ;
2155+ }
2156+ default :
2157+ break ;
2158+ }
2159+ }
2160+ }
2161+
2162+ static void DiagnoseNonTriviallyCopyableReason (Sema &SemaRef,
2163+ SourceLocation Loc, QualType T) {
2164+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait)
2165+ << T << diag::TraitName::TriviallyCopyable;
2166+
2167+ if (T->isReferenceType ())
2168+ SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2169+ << diag::TraitNotSatisfiedReason::Ref;
2170+
2171+ const CXXRecordDecl *D = T->getAsCXXRecordDecl ();
2172+ if (!D || D->isInvalidDecl ())
2173+ return ;
2174+
2175+ if (D->hasDefinition ())
2176+ DiagnoseNonTriviallyCopyableReason (SemaRef, Loc, D);
2177+
2178+ SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
2179+ }
2180+
21022181void Sema::DiagnoseTypeTraitDetails (const Expr *E) {
21032182 E = E->IgnoreParenImpCasts ();
21042183 if (E->containsErrors ())
@@ -2113,6 +2192,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
21132192 case UTT_IsCppTriviallyRelocatable:
21142193 DiagnoseNonTriviallyRelocatableReason (*this , E->getBeginLoc (), Args[0 ]);
21152194 break ;
2195+ case UTT_IsTriviallyCopyable:
2196+ DiagnoseNonTriviallyCopyableReason (*this , E->getBeginLoc (), Args[0 ]);
2197+ break ;
21162198 default :
21172199 break ;
21182200 }
0 commit comments