On Sun, 5 Apr 2020 at 15:17, Richard Smith <rich...@metafoo.co.uk> wrote:
> On Sun, 5 Apr 2020 at 14:44, David Zarzycki via cfe-commits < > cfe-commits@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 <rich...@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@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@lists.llvm.org >>> > > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> > > >>> > _______________________________________________ >>> > libcxx-dev mailing list >>> > libcxx-...@lists.llvm.org >>> > https://lists.llvm.org/cgi-bin/mailman/listinfo/libcxx-dev >>> > >>> _______________________________________________ >>> cfe-commits mailing list >>> cfe-commits@lists.llvm.org >>> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >>> >> _______________________________________________ >> cfe-commits mailing list >> cfe-commits@lists.llvm.org >> https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits >> >
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits