tbaeder created this revision.
tbaeder added reviewers: aaron.ballman, erichkeane, shafik, cor3ntin.
Herald added a project: All.
tbaeder requested review of this revision.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D156212

Files:
  clang/lib/AST/Interp/InterpBuiltin.cpp
  clang/test/AST/Interp/builtin-functions.cpp

Index: clang/test/AST/Interp/builtin-functions.cpp
===================================================================
--- clang/test/AST/Interp/builtin-functions.cpp
+++ clang/test/AST/Interp/builtin-functions.cpp
@@ -5,39 +5,228 @@
 // RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -fexperimental-new-constant-interpreter -triple i686 %s -verify
 // RUN: %clang_cc1 -std=c++20 -Wno-string-plus-int -verify=ref %s -Wno-constant-evaluated
 
-
-namespace strcmp {
+namespace StrcmpEtc {
   constexpr char kFoobar[6] = {'f','o','o','b','a','r'};
   constexpr char kFoobazfoobar[12] = {'f','o','o','b','a','z','f','o','o','b','a','r'};
 
-  static_assert(__builtin_strcmp("", "") == 0, "");
-  static_assert(__builtin_strcmp("abab", "abab") == 0, "");
-  static_assert(__builtin_strcmp("abab", "abba") == -1, "");
-  static_assert(__builtin_strcmp("abab", "abaa") == 1, "");
-  static_assert(__builtin_strcmp("ababa", "abab") == 1, "");
-  static_assert(__builtin_strcmp("abab", "ababa") == -1, "");
-  static_assert(__builtin_strcmp("a\203", "a") == 1, "");
-  static_assert(__builtin_strcmp("a\203", "a\003") == 1, "");
-  static_assert(__builtin_strcmp("abab\0banana", "abab") == 0, "");
-  static_assert(__builtin_strcmp("abab", "abab\0banana") == 0, "");
-  static_assert(__builtin_strcmp("abab\0banana", "abab\0canada") == 0, "");
-  static_assert(__builtin_strcmp(0, "abab") == 0, ""); // expected-error {{not an integral constant}} \
-                                                       // expected-note {{dereferenced null}} \
-                                                       // expected-note {{in call to}} \
-                                                       // ref-error {{not an integral constant}} \
-                                                       // ref-note {{dereferenced null}}
-  static_assert(__builtin_strcmp("abab", 0) == 0, ""); // expected-error {{not an integral constant}} \
-                                                       // expected-note {{dereferenced null}} \
-                                                       // expected-note {{in call to}} \
-                                                       // ref-error {{not an integral constant}} \
-                                                       // ref-note {{dereferenced null}}
-
-  static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar) == -1, "");
-  static_assert(__builtin_strcmp(kFoobar, kFoobazfoobar + 6) == 0, ""); // expected-error {{not an integral constant}} \
+  static_assert(__builtin_strncmp("abaa", "abba", 5) == -1);
+  static_assert(__builtin_strncmp("abaa", "abba", 4) == -1);
+  static_assert(__builtin_strncmp("abaa", "abba", 3) == -1);
+  static_assert(__builtin_strncmp("abaa", "abba", 2) == 0);
+  static_assert(__builtin_strncmp("abaa", "abba", 1) == 0);
+  static_assert(__builtin_strncmp("abaa", "abba", 0) == 0);
+  static_assert(__builtin_strncmp(0, 0, 0) == 0);
+  static_assert(__builtin_strncmp("abab\0banana", "abab\0canada", 100) == 0);
+
+  static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 6) == -1);
+  static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar, 7) == -1);
+  static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 6) == 0);
+  static_assert(__builtin_strncmp(kFoobar, kFoobazfoobar + 6, 7) == 0); // expected-error {{not an integral constant}} \
                                                                         // expected-note {{dereferenced one-past-the-end}} \
                                                                         // expected-note {{in call to}} \
-                                                                        // ref-error {{not an integral constant}} \
+                                                                        // ref-error {{not an integral constant expression}} \
                                                                         // ref-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_memcmp("abaa", "abba", 3) == -1);
+  static_assert(__builtin_memcmp("abaa", "abba", 2) == 0);
+  static_assert(__builtin_memcmp("a\203", "a", 2) == 1);
+  static_assert(__builtin_memcmp("a\203", "a\003", 2) == 1);
+  static_assert(__builtin_memcmp(0, 0, 0) == 0);
+  static_assert(__builtin_memcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} \
+                                                                             // expected-note {{dereferenced one-past-the-end}} \
+                                                                             // expected-note {{in call to}} \
+                                                                             // ref-error {{not an integral constant}} \
+                                                                             // ref-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 100) == -1);
+  static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 7) == -1);
+  static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 6) == -1);
+  static_assert(__builtin_memcmp("abab\0banana", "abab\0canada", 5) == 0);
+
+  static_assert(__builtin_memcmp(u8"abaa", u8"abba", 3) == -1);
+  static_assert(__builtin_memcmp(u8"abaa", u8"abba", 2) == 0);
+  static_assert(__builtin_memcmp(u8"a\203", u8"a", 2) == 1);
+  static_assert(__builtin_memcmp(u8"a\203", u8"a\003", 2) == 1);
+  static_assert(__builtin_memcmp(0, 0, 0) == 0);
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0banana", 100) == 0); // expected-error {{not an integral constant}} \
+                                                                                 // expected-note {{dereferenced one-past-the-end}} \
+                                                                                 // expected-note {{in call to}} \
+                                                                                 // ref-error {{not an integral constant}} \
+                                                                                 // ref-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 100) == -1);
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 7) == -1);
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 6) == -1);
+  static_assert(__builtin_memcmp(u8"abab\0banana", u8"abab\0canada", 5) == 0);
+
+  static_assert(__builtin_memcmp(u8"\u1234", "\xE1\x88\xB4", 4) == 0);
+  static_assert(__builtin_memcmp(u8"\u1234", "\xE1\x88\xB3", 4) == 1);
+
+  static_assert(__builtin_bcmp("abaa", "abba", 3) != 0);
+  static_assert(__builtin_bcmp("abaa", "abba", 2) == 0);
+  static_assert(__builtin_bcmp("a\203", "a", 2) != 0);
+  static_assert(__builtin_bcmp("a\203", "a\003", 2) != 0);
+  static_assert(__builtin_bcmp(0, 0, 0) == 0);
+  static_assert(__builtin_bcmp("abab\0banana", "abab\0banana", 100) == 0); // expected-error {{not an integral constant}} \
+                                                                           // expected-note {{dereferenced one-past-the-end}} \
+                                                                           // expected-note {{in call to}} \
+                                                                           // ref-error {{not an integral constant}} \
+                                                                           // ref-note {{dereferenced one-past-the-end}}
+  static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 100) != 0);
+  static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 7) != 0);
+  static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 6) != 0);
+  static_assert(__builtin_bcmp("abab\0banana", "abab\0canada", 5) == 0);
+
+  extern struct Incomplete incomplete;
+  /// FIXME: Referencing the incomplete struct above doesn't work yet.
+#if 0
+  static_assert(__builtin_memcmp(&incomplete, "", 0u) == 0);
+  static_assert(__builtin_memcmp("", &incomplete, 0u) == 0);
+  static_assert(__builtin_memcmp(&incomplete, "", 1u) == 42);
+  static_assert(__builtin_memcmp("", &incomplete, 1u) == 42);
+
+  static_assert(__builtin_bcmp(&incomplete, "", 0u) == 0);
+  static_assert(__builtin_bcmp("", &incomplete, 0u) == 0);
+  static_assert(__builtin_bcmp(&incomplete, "", 1u) == 42);
+  static_assert(__builtin_bcmp("", &incomplete, 1u) == 42);
+#endif
+
+  constexpr unsigned char ku00fe00[] = {0x00, 0xfe, 0x00};
+  constexpr unsigned char ku00feff[] = {0x00, 0xfe, 0xff};
+  constexpr signed char ks00fe00[] = {0, -2, 0};
+  constexpr signed char ks00feff[] = {0, -2, -1};
+  static_assert(__builtin_memcmp(ku00feff, ks00fe00, 2) == 0);
+  static_assert(__builtin_memcmp(ku00feff, ks00fe00, 99) == 1);
+  static_assert(__builtin_memcmp(ku00fe00, ks00feff, 99) == -1);
+  static_assert(__builtin_memcmp(ks00feff, ku00fe00, 2) == 0);
+  static_assert(__builtin_memcmp(ks00feff, ku00fe00, 99) == 1);
+  static_assert(__builtin_memcmp(ks00fe00, ku00feff, 99) == -1);
+  static_assert(__builtin_memcmp(ks00fe00, ks00feff, 2) == 0);
+  static_assert(__builtin_memcmp(ks00feff, ks00fe00, 99) == 1);
+  static_assert(__builtin_memcmp(ks00fe00, ks00feff, 99) == -1);
+
+  static_assert(__builtin_bcmp(ku00feff, ks00fe00, 2) == 0);
+  static_assert(__builtin_bcmp(ku00feff, ks00fe00, 99) != 0);
+  static_assert(__builtin_bcmp(ku00fe00, ks00feff, 99) != 0);
+  static_assert(__builtin_bcmp(ks00feff, ku00fe00, 2) == 0);
+  static_assert(__builtin_bcmp(ks00feff, ku00fe00, 99) != 0);
+  static_assert(__builtin_bcmp(ks00fe00, ku00feff, 99) != 0);
+  static_assert(__builtin_bcmp(ks00fe00, ks00feff, 2) == 0);
+  static_assert(__builtin_bcmp(ks00feff, ks00fe00, 99) != 0);
+  static_assert(__builtin_bcmp(ks00fe00, ks00feff, 99) != 0);
+
+  struct Bool3Tuple { bool bb[3]; };
+  constexpr Bool3Tuple kb000100 = {{false, true, false}};
+  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 1) == 0); // ref-error {{constant}} \
+                                                                                        // ref-note {{not supported}} \
+                                                                                        // expected-error {{constant}} \
+                                                                                        // expected-note {{not supported}} \
+                                                                                        // expected-note {{in call to}}
+  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, kb000100.bb, 2) == 1); // ref-error {{constant}} \
+                                                                                        // ref-note {{not supported}} \
+                                                                                        // expected-error {{constant}} \
+                                                                                        // expected-note {{not supported}} \
+                                                                                        // expected-note {{in call to}}
+  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, kb000100.bb, 1) == 0); // ref-error {{constant}} \
+                                                                                      // ref-note {{not supported}} \
+                                                                                      // expected-error {{constant}} \
+                                                                                      // expected-note {{not supported}} \
+                                                                                      // expected-note {{in call to}}
+
+  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, kb000100.bb, 2) != 0); // ref-error {{constant}} \
+                                                                                      // ref-note {{not supported}} \
+                                                                                      // expected-error {{constant}} \
+                                                                                      // expected-note {{not supported}} \
+                                                                                      // expected-note {{in call to}}
+
+  constexpr long ksl[] = {0, -1};
+  constexpr unsigned int kui[] = {0, 0u - 1};
+  constexpr unsigned long long kull[] = {0, 0ull - 1};
+  constexpr const auto *kuSizeofLong(void) {
+    if constexpr(sizeof(long) == sizeof(int)) {
+      return kui;
+    } else if constexpr(sizeof(long) == sizeof(long long)) {
+      return kull;
+    } else {
+      return nullptr;
+    }
+  }
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) - 1) == 0); // ref-error {{constant}} \
+                                                                               // ref-note {{not supported}} \
+                                                                               // expected-error {{constant}} \
+                                                                               // expected-note {{not supported}} \
+                                                                               // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 0) == 0); // ref-error {{constant}} \
+                                                                               // ref-note {{not supported}} \
+                                                                               // expected-error {{constant}} \
+                                                                               // expected-note {{not supported}} \
+                                                                               // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                               // expected-error {{constant}} \
+                                                                               // expected-note {{not supported}} \
+                                                                               // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) - 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                 // expected-error {{constant}} \
+                                                                                 // expected-note {{not supported}} \
+                                                                                 // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 0) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                 // expected-error {{constant}} \
+                                                                                 // expected-note {{not supported}} \
+                                                                                 // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 1) == 42); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                  // expected-error {{constant}} \
+                                                                                  // expected-note {{not supported}} \
+                                                                                  // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) - 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                       // expected-error {{constant}} \
+                                                                                       // expected-note {{not supported}} \
+                                                                                       // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 0) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                       // expected-error {{constant}} \
+                                                                                       // expected-note {{not supported}} \
+                                                                                       // expected-note {{in call to}}
+  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 1) == 42); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                        // expected-error {{constant}} \
+                                                                                        // expected-note {{not supported}} \
+                                                                                        // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) - 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                             // expected-error {{constant}} \
+                                                                             // expected-note {{not supported}} \
+                                                                             // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 0) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                             // expected-error {{constant}} \
+                                                                             // expected-note {{not supported}} \
+                                                                             // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                             // expected-error {{constant}} \
+                                                                             // expected-note {{not supported}} \
+                                                                             // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) - 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                               // expected-error {{constant}} \
+                                                                               // expected-note {{not supported}} \
+                                                                               // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 0) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                               // expected-error {{constant}} \
+                                                                               // expected-note {{not supported}} \
+                                                                               // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + 1) == 42); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                // expected-error {{constant}} \
+                                                                                // expected-note {{not supported}} \
+                                                                                // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) - 1) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                     // expected-error {{constant}} \
+                                                                                     // expected-note {{not supported}} \
+                                                                                     // expected-note {{in call to}}
+  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 0) == 0); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                    // expected-error {{constant}} \
+                                                                                    // expected-note {{not supported}} \
+                                                                                    // expected-note {{in call to}}
+static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, sizeof(long) + 1) == 42); // ref-error {{constant}} ref-note {{not supported}} \
+                                                                                    // expected-error {{constant}} \
+                                                                                    // expected-note {{not supported}} \
+                                                                                    // expected-note {{in call to}}
+#if 0
+constexpr int a = strcmp("hello", "world"); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strcmp' cannot be used in a constant expression}}
+  constexpr int b = strncmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'strncmp' cannot be used in a constant expression}}
+  constexpr int c = memcmp("hello", "world", 3); // expected-error {{constant expression}} expected-note {{non-constexpr function 'memcmp' cannot be used in a constant expression}}
+#endif
 }
 
 /// Copied from constant-expression-cxx11.cpp
Index: clang/lib/AST/Interp/InterpBuiltin.cpp
===================================================================
--- clang/lib/AST/Interp/InterpBuiltin.cpp
+++ clang/lib/AST/Interp/InterpBuiltin.cpp
@@ -80,21 +80,81 @@
   llvm_unreachable("size_t isn't 64 or 32 bit?");
 }
 
+static bool usableInStrcmp(const Pointer &P) {
+  if (!P.getFieldDesc()->isPrimitiveArray())
+    return false;
+
+  const ArrayType *AT = P.getFieldDesc()->getType()->getAsArrayTypeUnsafe();
+  if (!AT->getElementType()->isCharType() &&
+      !AT->getElementType()->isChar8Type())
+    return false;
+
+  return true;
+}
+
 static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
-                                   const InterpFrame *Frame) {
+                                   const InterpFrame *Frame,
+                                   const Function *F) {
   const Pointer &A = getParam<Pointer>(Frame, 0);
   const Pointer &B = getParam<Pointer>(Frame, 1);
 
+  unsigned BuiltinOp = F->getBuiltinID();
+  uint64_t MaxLength = uint64_t(-1);
+  if (BuiltinOp != Builtin::BIstrcmp && BuiltinOp != Builtin::BIwcscmp &&
+      BuiltinOp != Builtin::BI__builtin_strcmp &&
+      BuiltinOp != Builtin::BI__builtin_wcscmp) {
+    APSInt N =
+        peekToAPSInt(S.Stk, *S.getContext().classify(S.getCtx().getSizeType()));
+    MaxLength = N.getExtValue();
+  }
+
+  // Empty substrings compare equal by definition.
+  if (MaxLength == 0) {
+    pushInt(S, 0);
+    return true;
+  }
+
   if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
     return false;
 
+  bool IsRawByte = BuiltinOp == Builtin::BImemcmp ||
+                   BuiltinOp == Builtin::BIbcmp ||
+                   BuiltinOp == Builtin::BI__builtin_memcmp ||
+                   BuiltinOp == Builtin::BI__builtin_bcmp;
+  // FIXME: We could support comparing arbitary pointers by first bitcasting to
+  // a buffer.
+  if (IsRawByte && (!usableInStrcmp(A) || !usableInStrcmp(B))) {
+    const Expr *E = Frame->Caller->getExpr(OpPC);
+    S.FFDiag(E, diag::note_constexpr_memcmp_unsupported)
+        << ("'" + S.getCtx().BuiltinInfo.getName(BuiltinOp) + "'").str()
+        << A.getType() << B.getType() << E->getSourceRange();
+    return false;
+  }
+
+  bool StopAtNull = BuiltinOp != Builtin::BImemcmp &&
+                    BuiltinOp != Builtin::BIbcmp &&
+                    BuiltinOp != Builtin::BIwmemcmp &&
+                    BuiltinOp != Builtin::BI__builtin_memcmp &&
+                    BuiltinOp != Builtin::BI__builtin_bcmp &&
+                    BuiltinOp != Builtin::BI__builtin_wmemcmp;
+  bool IsWide = BuiltinOp == Builtin::BIwcscmp ||
+                BuiltinOp == Builtin::BIwcsncmp ||
+                BuiltinOp == Builtin::BIwmemcmp ||
+                BuiltinOp == Builtin::BI__builtin_wcscmp ||
+                BuiltinOp == Builtin::BI__builtin_wcsncmp ||
+                BuiltinOp == Builtin::BI__builtin_wmemcmp;
+
+  // FIXME: Implement support for the wide versions.
+  if (IsWide)
+    return false;
+
   assert(A.getFieldDesc()->isPrimitiveArray());
   assert(B.getFieldDesc()->isPrimitiveArray());
 
-  unsigned IndexA = A.getIndex();
-  unsigned IndexB = B.getIndex();
+  size_t IndexA = A.getIndex();
+  size_t IndexB = B.getIndex();
   int32_t Result = 0;
-  for (;; ++IndexA, ++IndexB) {
+  for (size_t I = 0; I < MaxLength; ++IndexA, ++IndexB, ++I) {
     const Pointer &PA = A.atIndex(IndexA);
     const Pointer &PB = B.atIndex(IndexB);
     if (!CheckRange(S, OpPC, PA, AK_Read) ||
@@ -111,7 +171,7 @@
       Result = -1;
       break;
     }
-    if (CA == 0 || CB == 0)
+    if (StopAtNull && (CA == 0 || CB == 0))
       break;
   }
 
@@ -402,7 +462,13 @@
   case Builtin::BI__builtin_assume:
     return RetVoid(S, OpPC, Dummy);
   case Builtin::BI__builtin_strcmp:
-    if (interp__builtin_strcmp(S, OpPC, Frame))
+  case Builtin::BI__builtin_wcscmp:
+  case Builtin::BI__builtin_strncmp:
+  case Builtin::BI__builtin_wcsncmp:
+  case Builtin::BI__builtin_memcmp:
+  case Builtin::BI__builtin_bcmp:
+  case Builtin::BI__builtin_wmemcmp:
+    if (interp__builtin_strcmp(S, OpPC, Frame, F))
       return retInt(S, OpPC, Dummy);
     break;
   case Builtin::BI__builtin_strlen:
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to