[clang] [Clang] Added explanation why a is trivial copyable evaluated to false. (PR #142341)

2025-06-03 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-03 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-03 Thread Shamshura Egor via cfe-commits

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)

2025-06-03 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-06 Thread Shamshura Egor via cfe-commits

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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits

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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits

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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-12 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits

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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-02 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-03 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-03 Thread Shamshura Egor via cfe-commits

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)

2025-06-08 Thread Shamshura Egor via cfe-commits

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)

2025-06-08 Thread Shamshura Egor via cfe-commits

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)

2025-06-06 Thread Shamshura Egor via cfe-commits

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)

2025-06-09 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-09 Thread Shamshura Egor via cfe-commits

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)

2025-06-09 Thread Shamshura Egor via cfe-commits

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)

2025-06-09 Thread Shamshura Egor via cfe-commits

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)

2025-06-14 Thread Shamshura Egor via cfe-commits

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)

2025-06-14 Thread Shamshura Egor via cfe-commits

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)

2025-06-18 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-16 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits


@@ -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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-15 Thread Shamshura Egor via cfe-commits

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)

2025-06-16 Thread Shamshura Egor via cfe-commits

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