aboutsummaryrefslogtreecommitdiff
path: root/test/CodeGenCXX/const-init-cxx11.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-01-14 04:30:29 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-01-14 04:30:29 +0000
commit2d6a5670465cb3f1d811695a9f23e372508240d2 (patch)
tree3f440e630f5fc50c2977e0e052ba4a6974734583 /test/CodeGenCXX/const-init-cxx11.cpp
parent8568ee743406ac4bb23c9768a0dffd627fdbc579 (diff)
constexpr irgen: Add irgen support for APValue::Struct, APValue::Union,
APValue::Array and APValue::MemberPointer. All APValue values can now be emitted as constants. Add new CGCXXABI entry point for emitting an APValue MemberPointer. The other entrypoints dealing with constant member pointers are no longer necessary and will be removed in a later change. Switch codegen from using EvaluateAsRValue/EvaluateAsLValue to VarDecl::evaluateValue. This performs caching and deals with the nasty cases in C++11 where a non-const object's initializer can refer indirectly to previously-initialized fields within the same object. Building the intermediate APValue object incurs a measurable performance hit on pathological testcases with huge initializer lists, so we continue to build IR directly from the Expr nodes for array and record types outside of C++11. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@148178 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/CodeGenCXX/const-init-cxx11.cpp')
-rw-r--r--test/CodeGenCXX/const-init-cxx11.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/test/CodeGenCXX/const-init-cxx11.cpp b/test/CodeGenCXX/const-init-cxx11.cpp
index 5ec9a690f9..fb5d2cce00 100644
--- a/test/CodeGenCXX/const-init-cxx11.cpp
+++ b/test/CodeGenCXX/const-init-cxx11.cpp
@@ -1,5 +1,193 @@
// RUN: %clang_cc1 -verify -triple x86_64-apple-darwin -emit-llvm -o - %s -std=c++11 | FileCheck %s
+// FIXME: The padding in all these objects should be zero-initialized.
+namespace StructUnion {
+ struct A {
+ int n;
+ double d;
+ union U {
+ constexpr U(int x) : x(x) {}
+ constexpr U(const char *y) : y(y) {}
+ int x;
+ const char *y;
+ } u;
+
+ constexpr A(int n, double d, int x) : n(n), d(d), u(x) {}
+ constexpr A(int n, double d, const char *y) : n(n), d(d), u(y) {}
+ };
+
+ // CHECK: @_ZN11StructUnion1aE = global {{.*}} { i32 1, double 2.000000e+00, {{.*}} { i32 3, [4 x i8] undef } }
+ extern constexpr A a(1, 2.0, 3);
+
+ // CHECK: @_ZN11StructUnion1bE = global {{.*}} { i32 4, double 5.000000e+00, {{.*}} { i8* getelementptr inbounds ([6 x i8]* @{{.*}}, i32 0, i32 0) } }
+ extern constexpr A b(4, 5, "hello");
+
+ struct B {
+ int n;
+ };
+
+ // CHECK: @_ZN11StructUnion1cE = global {{.*}} zeroinitializer
+ // CHECK: @_ZN11StructUnion2c2E = global {{.*}} zeroinitializer
+ B c;
+ B c2 = B();
+
+ // CHECK: @_ZN11StructUnion1dE = global {{.*}} zeroinitializer
+ B d[10];
+
+ struct C {
+ constexpr C() : c(0) {}
+ int c;
+ };
+
+ // CHECK: @_ZN11StructUnion1eE = global {{.*}} zeroinitializer
+ C e[10];
+
+ struct D {
+ constexpr D() : d(5) {}
+ int d;
+ };
+
+ // CHECK: @_ZN11StructUnion1fE = global {{.*}} { i32 5 }
+ D f;
+}
+
+namespace BaseClass {
+ template<typename T, unsigned> struct X : T {};
+ struct C { char c = 1; };
+ template<unsigned... Ns> struct Cs : X<C,Ns>... {};
+ struct N { int n = 3; };
+ struct D { double d = 4.0; };
+
+ template<typename ...Ts>
+ struct Test : Ts... { constexpr Test() : Ts()..., n(5) {} int n; };
+
+ using Test1 = Test<N, C, Cs<1,2>, D, X<C,1>>;
+ // CHECK: @_ZN9BaseClass2t1E = global {{.*}} { i32 3, i8 1, i8 1, i8 1, double 4.000000e+00, i8 1, i32 5 }, align 8
+ extern constexpr Test1 t1 = Test1();
+
+ struct DN : D, N {};
+ struct DND : DN, X<D,0> {};
+ struct DNN : DN, X<N,0> {};
+ // CHECK: @_ZN9BaseClass3dndE = global {{.*}} { double 4.000000e+00, i32 3, double 4.000000e+00 }
+ extern constexpr DND dnd = DND();
+ // Note, N subobject is laid out in DN subobject's tail padding.
+ // CHECK: @_ZN9BaseClass3dnnE = global {{.*}} { double 4.000000e+00, i32 3, i32 3 }
+ extern constexpr DNN dnn = DNN();
+
+ struct E {};
+ struct Test2 : X<E,0>, X<E,1>, X<E,2>, X<E,3> {};
+ // CHECK: @_ZN9BaseClass2t2E = global {{.*}} { [4 x i8] undef }
+ extern constexpr Test2 t2 = Test2();
+}
+
+namespace Array {
+ // CHECK: @_ZN5Array3arrE = constant [2 x i32] [i32 4, i32 0]
+ extern constexpr int arr[2] = { 4 };
+
+ // CHECK: @_ZN5Array1cE = constant [6 x [4 x i8]] [{{.*}} c"foo\00", [4 x i8] c"a\00\00\00", [4 x i8] c"bar\00", [4 x i8] c"xyz\00", [4 x i8] c"b\00\00\00", [4 x i8] c"123\00"]
+ extern constexpr char c[6][4] = { "foo", "a", { "bar" }, { 'x', 'y', 'z' }, { "b" }, '1', '2', '3' };
+
+ struct C { constexpr C() : n(5) {} int n, m = 3 * n + 1; };
+ // CHECK: @_ZN5Array5ctorsE = global [3 x {{.*}}] [{{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }, {{.*}} { i32 5, i32 16 }]
+ extern const C ctors[3];
+ constexpr C ctors[3];
+
+ // CHECK: @_ZN5Array1dE = constant {{.*}} { [2 x i32] [i32 1, i32 2], [3 x i32] [i32 3, i32 4, i32 5] }
+ struct D { int n[2]; int m[3]; } extern constexpr d = { 1, 2, 3, 4, 5 };
+}
+
+namespace MemberPtr {
+ struct B1 {
+ int a, b;
+ virtual void f();
+ void g();
+ };
+ struct B2 {
+ int c, d;
+ virtual void h();
+ void i();
+ };
+ struct C : B1 {
+ int e;
+ virtual void j();
+ void k();
+ };
+ struct D : C, B2 {
+ int z;
+ virtual void l();
+ void m();
+ };
+
+ // CHECK: @_ZN9MemberPtr2daE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2dbE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2dcE = constant i64 32
+ // CHECK: @_ZN9MemberPtr2ddE = constant i64 36
+ // CHECK: @_ZN9MemberPtr2deE = constant i64 16
+ // CHECK: @_ZN9MemberPtr2dzE = constant i64 40
+ extern constexpr int (D::*da) = &B1::a;
+ extern constexpr int (D::*db) = &C::b;
+ extern constexpr int (D::*dc) = &B2::c;
+ extern constexpr int (D::*dd) = &D::d;
+ extern constexpr int (D::*de) = &C::e;
+ extern constexpr int (D::*dz) = &D::z;
+
+ // CHECK: @_ZN9MemberPtr2baE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2bbE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2bcE = constant i64 8
+ // CHECK: @_ZN9MemberPtr2bdE = constant i64 12
+ // CHECK: @_ZN9MemberPtr2beE = constant i64 16
+ // CHECK: @_ZN9MemberPtr3b1zE = constant i64 40
+ // CHECK: @_ZN9MemberPtr3b2zE = constant i64 16
+ extern constexpr int (B1::*ba) = (int(B1::*))&B1::a;
+ extern constexpr int (B1::*bb) = (int(B1::*))&C::b;
+ extern constexpr int (B2::*bc) = (int(B2::*))&B2::c;
+ extern constexpr int (B2::*bd) = (int(B2::*))&D::d;
+ extern constexpr int (B1::*be) = (int(B1::*))&C::e;
+ extern constexpr int (B1::*b1z) = (int(B1::*))&D::z;
+ extern constexpr int (B2::*b2z) = (int(B2::*))&D::z;
+
+ // CHECK: @_ZN9MemberPtr2dfE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dhE = constant {{.*}} { i64 1, i64 24 }
+ // CHECK: @_ZN9MemberPtr2diE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 24 }
+ // CHECK: @_ZN9MemberPtr2djE = constant {{.*}} { i64 9, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dlE = constant {{.*}} { i64 17, i64 0 }
+ // CHECK: @_ZN9MemberPtr2dmE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+ extern constexpr void (D::*df)() = &C::f;
+ extern constexpr void (D::*dg)() = &B1::g;
+ extern constexpr void (D::*dh)() = &B2::h;
+ extern constexpr void (D::*di)() = &D::i;
+ extern constexpr void (D::*dj)() = &C::j;
+ extern constexpr void (D::*dk)() = &C::k;
+ extern constexpr void (D::*dl)() = &D::l;
+ extern constexpr void (D::*dm)() = &D::m;
+
+ // CHECK: @_ZN9MemberPtr2bfE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bgE = constant {{.*}} { i64 {{.*}}2B11gEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bhE = constant {{.*}} { i64 1, i64 0 }
+ // CHECK: @_ZN9MemberPtr2biE = constant {{.*}} { i64 {{.*}}2B21iEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bjE = constant {{.*}} { i64 9, i64 0 }
+ // CHECK: @_ZN9MemberPtr2bkE = constant {{.*}} { i64 {{.*}}1C1kEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b1lE = constant {{.*}} { i64 17, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b1mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 0 }
+ // CHECK: @_ZN9MemberPtr3b2lE = constant {{.*}} { i64 17, i64 -24 }
+ // CHECK: @_ZN9MemberPtr3b2mE = constant {{.*}} { i64 {{.*}}1D1mEv{{.*}}, i64 -24 }
+ extern constexpr void (B1::*bf)() = (void(B1::*)())&C::f;
+ extern constexpr void (B1::*bg)() = (void(B1::*)())&B1::g;
+ extern constexpr void (B2::*bh)() = (void(B2::*)())&B2::h;
+ extern constexpr void (B2::*bi)() = (void(B2::*)())&D::i;
+ extern constexpr void (B1::*bj)() = (void(B1::*)())&C::j;
+ extern constexpr void (B1::*bk)() = (void(B1::*)())&C::k;
+ extern constexpr void (B1::*b1l)() = (void(B1::*)())&D::l;
+ extern constexpr void (B1::*b1m)() = (void(B1::*)())&D::m;
+ extern constexpr void (B2::*b2l)() = (void(B2::*)())&D::l;
+ extern constexpr void (B2::*b2m)() = (void(B2::*)())&D::m;
+}
+
+// Constant initialization tests go before this point,
+// dynamic initialization tests go after.
+
namespace CrossFuncLabelDiff {
// Make sure we refuse to constant-fold the variable b.
constexpr long a() { return (long)&&lbl + (0 && ({lbl: 0;})); }