<div dir="ltr">I'm assuming libc++ should move to this trait instead?<div><br></div><div>/Eric</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, May 31, 2017 at 6:28 PM, Richard Smith via cfe-commits <span dir="ltr"><<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: rsmith<br>
Date: Wed May 31 19:28:16 2017<br>
New Revision: 304376<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=304376&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project?rev=304376&view=rev</a><br>
Log:<br>
PR33232: implement support for MSVC's __is_trivially_destructible trait.<br>
<br>
Unlike the GCC-compatible __has_trivial_destructor trait, this one computes the<br>
right answer rather than performing the quirky set of checks described in GCC's<br>
documentation (<a href="https://gcc.gnu.org/onlinedocs/gcc/Type-Traits.html" rel="noreferrer" target="_blank">https://gcc.gnu.org/<wbr>onlinedocs/gcc/Type-Traits.<wbr>html</a>).<br>
<br>
MSVC also has a __has_trivial_destructor trait which is the same as its (and<br>
now Clang's) __is_trivially_destructible trait; we might want to consider<br>
changing the behavior of __has_trivial_destructor if we're targeting an MSVC<br>
platform, but I'm not doing so for now.<br>
<br>
While implementing this I found that we were incorrectly rejecting<br>
__is_destructible queries on arrays of unknown bound of incomplete types; that<br>
too is fixed, and I've added similar tests for other traits for good measure.<br>
<br>
Modified:<br>
    cfe/trunk/include/clang/Basic/<wbr>TokenKinds.def<br>
    cfe/trunk/include/clang/Basic/<wbr>TypeTraits.h<br>
    cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
    cfe/trunk/test/SemaCXX/type-<wbr>traits.cpp<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>TokenKinds.def<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TokenKinds.def?rev=304376&r1=304375&r2=304376&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/TokenKinds.def?<wbr>rev=304376&r1=304375&r2=<wbr>304376&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>TokenKinds.def (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>TokenKinds.def Wed May 31 19:28:16 2017<br>
@@ -411,6 +411,7 @@ TYPE_TRAIT_1(__is_sealed, IsSealed, KEYM<br>
<br>
 // MSVC12.0 / VS2013 Type Traits<br>
 TYPE_TRAIT_1(__is_<wbr>destructible, IsDestructible, KEYMS)<br>
+TYPE_TRAIT_1(__is_trivially_<wbr>destructible, IsTriviallyDestructible, KEYCXX)<br>
 TYPE_TRAIT_1(__is_nothrow_<wbr>destructible, IsNothrowDestructible, KEYMS)<br>
 TYPE_TRAIT_2(__is_nothrow_<wbr>assignable, IsNothrowAssignable, KEYCXX)<br>
 TYPE_TRAIT_N(__is_<wbr>constructible, IsConstructible, KEYCXX)<br>
@@ -439,7 +440,6 @@ TYPE_TRAIT_2(__is_convertible_<wbr>to, IsConv<br>
 TYPE_TRAIT_1(__is_empty, IsEmpty, KEYCXX)<br>
 TYPE_TRAIT_1(__is_enum, IsEnum, KEYCXX)<br>
 TYPE_TRAIT_1(__is_final, IsFinal, KEYCXX)<br>
-// Tentative name - there's no implementation of std::is_literal_type yet.<br>
 TYPE_TRAIT_1(__is_literal, IsLiteral, KEYCXX)<br>
 // Name for GCC 4.6 compatibility - people have already written libraries using<br>
 // this name unfortunately.<br>
<br>
Modified: cfe/trunk/include/clang/Basic/<wbr>TypeTraits.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TypeTraits.h?rev=304376&r1=304375&r2=304376&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/include/<wbr>clang/Basic/TypeTraits.h?rev=<wbr>304376&r1=304375&r2=304376&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/include/clang/Basic/<wbr>TypeTraits.h (original)<br>
+++ cfe/trunk/include/clang/Basic/<wbr>TypeTraits.h Wed May 31 19:28:16 2017<br>
@@ -65,6 +65,7 @@ namespace clang {<br>
     UTT_IsStandardLayout,<br>
     UTT_IsTrivial,<br>
     UTT_IsTriviallyCopyable,<br>
+    UTT_IsTriviallyDestructible,<br>
     UTT_IsUnion,<br>
     UTT_IsUnsigned,<br>
     UTT_IsVoid,<br>
<br>
Modified: cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaExprCXX.cpp?rev=304376&r1=304375&r2=304376&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp?rev=304376&r1=<wbr>304375&r2=304376&view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp (original)<br>
+++ cfe/trunk/lib/Sema/<wbr>SemaExprCXX.cpp Wed May 31 19:28:16 2017<br>
@@ -4080,24 +4080,23 @@ static bool CheckUnaryTypeTraitTypeCompl<br>
           Loc, ArgTy, diag::err_incomplete_type_<wbr>used_in_type_trait_expr);<br>
     return true;<br>
<br>
-  // C++0x [meta.unary.prop] Table 49 requires the following traits to be<br>
-  // applied to a complete type.<br>
+  // C++1z [meta.unary.prop]:<br>
+  //   remove_all_extents_t<T> shall be a complete type or cv void.<br>
   case UTT_IsAggregate:<br>
   case UTT_IsTrivial:<br>
   case UTT_IsTriviallyCopyable:<br>
   case UTT_IsStandardLayout:<br>
   case UTT_IsPOD:<br>
   case UTT_IsLiteral:<br>
+    ArgTy = QualType(ArgTy-><wbr>getBaseElementTypeUnsafe(), 0);<br>
+    LLVM_FALLTHROUGH;<br>
<br>
+  // C++1z [meta.unary.prop]:<br>
+  //   T shall be a complete type, cv void, or an array of unknown bound.<br>
   case UTT_IsDestructible:<br>
   case UTT_IsNothrowDestructible:<br>
-    // Fall-through<br>
-<br>
-    // These trait expressions are designed to help implement predicates in<br>
-    // [meta.unary.prop] despite not being named the same. They are specified<br>
-    // by both GCC and the Embarcadero C++ compiler, and require the complete<br>
-    // type due to the overarching C++0x type predicates being implemented<br>
-    // requiring the complete type.<br>
+  case UTT_IsTriviallyDestructible:<br>
+  // Per the GCC type traits documentation, the same constraints apply to these.<br>
   case UTT_HasNothrowAssign:<br>
   case UTT_HasNothrowMoveAssign:<br>
   case UTT_HasNothrowConstructor:<br>
@@ -4109,17 +4108,11 @@ static bool CheckUnaryTypeTraitTypeCompl<br>
   case UTT_HasTrivialCopy:<br>
   case UTT_HasTrivialDestructor:<br>
   case UTT_HasVirtualDestructor:<br>
-    // Arrays of unknown bound are expressly allowed.<br>
-    QualType ElTy = ArgTy;<br>
-    if (ArgTy->isIncompleteArrayType(<wbr>))<br>
-      ElTy = S.Context.getAsArrayType(<wbr>ArgTy)->getElementType();<br>
-<br>
-    // The void type is expressly allowed.<br>
-    if (ElTy->isVoidType())<br>
+    if (ArgTy->isIncompleteArrayType(<wbr>) || ArgTy->isVoidType())<br>
       return true;<br>
<br>
     return !S.RequireCompleteType(<br>
-      Loc, ElTy, diag::err_incomplete_type_<wbr>used_in_type_trait_expr);<br>
+        Loc, ArgTy, diag::err_incomplete_type_<wbr>used_in_type_trait_expr);<br>
   }<br>
 }<br>
<br>
@@ -4356,6 +4349,7 @@ static bool EvaluateUnaryTypeTrait(Sema<br>
              !RD-><wbr>hasNonTrivialCopyAssignment();<br>
     return false;<br>
   case UTT_IsDestructible:<br>
+  case UTT_IsTriviallyDestructible:<br>
   case UTT_IsNothrowDestructible:<br>
     // C++14 [meta.unary.prop]:<br>
     //   For reference types, is_destructible<T>::value is true.<br>
@@ -4373,6 +4367,11 @@ static bool EvaluateUnaryTypeTrait(Sema<br>
     if (T->isIncompleteType() || T->isFunctionType())<br>
       return false;<br>
<br>
+    // A type that requires destruction (via a non-trivial destructor or ARC<br>
+    // lifetime semantics) is not trivially-destructible.<br>
+    if (UTT == UTT_IsTriviallyDestructible && T.isDestructedType())<br>
+      return false;<br>
+<br>
     // C++14 [meta.unary.prop]:<br>
     //   For object types and given U equal to remove_all_extents_t<T>, if the<br>
     //   expression std::declval<U&>().~U() is well-formed when treated as an<br>
<br>
Modified: cfe/trunk/test/SemaCXX/type-<wbr>traits.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/type-traits.cpp?rev=304376&r1=304375&r2=304376&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-<wbr>project/cfe/trunk/test/<wbr>SemaCXX/type-traits.cpp?rev=<wbr>304376&r1=304375&r2=304376&<wbr>view=diff</a><br>
==============================<wbr>==============================<wbr>==================<br>
--- cfe/trunk/test/SemaCXX/type-<wbr>traits.cpp (original)<br>
+++ cfe/trunk/test/SemaCXX/type-<wbr>traits.cpp Wed May 31 19:28:16 2017<br>
@@ -252,6 +252,11 @@ void is_pod()<br>
   { int arr[F(__is_pod(void))]; }<br>
   { int arr[F(__is_pod(cvoid))]; }<br>
 // { int arr[F(__is_pod(NonPODUnion))]; }<br>
+<br>
+  { int arr[T(__is_pod(ACompleteType))<wbr>]; }<br>
+  { int arr[F(__is_pod(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_pod(<wbr>AnIncompleteType[]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_pod(<wbr>AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
 }<br>
<br>
 typedef Empty EmptyAr[10];<br>
@@ -287,6 +292,11 @@ void is_empty()<br>
   { int arr[F(__is_empty(IntArNB))]; }<br>
   { int arr[F(__is_empty(<wbr>HasAnonymousUnion))]; }<br>
 //  { int arr[F(__is_empty(DerivesVirt))<wbr>]; }<br>
+<br>
+  { int arr[T(__is_empty(<wbr>ACompleteType))]; }<br>
+  { int arr[F(__is_empty(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_empty(<wbr>AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_empty(<wbr>AnIncompleteType[1]))]; }<br>
 }<br>
<br>
 typedef Derives ClassType;<br>
@@ -511,6 +521,8 @@ void is_aggregate()<br>
   constexpr bool TrueAfterCpp14 = __cplusplus > 201402L;<br>
<br>
   __is_aggregate(<wbr>AnIncompleteType); // expected-error {{incomplete type}}<br>
+  __is_aggregate(<wbr>AnIncompleteType[]); // expected-error {{incomplete type}}<br>
+  __is_aggregate(<wbr>AnIncompleteType[1]); // expected-error {{incomplete type}}<br>
   __is_aggregate(<wbr>AnIncompleteTypeAr); // expected-error {{incomplete type}}<br>
   __is_aggregate(<wbr>AnIncompleteTypeArNB); // expected-error {{incomplete type}}<br>
   __is_aggregate(<wbr>AnIncompleteTypeArMB); // expected-error {{incomplete type}}<br>
@@ -1220,6 +1232,13 @@ void is_trivial2()<br>
   int t32[F(__is_trivial(<wbr>SuperNonTrivialStruct))];<br>
   int t33[F(__is_trivial(<wbr>NonTCStruct))];<br>
   int t34[F(__is_trivial(<wbr>ExtDefaulted))];<br>
+<br>
+  int t40[T(__is_trivial(<wbr>ACompleteType))];<br>
+  int t41[F(__is_trivial(<wbr>AnIncompleteType))]; // expected-error {{incomplete type}}<br>
+  int t42[F(__is_trivial(<wbr>AnIncompleteType[]))]; // expected-error {{incomplete type}}<br>
+  int t43[F(__is_trivial(<wbr>AnIncompleteType[1]))]; // expected-error {{incomplete type}}<br>
+  int t44[F(__is_trivial(void))];<br>
+  int t45[F(__is_trivial(const volatile void))];<br>
 }<br>
<br>
 void is_trivially_copyable2()<br>
@@ -1257,6 +1276,13 @@ void is_trivially_copyable2()<br>
<br>
   int t34[T(__is_trivially_copyable(<wbr>const int))];<br>
   int t35[T(__is_trivially_copyable(<wbr>volatile int))];<br>
+<br>
+  int t40[T(__is_trivially_copyable(<wbr>ACompleteType))];<br>
+  int t41[F(__is_trivially_copyable(<wbr>AnIncompleteType))]; // expected-error {{incomplete type}}<br>
+  int t42[F(__is_trivially_copyable(<wbr>AnIncompleteType[]))]; // expected-error {{incomplete type}}<br>
+  int t43[F(__is_trivially_copyable(<wbr>AnIncompleteType[1]))]; // expected-error {{incomplete type}}<br>
+  int t44[F(__is_trivially_copyable(<wbr>void))];<br>
+  int t45[F(__is_trivially_copyable(<wbr>const volatile void))];<br>
 }<br>
<br>
 struct CStruct {<br>
@@ -1320,6 +1346,13 @@ void is_standard_layout()<br>
   int t15[F(__is_standard_layout(<wbr>CppStructNonStandardByBaseAr))<wbr>];<br>
   int t16[F(__is_standard_layout(<wbr>CppStructNonStandardBySameBase<wbr>))];<br>
   int t17[F(__is_standard_layout(<wbr>CppStructNonStandardBy2ndVirtB<wbr>ase))];<br>
+<br>
+  int t40[T(__is_standard_layout(<wbr>ACompleteType))];<br>
+  int t41[F(__is_standard_layout(<wbr>AnIncompleteType))]; // expected-error {{incomplete type}}<br>
+  int t42[F(__is_standard_layout(<wbr>AnIncompleteType[]))]; // expected-error {{incomplete type}}<br>
+  int t43[F(__is_standard_layout(<wbr>AnIncompleteType[1]))]; // expected-error {{incomplete type}}<br>
+  int t44[F(__is_standard_layout(<wbr>void))];<br>
+  int t45[F(__is_standard_layout(<wbr>const volatile void))];<br>
 }<br>
<br>
 void is_signed()<br>
@@ -2133,6 +2166,13 @@ void trivial_checks()<br>
                                TrivialMoveButNotCopy)))]; }<br>
   { int arr[T((__is_assignable(<wbr>TrivialMoveButNotCopy &,<br>
                                TrivialMoveButNotCopy &&)))]; }<br>
+<br>
+  { int arr[T(__is_assignable(<wbr>ACompleteType, ACompleteType))]; }<br>
+  { int arr[F(__is_assignable(<wbr>AnIncompleteType, AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_assignable(<wbr>AnIncompleteType[], AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_assignable(<wbr>AnIncompleteType[1], AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_assignable(void, void))]; }<br>
+  { int arr[F(__is_assignable(const volatile void, const volatile void))]; }<br>
 }<br>
<br>
 void constructible_checks() {<br>
@@ -2164,6 +2204,19 @@ void constructible_checks() {<br>
<br>
   // PR25513<br>
   { int arr[F(__is_constructible(int(<wbr>int)))]; }<br>
+<br>
+  { int arr[T(__is_constructible(<wbr>ACompleteType))]; }<br>
+  { int arr[T(__is_nothrow_<wbr>constructible(ACompleteType))]<wbr>; }<br>
+  { int arr[F(__is_constructible(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_nothrow_<wbr>constructible(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_constructible(<wbr>AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_nothrow_<wbr>constructible(<wbr>AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_constructible(<wbr>AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_nothrow_<wbr>constructible(<wbr>AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_constructible(void)<wbr>)]; }<br>
+  { int arr[F(__is_nothrow_<wbr>constructible(void))]; }<br>
+  { int arr[F(__is_constructible(const volatile void))]; }<br>
+  { int arr[F(__is_nothrow_<wbr>constructible(const volatile void))]; }<br>
 }<br>
<br>
 // Instantiation of __is_trivially_constructible<br>
@@ -2192,6 +2245,13 @@ void is_trivially_constructible_<wbr>test() {<br>
   { int arr[F((is_trivially_<wbr>constructible<<wbr>NonTrivialDefault>::value))]; }<br>
   { int arr[F((is_trivially_<wbr>constructible<ThreeArgCtor, int*, char*, int&>::value))]; }<br>
   { int arr[F((is_trivially_<wbr>constructible<Abstract>::<wbr>value))]; } // PR19178<br>
+<br>
+  { int arr[T(__is_trivially_<wbr>constructible(ACompleteType))]<wbr>; }<br>
+  { int arr[F(__is_trivially_<wbr>constructible(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_trivially_<wbr>constructible(<wbr>AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_trivially_<wbr>constructible(<wbr>AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_trivially_<wbr>constructible(void))]; }<br>
+  { int arr[F(__is_trivially_<wbr>constructible(const volatile void))]; }<br>
 }<br>
<br>
 void array_rank() {<br>
@@ -2218,6 +2278,13 @@ void is_destructible_test() {<br>
   { int arr[F(__is_destructible(<wbr>AllDeleted))]; }<br>
   { int arr[T(__is_destructible(<wbr>ThrowingDtor))]; }<br>
   { int arr[T(__is_destructible(<wbr>NoThrowDtor))]; }<br>
+<br>
+  { int arr[T(__is_destructible(<wbr>ACompleteType))]; }<br>
+  { int arr[F(__is_destructible(<wbr>AnIncompleteType))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_destructible(<wbr>AnIncompleteType[]))]; }<br>
+  { int arr[F(__is_destructible(<wbr>AnIncompleteType[1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_destructible(void))<wbr>]; }<br>
+  { int arr[F(__is_destructible(const volatile void))]; }<br>
 }<br>
<br>
 void is_nothrow_destructible_test() {<br>
@@ -2234,4 +2301,33 @@ void is_nothrow_destructible_test() {<br>
   { int arr[F(__is_nothrow_<wbr>destructible(ThrowingDtor))]; }<br>
   { int arr[T(__is_nothrow_<wbr>destructible(NoExceptDtor))]; }<br>
   { int arr[T(__is_nothrow_<wbr>destructible(NoThrowDtor))]; }<br>
+<br>
+  { int arr[T(__is_nothrow_<wbr>destructible(ACompleteType))]; }<br>
+  { int arr[F(__is_nothrow_<wbr>destructible(AnIncompleteType)<wbr>)]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_nothrow_<wbr>destructible(AnIncompleteType[<wbr>]))]; }<br>
+  { int arr[F(__is_nothrow_<wbr>destructible(AnIncompleteType[<wbr>1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_nothrow_<wbr>destructible(void))]; }<br>
+  { int arr[F(__is_nothrow_<wbr>destructible(const volatile void))]; }<br>
+}<br>
+<br>
+void is_trivially_destructible_<wbr>test() {<br>
+  { int arr[T(__is_trivially_<wbr>destructible(int))]; }<br>
+  { int arr[T(__is_trivially_<wbr>destructible(int[2]))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(int[]))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(void))]; }<br>
+  { int arr[T(__is_trivially_<wbr>destructible(int &))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(HasDest))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(AllPrivate))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(<wbr>SuperNonTrivialStruct))]; }<br>
+  { int arr[T(__is_trivially_<wbr>destructible(AllDefaulted))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(AllDeleted))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(ThrowingDtor))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(NoThrowDtor))]; }<br>
+<br>
+  { int arr[T(__is_trivially_<wbr>destructible(ACompleteType))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(AnIncompleteType)<wbr>)]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_trivially_<wbr>destructible(AnIncompleteType[<wbr>]))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(AnIncompleteType[<wbr>1]))]; } // expected-error {{incomplete type}}<br>
+  { int arr[F(__is_trivially_<wbr>destructible(void))]; }<br>
+  { int arr[F(__is_trivially_<wbr>destructible(const volatile void))]; }<br>
 }<br>
<br>
<br>
______________________________<wbr>_________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/<wbr>mailman/listinfo/cfe-commits</a><br>
</blockquote></div><br></div>