[libcxx-dev] [clang] 4ede887 - PR45402: Make the restrictions on constant evaluation of memcmp and

Richard Smith via libcxx-dev libcxx-dev at lists.llvm.org
Sun Apr 5 15:36:17 PDT 2020


On Sun, 5 Apr 2020 at 15:17, Richard Smith <richard at metafoo.co.uk> wrote:

> On Sun, 5 Apr 2020 at 14:44, David Zarzycki via cfe-commits <
> cfe-commits at lists.llvm.org> wrote:
>
>> We have overloaded builtins. Can that not solve __builtin_strlen?
>>
>
> 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.
>

I see you already did this for memcmp in llvmorg-11-init-7822-g2c88a485c71
:)
I added documentation and testing and extended this to also cover memchr
in llvmorg-11-init-7851-g7f24db01751.


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


More information about the libcxx-dev mailing list