summaryrefslogtreecommitdiffstats
path: root/clang/test/CodeGenCXX
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2014-04-24 22:45:46 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2014-04-24 22:45:46 +0000
commiteb36ddf462de5621fab3a1fb064f526d7bd5fb3d (patch)
treea08ef1c37dde709da7fdc2243f281b734e521cc6 /clang/test/CodeGenCXX
parent9a5c95ad3adb9cf6dd1957dc36b0d9bf4d73fe55 (diff)
downloadbcm5719-llvm-eb36ddf462de5621fab3a1fb064f526d7bd5fb3d.tar.gz
bcm5719-llvm-eb36ddf462de5621fab3a1fb064f526d7bd5fb3d.zip
If we see an explicit instantiation declaration or definition of a function
after we've already instantiated a definition for the function, pass it to the ASTConsumer again so that it knows the specialization kind has changed and can update the function's linkage. This only matters if we instantiate the definition of the function before we reach the end of the TU; this can happen in at least three different ways: C++11 constexpr functions, C++14 deduced return types, and functions instantiated within modules. llvm-svn: 207152
Diffstat (limited to 'clang/test/CodeGenCXX')
-rw-r--r--clang/test/CodeGenCXX/explicit-instantiation.cpp76
1 files changed, 75 insertions, 1 deletions
diff --git a/clang/test/CodeGenCXX/explicit-instantiation.cpp b/clang/test/CodeGenCXX/explicit-instantiation.cpp
index 6a4fd822122..5bd06784cfa 100644
--- a/clang/test/CodeGenCXX/explicit-instantiation.cpp
+++ b/clang/test/CodeGenCXX/explicit-instantiation.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -o - %s | FileCheck %s
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-NO-OPT
+// RUN: %clang_cc1 -emit-llvm -triple i686-pc-linux-gnu -std=c++1y -O3 -disable-llvm-optzns -o - %s | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-OPT
// This check logically is attached to 'template int S<int>::i;' below.
// CHECK: @_ZN1SIiE1iE = weak_odr global i32
@@ -16,6 +17,79 @@ Result plus<T, U, Result>::operator()(const T& t, const U& u) const {
// CHECK-LABEL: define weak_odr i32 @_ZNK4plusIillEclERKiRKl
template struct plus<int, long, long>;
+namespace EarlyInstantiation {
+ // Check that we emit definitions if we instantiate a function definition before
+ // it gets explicitly instantiatied.
+ template<typename T> struct S {
+ constexpr int constexpr_function() { return 0; }
+ auto deduced_return_type() { return 0; }
+ };
+
+ // From an implicit instantiation.
+ constexpr int a = S<char>().constexpr_function();
+ int b = S<char>().deduced_return_type();
+
+ // From an explicit instantiation declaration.
+ extern template struct S<int>;
+ constexpr int c = S<int>().constexpr_function();
+ int d = S<int>().deduced_return_type();
+
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE18constexpr_functionEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIcE19deduced_return_typeEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE18constexpr_functionEv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation1SIiE19deduced_return_typeEv(
+ template struct S<char>;
+ template struct S<int>;
+
+ template<typename T> constexpr int constexpr_function() { return 0; }
+ template<typename T> auto deduced_return_type() { return 0; }
+
+ // From an implicit instantiation.
+ constexpr int e = constexpr_function<char>();
+ int f = deduced_return_type<char>();
+
+ // From an explicit instantiation declaration.
+ extern template int constexpr_function<int>();
+ extern template auto deduced_return_type<int>();
+ constexpr int g = constexpr_function<int>();
+ int h = deduced_return_type<int>();
+
+ // The FIXMEs below are for PR19551.
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIcEEiv(
+ // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIcEEiv(
+ // CHECK: define weak_odr i32 @_ZN18EarlyInstantiation18constexpr_functionIiEEiv(
+ // FIXME: define weak_odr i32 @_ZN18EarlyInstantiation19deduced_return_typeIiEEiv(
+ template int constexpr_function<char>();
+ // FIXME template auto deduced_return_type<char>();
+ template int constexpr_function<int>();
+ // FIXME template auto deduced_return_type<int>();
+}
+
+namespace LateInstantiation {
+ // Check that we downgrade the linkage to available_externally if we see an
+ // explicit instantiation declaration after the function template is
+ // instantiated.
+ template<typename T> struct S { constexpr int f() { return 0; } };
+ template<typename T> constexpr int f() { return 0; }
+
+ // Trigger eager instantiation of the function definitions.
+ int a, b = S<char>().f() + f<char>() + a;
+ int c, d = S<int>().f() + f<int>() + a;
+
+ // Don't allow some of those definitions to be emitted.
+ extern template struct S<int>;
+ extern template int f<int>();
+
+ // Check that we declare, define, or provide an available-externally
+ // definition as appropriate.
+ // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1SIcE1fEv(
+ // CHECK: define linkonce_odr i32 @_ZN17LateInstantiation1fIcEEiv(
+ // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1SIiE1fEv(
+ // CHECK-NO-OPT: declare i32 @_ZN17LateInstantiation1fIiEEiv(
+ // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1SIiE1fEv(
+ // CHECK-OPT: define available_externally i32 @_ZN17LateInstantiation1fIiEEiv(
+}
+
// Check that we emit definitions from explicit instantiations even when they
// occur prior to the definition itself.
template <typename T> struct S {
OpenPOWER on IntegriCloud