[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,87 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + for (const CXXMethodDecl *Method : D->methods()) { +if (Method->isTrivial() || !Method->isUserProvided()) { + continue; +} +auto SpecialMemberKind = +SemaRef.getDefaultedFunctionKind(Method).asSpecialMember(); +switch (SpecialMemberKind) { +case CXXSpecialMemberKind::CopyConstructor: +case CXXSpecialMemberKind::MoveConstructor: +case CXXSpecialMemberKind::CopyAssignment: +case CXXSpecialMemberKind::MoveAssignment: { + bool IsAssignment = + SpecialMemberKind == CXXSpecialMemberKind::CopyAssignment || + SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment; + bool IsMove = + SpecialMemberKind == CXXSpecialMemberKind::MoveConstructor || + SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment; + + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign + : diag::TraitNotSatisfiedReason::UserProvidedCtr) + << IsMove << Method->getSourceRange(); + break; +} +default: { + break; +} +} egorshamshura wrote: Fixed https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,87 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + for (const CXXMethodDecl *Method : D->methods()) { +if (Method->isTrivial() || !Method->isUserProvided()) { + continue; +} +auto SpecialMemberKind = +SemaRef.getDefaultedFunctionKind(Method).asSpecialMember(); +switch (SpecialMemberKind) { +case CXXSpecialMemberKind::CopyConstructor: +case CXXSpecialMemberKind::MoveConstructor: +case CXXSpecialMemberKind::CopyAssignment: +case CXXSpecialMemberKind::MoveAssignment: { + bool IsAssignment = + SpecialMemberKind == CXXSpecialMemberKind::CopyAssignment || + SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment; + bool IsMove = + SpecialMemberKind == CXXSpecialMemberKind::MoveConstructor || + SpecialMemberKind == CXXSpecialMemberKind::MoveAssignment; + + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << (IsAssignment ? diag::TraitNotSatisfiedReason::UserProvidedAssign + : diag::TraitNotSatisfiedReason::UserProvidedCtr) + << IsMove << Method->getSourceRange(); + break; +} +default: { + break; +} +} + } + CXXDestructorDecl *Dtr = D->getDestructor(); + if (Dtr && !Dtr->isTrivial()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 1 +<< Dtr->getSourceRange(); +} egorshamshura wrote: Oh, fixed it, decided to write "has a deleted destructor" https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/9] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) egorshamshura wrote: I'm not sure if I did it right, but I couldn't figure out how TYPE_TRAIT_1 could get a name without the "__" prefix. So I made a TYPE_TRAIT_DIAG for this https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/9] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -2253,6 +2260,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + bool CompleteTypes = true; + for (const auto &ArgTy : Ts) { +if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType()) + continue; +if (ArgTy->isIncompleteType()) { + SemaRef.Diag(Loc, diag::err_incomplete_type_used_in_type_trait_expr) + << ArgTy; + CompleteTypes = false; +} + } + if (!CompleteTypes) +return; egorshamshura wrote: And now, for every cv void type, we show a note, but is this a good practice? Or do we want to show it once? https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/143309 >From ed1f379144736e0c645dca87b0111f685bdd7e53 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Sun, 8 Jun 2025 13:09:54 + Subject: [PATCH 1/7] Fixed problem when std::is_xxx_v<> tries to get Argument as type when it is pack; added is_constructible support --- .../clang/Basic/DiagnosticSemaKinds.td| 7 +- clang/lib/Sema/SemaTypeTraits.cpp | 35 - .../type-traits-unsatisfied-diags-std.cpp | 72 +++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 44 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5f44d503580b9..b04537d2cac3c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1765,7 +1765,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1785,7 +1786,9 @@ def note_unsatisfied_trait_reason "%UserProvidedAssign{has a user provided %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 330f2aa750a09..37fe965815269 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaHLSL.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; @@ -1941,6 +1942,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1977,8 +1979,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); +} return {{Trait.value(), std::move(Args)}}; } @@ -2159,6 +2167,26 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << T << diag::TraitName::Constructible; + + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isVoidType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2195,6 +2223,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsTriviallyCopyable: DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); break; + case TT_IsConstructible: +DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args[0]); +break; default: break; } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 498e202e26265..b9ee677a1cffc 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -1981,8 +1982,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); egorshamshura wrote: getAsType would assert for us https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -1981,8 +1982,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) egorshamshura wrote: Fixed https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -2253,6 +2260,53 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + for (const auto &ArgTy : Ts) { egorshamshura wrote: Fixed https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -2253,6 +2260,53 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + for (const auto &ArgTy : Ts) { +if (ArgTy->isVoidType()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::CVVoidType; + } + + QualType T = Ts[0]; egorshamshura wrote: Added early-exit, thanks https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -2253,6 +2260,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + bool CompleteTypes = true; + for (const auto &ArgTy : Ts) { +if (ArgTy->isVoidType() || ArgTy->isIncompleteArrayType()) + continue; +if (ArgTy->isIncompleteType()) { + SemaRef.Diag(Loc, diag::err_incomplete_type_used_in_type_trait_expr) + << ArgTy; + CompleteTypes = false; +} + } + if (!CompleteTypes) +return; egorshamshura wrote: So I decided to show it once https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -1981,8 +1983,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) egorshamshura wrote: Fixed, added curley brackets https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/143309 >From ed1f379144736e0c645dca87b0111f685bdd7e53 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Sun, 8 Jun 2025 13:09:54 + Subject: [PATCH 1/8] Fixed problem when std::is_xxx_v<> tries to get Argument as type when it is pack; added is_constructible support --- .../clang/Basic/DiagnosticSemaKinds.td| 7 +- clang/lib/Sema/SemaTypeTraits.cpp | 35 - .../type-traits-unsatisfied-diags-std.cpp | 72 +++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 44 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5f44d503580b9..b04537d2cac3c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1765,7 +1765,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1785,7 +1786,9 @@ def note_unsatisfied_trait_reason "%UserProvidedAssign{has a user provided %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 330f2aa750a09..37fe965815269 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaHLSL.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; @@ -1941,6 +1942,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1977,8 +1979,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); +} return {{Trait.value(), std::move(Args)}}; } @@ -2159,6 +2167,26 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << T << diag::TraitName::Constructible; + + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isVoidType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2195,6 +2223,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsTriviallyCopyable: DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); break; + case TT_IsConstructible: +DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args[0]); +break; default: break; } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 498e202e26265..b9ee677a1cffc 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -1981,8 +1983,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); + assert((Arg.getKind() == TemplateArgument::ArgKind::Type || egorshamshura wrote: changed assert to llvm_unreachable https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -1981,8 +1982,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); +} egorshamshura wrote: Added assert https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -564,11 +564,12 @@ struct A { namespace ex2 { #if __cplusplus >= 201103L struct Bar { - struct Baz { + struct Baz { // #Baz egorshamshura wrote: Fixed https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } egorshamshura wrote: Removed https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) { +const auto *Decl = cast( +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false)); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedCtr + << Decl->isMoveConstructor() << Decl->getSourceRange(); + } + if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) { +CXXMethodDecl *Decl = +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedAssign + << Decl->isMoveAssignmentOperator() << Decl->getSourceRange(); + } + CXXDestructorDecl *Dtr = D->getDestructor(); + if (Dtr && Dtr->isUserProvided() && !Dtr->isDefaulted()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 1 +<< Dtr->getSourceRange(); egorshamshura wrote: Fixed, now using Dtr->isTrivial() https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) { +const auto *Decl = cast( +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false)); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedCtr + << Decl->isMoveConstructor() << Decl->getSourceRange(); + } + if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) { +CXXMethodDecl *Decl = +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedAssign + << Decl->isMoveAssignmentOperator() << Decl->getSourceRange(); + } egorshamshura wrote: Fixed it, now I'm iterating over all special member functions https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (!D->hasSimpleMoveConstructor() && !D->hasSimpleCopyConstructor()) { +const auto *Decl = cast( +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/false)); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedCtr + << Decl->isMoveConstructor() << Decl->getSourceRange(); + } + if (!D->hasSimpleMoveAssignment() && !D->hasSimpleCopyAssignment()) { +CXXMethodDecl *Decl = +LookupSpecialMemberFromXValue(SemaRef, D, /*Assign=*/true); +if (Decl && Decl->isUserProvided()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::UserProvidedAssign + << Decl->isMoveAssignmentOperator() << Decl->getSourceRange(); + } + CXXDestructorDecl *Dtr = D->getDestructor(); + if (Dtr && Dtr->isUserProvided() && !Dtr->isDefaulted()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 1 +<< Dtr->getSourceRange(); +} + +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << T << diag::TraitName::TriviallyCopyable; + + if (T->isReferenceType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::Ref; + + T = T.getNonReferenceType(); + + if (T.hasNonTrivialObjCLifetime()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::HasArcLifetime; egorshamshura wrote: Removed https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/4] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/3] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/6] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) egorshamshura wrote: Should I revert changes? https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/7] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/5] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/6] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,88 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { egorshamshura wrote: Added test for it https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,88 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + for (const CXXMethodDecl *Method : D->methods()) { +if (Method->isIneligibleOrNotSelected() || Method->isTrivial() || +!Method->isUserProvided()) { + continue; +} +auto SpecialMemberKind = +SemaRef.getDefaultedFunctionKind(Method).asSpecialMember(); +switch (SpecialMemberKind) { +case CXXSpecialMemberKind::CopyConstructor: egorshamshura wrote: Added tests for every single case https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura deleted https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/5] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" egorshamshura wrote: Changed NR to NTR https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/7] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -2083,6 +2086,88 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + for (const CXXMethodDecl *Method : D->methods()) { +if (Method->isIneligibleOrNotSelected() || Method->isTrivial() || egorshamshura wrote: Added coverage for two conditions, removed ```Method->isIneligibleOrNotSelected()```. Frankly speaking, I could not create a case when ```Method->isIneligibleOrNotSelected()``` is true and ```!(Method->isTrivial() || !Method->isUserProvided())``` https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura created https://github.com/llvm/llvm-project/pull/142341 None >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) egorshamshura wrote: Okay, thanks) https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -144,3 +144,54 @@ static_assert(__builtin_is_cpp_trivially_relocatable(U2)); // expected-note@#tr-U2 {{'U2' defined here}} } + +namespace trivially_copyable { +struct B { + virtual ~B(); +}; +struct S : virtual B { // #tc-S +S(); +int & a; +const int ci; +B & b; +B c; +~S(); +}; +static_assert(__is_trivially_copyable(S)); +// expected-error@-1 {{static assertion failed due to requirement '__is_trivially_copyable(trivially_copyable::S)'}} \ +// expected-note@-1 {{'S' is not trivially copyable}} \ +// expected-note@-1 {{because it has a virtual base 'B'}} \ +// expected-note@-1 {{because it has a non-trivially-copyable base 'B'}} \ egorshamshura wrote: Added some tests for this case https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -144,3 +144,54 @@ static_assert(__builtin_is_cpp_trivially_relocatable(U2)); // expected-note@#tr-U2 {{'U2' defined here}} } + +namespace trivially_copyable { +struct B { + virtual ~B(); +}; +struct S : virtual B { // #tc-S +S(); +int & a; +const int ci; +B & b; +B c; +~S(); +}; +static_assert(__is_trivially_copyable(S)); +// expected-error@-1 {{static assertion failed due to requirement '__is_trivially_copyable(trivially_copyable::S)'}} \ +// expected-note@-1 {{'S' is not trivially copyable}} \ +// expected-note@-1 {{because it has a virtual base 'B'}} \ +// expected-note@-1 {{because it has a non-trivially-copyable base 'B'}} \ egorshamshura wrote: Added tests for non-trvial-copyable bases. https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
@@ -144,3 +144,54 @@ static_assert(__builtin_is_cpp_trivially_relocatable(U2)); // expected-note@#tr-U2 {{'U2' defined here}} } + +namespace trivially_copyable { +struct B { + virtual ~B(); +}; +struct S : virtual B { // #tc-S +S(); +int & a; +const int ci; +B & b; +B c; +~S(); +}; +static_assert(__is_trivially_copyable(S)); +// expected-error@-1 {{static assertion failed due to requirement '__is_trivially_copyable(trivially_copyable::S)'}} \ +// expected-note@-1 {{'S' is not trivially copyable}} \ +// expected-note@-1 {{because it has a virtual base 'B'}} \ +// expected-note@-1 {{because it has a non-trivially-copyable base 'B'}} \ egorshamshura wrote: It seems that I've figured it out. I added one more test. https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/142341 >From 2e423a75e5ee8b5ecc450d4457fc677fd0c08ad2 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Mon, 2 Jun 2025 07:25:26 + Subject: [PATCH 1/8] [Clang] Added explanation why a is trivial copyable evaluated to false. --- .../clang/Basic/DiagnosticSemaKinds.td| 5 +- clang/lib/Sema/SemaTypeTraits.cpp | 97 +++ .../type-traits-unsatisfied-diags-std.cpp | 72 ++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 80 +++ 4 files changed, 253 insertions(+), 1 deletion(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index efc842bb4c42e..748e0720c5ef5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1764,7 +1764,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" - "%TriviallyRelocatable{trivially relocatable}" + "%TriviallyRelocatable{trivially relocatable}|" + "%TriviallyCopyable{trivially copyable}" "}1">; def note_unsatisfied_trait_reason @@ -1776,6 +1777,8 @@ def note_unsatisfied_trait_reason "%VBase{has a virtual base %1}|" "%NRBase{has a non-trivially-relocatable base %1}|" "%NRField{has a non-trivially-relocatable member %1 of type %2}|" + "%NTCBase{has a non-trivially-copyable base %1}|" + "%NTCField{has a non-trivially-copyable member %1 of type %2}|" "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|" "%UserProvidedCtr{has a user provided %select{copy|move}1 " "constructor}|" diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 7bf3c8eaabf4b..aaa5aff53fbc5 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,8 +11,10 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" +#include "clang/Basic/TypeTraits.h" #include "clang/Sema/EnterExpressionEvaluationContext.h" #include "clang/Sema/Initialization.h" #include "clang/Sema/Lookup.h" @@ -1922,6 +1924,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { return llvm::StringSwitch>(Name) .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) + .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) .Default(std::nullopt); } @@ -2083,6 +2086,97 @@ static void DiagnoseNonTriviallyRelocatableReason(Sema &SemaRef, SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; } +static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, + SourceLocation Loc, + const CXXRecordDecl *D) { + for (const CXXBaseSpecifier &B : D->bases()) { +assert(B.getType()->getAsCXXRecordDecl() && "invalid base?"); +if (B.isVirtual()) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::VBase << B.getType() + << B.getSourceRange(); +if (!B.getType().isTriviallyCopyableType(D->getASTContext())) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCBase << B.getType() + << B.getSourceRange(); +} + } + for (const FieldDecl *Field : D->fields()) { +if (!Field->getType().isTriviallyCopyableType(Field->getASTContext())) + SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) + << diag::TraitNotSatisfiedReason::NTCField << Field + << Field->getType() << Field->getSourceRange(); + } + if (D->hasDeletedDestructor()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::DeletedDtr << 0 +<< D->getDestructor()->getSourceRange(); + + if (D->isUnion()) { +auto DiagSPM = [&](CXXSpecialMemberKind K, bool Has) { + if (Has) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::UnionWithUserDeclaredSMF << K; +}; +DiagSPM(CXXSpecialMemberKind::CopyConstructor, +D->hasUserDeclaredCopyConstructor()); +DiagSPM(CXXSpecialMemberKind::CopyAssignment, +D->hasUserDeclaredCopyAssignment()); +DiagSPM(CXXSpecialMemberKind::MoveConstructor, +D->hasUserDeclaredMoveConstructor()); +DiagSPM(CXXSpecialMemberKind::MoveAssignment, +D->hasUserDeclaredMoveAssignment()); +return; + } + + if (
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura created https://github.com/llvm/llvm-project/pull/143309 Also fixed problem with ```ExtractTypeTraitFromExpression```. In case ```std::is_xxx_v<>``` with variadic pack it tries to get template argument, but fails in expression ```Arg.getAsType()``` due to ```Arg.getKind() == TemplateArgument::ArgKind::Pack```, but not ```TemplateArgument::ArgKind::Type```. >From ed1f379144736e0c645dca87b0111f685bdd7e53 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Sun, 8 Jun 2025 13:09:54 + Subject: [PATCH] Fixed problem when std::is_xxx_v<> tries to get Argument as type when it is pack; added is_constructible support --- .../clang/Basic/DiagnosticSemaKinds.td| 7 +- clang/lib/Sema/SemaTypeTraits.cpp | 35 - .../type-traits-unsatisfied-diags-std.cpp | 72 +++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 44 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5f44d503580b9..b04537d2cac3c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1765,7 +1765,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1785,7 +1786,9 @@ def note_unsatisfied_trait_reason "%UserProvidedAssign{has a user provided %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 330f2aa750a09..37fe965815269 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaHLSL.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; @@ -1941,6 +1942,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1977,8 +1979,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); +} return {{Trait.value(), std::move(Args)}}; } @@ -2159,6 +2167,26 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << T << diag::TraitName::Constructible; + + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isVoidType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2195,6 +2223,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsTriviallyCopyable: DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); break; + case TT_IsConstructible: +DiagnoseNonConstructibleR
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)
egorshamshura wrote: > LGTM! Thanks a lot. Will you need us to merge that for you? Yep, that would be great https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
@@ -2159,6 +2167,26 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) egorshamshura wrote: Thanks for your advice. I have tried to use ```InitializationSequence::Diagnose```. However I'm dealing with some issues. 1) ```InitializationSequence::Diagnose``` does not emit any diagnostic. It correctly returns true or false, but nothing appears in console. Although the FailureKind in ```InitializationSequence``` is defined correctly. 2) After ```InitializationSequence::Diagnose``` I can not use ```SemaRef.Diag```. Nothing is being written to the console. However I can write in ```llvm::errs``` manually. So, can you please help me understand what I'm doing wrong? I have uploaded the latest update. https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/143309 >From ed1f379144736e0c645dca87b0111f685bdd7e53 Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Sun, 8 Jun 2025 13:09:54 + Subject: [PATCH 1/2] Fixed problem when std::is_xxx_v<> tries to get Argument as type when it is pack; added is_constructible support --- .../clang/Basic/DiagnosticSemaKinds.td| 7 +- clang/lib/Sema/SemaTypeTraits.cpp | 35 - .../type-traits-unsatisfied-diags-std.cpp | 72 +++ .../SemaCXX/type-traits-unsatisfied-diags.cpp | 44 4 files changed, 154 insertions(+), 4 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 5f44d503580b9..b04537d2cac3c 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1765,7 +1765,8 @@ def err_user_defined_msg_constexpr : Error< // Type traits explanations def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1785,7 +1786,9 @@ def note_unsatisfied_trait_reason "%UserProvidedAssign{has a user provided %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 330f2aa750a09..37fe965815269 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -21,6 +21,7 @@ #include "clang/Sema/Overload.h" #include "clang/Sema/Sema.h" #include "clang/Sema/SemaHLSL.h" +#include "llvm/Support/raw_ostream.h" using namespace clang; @@ -1941,6 +1942,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { .Case("is_trivially_relocatable", TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1977,8 +1979,14 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } + if (Arg.getKind() == TemplateArgument::ArgKind::Type) +Args.push_back(Arg.getAsType()); +} return {{Trait.value(), std::move(Args)}}; } @@ -2159,6 +2167,26 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason(Sema &SemaRef, SourceLocation Loc, + QualType T) { + SemaRef.Diag(Loc, diag::note_unsatisfied_trait) + << T << diag::TraitName::Constructible; + + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isVoidType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D; +} + static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, SourceLocation Loc, QualType T) { SemaRef.Diag(Loc, diag::note_unsatisfied_trait) @@ -2195,6 +2223,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) { case UTT_IsTriviallyCopyable: DiagnoseNonTriviallyCopyableReason(*this, E->getBeginLoc(), Args[0]); break; + case TT_IsConstructible: +DiagnoseNonConstructibleReason(*this, E->getBeginLoc(), Args[0]); +break; default: break; } diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp index 498e202e26265..b9ee677a1cffc 100644 --- a/clang/test/SemaCXX/type-traits-unsatisfied-
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why a is constructible evaluated to false. (PR #143309)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/143309 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura created https://github.com/llvm/llvm-project/pull/144220 Reverts #144127 Fixies https://github.com/llvm/llvm-project/pull/143309#issuecomment-2970012054 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/2] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() ||
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
egorshamshura wrote: Hi, @AaronBallman! I noticed that the libc++ tests are not using the latest version of my code. How can I run them with the latest version? Thank you! https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Added explanation why is_constructible evaluated to false. Updated the diagnostics checks in libc++ tests. (PR #144220)
egorshamshura wrote: @philnik777 Is it my fault that tests fail with ```Error: Process completed with exit code 255```? https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why ```is trivial copyable``` evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why ```is_trivially_copyable``` evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [Clang] Added explanation why ```is_trivial_copyable``` evaluated to false. (PR #142341)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/142341 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/144220 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/3] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); +ArgExp
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
@@ -124,8 +126,8 @@ void test() { #if _LIBCPP_HAS_EXCEPTIONS // expected-error-re@*:* {{call to deleted constructor of{{.* // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* egorshamshura wrote: In older versions of Clang, there were 4 errors displayed: ```{{call to deleted constructor of{{.*```, but in the new version there are 6 errors. When I added ```{{call to deleted constructor of 'MoveOnly'}}```, one of the errors ```{{call to deleted constructor of{{.*``` was taken away, so I needed to add "0-1" here. https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
@@ -28,14 +28,15 @@ int main(int, char**) { { MoveOnly mo[] = {MoveOnly{3}}; // expected-error@array:* {{to_array requires copy constructible elements}} -// expected-error-re@array:* (call to implicitly-deleted copy constructor of 'MoveOnly')|(call to deleted constructor of 'MoveOnly') +// expected-error-re@array:* 0-1(call to implicitly-deleted copy constructor of 'MoveOnly')|(call to deleted constructor of 'MoveOnly') +// expected-error@array:* 0-1{{call to deleted constructor of 'MoveOnly'}} egorshamshura wrote: The same thing as above https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura deleted https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
@@ -124,8 +126,8 @@ void test() { #if _LIBCPP_HAS_EXCEPTIONS // expected-error-re@*:* {{call to deleted constructor of{{.* // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* egorshamshura wrote: In older versions of Clang, 4 errors are displayed: ```{{call to deleted constructor of{{.*```, but in new version is 6 errors. So when I have added ```{{call to deleted constructor of 'MoveOnly'}}``` It takes one of the error ```{{call to deleted constructor of{{.*```, that's why I needed to add 0-1 here https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Added explanation why is_constructible evaluated to false. Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura edited https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/144220 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/6] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); +ArgExp
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
@@ -124,8 +126,8 @@ void test() { #if _LIBCPP_HAS_EXCEPTIONS // expected-error-re@*:* {{call to deleted constructor of{{.* // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* - // expected-error-re@*:* {{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* + // expected-error-re@*:* 0-1{{call to deleted constructor of{{.* egorshamshura wrote: Yes, I guess we can.. Sorry https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Added explanation why is_constructible evaluated to false. Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/144220 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/7] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); +ArgExp
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
egorshamshura wrote: > > Hi, @AaronBallman! I noticed that the libc++ tests are not using the latest > > version of my code. How can I run them with the latest version? Thank you! > > They are being run with the current trunk, but also with older versions of > Clang, because libc++ supports older versions. Assuming the changes are > actually correct, you should be able to simply use `expected-error 0-1` to > work around the different diagnostic behaviour in different Clang versions. Thanks, I get it! https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
@@ -55,6 +55,7 @@ void test() { // expected-error-re@*:* {{static assertion failed {{.*}}The result of f(value()) must be a specialization of std::expected}} // expected-error-re@*:* .*}}cannot be used prior to '::' because it has no members}} // expected-error-re@*:* {{no matching constructor for initialization of{{.* + // expected-error@*:* {{excess elements in struct initializer}} egorshamshura wrote: This was discussed here: https://github.com/llvm/llvm-project/pull/143309#discussion_r2134728164 As I understand it, this is a temporary solution. https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/144220 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/4] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); +ArgExp
[clang] [libcxx] [libc++][Clang] Updated the diagnostics checks in libc++ tests. (PR #144220)
https://github.com/egorshamshura updated https://github.com/llvm/llvm-project/pull/144220 >From 30935f3d8a910646d50f27202611deebfbae95bf Mon Sep 17 00:00:00 2001 From: Shamshura Egor Date: Fri, 13 Jun 2025 19:48:52 + Subject: [PATCH 1/5] Revert "Revert "[Clang] Added explanation why `is_constructible` evaluated to false. " (#144127)" This reverts commit 90d98a38b273f5d62424a3815447675860947927. --- .../clang/Basic/DiagnosticSemaKinds.td| 8 ++- clang/lib/Sema/SemaTypeTraits.cpp | 71 ++- clang/test/CXX/drs/cwg18xx.cpp| 3 +- ...overload-resolution-deferred-templates.cpp | 19 +++-- .../type-traits-unsatisfied-diags-std.cpp | 66 + .../SemaCXX/type-traits-unsatisfied-diags.cpp | 62 6 files changed, 219 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8fe7ad6138aa0..95d24e9f1e6b5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -1767,7 +1767,8 @@ def note_unsatisfied_trait : Note<"%0 is not %enum_select{" "%TriviallyRelocatable{trivially relocatable}|" "%Replaceable{replaceable}|" - "%TriviallyCopyable{trivially copyable}" + "%TriviallyCopyable{trivially copyable}|" + "%Constructible{constructible with provided types}" "}1">; def note_unsatisfied_trait_reason @@ -1797,7 +1798,10 @@ def note_unsatisfied_trait_reason "%DeletedAssign{has a deleted %select{copy|move}1 " "assignment operator}|" "%UnionWithUserDeclaredSMF{is a union with a user-declared " - "%sub{select_special_member_kind}1}" + "%sub{select_special_member_kind}1}|" + "%FunctionType{is a function type}|" + "%CVVoidType{is a cv void type}|" + "%IncompleteArrayType{is an incomplete array type}" "}0">; def warn_consteval_if_always_true : Warning< diff --git a/clang/lib/Sema/SemaTypeTraits.cpp b/clang/lib/Sema/SemaTypeTraits.cpp index 1738ab4466001..22c690bedc1ed 100644 --- a/clang/lib/Sema/SemaTypeTraits.cpp +++ b/clang/lib/Sema/SemaTypeTraits.cpp @@ -11,6 +11,7 @@ //===--===// #include "clang/AST/DeclCXX.h" +#include "clang/AST/TemplateBase.h" #include "clang/AST/Type.h" #include "clang/Basic/DiagnosticParse.h" #include "clang/Basic/DiagnosticSema.h" @@ -1947,6 +1948,7 @@ static std::optional StdNameToTypeTrait(StringRef Name) { TypeTrait::UTT_IsCppTriviallyRelocatable) .Case("is_replaceable", TypeTrait::UTT_IsReplaceable) .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable) + .Case("is_constructible", TypeTrait::TT_IsConstructible) .Default(std::nullopt); } @@ -1983,8 +1985,16 @@ static ExtractedTypeTraitInfo ExtractTypeTraitFromExpression(const Expr *E) { Trait = StdNameToTypeTrait(Name); if (!Trait) return std::nullopt; -for (const auto &Arg : VD->getTemplateArgs().asArray()) - Args.push_back(Arg.getAsType()); +for (const auto &Arg : VD->getTemplateArgs().asArray()) { + if (Arg.getKind() == TemplateArgument::ArgKind::Pack) { +for (const auto &InnerArg : Arg.pack_elements()) + Args.push_back(InnerArg.getAsType()); + } else if (Arg.getKind() == TemplateArgument::ArgKind::Type) { +Args.push_back(Arg.getAsType()); + } else { +llvm_unreachable("Unexpected kind"); + } +} return {{Trait.value(), std::move(Args)}}; } @@ -2257,6 +2267,60 @@ static void DiagnoseNonTriviallyCopyableReason(Sema &SemaRef, } } +static void DiagnoseNonConstructibleReason( +Sema &SemaRef, SourceLocation Loc, +const llvm::SmallVector &Ts) { + if (Ts.empty()) { +return; + } + + bool ContainsVoid = false; + for (const QualType &ArgTy : Ts) { +ContainsVoid |= ArgTy->isVoidType(); + } + + if (ContainsVoid) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::CVVoidType; + + QualType T = Ts[0]; + if (T->isFunctionType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::FunctionType; + + if (T->isIncompleteArrayType()) +SemaRef.Diag(Loc, diag::note_unsatisfied_trait_reason) +<< diag::TraitNotSatisfiedReason::IncompleteArrayType; + + const CXXRecordDecl *D = T->getAsCXXRecordDecl(); + if (!D || D->isInvalidDecl() || !D->hasDefinition()) +return; + + llvm::BumpPtrAllocator OpaqueExprAllocator; + SmallVector ArgExprs; + ArgExprs.reserve(Ts.size() - 1); + for (unsigned I = 1, N = Ts.size(); I != N; ++I) { +QualType ArgTy = Ts[I]; +if (ArgTy->isObjectType() || ArgTy->isFunctionType()) + ArgTy = SemaRef.Context.getRValueReferenceType(ArgTy); +ArgExp
[clang] [libcxx] [libc++][Clang] Added explanation why is_constructible evaluated to false. Updated the diagnostics checks in libc++ tests. (PR #144220)
egorshamshura wrote: > Can you update the title/description to reflect the entire change (ie reuse > the title/description of the previous PR)? Otherwise LGTM > > Thanks for fixing the libc++ tests I have changed title and added description. How can I rerun job? https://github.com/llvm/llvm-project/pull/144220 ___ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits