diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 22:16:19 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-02-13 22:16:19 +0000 |
commit | 7ca4850a3e3530fa6c93b64b740446e32c97f992 (patch) | |
tree | 4bdd8740e76bd15404199f6d10d6930bbab91cf3 /test/CodeGenCXX/const-init-cxx11.cpp | |
parent | 5ad3af90dd09b482c61dca565be4b50efcd8021d (diff) |
Deal with a horrible C++11 special case. If a non-literal type has a constexpr
constructor, and that constructor is used to initialize an object of static
storage duration such that all members and bases are initialized by constant
expressions, constant initialization is performed. In this case, the object
can still have a non-trivial destructor, and if it does, we must emit a dynamic
initializer which performs no initialization and instead simply registers that
destructor.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150419 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/const-init-cxx11.cpp')
-rw-r--r-- | test/CodeGenCXX/const-init-cxx11.cpp | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp index 6f13faa2fc..70fa2984fa 100644 --- a/test/CodeGenCXX/const-init-cxx11.cpp +++ b/test/CodeGenCXX/const-init-cxx11.cpp @@ -185,9 +185,93 @@ namespace MemberPtr { extern constexpr void (B2::*b2m)() = (void(B2::*)())&D::m; } +namespace LiteralReference { + struct Lit { + constexpr Lit() : n(5) {} + int n; + }; + // FIXME: This should have static initialization, but we do not implement + // that yet. For now, just check that we don't set the (pointer) value of + // the reference to 5! + // + // CHECK: @_ZN16LiteralReference3litE = global {{.*}} null + const Lit &lit = Lit(); +} + +namespace NonLiteralConstexpr { + constexpr int factorial(int n) { + return n ? factorial(n-1) * n : 1; + } + extern void f(int *p); + + struct NonTrivialDtor { + constexpr NonTrivialDtor() : n(factorial(5)), p(&n) {} + ~NonTrivialDtor() { + f(p); + } + + int n; + int *p; + }; + static_assert(!__is_literal(NonTrivialDtor), ""); + // CHECK: @_ZN19NonLiteralConstexpr3ntdE = global {{.*}} { i32 120, i32* getelementptr + NonTrivialDtor ntd; + + struct VolatileMember { + constexpr VolatileMember() : n(5) {} + volatile int n; + }; + static_assert(!__is_literal(VolatileMember), ""); + // CHECK: @_ZN19NonLiteralConstexpr2vmE = global {{.*}} { i32 5 } + VolatileMember vm; + + struct Both { + constexpr Both() : n(10) {} + ~Both(); + volatile int n; + }; + // CHECK: @_ZN19NonLiteralConstexpr1bE = global {{.*}} { i32 10 } + Both b; + + void StaticVars() { + // CHECK: @_ZZN19NonLiteralConstexpr10StaticVarsEvE3ntd = {{.*}} { i32 120, i32* getelementptr {{.*}} + // CHECK: @_ZGVZN19NonLiteralConstexpr10StaticVarsEvE3ntd = + static NonTrivialDtor ntd; + // CHECK: @_ZZN19NonLiteralConstexpr10StaticVarsEvE2vm = {{.*}} { i32 5 } + // CHECK-NOT: @_ZGVZN19NonLiteralConstexpr10StaticVarsEvE2vm = + static VolatileMember vm; + // CHECK: @_ZZN19NonLiteralConstexpr10StaticVarsEvE1b = {{.*}} { i32 10 } + // CHECK: @_ZGVZN19NonLiteralConstexpr10StaticVarsEvE1b = + static Both b; + } +} + // Constant initialization tests go before this point, // dynamic initialization tests go after. +// We must emit a constant initializer for NonLiteralConstexpr::ntd, but also +// emit an initializer to register its destructor. +// CHECK: define {{.*}}cxx_global_var_init{{.*}} +// CHECK-NOT: NonLiteralConstexpr +// CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr14NonTrivialDtorD1Ev {{.*}} @_ZN19NonLiteralConstexpr3ntdE +// CHECK-NEXT: ret void + +// We don't need to emit any dynamic initialization for NonLiteralConstexpr::vm. +// CHECK-NOT: NonLiteralConstexpr2vm + +// We must emit a constant initializer for NonLiteralConstexpr::b, but also +// emit an initializer to register its destructor. +// CHECK: define {{.*}}cxx_global_var_init{{.*}} +// CHECK-NOT: NonLiteralConstexpr +// CHECK: call {{.*}}cxa_atexit{{.*}} @_ZN19NonLiteralConstexpr4BothD1Ev {{.*}} @_ZN19NonLiteralConstexpr1bE +// CHECK-NEXT: ret void + +// CHECK: define {{.*}}NonLiteralConstexpr10StaticVars +// CHECK-NOT: } +// CHECK: call {{.*}}cxa_atexit{{.*}}@_ZN19NonLiteralConstexpr14NonTrivialDtorD1Ev +// CHECK-NOT: } +// CHECK: call {{.*}}cxa_atexit{{.*}}@_ZN19NonLiteralConstexpr4BothD1Ev + namespace CrossFuncLabelDiff { // Make sure we refuse to constant-fold the variable b. constexpr long a(bool x) { return x ? 0 : (long)&&lbl + (0 && ({lbl: 0;})); } |