https://github.com/snarang181 updated 
https://github.com/llvm/llvm-project/pull/145044

>From 29de582dd07ceb89ead7ecf24be6c19004edd46e Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Fri, 20 Jun 2025 10:51:04 -0400
Subject: [PATCH 1/3] Explain why 'is_empty' evaluates to false Add tests for
 various cases of 'is_empty' evaluating to false // and ensure that the
 diagnostics are correct.

---
 .../clang/Basic/DiagnosticSemaKinds.td        |  8 ++-
 clang/lib/Sema/SemaTypeTraits.cpp             | 66 +++++++++++++++++++
 .../type-traits-unsatisfied-diags-std.cpp     | 44 +++++++++++++
 .../SemaCXX/type-traits-unsatisfied-diags.cpp | 58 ++++++++++++++++
 4 files changed, 175 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 9392cbb39c021..f8b733063f10b 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<TraitName>{"
            "%TriviallyRelocatable{trivially relocatable}|"
            "%Replaceable{replaceable}|"
-           "%TriviallyCopyable{trivially copyable}"
+           "%TriviallyCopyable{trivially copyable}|"
+           "%Empty{empty}"
            "}1">;
 
 def note_unsatisfied_trait_reason
@@ -1787,6 +1788,11 @@ def note_unsatisfied_trait_reason
            "%NonReplaceableField{has a non-replaceable member %1 of type %2}|"
            "%NTCBase{has a non-trivially-copyable base %1}|"
            "%NTCField{has a non-trivially-copyable member %1 of type %2}|"
+           "%NonEmptyMember{has a non-static data member %1 of type %2}|"
+           "%VirtualFunction{has a virtual function %1}|"
+           "%VirtualBase{has a virtual base class %1}|"
+           "%NonEmptyBase{has a base class %1 that is not empty}|"
+           "%ZeroLengthField{field %1 is a non-zero-length bit-field}|"
            "%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 bf59bbb87fd8a..1c71ca2448f1c 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -1958,6 +1958,7 @@ static std::optional<TypeTrait> 
StdNameToTypeTrait(StringRef Name) {
       .Case("is_replaceable", TypeTrait::UTT_IsReplaceable)
       .Case("is_trivially_copyable", TypeTrait::UTT_IsTriviallyCopyable)
       .Case("is_assignable", TypeTrait::BTT_IsAssignable)
+      .Case("is_empty", TypeTrait::UTT_IsEmpty)
       .Default(std::nullopt);
 }
 
@@ -2313,6 +2314,68 @@ static void DiagnoseNonAssignableReason(Sema &SemaRef, 
SourceLocation Loc,
   SemaRef.Diag(D->getLocation(), diag::note_defined_here) << D;
 }
 
+static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc,
+                                  const CXXRecordDecl *D) {
+  // Non-static data members (ignore zero-width bit‐fields).
+  for (auto *Field : D->fields()) {
+    if (Field->isBitField() && Field->getBitWidthValue() == 0)
+      continue;
+    S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+        << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
+        << Field->getType() << Field->getSourceRange();
+  }
+
+  // Virtual functions.
+  for (auto *M : D->methods()) {
+    if (M->isVirtual()) {
+      S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+          << diag::TraitNotSatisfiedReason::VirtualFunction << M->getDeclName()
+          << M->getSourceRange();
+      break;
+    }
+  }
+
+  // Virtual bases and non-empty bases.
+  for (auto &B : D->bases()) {
+    auto *BR = B.getType()->getAsCXXRecordDecl();
+    if (!BR || BR->isInvalidDecl())
+      continue;
+    if (B.isVirtual()) {
+      S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+          << diag::TraitNotSatisfiedReason::VirtualBase << B.getType()
+          << B.getSourceRange();
+    }
+    if (!BR->isEmpty()) {
+      S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+          << diag::TraitNotSatisfiedReason::NonEmptyBase << B.getType()
+          << B.getSourceRange();
+    }
+  }
+}
+
+static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc, QualType T) {
+  // Emit primary "not empty" diagnostic.
+  S.Diag(Loc, diag::note_unsatisfied_trait) << T << diag::TraitName::Empty;
+
+  // While diagnosing is_empty<T>, we want to look at the actual type, not a
+  // reference or an array of it. So we need to massage the QualType param to
+  // strip refs and arrays.
+  if (T->isReferenceType())
+    S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+        << diag::TraitNotSatisfiedReason::Ref;
+  T = T.getNonReferenceType();
+
+  if (auto *AT = S.Context.getAsArrayType(T))
+    T = AT->getElementType();
+
+  if (auto *D = T->getAsCXXRecordDecl()) {
+    if (D->hasDefinition()) {
+      DiagnoseIsEmptyReason(S, Loc, D);
+      S.Diag(D->getLocation(), diag::note_defined_here) << D;
+    }
+  }
+}
+
 void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
   E = E->IgnoreParenImpCasts();
   if (E->containsErrors())
@@ -2336,6 +2399,9 @@ void Sema::DiagnoseTypeTraitDetails(const Expr *E) {
   case BTT_IsAssignable:
     DiagnoseNonAssignableReason(*this, E->getBeginLoc(), Args[0], Args[1]);
     break;
+  case UTT_IsEmpty:
+    DiagnoseIsEmptyReason(*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 33b92326aec21..89fbad0c5b9b8 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags-std.cpp
@@ -28,6 +28,13 @@ struct is_assignable {
 
 template <typename T, typename U>
 constexpr bool is_assignable_v = __is_assignable(T, U);
+
+template <typename T>
+struct is_empty {
+    static constexpr bool value = __is_empty(T);
+};
+template <typename T>
+constexpr bool is_empty_v = __is_empty(T);
 #endif
 
 #ifdef STD2
@@ -63,6 +70,15 @@ using is_assignable = __details_is_assignable<T, U>;
 
 template <typename T, typename U>
 constexpr bool is_assignable_v = __is_assignable(T, U);
+
+template <typename T>
+struct __details_is_empty {
+    static constexpr bool value = __is_empty(T);
+};
+template <typename T>
+using is_empty  = __details_is_empty<T>;
+template <typename T>
+constexpr bool is_empty_v = __is_empty(T);
 #endif
 
 
@@ -101,6 +117,13 @@ using is_assignable  = __details_is_assignable<T, U>;
 
 template <typename T, typename U>
 constexpr bool is_assignable_v = is_assignable<T, U>::value;
+
+template <typename T>
+struct __details_is_empty : bool_constant<__is_empty(T)> {};
+template <typename T>
+using is_empty  = __details_is_empty<T>;
+template <typename T>
+constexpr bool is_empty_v = is_empty<T>::value;
 #endif
 
 }
@@ -127,6 +150,18 @@ static_assert(std::is_trivially_copyable_v<int&>);
 // expected-note@-1 {{'int &' is not trivially copyable}} \
 // expected-note@-1 {{because it is a reference type}}
 
+static_assert(!std::is_empty<int>::value);
+
+static_assert(std::is_empty<int&>::value);
+// expected-error-re@-1 {{static assertion failed due to requirement 
'std::{{.*}}is_empty<int &>::value'}} \
+// expected-note@-1 {{'int &' is not empty}} \
+// expected-note@-1 {{because it is a reference type}}
+static_assert(std::is_empty_v<int&>);
+// expected-error@-1 {{static assertion failed due to requirement 
'std::is_empty_v<int &>'}} \
+// expected-note@-1 {{'int &' is not empty}} \
+// expected-note@-1 {{because it is a reference type}}
+
+
 static_assert(std::is_assignable<int&, int>::value);
 
 static_assert(std::is_assignable<int&, void>::value);
@@ -162,6 +197,15 @@ namespace test_namespace {
     static_assert(is_assignable_v<int&, void>);
     // expected-error@-1 {{static assertion failed due to requirement 
'is_assignable_v<int &, void>'}} \
     // expected-error@-1 {{assigning to 'int' from incompatible type 'void'}}
+
+    static_assert(is_empty<int&>::value);
+    // expected-error-re@-1 {{static assertion failed due to requirement 
'{{.*}}is_empty<int &>::value'}} \
+    // expected-note@-1 {{'int &' is not empty}} \
+    // expected-note@-1 {{because it is a reference type}} 
+    static_assert(is_empty_v<int&>);
+    // expected-error@-1 {{static assertion failed due to requirement 
'is_empty_v<int &>'}} \
+    // expected-note@-1 {{'int &' is not empty}} \
+    // expected-note@-1 {{because it is a reference type}}
 }
 
 
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp 
b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
index 975174353a2a1..bdcb56d6fcc01 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
@@ -559,3 +559,61 @@ static_assert(__is_assignable(C1, C1));
 // expected-note@#ama-C1 {{implicitly declared private here}} \
 // expected-note@#a-C1 {{'C1' defined here}}
 }
+
+namespace is_empty_tests {
+    // Non-static data member.
+    struct A { int x; }; // #e-A
+    static_assert(__is_empty(A));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::A)'}} \
+    // expected-note@-1 {{'A' is not empty}} \
+    // expected-note@-1 {{because it has a non-static data member 'x' of type 
'int'}} \
+    // expected-note@#e-A {{'A' defined here}}
+
+    // Reference member.
+    struct R {int &r; }; // #e-R
+    static_assert(__is_empty(R));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::R)'}} \
+    // expected-note@-1 {{'R' is not empty}} \
+    // expected-note@-1 {{because it has a non-static data member 'r' of type 
'int &'}} \
+    // expected-note@#e-R {{'R' defined here}}
+
+    // Virtual function.
+    struct VirtualFunc {virtual void f(); }; // #e-VirtualFunc
+    static_assert(__is_empty(VirtualFunc));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::VirtualFunc)'}} \
+    // expected-note@-1 {{'VirtualFunc' is not empty}} \
+    // expected-note@-1 {{because it has a virtual function 'f'}} \
+    // expected-note@#e-VirtualFunc {{'VirtualFunc' defined here}}
+
+    // Virtual base class.
+    struct EB {};
+    struct VB: virtual EB {}; // #e-VB
+    static_assert(__is_empty(VB));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::VB)'}} \
+    // expected-note@-1 {{'VB' is not empty}} \
+    // expected-note@-1 {{because it has a virtual base class 'EB'}} \
+    // expected-note@#e-VB {{'VB' defined here}}
+
+    // Non-empty base class.
+    struct Base { int b; }; // #e-Base
+    struct Derived : Base {}; // #e-Derived
+    static_assert(__is_empty(Derived));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::Derived)'}} \
+    // expected-note@-1 {{'Derived' is not empty}} \
+    // expected-note@-1 {{because it has a base class 'Base' that is not 
empty}} \
+    // expected-note@#e-Derived {{'Derived' defined here}} 
+
+    // Combination of the above.
+    struct Multi : Base, virtual EB { // #e-Multi
+        int z;
+        virtual void g();
+    };
+    static_assert(__is_empty(Multi));
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::Multi)'}} \
+    // expected-note@-1 {{'Multi' is not empty}} \
+    // expected-note@-1 {{because it has a non-static data member 'z' of type 
'int'}} \
+    // expected-note@-1 {{because it has a virtual function 'g'}} \
+    // expected-note@-1 {{because it has a base class 'Base' that is not 
empty}} \
+    // expected-note@-1 {{because it has a virtual base class 'EB'}} \
+    // expected-note@#e-Multi {{'Multi' defined here}}
+}

>From aecedc927ba79f41c301c090f1e515d428c6a4d2 Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Tue, 24 Jun 2025 23:50:15 -0400
Subject: [PATCH 2/3] Address PR comments Add info about diagnostic in
 ReleaseNotes.rst

---
 clang/docs/ReleaseNotes.rst                   |  4 ++++
 .../clang/Basic/DiagnosticSemaKinds.td        |  1 -
 clang/lib/Sema/SemaTypeTraits.cpp             | 20 +++++++++++-------
 .../SemaCXX/type-traits-unsatisfied-diags.cpp | 21 +++++++++++++++++--
 4 files changed, 36 insertions(+), 10 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index e1fe22393eebb..05efdd0b1ce10 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -644,6 +644,10 @@ Improvements to Clang's diagnostics
   #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
   #GH36703, #GH32903, #GH23312, #GH69874.
 
+- Clang now gives pinpointed diagnostics for std::is_empty<T> 
failures—emitting a “not empty” error 
+  plus “because…” notes for non-static members, virtual functions/bases, 
non-empty bases, and non-zero bit-fields 
+  (including dependent widths) while correctly ignoring zero-width bit-fields. 
+
 
 Improvements to Clang's time-trace
 ----------------------------------
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f8b733063f10b..1c3d7d50e8689 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1790,7 +1790,6 @@ def note_unsatisfied_trait_reason
            "%NTCField{has a non-trivially-copyable member %1 of type %2}|"
            "%NonEmptyMember{has a non-static data member %1 of type %2}|"
            "%VirtualFunction{has a virtual function %1}|"
-           "%VirtualBase{has a virtual base class %1}|"
            "%NonEmptyBase{has a base class %1 that is not empty}|"
            "%ZeroLengthField{field %1 is a non-zero-length bit-field}|"
            "%DeletedDtr{has a %select{deleted|user-provided}1 destructor}|"
diff --git a/clang/lib/Sema/SemaTypeTraits.cpp 
b/clang/lib/Sema/SemaTypeTraits.cpp
index 1c71ca2448f1c..64b7c1ad5c028 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -2317,32 +2317,38 @@ static void DiagnoseNonAssignableReason(Sema &SemaRef, 
SourceLocation Loc,
 static void DiagnoseIsEmptyReason(Sema &S, SourceLocation Loc,
                                   const CXXRecordDecl *D) {
   // Non-static data members (ignore zero-width bit‐fields).
-  for (auto *Field : D->fields()) {
-    if (Field->isBitField() && Field->getBitWidthValue() == 0)
+  for (const auto *Field : D->fields()) {
+    if (Field->isZeroLengthBitField())
       continue;
+    if (Field->isBitField()) {
+      S.Diag(Loc, diag::note_unsatisfied_trait_reason)
+          << diag::TraitNotSatisfiedReason::ZeroLengthField << Field
+          << Field->getSourceRange();
+      continue;
+    }
     S.Diag(Loc, diag::note_unsatisfied_trait_reason)
         << diag::TraitNotSatisfiedReason::NonEmptyMember << Field
         << Field->getType() << Field->getSourceRange();
   }
 
   // Virtual functions.
-  for (auto *M : D->methods()) {
+  for (const auto *M : D->methods()) {
     if (M->isVirtual()) {
       S.Diag(Loc, diag::note_unsatisfied_trait_reason)
-          << diag::TraitNotSatisfiedReason::VirtualFunction << M->getDeclName()
+          << diag::TraitNotSatisfiedReason::VirtualFunction << M
           << M->getSourceRange();
       break;
     }
   }
 
   // Virtual bases and non-empty bases.
-  for (auto &B : D->bases()) {
-    auto *BR = B.getType()->getAsCXXRecordDecl();
+  for (const auto &B : D->bases()) {
+    const auto *BR = B.getType()->getAsCXXRecordDecl();
     if (!BR || BR->isInvalidDecl())
       continue;
     if (B.isVirtual()) {
       S.Diag(Loc, diag::note_unsatisfied_trait_reason)
-          << diag::TraitNotSatisfiedReason::VirtualBase << B.getType()
+          << diag::TraitNotSatisfiedReason::VBase << B.getType()
           << B.getSourceRange();
     }
     if (!BR->isEmpty()) {
diff --git a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp 
b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
index bdcb56d6fcc01..f1624f0a6e553 100644
--- a/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
+++ b/clang/test/SemaCXX/type-traits-unsatisfied-diags.cpp
@@ -591,7 +591,7 @@ namespace is_empty_tests {
     static_assert(__is_empty(VB));
     // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::VB)'}} \
     // expected-note@-1 {{'VB' is not empty}} \
-    // expected-note@-1 {{because it has a virtual base class 'EB'}} \
+    // expected-note@-1 {{because it has a virtual base 'EB'}} \
     // expected-note@#e-VB {{'VB' defined here}}
 
     // Non-empty base class.
@@ -614,6 +614,23 @@ namespace is_empty_tests {
     // expected-note@-1 {{because it has a non-static data member 'z' of type 
'int'}} \
     // expected-note@-1 {{because it has a virtual function 'g'}} \
     // expected-note@-1 {{because it has a base class 'Base' that is not 
empty}} \
-    // expected-note@-1 {{because it has a virtual base class 'EB'}} \
+    // expected-note@-1 {{because it has a virtual base 'EB'}} \
     // expected-note@#e-Multi {{'Multi' defined here}}
+
+    // Zero-width bit-field.
+    struct BitField { int : 0; }; // #e-BitField
+    static_assert(__is_empty(BitField)); // no diagnostics  
+
+    // Dependent bit-field width. 
+    template <int N>
+    struct DependentBitField { int : N; }; // #e-DependentBitField
+
+    static_assert(__is_empty(DependentBitField<0>)); // no diagnostics
+
+    static_assert(__is_empty(DependentBitField<2>)); 
+    // expected-error@-1 {{static assertion failed due to requirement 
'__is_empty(is_empty_tests::DependentBitField<2>)'}} \
+    // expected-note@-1 {{'DependentBitField<2>' is not empty}} \
+    // expected-note@-1 {{because it field '' is a non-zero-length bit-field}} 
\
+    // expected-note@#e-DependentBitField {{'DependentBitField<2>' defined 
here}}
+
 }

>From 93c89fc7e3131c9262e0c6620d0cb22f2aab1983 Mon Sep 17 00:00:00 2001
From: Samarth Narang <snar...@umass.edu>
Date: Wed, 25 Jun 2025 09:18:46 -0400
Subject: [PATCH 3/3] Minor change in tablegen Revert info in ReleaseNotes.rst

---
 clang/docs/ReleaseNotes.rst                      | 6 +-----
 clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
 clang/lib/Sema/SemaTypeTraits.cpp                | 2 +-
 3 files changed, 3 insertions(+), 7 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 05efdd0b1ce10..357dcc1e451b5 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -644,11 +644,7 @@ Improvements to Clang's diagnostics
   #GH69470, #GH59391, #GH58172, #GH46215, #GH45915, #GH45891, #GH44490,
   #GH36703, #GH32903, #GH23312, #GH69874.
 
-- Clang now gives pinpointed diagnostics for std::is_empty<T> 
failures—emitting a “not empty” error 
-  plus “because…” notes for non-static members, virtual functions/bases, 
non-empty bases, and non-zero bit-fields 
-  (including dependent widths) while correctly ignoring zero-width bit-fields. 
-
-
+  
 Improvements to Clang's time-trace
 ----------------------------------
 
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 1c3d7d50e8689..6eba0619883d3 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -1791,7 +1791,7 @@ def note_unsatisfied_trait_reason
            "%NonEmptyMember{has a non-static data member %1 of type %2}|"
            "%VirtualFunction{has a virtual function %1}|"
            "%NonEmptyBase{has a base class %1 that is not empty}|"
-           "%ZeroLengthField{field %1 is a non-zero-length bit-field}|"
+           "%NonZeroLengthField{field %1 is a non-zero-length bit-field}|"
            "%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 64b7c1ad5c028..c8a764d19c3d5 100644
--- a/clang/lib/Sema/SemaTypeTraits.cpp
+++ b/clang/lib/Sema/SemaTypeTraits.cpp
@@ -2322,7 +2322,7 @@ static void DiagnoseIsEmptyReason(Sema &S, SourceLocation 
Loc,
       continue;
     if (Field->isBitField()) {
       S.Diag(Loc, diag::note_unsatisfied_trait_reason)
-          << diag::TraitNotSatisfiedReason::ZeroLengthField << Field
+          << diag::TraitNotSatisfiedReason::NonZeroLengthField << Field
           << Field->getSourceRange();
       continue;
     }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to