summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorChandler Carruth <chandlerc@gmail.com>2011-05-27 01:33:31 +0000
committerChandler Carruth <chandlerc@gmail.com>2011-05-27 01:33:31 +0000
commit7c430c0ec22fc1aee30f2bcfca19cc84a08c2fc8 (patch)
tree150003068c921ffe2e0b31b419cdd21777ecccb6 /clang/test
parenta9d84933107df34f08c201ef6a6f16b354f730da (diff)
downloadbcm5719-llvm-7c430c0ec22fc1aee30f2bcfca19cc84a08c2fc8.tar.gz
bcm5719-llvm-7c430c0ec22fc1aee30f2bcfca19cc84a08c2fc8.zip
Enhance Clang to start instantiating static data member definitions
within class templates when they are necessary to complete the type of the member. The canonical example is code like: template <typename T> struct S { static const int arr[]; static const int x; static int f(); }; template <typename T> const int S<T>::arr[] = { 1, 2, 3 }; template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]); template <typename T> int S<T>::f() { return x; } int x = S<int>::f(); We need to instantiate S<T>::arr's definition to pick up its initializer and complete the array type. This involves new code to specially handle completing the type of an expression where the type alone is insufficient. It also requires *updating* the expression with the newly completed type. Fortunately, all the other infrastructure is already in Clang to do the instantiation, do the completion, and prune out the unused bits of code that result from this instantiation. This addresses the initial bug in PR10001, and will be a step to fleshing out other cases where we need to work harder to complete an expression's type. Who knew we still had missing C++03 "features"? llvm-svn: 132172
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CodeGenCXX/template-instantiation.cpp30
-rw-r--r--clang/test/SemaTemplate/instantiate-init.cpp18
2 files changed, 48 insertions, 0 deletions
diff --git a/clang/test/CodeGenCXX/template-instantiation.cpp b/clang/test/CodeGenCXX/template-instantiation.cpp
index 635e1d2099b..cc30af0aba4 100644
--- a/clang/test/CodeGenCXX/template-instantiation.cpp
+++ b/clang/test/CodeGenCXX/template-instantiation.cpp
@@ -1,9 +1,15 @@
// RUN: %clang_cc1 %s -O1 -triple=x86_64-apple-darwin10 -emit-llvm -o - | FileCheck %s
+// CHECK: @_ZN7PR100011xE = global
+// CHECK-NOT: @_ZN7PR100014kBarE = external global i32
+//
// CHECK-NOT: @_ZTVN5test118stdio_sync_filebufIwEE = constant
// CHECK-NOT: _ZTVN5test315basic_fstreamXXIcEE
// CHECK: @_ZTVN5test018stdio_sync_filebufIwEE = unnamed_addr constant
+// CHECK: @_ZN7PR100011SIiE3arrE = weak_odr global [3 x i32]
+// CHECK-NOT: @_ZN7PR100011SIiE3arr2E = weak_odr global [3 x i32]A
+
// CHECK-NOT: _ZTVN5test31SIiEE
// CHECK-NOT: _ZTSN5test31SIiEE
@@ -122,3 +128,27 @@ class B {
// CHECK-NOT: _ZN6PR85051AILi0EE1B1fEv
template class A<0>;
}
+
+// Ensure that when instantiating initializers for static data members to
+// complete their type in an unevaluated context, we *do* emit initializers with
+// side-effects, but *don't* emit initializers and variables which are otherwise
+// unused in the program.
+namespace PR10001 {
+ template <typename T> struct S {
+ static const int arr[];
+ static const int arr2[];
+ static const int x, y;
+ static int f();
+ };
+
+ extern int foo();
+ extern int kBar;
+
+ template <typename T> const int S<T>::arr[] = { 1, 2, foo() }; // possible side effects
+ template <typename T> const int S<T>::arr2[] = { 1, 2, kBar }; // no side effects
+ template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
+ template <typename T> const int S<T>::y = sizeof(arr2) / sizeof(arr2[0]);
+ template <typename T> int S<T>::f() { return x + y; }
+
+ int x = S<int>::f();
+}
diff --git a/clang/test/SemaTemplate/instantiate-init.cpp b/clang/test/SemaTemplate/instantiate-init.cpp
index e292aa3c5f7..d5711ddf5a2 100644
--- a/clang/test/SemaTemplate/instantiate-init.cpp
+++ b/clang/test/SemaTemplate/instantiate-init.cpp
@@ -55,3 +55,21 @@ namespace PR6657 {
f0<int>();
}
}
+
+// Instantiate out-of-line definitions of static data members which complete
+// types through an initializer even when the only use of the member that would
+// cause instantiation is in an unevaluated context, but one requiring its
+// complete type.
+namespace PR10001 {
+ template <typename T> struct S {
+ static const int arr[];
+ static const int x;
+ static int f();
+ };
+
+ template <typename T> const int S<T>::arr[] = { 1, 2, 3 };
+ template <typename T> const int S<T>::x = sizeof(arr) / sizeof(arr[0]);
+ template <typename T> int S<T>::f() { return x; }
+
+ int x = S<int>::f();
+}
OpenPOWER on IntegriCloud