11
11
// ===----------------------------------------------------------------------===//
12
12
13
13
#include " clang/AST/DeclCXX.h"
14
+ #include " clang/AST/Type.h"
14
15
#include " clang/Basic/DiagnosticParse.h"
15
16
#include " clang/Basic/DiagnosticSema.h"
17
+ #include " clang/Basic/TypeTraits.h"
16
18
#include " clang/Sema/EnterExpressionEvaluationContext.h"
17
19
#include " clang/Sema/Initialization.h"
18
20
#include " clang/Sema/Lookup.h"
@@ -1938,6 +1940,7 @@ static std::optional<TypeTrait> StdNameToTypeTrait(StringRef Name) {
1938
1940
return llvm::StringSwitch<std::optional<TypeTrait>>(Name)
1939
1941
.Case (" is_trivially_relocatable" ,
1940
1942
TypeTrait::UTT_IsCppTriviallyRelocatable)
1943
+ .Case (" is_trivially_copyable" , TypeTrait::UTT_IsTriviallyCopyable)
1941
1944
.Default (std::nullopt);
1942
1945
}
1943
1946
@@ -2013,15 +2016,15 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2013
2016
<< B.getSourceRange ();
2014
2017
if (!SemaRef.IsCXXTriviallyRelocatableType (B.getType ()))
2015
2018
SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
2016
- << diag::TraitNotSatisfiedReason::NRBase << B.getType ()
2019
+ << diag::TraitNotSatisfiedReason::NTRBase << B.getType ()
2017
2020
<< B.getSourceRange ();
2018
2021
}
2019
2022
for (const FieldDecl *Field : D->fields ()) {
2020
2023
if (!Field->getType ()->isReferenceType () &&
2021
2024
!SemaRef.IsCXXTriviallyRelocatableType (Field->getType ()))
2022
2025
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 ();
2025
2028
}
2026
2029
if (D->hasDeletedDestructor ())
2027
2030
SemaRef.Diag (Loc, diag::note_unsatisfied_trait_reason)
@@ -2099,6 +2102,82 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef,
2099
2102
SemaRef.Diag (D->getLocation (), diag::note_defined_here) << D;
2100
2103
}
2101
2104
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
+
2102
2181
void Sema::DiagnoseTypeTraitDetails (const Expr *E) {
2103
2182
E = E->IgnoreParenImpCasts ();
2104
2183
if (E->containsErrors ())
@@ -2113,6 +2192,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
2113
2192
case UTT_IsCppTriviallyRelocatable:
2114
2193
DiagnoseNonTriviallyRelocatableReason (*this , E->getBeginLoc (), Args[0 ]);
2115
2194
break ;
2195
+ case UTT_IsTriviallyCopyable:
2196
+ DiagnoseNonTriviallyCopyableReason (*this , E->getBeginLoc (), Args[0 ]);
2197
+ break ;
2116
2198
default :
2117
2199
break ;
2118
2200
}
0 commit comments