Skip to content

Commit f07639c

Browse files
authored
Merge branch 'main' into fix_inf_recur
2 parents a52a125 + eec9431 commit f07639c

File tree

33 files changed

+427
-30
lines changed

33 files changed

+427
-30
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error<
17641764

17651765
// Type traits explanations
17661766
def note_unsatisfied_trait : Note<"%0 is not %enum_select<TraitName>{"
1767-
"%TriviallyRelocatable{trivially relocatable}"
1767+
"%TriviallyRelocatable{trivially relocatable}|"
1768+
"%TriviallyCopyable{trivially copyable}"
17681769
"}1">;
17691770

17701771
def note_unsatisfied_trait_reason
@@ -1774,8 +1775,10 @@ def note_unsatisfied_trait_reason
17741775
"%HasArcLifetime{has an ARC lifetime qualifier}|"
17751776
"%VLA{is a variably-modified type}|"
17761777
"%VBase{has a virtual base %1}|"
1777-
"%NRBase{has a non-trivially-relocatable base %1}|"
1778-
"%NRField{has a non-trivially-relocatable member %1 of type %2}|"
1778+
"%NTRBase{has a non-trivially-relocatable base %1}|"
1779+
"%NTRField{has a non-trivially-relocatable member %1 of type %2}|"
1780+
"%NTCBase{has a non-trivially-copyable base %1}|"
1781+
"%NTCField{has a non-trivially-copyable member %1 of type %2}|"
17791782
"%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|"
17801783
"%UserProvidedCtr{has a user provided %select{copy|move}1 "
17811784
"constructor}|"

clang/lib/Sema/SemaTypeTraits.cpp

Lines changed: 85 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
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+
21022181
void 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
}

clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,14 @@ struct is_trivially_relocatable {
1212

1313
template <typename T>
1414
constexpr bool is_trivially_relocatable_v = __builtin_is_cpp_trivially_relocatable(T);
15+
16+
template <typename T>
17+
struct is_trivially_copyable {
18+
static constexpr bool value = __is_trivially_copyable(T);
19+
};
20+
21+
template <typename T>
22+
constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
1523
#endif
1624

1725
#ifdef STD2
@@ -25,6 +33,17 @@ using is_trivially_relocatable = __details_is_trivially_relocatable<T>;
2533

2634
template <typename T>
2735
constexpr bool is_trivially_relocatable_v = __builtin_is_cpp_trivially_relocatable(T);
36+
37+
template <typename T>
38+
struct __details_is_trivially_copyable {
39+
static constexpr bool value = __is_trivially_copyable(T);
40+
};
41+
42+
template <typename T>
43+
using is_trivially_copyable = __details_is_trivially_copyable<T>;
44+
45+
template <typename T>
46+
constexpr bool is_trivially_copyable_v = __is_trivially_copyable(T);
2847
#endif
2948

3049

@@ -45,6 +64,15 @@ using is_trivially_relocatable = __details_is_trivially_relocatable<T>;
4564

4665
template <typename T>
4766
constexpr bool is_trivially_relocatable_v = is_trivially_relocatable<T>::value;
67+
68+
template <typename T>
69+
struct __details_is_trivially_copyable : bool_constant<__is_trivially_copyable(T)> {};
70+
71+
template <typename T>
72+
using is_trivially_copyable = __details_is_trivially_copyable<T>;
73+
74+
template <typename T>
75+
constexpr bool is_trivially_copyable_v = is_trivially_copyable<T>::value;
4876
#endif
4977

5078
}
@@ -60,6 +88,18 @@ static_assert(std::is_trivially_relocatable_v<int&>);
6088
// expected-note@-1 {{'int &' is not trivially relocatable}} \
6189
// expected-note@-1 {{because it is a reference type}}
6290

91+
static_assert(std::is_trivially_copyable<int>::value);
92+
93+
static_assert(std::is_trivially_copyable<int&>::value);
94+
// expected-error-re@-1 {{static assertion failed due to requirement 'std::{{.*}}is_trivially_copyable<int &>::value'}} \
95+
// expected-note@-1 {{'int &' is not trivially copyable}} \
96+
// expected-note@-1 {{because it is a reference type}}
97+
static_assert(std::is_trivially_copyable_v<int&>);
98+
// expected-error@-1 {{static assertion failed due to requirement 'std::is_trivially_copyable_v<int &>'}} \
99+
// expected-note@-1 {{'int &' is not trivially copyable}} \
100+
// expected-note@-1 {{because it is a reference type}}
101+
102+
63103
namespace test_namespace {
64104
using namespace std;
65105
static_assert(is_trivially_relocatable<int&>::value);
@@ -70,6 +110,15 @@ namespace test_namespace {
70110
// expected-error@-1 {{static assertion failed due to requirement 'is_trivially_relocatable_v<int &>'}} \
71111
// expected-note@-1 {{'int &' is not trivially relocatable}} \
72112
// expected-note@-1 {{because it is a reference type}}
113+
114+
static_assert(is_trivially_copyable<int&>::value);
115+
// expected-error-re@-1 {{static assertion failed due to requirement '{{.*}}is_trivially_copyable<int &>::value'}} \
116+
// expected-note@-1 {{'int &' is not trivially copyable}} \
117+
// expected-note@-1 {{because it is a reference type}}
118+
static_assert(is_trivially_copyable_v<int&>);
119+
// expected-error@-1 {{static assertion failed due to requirement 'is_trivially_copyable_v<int &>'}} \
120+
// expected-note@-1 {{'int &' is not trivially copyable}} \
121+
// expected-note@-1 {{because it is a reference type}}
73122
}
74123

75124

@@ -82,6 +131,14 @@ concept C = std::is_trivially_relocatable_v<T>; // #concept2
82131

83132
template <C T> void g(); // #cand2
84133

134+
template <typename T>
135+
requires std::is_trivially_copyable<T>::value void f2(); // #cand3
136+
137+
template <typename T>
138+
concept C2 = std::is_trivially_copyable_v<T>; // #concept4
139+
140+
template <C2 T> void g2(); // #cand4
141+
85142
void test() {
86143
f<int&>();
87144
// expected-error@-1 {{no matching function for call to 'f'}} \
@@ -97,5 +154,20 @@ void test() {
97154
// expected-note@#concept2 {{because 'std::is_trivially_relocatable_v<int &>' evaluated to false}} \
98155
// expected-note@#concept2 {{'int &' is not trivially relocatable}} \
99156
// expected-note@#concept2 {{because it is a reference type}}
157+
158+
f2<int&>();
159+
// expected-error@-1 {{no matching function for call to 'f2'}} \
160+
// expected-note@#cand3 {{candidate template ignored: constraints not satisfied [with T = int &]}} \
161+
// expected-note-re@#cand3 {{because '{{.*}}is_trivially_copyable<int &>::value' evaluated to false}} \
162+
// expected-note@#cand3 {{'int &' is not trivially copyable}} \
163+
// expected-note@#cand3 {{because it is a reference type}}
164+
165+
g2<int&>();
166+
// expected-error@-1 {{no matching function for call to 'g2'}} \
167+
// expected-note@#cand4 {{candidate template ignored: constraints not satisfied [with T = int &]}} \
168+
// expected-note@#cand4 {{because 'int &' does not satisfy 'C2'}} \
169+
// expected-note@#concept4 {{because 'std::is_trivially_copyable_v<int &>' evaluated to false}} \
170+
// expected-note@#concept4 {{'int &' is not trivially copyable}} \
171+
// expected-note@#concept4 {{because it is a reference type}}
100172
}
101173
}

0 commit comments

Comments
 (0)