<div dir="ltr"><div dir="ltr">On Sun, 5 Apr 2020 at 14:44, David Zarzycki via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org">cfe-commits@lists.llvm.org</a>> wrote:<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto">We have overloaded builtins. Can that not solve __builtin_strlen?<br></div></blockquote><div><br></div><div>I suppose it could, but we generally want __builtin_<libfunc> to behave the same as <libfunc>. (The difference would not be visible most of the time, but there's enough pre-existing use of __builtin_strlen through "clever" macros and the like that I'd be worried that this would break something important.) Maybe we should just make the mem* functions work again for char8_t; then you can use __builtin_memchr(p,  0) - p as an optimized compile-time strlen.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr">-- <div>Sent from my iPhone</div></div><div dir="ltr"><br><blockquote type="cite">On Apr 5, 2020, at 14:53, Richard Smith <<a href="mailto:richard@metafoo.co.uk" target="_blank">richard@metafoo.co.uk</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr">Thanks. We need to figure out what the right way to support char8_t with string builtins is. These ones could work in principle, whereas things like __builtin_strlen would never work because they take operands of the wrong types (and we can't cast const char8_t* -> const char* in a constant expression).</div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Sun, 5 Apr 2020 at 04:14, David Zarzycki via cfe-commits <<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Richard,<br>
<br>
I'm going to commit a narrow fix to clang to make the libcxx test suite pass again by allowing char8_t again. If you feel that this is the wrong long-term solution, please help the libcxx folks with whatever adjustments they need.<br>
<br>
Thanks!<br>
<br>
Dave<br>
<br>
<br>
On Sat, Apr 4, 2020, at 9:55 AM, David Zarzycki via libcxx-dev wrote:<br>
> Hi Richard,<br>
> <br>
> This breaks libcxx. Can we please revert this or is a quick fix to <br>
> libcxx possible?<br>
> <br>
> <br>
> FAIL: libc++ :: <br>
> std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp (58624 of 62672)<br>
> ******************** TEST 'libc++ :: <br>
> std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp' FAILED ********************<br>
> Command: ['/p/tllvm/bin/clang++', '-o', <br>
> '/tmp/_update_lc/t/projects/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/Output/compare.pass.cpp.o', '-x', 'c++', '/home/dave/s/lp/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp', '-c', '-v', '-Werror=thread-safety', '-std=c++2a', '-include', '/home/dave/s/lp/libcxx/test/support/nasty_macros.h', '-nostdinc++', '-I/home/dave/s/lp/libcxx/include', '-I/tmp/_update_lc/t/projects/libcxx/include/c++build', '-D__STDC_FORMAT_MACROS', '-D__STDC_LIMIT_MACROS', '-D__STDC_CONSTANT_MACROS', '-I/home/dave/s/lp/libcxx/test/support', '-ftemplate-depth=270', '-D_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER', '-Wall', '-Wextra', '-Werror', '-Wuser-defined-warnings', '-Wshadow', '-Wno-unused-command-line-argument', '-Wno-attributes', '-Wno-pessimizing-move', '-Wno-c++11-extensions', '-Wno-user-defined-literals', '-Wno-noexcept-type', '-Wsign-compare', '-Wunused-variable', '-Wunused-parameter', '-Wunreachable-code', '-c']<br>
> Exit Code: 1<br>
> Standard Error:<br>
> --<br>
> clang version 11.0.0 (<a href="https://github.com/llvm/llvm-project.git" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project.git</a> <br>
> 22127da8f17c03c69231f3631472f7f99ad9cb7f)<br>
> Target: x86_64-unknown-linux-gnu<br>
> Thread model: posix<br>
> InstalledDir: /p/tllvm/bin<br>
> Found candidate GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9<br>
> Selected GCC installation: /usr/lib/gcc/x86_64-redhat-linux/9<br>
> Candidate multilib: .;@m64<br>
> Candidate multilib: 32;@m32<br>
> Selected multilib: .;@m64<br>
>  (in-process)<br>
>  "/p/tllvm/bin/clang-11" -cc1 -triple x86_64-unknown-linux-gnu <br>
> -emit-obj -mrelax-all -disable-free -disable-llvm-verifier <br>
> -discard-value-names -main-file-name compare.pass.cpp <br>
> -mrelocation-model static -mthread-model posix -mframe-pointer=all <br>
> -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables <br>
> -target-cpu x86-64 -dwarf-column-info -fno-split-dwarf-inlining <br>
> -debugger-tuning=gdb -v -nostdinc++ -resource-dir <br>
> /p/tllvm/lib64/clang/11.0.0 -include <br>
> /home/dave/s/lp/libcxx/test/support/nasty_macros.h -I <br>
> /home/dave/s/lp/libcxx/include -I <br>
> /tmp/_update_lc/t/projects/libcxx/include/c++build -D <br>
> __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS <br>
> -I /home/dave/s/lp/libcxx/test/support -D <br>
> _LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER -internal-isystem <br>
> /usr/local/include -internal-isystem <br>
> /p/tllvm/lib64/clang/11.0.0/include -internal-externc-isystem /include <br>
> -internal-externc-isystem /usr/include -Werror=thread-safety -Wall <br>
> -Wextra -Werror -Wuser-defined-warnings -Wshadow <br>
> -Wno-unused-command-line-argument -Wno-attributes -Wno-pessimizing-move <br>
> -Wno-c++11-extensions -Wno-user-defined-literals -Wno-noexcept-type <br>
> -Wsign-compare -Wunused-variable -Wunused-parameter -Wunreachable-code <br>
> -std=c++2a -fdeprecated-macro -fdebug-compilation-dir <br>
> /tmp/_update_lc/t/projects/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t -ftemplate-depth 270 -ferror-limit 19 -fgnuc-version=4.2.1 -fno-implicit-modules -fcxx-exceptions -fexceptions -faddrsig -o /tmp/_update_lc/t/projects/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/Output/compare.pass.cpp.o -x c++ /home/dave/s/lp/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp<br>
> clang -cc1 version 11.0.0 based upon LLVM 11.0.0git default target <br>
> x86_64-unknown-linux-gnu<br>
> ignoring nonexistent directory "/include"<br>
> #include "..." search starts here:<br>
> #include <...> search starts here:<br>
>  /home/dave/s/lp/libcxx/include<br>
>  /tmp/_update_lc/t/projects/libcxx/include/c++build<br>
>  /home/dave/s/lp/libcxx/test/support<br>
>  /usr/local/include<br>
>  /p/tllvm/lib64/clang/11.0.0/include<br>
>  /usr/include<br>
> End of search list.<br>
> /home/dave/s/lp/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp:53:19: error: static_assert expression is not an integral constant expression<br>
>     static_assert(test_constexpr(), "" );<br>
>                   ^~~~~~~~~~~~~~~~<br>
> /home/dave/s/lp/libcxx/include/__string:662:12: note: constant <br>
> evaluation of '__builtin_memcmp' between arrays of types 'const <br>
> char8_t' and 'const char8_t' is not supported; only arrays of narrow <br>
> character types can be compared<br>
>     return __builtin_memcmp(__s1, __s2, __n);<br>
>            ^<br>
> /home/dave/s/lp/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp:24:12: note: in call to 'compare(&u8"123"[0], &u8"223"[0], 3)'<br>
>     return std::char_traits<char8_t>::compare(u8"123", u8"223", 3) < 0<br>
>            ^<br>
> /home/dave/s/lp/libcxx/test/std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp:53:19: note: in call to 'test_constexpr()'<br>
>     static_assert(test_constexpr(), "" );<br>
>                   ^<br>
> 1 error generated.<br>
> --<br>
> <br>
> Compilation failed unexpectedly!<br>
> ********************<br>
> <br>
> Testing Time: 135.49s<br>
> ********************<br>
> Failing Tests (1):<br>
>     libc++ :: <br>
> std/strings/char.traits/char.traits.specializations/char.traits.specializations.char8_t/compare.pass.cpp<br>
> <br>
>   Expected Passes    : 45503<br>
>   Expected Failures  : 118<br>
>   Unsupported Tests  : 17050<br>
>   Unexpected Failures: 1<br>
> <br>
> <br>
> On Fri, Apr 3, 2020, at 9:26 PM, Richard Smith via cfe-commits wrote:<br>
> > <br>
> > Author: Richard Smith<br>
> > Date: 2020-04-03T18:26:14-07:00<br>
> > New Revision: 4ede8879924c08ae5b495d3f421c167d822a60be<br>
> > <br>
> > URL: <br>
> > <a href="https://github.com/llvm/llvm-project/commit/4ede8879924c08ae5b495d3f421c167d822a60be" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/4ede8879924c08ae5b495d3f421c167d822a60be</a><br>
> > DIFF: <br>
> > <a href="https://github.com/llvm/llvm-project/commit/4ede8879924c08ae5b495d3f421c167d822a60be.diff" rel="noreferrer" target="_blank">https://github.com/llvm/llvm-project/commit/4ede8879924c08ae5b495d3f421c167d822a60be.diff</a><br>
> > <br>
> > LOG: PR45402: Make the restrictions on constant evaluation of memcmp and<br>
> > memchr consistent and comprehensible, and document them.<br>
> > <br>
> > We previously allowed evaluation of memcmp on arrays of integers of any<br>
> > size, so long as the call evaluated to 0, and allowed evaluation of<br>
> > memchr on any array of integral type of size 1 (including enums). The<br>
> > purpose of constant-evaluating these builtins is only to support<br>
> > constexpr std::char_traits, so we now consistently allow them on arrays<br>
> > of (possibly signed or unsigned) char only.<br>
> > <br>
> > Added: <br>
> >     <br>
> > <br>
> > Modified: <br>
> >     clang/docs/LanguageExtensions.rst<br>
> >     clang/include/clang/Basic/DiagnosticASTKinds.td<br>
> >     clang/lib/AST/ExprConstant.cpp<br>
> >     clang/test/SemaCXX/constexpr-string.cpp<br>
> > <br>
> > Removed: <br>
> >     <br>
> > <br>
> > <br>
> > ################################################################################<br>
> > diff  --git a/clang/docs/LanguageExtensions.rst <br>
> > b/clang/docs/LanguageExtensions.rst<br>
> > index 558ce7dee653..6dcfd1a49f06 100644<br>
> > --- a/clang/docs/LanguageExtensions.rst<br>
> > +++ b/clang/docs/LanguageExtensions.rst<br>
> > @@ -2333,10 +2333,11 @@ String builtins<br>
> >  ---------------<br>
> >  <br>
> >  Clang provides constant expression evaluation support for builtins forms of<br>
> > -the following functions from the C standard library ``<string.h>`` header:<br>
> > +the following functions from the C standard library headers<br>
> > +``<string.h>`` and ``<wchar.h>``:<br>
> >  <br>
> >  * ``memchr``<br>
> > -* ``memcmp``<br>
> > +* ``memcmp`` (and its deprecated BSD / POSIX alias ``bcmp``)<br>
> >  * ``strchr``<br>
> >  * ``strcmp``<br>
> >  * ``strlen``<br>
> > @@ -2366,7 +2367,11 @@ In addition to the above, one further builtin is <br>
> > provided:<br>
> >  constant expressions in C++11 onwards (where a cast from ``void*`` to <br>
> > ``char*``<br>
> >  is disallowed in general).<br>
> >  <br>
> > -Support for constant expression evaluation for the above builtins be <br>
> > detected<br>
> > +Constant evaluation support for the ``__builtin_mem*`` functions is <br>
> > provided<br>
> > +only for arrays of ``char``, ``signed char``, or ``unsigned char``, <br>
> > despite<br>
> > +these functions accepting an argument of type ``const void*``.<br>
> > +<br>
> > +Support for constant expression evaluation for the above builtins can <br>
> > be detected<br>
> >  with ``__has_feature(cxx_constexpr_string_builtins)``.<br>
> >  <br>
> >  Memory builtins<br>
> > @@ -2386,6 +2391,25 @@ more information.<br>
> >  <br>
> >  Note that the `size` argument must be a compile time constant.<br>
> >  <br>
> > +Clang provides constant expression evaluation support for builtin <br>
> > forms of the<br>
> > +following functions from the C standard library headers<br>
> > +``<string.h>`` and ``<wchar.h>``:<br>
> > +<br>
> > +* ``memcpy``<br>
> > +* ``memmove``<br>
> > +* ``wmemcpy``<br>
> > +* ``wmemmove``<br>
> > +<br>
> > +In each case, the builtin form has the name of the C library function <br>
> > prefixed<br>
> > +by ``__builtin_``.<br>
> > +<br>
> > +Constant evaluation support is only provided when the source and <br>
> > destination<br>
> > +are pointers to arrays with the same trivially copyable element type, <br>
> > and the<br>
> > +given size is an exact multiple of the element size that is no greater <br>
> > than<br>
> > +the number of elements accessible through the source and destination <br>
> > operands.<br>
> > +<br>
> > +Constant evaluation support is not yet provided for <br>
> > ``__builtin_memcpy_inline``.<br>
> > +<br>
> >  Atomic Min/Max builtins with memory ordering<br>
> >  --------------------------------------------<br>
> >  <br>
> > <br>
> > diff  --git a/clang/include/clang/Basic/DiagnosticASTKinds.td <br>
> > b/clang/include/clang/Basic/DiagnosticASTKinds.td<br>
> > index 544573edffdf..a1415f9ec0e1 100644<br>
> > --- a/clang/include/clang/Basic/DiagnosticASTKinds.td<br>
> > +++ b/clang/include/clang/Basic/DiagnosticASTKinds.td<br>
> > @@ -244,6 +244,12 @@ def note_constexpr_unsupported_unsized_array : <br>
> > Note<<br>
> >  def note_constexpr_unsized_array_indexed : Note<<br>
> >    "indexing of array without known bound is not allowed "<br>
> >    "in a constant expression">;<br>
> > +def note_constexpr_memcmp_unsupported : Note<<br>
> > +  "constant evaluation of %0 between arrays of types %1 and %2 "<br>
> > +  "is not supported; only arrays of narrow character types can be <br>
> > compared">;<br>
> > +def note_constexpr_memchr_unsupported : Note<<br>
> > +  "constant evaluation of %0 on array of type %1 "<br>
> > +  "is not supported; only arrays of narrow character types can be <br>
> > searched">;<br>
> >  def note_constexpr_memcpy_null : Note<<br>
> >    "%select{source|destination}2 of "<br>
> >    "'%select{%select{memcpy|wmemcpy}1|%select{memmove|wmemmove}1}0' "<br>
> > <br>
> > diff  --git a/clang/lib/AST/ExprConstant.cpp <br>
> > b/clang/lib/AST/ExprConstant.cpp<br>
> > index c6e1cc7b67df..a83b2e24e17f 100644<br>
> > --- a/clang/lib/AST/ExprConstant.cpp<br>
> > +++ b/clang/lib/AST/ExprConstant.cpp<br>
> > @@ -8469,8 +8469,12 @@ bool <br>
> > PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,<br>
> >      }<br>
> >      // Give up on byte-oriented matching against multibyte elements.<br>
> >      // FIXME: We can compare the bytes in the correct order.<br>
> > -    if (IsRawByte && Info.Ctx.getTypeSizeInChars(CharTy) != <br>
> > CharUnits::One())<br>
> > +    if (IsRawByte && !CharTy->isCharType()) {<br>
> > +      Info.FFDiag(E, diag::note_constexpr_memchr_unsupported)<br>
> > +          << (std::string("'") + <br>
> > Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")<br>
> > +          << CharTy;<br>
> >        return false;<br>
> > +    }<br>
> >      // Figure out what value we're actually looking for (after <br>
> > converting to<br>
> >      // the corresponding unsigned type if necessary).<br>
> >      uint64_t DesiredVal;<br>
> > @@ -8586,6 +8590,7 @@ bool <br>
> > PointerExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,<br>
> >      QualType T = Dest.Designator.getType(Info.Ctx);<br>
> >      QualType SrcT = Src.Designator.getType(Info.Ctx);<br>
> >      if (!Info.Ctx.hasSameUnqualifiedType(T, SrcT)) {<br>
> > +      // FIXME: Consider using our bit_cast implementation to support <br>
> > this.<br>
> >        Info.FFDiag(E, diag::note_constexpr_memcpy_type_pun) << Move << <br>
> > SrcT << T;<br>
> >        return false;<br>
> >      }<br>
> > @@ -11149,6 +11154,16 @@ bool <br>
> > IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,<br>
> >                  CharTy1, E->getArg(0)->getType()->getPointeeType()) &&<br>
> >              Info.Ctx.hasSameUnqualifiedType(CharTy1, CharTy2)));<br>
> >  <br>
> > +    // For memcmp, allow comparing any arrays of '[[un]signed] char',<br>
> > +    // but no other types.<br>
> > +    if (IsRawByte && !(CharTy1->isCharType() && <br>
> > CharTy2->isCharType())) {<br>
> > +      // FIXME: Consider using our bit_cast implementation to support <br>
> > this.<br>
> > +      Info.FFDiag(E, diag::note_constexpr_memcmp_unsupported)<br>
> > +          << (std::string("'") + <br>
> > Info.Ctx.BuiltinInfo.getName(BuiltinOp) + "'")<br>
> > +          << CharTy1 << CharTy2;<br>
> > +      return false;<br>
> > +    }<br>
> > +<br>
> >      const auto &ReadCurElems = [&](APValue &Char1, APValue &Char2) {<br>
> >        return handleLValueToRValueConversion(Info, E, CharTy1, String1, <br>
> > Char1) &&<br>
> >               handleLValueToRValueConversion(Info, E, CharTy2, String2, <br>
> > Char2) &&<br>
> > @@ -11159,57 +11174,6 @@ bool <br>
> > IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,<br>
> >               HandleLValueArrayAdjustment(Info, E, String2, CharTy2, 1);<br>
> >      };<br>
> >  <br>
> > -    if (IsRawByte) {<br>
> > -      uint64_t BytesRemaining = MaxLength;<br>
> > -      // Pointers to const void may point to objects of incomplete <br>
> > type.<br>
> > -      if (CharTy1->isIncompleteType()) {<br>
> > -        Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << <br>
> > CharTy1;<br>
> > -        return false;<br>
> > -      }<br>
> > -      if (CharTy2->isIncompleteType()) {<br>
> > -        Info.FFDiag(E, diag::note_constexpr_ltor_incomplete_type) << <br>
> > CharTy2;<br>
> > -        return false;<br>
> > -      }<br>
> > -      uint64_t CharTy1Width{Info.Ctx.getTypeSize(CharTy1)};<br>
> > -      CharUnits CharTy1Size = <br>
> > Info.Ctx.toCharUnitsFromBits(CharTy1Width);<br>
> > -      // Give up on comparing between elements with disparate widths.<br>
> > -      if (CharTy1Size != Info.Ctx.getTypeSizeInChars(CharTy2))<br>
> > -        return false;<br>
> > -      uint64_t BytesPerElement = CharTy1Size.getQuantity();<br>
> > -      assert(BytesRemaining && "BytesRemaining should not be zero: the <br>
> > "<br>
> > -                               "following loop considers at least one <br>
> > element");<br>
> > -      while (true) {<br>
> > -        APValue Char1, Char2;<br>
> > -        if (!ReadCurElems(Char1, Char2))<br>
> > -          return false;<br>
> > -        // We have compatible in-memory widths, but a possible type and<br>
> > -        // (for `bool`) internal representation mismatch.<br>
> > -        // Assuming two's complement representation, including 0 for <br>
> > `false` and<br>
> > -        // 1 for `true`, we can check an appropriate number of <br>
> > elements for<br>
> > -        // equality even if they are not byte-sized.<br>
> > -        APSInt Char1InMem = Char1.getInt().extOrTrunc(CharTy1Width);<br>
> > -        APSInt Char2InMem = Char2.getInt().extOrTrunc(CharTy1Width);<br>
> > -        if (Char1InMem.ne(Char2InMem)) {<br>
> > -          // If the elements are byte-sized, then we can produce a <br>
> > three-way<br>
> > -          // comparison result in a straightforward manner.<br>
> > -          if (BytesPerElement == 1u) {<br>
> > -            // memcmp always compares unsigned chars.<br>
> > -            return Success(Char1InMem.ult(Char2InMem) ? -1 : 1, E);<br>
> > -          }<br>
> > -          // The result is byte-order sensitive, and we have multibyte <br>
> > elements.<br>
> > -          // FIXME: We can compare the remaining bytes in the correct <br>
> > order.<br>
> > -          return false;<br>
> > -        }<br>
> > -        if (!AdvanceElems())<br>
> > -          return false;<br>
> > -        if (BytesRemaining <= BytesPerElement)<br>
> > -          break;<br>
> > -        BytesRemaining -= BytesPerElement;<br>
> > -      }<br>
> > -      // Enough elements are equal to account for the memcmp limit.<br>
> > -      return Success(0, E);<br>
> > -    }<br>
> > -<br>
> >      bool StopAtNull =<br>
> >          (BuiltinOp != Builtin::BImemcmp && BuiltinOp != <br>
> > Builtin::BIbcmp &&<br>
> >           BuiltinOp != Builtin::BIwmemcmp &&<br>
> > @@ -11227,7 +11191,7 @@ bool <br>
> > IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,<br>
> >        APValue Char1, Char2;<br>
> >        if (!ReadCurElems(Char1, Char2))<br>
> >          return false;<br>
> > -      if (Char1.getInt() != Char2.getInt()) {<br>
> > +      if (Char1.getInt().ne(Char2.getInt())) {<br>
> >          if (IsWide) // wmemcmp compares with wchar_t signedness.<br>
> >            return Success(Char1.getInt() < Char2.getInt() ? -1 : 1, E);<br>
> >          // memcmp always compares unsigned chars.<br>
> > <br>
> > diff  --git a/clang/test/SemaCXX/constexpr-string.cpp <br>
> > b/clang/test/SemaCXX/constexpr-string.cpp<br>
> > index f540be8f8e5b..79ac3bf2cc4d 100644<br>
> > --- a/clang/test/SemaCXX/constexpr-string.cpp<br>
> > +++ b/clang/test/SemaCXX/constexpr-string.cpp<br>
> > @@ -47,7 +47,7 @@ extern "C" {<br>
> >    extern wchar_t *wmemmove(wchar_t *d, const wchar_t *s, size_t n);<br>
> >  }<br>
> >  <br>
> > -# 45 "SemaCXX/constexpr-string.cpp" 2<br>
> > +# 51 "SemaCXX/constexpr-string.cpp" 2<br>
> >  namespace Strlen {<br>
> >    constexpr int n = __builtin_strlen("hello"); // ok<br>
> >    static_assert(n == 5);<br>
> > @@ -121,13 +121,13 @@ namespace StrcmpEtc {<br>
> >    extern struct Incomplete incomplete;<br>
> >    static_assert(__builtin_memcmp(&incomplete, "", 0u) == 0);<br>
> >    static_assert(__builtin_memcmp("", &incomplete, 0u) == 0);<br>
> > -  static_assert(__builtin_memcmp(&incomplete, "", 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{read of <br>
> > incomplete type 'struct Incomplete'}}<br>
> > -  static_assert(__builtin_memcmp("", &incomplete, 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{read of <br>
> > incomplete type 'struct Incomplete'}}<br>
> > +  static_assert(__builtin_memcmp(&incomplete, "", 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{not <br>
> > supported}}<br>
> > +  static_assert(__builtin_memcmp("", &incomplete, 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{not <br>
> > supported}}<br>
> >  <br>
> >    static_assert(__builtin_bcmp(&incomplete, "", 0u) == 0);<br>
> >    static_assert(__builtin_bcmp("", &incomplete, 0u) == 0);<br>
> > -  static_assert(__builtin_bcmp(&incomplete, "", 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{read of <br>
> > incomplete type 'struct Incomplete'}}<br>
> > -  static_assert(__builtin_bcmp("", &incomplete, 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{read of <br>
> > incomplete type 'struct Incomplete'}}<br>
> > +  static_assert(__builtin_bcmp(&incomplete, "", 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{not <br>
> > supported}}<br>
> > +  static_assert(__builtin_bcmp("", &incomplete, 1u) == 42); // <br>
> > expected-error {{not an integral constant}} expected-note {{not <br>
> > supported}}<br>
> >  <br>
> >    constexpr unsigned char ku00fe00[] = {0x00, 0xfe, 0x00};<br>
> >    constexpr unsigned char ku00feff[] = {0x00, 0xfe, 0xff};<br>
> > @@ -155,11 +155,11 @@ namespace StrcmpEtc {<br>
> >  <br>
> >    struct Bool3Tuple { bool bb[3]; };<br>
> >    constexpr Bool3Tuple kb000100 = {{false, true, false}};<br>
> > -  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 1) == 0);<br>
> > -  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 2) == 1);<br>
> > +  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 1) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(sizeof(bool) != 1u || __builtin_memcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 2) == 1); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> >  <br>
> > -  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 1) == 0);<br>
> > -  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 2) != 0);<br>
> > +  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 1) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(sizeof(bool) != 1u || __builtin_bcmp(ks00fe00, <br>
> > <a href="http://kb000100.bb" rel="noreferrer" target="_blank">kb000100.bb</a>, 2) != 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> >  <br>
> >    constexpr long ksl[] = {0, -1};<br>
> >    constexpr unsigned int kui[] = {0, 0u - 1};<br>
> > @@ -173,25 +173,25 @@ namespace StrcmpEtc {<br>
> >        return nullptr;<br>
> >      }<br>
> >    }<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) - <br>
> > 1) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + <br>
> > 0) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + <br>
> > 1) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) - <br>
> > 1) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 0) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 1) == 42); // expected-error {{not an integral constant}} expected-note <br>
> > {{dereferenced one-past-the-end}}<br>
> > -  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) - 1) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 0) == 0);<br>
> > -  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 1) == 42); // expected-error {{not an integral <br>
> > constant}} expected-note {{dereferenced one-past-the-end}}<br>
> > -<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) - 1) <br>
> > == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 0) <br>
> > == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 1) <br>
> > == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) - <br>
> > 1) == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 0) == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 1) == 42); // expected-error {{not an integral constant}} expected-note <br>
> > {{dereferenced one-past-the-end}}<br>
> > -  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) - 1) == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 0) == 0);<br>
> > -  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 1) == 42); // expected-error {{not an integral <br>
> > constant}} expected-note {{dereferenced one-past-the-end}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) - <br>
> > 1) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + <br>
> > 0) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), sizeof(long) + <br>
> > 1) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) - <br>
> > 1) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 0) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 1) == 42); // expected-error {{constant}} expected-note {{not <br>
> > supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) - 1) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 0) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(__builtin_memcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 1) == 42); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) - 1) <br>
> > == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 0) <br>
> > == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), sizeof(long) + 1) <br>
> > == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) - <br>
> > 1) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 0) == 0); // expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl, kuSizeofLong(), 2*sizeof(long) + <br>
> > 1) == 42); // expected-error {{constant}} expected-note {{not <br>
> > supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) - 1) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 0) == 0); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> > +  static_assert(__builtin_bcmp(ksl + 1, kuSizeofLong() + 1, <br>
> > sizeof(long) + 1) == 42); // expected-error {{constant}} expected-note <br>
> > {{not supported}}<br>
> >  <br>
> >    constexpr int a = strcmp("hello", "world"); // expected-error <br>
> > {{constant expression}} expected-note {{non-constexpr function 'strcmp' <br>
> > cannot be used in a constant expression}}<br>
> >    constexpr int b = strncmp("hello", "world", 3); // expected-error <br>
> > {{constant expression}} expected-note {{non-constexpr function <br>
> > 'strncmp' cannot be used in a constant expression}}<br>
> > @@ -385,14 +385,14 @@ namespace StrchrEtc {<br>
> >    enum class E : unsigned char {};<br>
> >    struct EPair { E e, f; };<br>
> >    constexpr EPair ee{E{240}};<br>
> > -  static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e);<br>
> > +  static_assert(__builtin_memchr(&ee.e, 240, 1) == &ee.e); // <br>
> > expected-error {{constant}} expected-note {{not supported}}<br>
> >  <br>
> >    constexpr bool kBool[] = {false, true, false};<br>
> >    constexpr const bool *const kBoolPastTheEndPtr = kBool + 3;<br>
> > -  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1);<br>
> > -  static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, <br>
> > 99) == kBoolPastTheEndPtr - 1);<br>
> > -  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr);<br>
> > -  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // <br>
> > expected-error {{not an integral constant}} expected-note <br>
> > {{dereferenced one-past-the-end}}<br>
> > +  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr - 3, 1, 99) == kBool + 1); // <br>
> > expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(sizeof(bool) != 1u || __builtin_memchr(kBool + 1, 0, <br>
> > 99) == kBoolPastTheEndPtr - 1); // expected-error {{constant}} <br>
> > expected-note {{not supported}}<br>
> > +  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr - 3, -1, 3) == nullptr); // <br>
> > expected-error {{constant}} expected-note {{not supported}}<br>
> > +  static_assert(sizeof(bool) != 1u || <br>
> > __builtin_memchr(kBoolPastTheEndPtr, 0, 1) == nullptr); // <br>
> > expected-error {{constant}} expected-note {{not supported}}<br>
> >  <br>
> >    static_assert(__builtin_char_memchr(kStr, 'a', 0) == nullptr);<br>
> >    static_assert(__builtin_char_memchr(kStr, 'a', 1) == kStr);<br>
> > <br>
> > <br>
> >         <br>
> > _______________________________________________<br>
> > cfe-commits mailing list<br>
> > <a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
> > <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
> ><br>
> _______________________________________________<br>
> libcxx-dev mailing list<br>
> <a href="mailto:libcxx-dev@lists.llvm.org" target="_blank">libcxx-dev@lists.llvm.org</a><br>
> <a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev</a><br>
><br>
_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div>
</div></blockquote></div>_______________________________________________<br>
cfe-commits mailing list<br>
<a href="mailto:cfe-commits@lists.llvm.org" target="_blank">cfe-commits@lists.llvm.org</a><br>
<a href="https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits" rel="noreferrer" target="_blank">https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits</a><br>
</blockquote></div></div>