On Wed, 24 Apr 2019 at 19:28, Eric Fiselier via cfe-commits <cfe-commits@lists.llvm.org> wrote: > Do I just edit the HTML file directly? > Or is it generated by something?
Just edit the HTML file directly. > On Wed, Apr 24, 2019 at 3:35 PM Richard Smith <rich...@metafoo.co.uk> wrote: >> >> Thanks! Can you update cxx_status.html to mark P0595R2 as done? >> >> On Tue, 23 Apr 2019 at 19:21, Eric Fiselier via cfe-commits >> <cfe-commits@lists.llvm.org> wrote: >> > >> > Author: ericwf >> > Date: Tue Apr 23 19:23:30 2019 >> > New Revision: 359067 >> > >> > URL: http://llvm.org/viewvc/llvm-project?rev=359067&view=rev >> > Log: >> > [Builtins] Implement __builtin_is_constant_evaluated for use in C++2a >> > >> > Summary: >> > This patch implements `__builtin_is_constant_evaluated` as specifier by >> > [P0595R2](https://wg21.link/p0595r2). It is built on the back of Bill >> > Wendling's work for `__builtin_constant_p()`. >> > >> > More tests to come, but early feedback is appreciated. >> > >> > I plan to implement warnings for common mis-usages like those belowe in a >> > following patch: >> > ``` >> > void foo(int x) { >> > if constexpr (std::is_constant_evaluated())) { // condition is always >> > `true`. Should use plain `if` instead. >> > foo_constexpr(x); >> > } else { >> > foo_runtime(x); >> > } >> > } >> > ``` >> > >> > >> > >> > Reviewers: rsmith, MaskRay, bruno, void >> > >> > Reviewed By: rsmith >> > >> > Subscribers: dexonsmith, zoecarver, fdeazeve, kristina, cfe-commits >> > >> > Differential Revision: https://reviews.llvm.org/D55500 >> > >> > Added: >> > cfe/trunk/test/CodeGenCXX/builtin-is-constant-evaluated.cpp >> > cfe/trunk/test/SemaCXX/builtin-is-constant-evaluated.cpp >> > Modified: >> > cfe/trunk/include/clang/Basic/Builtins.def >> > cfe/trunk/lib/AST/ExprConstant.cpp >> > cfe/trunk/lib/Basic/Builtins.cpp >> > cfe/trunk/lib/CodeGen/CGDecl.cpp >> > cfe/trunk/test/Sema/builtins.c >> > >> > Modified: cfe/trunk/include/clang/Basic/Builtins.def >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/Builtins.def?rev=359067&r1=359066&r2=359067&view=diff >> > ============================================================================== >> > --- cfe/trunk/include/clang/Basic/Builtins.def (original) >> > +++ cfe/trunk/include/clang/Basic/Builtins.def Tue Apr 23 19:23:30 2019 >> > @@ -500,6 +500,7 @@ BUILTIN(__builtin_vsprintf, "ic*cC*a", " >> > BUILTIN(__builtin_vsnprintf, "ic*zcC*a", "nFP:2:") >> > BUILTIN(__builtin_thread_pointer, "v*", "nc") >> > BUILTIN(__builtin_launder, "v*v*", "nt") >> > +LANGBUILTIN(__builtin_is_constant_evaluated, "b", "n", CXX_LANG) >> > >> > // GCC exception builtins >> > BUILTIN(__builtin_eh_return, "vzv*", "r") // FIXME: Takes intptr_t, not >> > size_t! >> > >> > Modified: cfe/trunk/lib/AST/ExprConstant.cpp >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExprConstant.cpp?rev=359067&r1=359066&r2=359067&view=diff >> > ============================================================================== >> > --- cfe/trunk/lib/AST/ExprConstant.cpp (original) >> > +++ cfe/trunk/lib/AST/ExprConstant.cpp Tue Apr 23 19:23:30 2019 >> > @@ -8279,6 +8279,9 @@ bool IntExprEvaluator::VisitBuiltinCallE >> > return Success(false, E); >> > } >> > >> > + case Builtin::BI__builtin_is_constant_evaluated: >> > + return Success(Info.InConstantContext, E); >> > + >> > case Builtin::BI__builtin_ctz: >> > case Builtin::BI__builtin_ctzl: >> > case Builtin::BI__builtin_ctzll: >> > @@ -11139,6 +11142,7 @@ bool Expr::EvaluateAsConstantExpr(EvalRe >> > EvalInfo::EvaluationMode EM = EvalInfo::EM_ConstantExpression; >> > EvalInfo Info(Ctx, Result, EM); >> > Info.InConstantContext = true; >> > + >> > if (!::Evaluate(Result.Val, Info, this)) >> > return false; >> > >> > >> > Modified: cfe/trunk/lib/Basic/Builtins.cpp >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Basic/Builtins.cpp?rev=359067&r1=359066&r2=359067&view=diff >> > ============================================================================== >> > --- cfe/trunk/lib/Basic/Builtins.cpp (original) >> > +++ cfe/trunk/lib/Basic/Builtins.cpp Tue Apr 23 19:23:30 2019 >> > @@ -75,9 +75,12 @@ bool Builtin::Context::builtinIsSupporte >> > bool OclCUnsupported = !LangOpts.OpenCL && >> > (BuiltinInfo.Langs & ALL_OCLC_LANGUAGES); >> > bool OpenMPUnsupported = !LangOpts.OpenMP && BuiltinInfo.Langs == >> > OMP_LANG; >> > + bool CPlusPlusUnsupported = >> > + !LangOpts.CPlusPlus && BuiltinInfo.Langs == CXX_LANG; >> > return !BuiltinsUnsupported && !MathBuiltinsUnsupported && >> > !OclCUnsupported && >> > !OclC1Unsupported && !OclC2Unsupported && !OpenMPUnsupported && >> > - !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported; >> > + !GnuModeUnsupported && !MSModeUnsupported && !ObjCUnsupported && >> > + !CPlusPlusUnsupported; >> > } >> > >> > /// initializeBuiltins - Mark the identifiers for all the builtins with >> > their >> > >> > Modified: cfe/trunk/lib/CodeGen/CGDecl.cpp >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGDecl.cpp?rev=359067&r1=359066&r2=359067&view=diff >> > ============================================================================== >> > --- cfe/trunk/lib/CodeGen/CGDecl.cpp (original) >> > +++ cfe/trunk/lib/CodeGen/CGDecl.cpp Tue Apr 23 19:23:30 2019 >> > @@ -1783,7 +1783,8 @@ void CodeGenFunction::EmitAutoVarInit(co >> > } >> > >> > llvm::Constant *constant = nullptr; >> > - if (emission.IsConstantAggregate || D.isConstexpr()) { >> > + if (emission.IsConstantAggregate || D.isConstexpr() || >> > + D.isUsableInConstantExpressions(getContext())) { >> > assert(!capturedByInit && "constant init contains a capturing >> > block?"); >> > constant = ConstantEmitter(*this).tryEmitAbstractForInitializer(D); >> > if (constant && trivialAutoVarInit != >> > >> > Added: cfe/trunk/test/CodeGenCXX/builtin-is-constant-evaluated.cpp >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/builtin-is-constant-evaluated.cpp?rev=359067&view=auto >> > ============================================================================== >> > --- cfe/trunk/test/CodeGenCXX/builtin-is-constant-evaluated.cpp (added) >> > +++ cfe/trunk/test/CodeGenCXX/builtin-is-constant-evaluated.cpp Tue Apr 23 >> > 19:23:30 2019 >> > @@ -0,0 +1,133 @@ >> > +// RUN: %clang_cc1 -triple x86_64-unknown-unknown -emit-llvm %s >> > -std=c++2a -o %t.ll >> > +// RUN: FileCheck -check-prefix=CHECK-FN-CG -input-file=%t.ll %s >> > +// RUN: FileCheck -check-prefix=CHECK-STATIC -input-file=%t.ll %s >> > +// RUN: FileCheck -check-prefix=CHECK-DYN -input-file=%t.ll %s >> > +// RUN: FileCheck -check-prefix=CHECK-ARR -input-file=%t.ll %s >> > +// RUN: FileCheck -check-prefix=CHECK-FOLD -input-file=%t.ll %s >> > + >> > +using size_t = decltype(sizeof(int)); >> > + >> > +#define CONSTINIT __attribute__((require_constant_initialization)) >> > + >> > +extern "C" [[noreturn]] void BOOM(); >> > +extern "C" void OK(); >> > +extern "C" size_t RANDU(); >> > + >> > +namespace std { >> > +inline constexpr bool is_constant_evaluated() noexcept { >> > + return __builtin_is_constant_evaluated(); >> > +} >> > +} // namespace std >> > + >> > +// CHECK-FN-CG-LABEL: define zeroext i1 @_Z3foov() >> > +// CHECK-FN-CG: ret i1 false >> > +bool foo() { >> > + return __builtin_is_constant_evaluated(); >> > +} >> > + >> > +// CHECK-FN-CG-LABEL: define linkonce_odr i32 @_Z1fv() >> > +constexpr int f() { >> > + // CHECK-FN-CG: store i32 13, i32* %n, align 4 >> > + // CHECK-FN-CG: store i32 17, i32* %m, align 4 >> > + // CHECK-FN-CG: %1 = load i32, i32* %m, align 4 >> > + // CHECK-FN-CG: %add = add nsw i32 %1, 13 >> > + // CHECK-FN-CG: ret i32 %add >> > + const int n = __builtin_is_constant_evaluated() && >> > std::is_constant_evaluated() ? 13 : 17; // n == 13 >> > + int m = __builtin_is_constant_evaluated() ? 13 : 17; // m might >> > be 13 or 17 (see below) >> > + char arr[n] = {}; // char[13] >> > + return m + int(sizeof(arr)); >> > +} >> > + >> > +// CHECK-STATIC-DAG: @p = global i32 26, >> > +CONSTINIT int p = f(); // f().m == 13; initialized to 26 >> > +// CHECK-STATIC-DAG: @p2 = global i32 26, >> > +int p2 = f(); // same result without CONSTINIT >> > + >> > +// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init() >> > +// CHECK-DYN: %0 = load i32, i32* @p, align 4 >> > +// CHECK-DYN-NEXT: %call = call i32 @_Z1fv() >> > +// CHECK-DYN-NEXT: %add = add nsw i32 %0, %call >> > +// CHECK-DYN-NEXT: store i32 %add, i32* @q, align 4 >> > +// CHECK-DYN-NEXT: ret void >> > +int q = p + f(); // m == 17 for this call; initialized to 56 >> > + >> > +int y; >> > + >> > +// CHECK-STATIC-DAG: @b = global i32 2, >> > +CONSTINIT int b = __builtin_is_constant_evaluated() ? 2 : y; // static >> > initialization to 2 >> > + >> > +// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.1() >> > +// CHECK-DYN: %0 = load i32, i32* @y, align 4 >> > +// CHECK-DYN: %1 = load i32, i32* @y, align 4 >> > +// CHECK-DYN-NEXT: %add = add >> > +// CHECK-DYN-NEXT: store i32 %add, i32* @c, >> > +int c = y + (__builtin_is_constant_evaluated() ? 2 : y); // dynamic >> > initialization to y+y >> > + >> > +// CHECK-DYN-LABEL: define internal void @__cxx_global_var_init.2() >> > +// CHECK-DYN: store i32 1, i32* @_ZL1a, align 4 >> > +// CHECK-DYN-NEXT: ret void >> > +const int a = __builtin_is_constant_evaluated() ? y : 1; // dynamic >> > initialization to 1 >> > +const int *a_sink = &a; >> > + >> > +// CHECK-ARR-LABEL: define void @_Z13test_arr_exprv >> > +void test_arr_expr() { >> > + // CHECK-ARR: %x1 = alloca [101 x i8], >> > + char x1[std::is_constant_evaluated() && >> > __builtin_is_constant_evaluated() ? 101 : 1]; >> > + >> > + // CHECK-ARR: %x2 = alloca [42 x i8], >> > + char x2[std::is_constant_evaluated() && >> > __builtin_is_constant_evaluated() ? 42 : RANDU()]; >> > + >> > + // CHECK-ARR: call i8* @llvm.stacksave() >> > + // CHECK-ARR: %vla = alloca i8, i64 13, >> > + char x3[std::is_constant_evaluated() || >> > __builtin_is_constant_evaluated() ? RANDU() : 13]; >> > +} >> > + >> > +// CHECK-ARR-LABEL: define void @_Z17test_new_arr_exprv >> > +void test_new_arr_expr() { >> > + // CHECK-ARR: call i8* @_Znam(i64 17) >> > + new char[std::is_constant_evaluated() || >> > __builtin_is_constant_evaluated() ? 1 : 17]; >> > +} >> > + >> > +// CHECK-FOLD-LABEL: @_Z31test_constant_initialized_locali( >> > +bool test_constant_initialized_local(int k) { >> > + // CHECK-FOLD: store i8 1, i8* %n, >> > + // CHECK-FOLD: store volatile i8* %n, i8** %p, >> > + const bool n = __builtin_is_constant_evaluated() && >> > std::is_constant_evaluated(); >> > + const bool *volatile p = &n; >> > + return *p; >> > +} >> > + >> > +// CHECK-FOLD-LABEL: define void @_Z21test_ir_constant_foldv() >> > +void test_ir_constant_fold() { >> > + // CHECK-FOLD-NEXT: entry: >> > + // CHECK-FOLD-NEXT: call void @OK() >> > + // CHECK-FOLD-NEXT: call void @OK() >> > + // CHECK-FOLD-NEXT: ret void >> > + if (std::is_constant_evaluated()) { >> > + BOOM(); >> > + } else { >> > + OK(); >> > + } >> > + std::is_constant_evaluated() ? BOOM() : OK(); >> > +} >> > + >> > +// CHECK-STATIC-DAG: @ir = constant i32* @i_constant, >> > +int i_constant; >> > +int i_not_constant; >> > +int &ir = __builtin_is_constant_evaluated() ? i_constant : i_not_constant; >> > + >> > +// CHECK-FOLD-LABEL: @_Z35test_ref_initialization_local_scopev() >> > +void test_ref_initialization_local_scope() { >> > + const int i_constant = 42; >> > + const int i_non_constant = 101; >> > + // CHECK-FOLD: store i32* %i_non_constant, i32** %r, >> > + const int &r = __builtin_is_constant_evaluated() ? i_constant : >> > i_non_constant; >> > +} >> > + >> > +// CHECK-FOLD-LABEL: @_Z22test_ref_to_static_varv() >> > +void test_ref_to_static_var() { >> > + static int i_constant = 42; >> > + static int i_non_constant = 101; >> > + // CHECK-FOLD: store i32* @_ZZ22test_ref_to_static_varvE10i_constant, >> > i32** %r, >> > + int &r = __builtin_is_constant_evaluated() ? i_constant : >> > i_non_constant; >> > +} >> > \ No newline at end of file >> > >> > Modified: cfe/trunk/test/Sema/builtins.c >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Sema/builtins.c?rev=359067&r1=359066&r2=359067&view=diff >> > ============================================================================== >> > --- cfe/trunk/test/Sema/builtins.c (original) >> > +++ cfe/trunk/test/Sema/builtins.c Tue Apr 23 19:23:30 2019 >> > @@ -314,3 +314,9 @@ void test23() { >> > memcpy(buf, src, 11); // expected-warning{{'memcpy' will always >> > overflow; destination buffer has size 10, but size argument is 11}} >> > my_memcpy(buf, src, 11); // expected-warning{{'memcpy' will always >> > overflow; destination buffer has size 10, but size argument is 11}} >> > } >> > + >> > +// Test that __builtin_is_constant_evaluated() is not allowed in C >> > +int test_cxx_builtin() { >> > + // expected-error@+1 {{use of unknown builtin >> > '__builtin_is_constant_evaluated'}} >> > + return __builtin_is_constant_evaluated(); >> > +} >> > >> > Added: cfe/trunk/test/SemaCXX/builtin-is-constant-evaluated.cpp >> > URL: >> > http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/builtin-is-constant-evaluated.cpp?rev=359067&view=auto >> > ============================================================================== >> > --- cfe/trunk/test/SemaCXX/builtin-is-constant-evaluated.cpp (added) >> > +++ cfe/trunk/test/SemaCXX/builtin-is-constant-evaluated.cpp Tue Apr 23 >> > 19:23:30 2019 >> > @@ -0,0 +1,121 @@ >> > +// RUN: %clang_cc1 -std=c++2a -verify %s -fcxx-exceptions >> > -triple=x86_64-linux-gnu >> > + >> > +using size_t = decltype(sizeof(int)); >> > + >> > +namespace std { >> > +inline constexpr bool is_constant_evaluated() noexcept { >> > + return __builtin_is_constant_evaluated(); >> > +} >> > +} // namespace std >> > + >> > +extern int dummy; // expected-note 1+ {{declared here}} >> > + >> > +static_assert(__builtin_is_constant_evaluated()); >> > +static_assert(noexcept(__builtin_is_constant_evaluated())); >> > + >> > +constexpr bool b = __builtin_is_constant_evaluated(); >> > +static_assert(b); >> > + >> > +const int n = __builtin_is_constant_evaluated() ? 4 : dummy; >> > +static_assert(n == 4); >> > +constexpr int cn = __builtin_is_constant_evaluated() ? 11 : dummy; >> > +static_assert(cn == 11); >> > +// expected-error@+1 {{'bn' must be initialized by a constant expression}} >> > +constexpr int bn = __builtin_is_constant_evaluated() ? dummy : 42; // >> > expected-note {{non-const variable 'dummy' is not allowed}} >> > + >> > +const int n2 = __builtin_is_constant_evaluated() ? dummy : 42; // >> > expected-note {{declared here}} >> > +static_assert(n2 == 42); // >> > expected-error {{static_assert expression is not an integral constant}} >> > +// expected-note@-1 {{initializer of 'n2' is not a constant expression}} >> > + >> > +template <bool V, bool Default = std::is_constant_evaluated()> >> > +struct Templ { static_assert(V); static_assert(Default); }; >> > +Templ<__builtin_is_constant_evaluated()> x; // type X<true> >> > + >> > +template <class T> >> > +void test_if_constexpr() { >> > + if constexpr (__builtin_is_constant_evaluated()) { >> > + static_assert(__is_same(T, int)); >> > + } else { >> > + using Test = typename T::DOES_NOT_EXIST; >> > + } >> > +} >> > +template void test_if_constexpr<int>(); >> > + >> > +void test_array_decl() { >> > + char x[__builtin_is_constant_evaluated() + >> > std::is_constant_evaluated()]; >> > + static_assert(sizeof(x) == 2, ""); >> > +} >> > + >> > +void test_case_stmt(int x) { >> > + switch (x) { >> > + case 0: >> > // OK >> > + case __builtin_is_constant_evaluated(): >> > // expected-note {{previous case}} >> > + case std::is_constant_evaluated() + __builtin_is_constant_evaluated(): >> > // expected-note {{previous case}} >> > + case 1: >> > // expected-error {{duplicate case value '1'}} >> > + case 2: >> > // expected-error {{duplicate case value '2'}} >> > + break; >> > + } >> > +} >> > + >> > +constexpr size_t good_array_size() { >> > + return std::is_constant_evaluated() ? 42 : static_cast<size_t>(-1); >> > +} >> > + >> > +constexpr size_t bad_array_size() { >> > + return std::is_constant_evaluated() ? static_cast<size_t>(-1) : 13; >> > +} >> > + >> > +template <class T> >> > +constexpr T require_constexpr(T v) { >> > + if (!std::is_constant_evaluated()) >> > + throw "BOOM"; >> > + return v; >> > +} >> > + >> > +void test_new_expr() { >> > + constexpr size_t TooLarge = -1; >> > + auto *x = new int[std::is_constant_evaluated() ? 1 : TooLarge]; // >> > expected-error {{array is too large}} >> > + auto *x2 = new int[std::is_constant_evaluated() ? TooLarge : 1]; // >> > OK >> > + auto *y = new int[1][std::is_constant_evaluated() ? TooLarge : 1]{}; // >> > expected-error {{array is too large}} >> > + auto *y2 = new int[1][require_constexpr(42)]; >> > +} >> > + >> > +void test_alignas_operand() { >> > + alignas(std::is_constant_evaluated() ? 8 : 2) char dummy; >> > + static_assert(__alignof(dummy) == 8); >> > +} >> > + >> > +void test_static_assert_operand() { >> > + static_assert(std::is_constant_evaluated(), ""); >> > +} >> > + >> > +void test_enumerator() { >> > + enum MyEnum { >> > + ZERO = 0, >> > + ONE = std::is_constant_evaluated() >> > + }; >> > + static_assert(ONE == 1, ""); >> > +} >> > + >> > +struct TestBitfieldWidth { >> > + unsigned Bits : std::is_constant_evaluated(); >> > +}; >> > + >> > +void test_operand_of_noexcept_fn() noexcept(std::is_constant_evaluated()); >> > +static_assert(noexcept(test_operand_of_noexcept_fn()), ""); >> > + >> > + >> > +namespace test_ref_initialization { >> > +int x; >> > +int y; >> > +int &r = __builtin_is_constant_evaluated() ? x : y; >> > +static_assert(&r == &x); >> > + >> > +} // namespace test_ref_initialization >> > + >> > +#if defined(__cpp_conditional_explicit) >> > +struct TestConditionalExplicit { >> > + explicit(__builtin_is_constant_evaluated()) >> > TestConditionalExplicit(int) {} >> > +}; >> > +TestConditionalExplicit e = 42; >> > +#endif >> > >> > >> > _______________________________________________ >> > 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