summaryrefslogtreecommitdiff
path: root/test/SemaTemplate/constexpr-instantiate.cpp
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2012-02-14 22:25:15 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2012-02-14 22:25:15 +0000
commit57b9c4e9d85971e20ab0dac3eadabae672c43c62 (patch)
tree0d9397c00fe6d48663c59c0030a08143bfad60ad /test/SemaTemplate/constexpr-instantiate.cpp
parent58d2dbea680a75de266c5eff77cc15c323cfd48a (diff)
downloadclang-57b9c4e9d85971e20ab0dac3eadabae672c43c62.tar.gz
If a constexpr function template specialization is referenced, and then the
template is defined, and then the specialization is referenced again, don't forget to instantiate the template on the second reference. Use the source location of the first reference as the point of instantiation, though. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150518 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/SemaTemplate/constexpr-instantiate.cpp')
-rw-r--r--test/SemaTemplate/constexpr-instantiate.cpp59
1 files changed, 59 insertions, 0 deletions
diff --git a/test/SemaTemplate/constexpr-instantiate.cpp b/test/SemaTemplate/constexpr-instantiate.cpp
new file mode 100644
index 0000000000..69ac0e476b
--- /dev/null
+++ b/test/SemaTemplate/constexpr-instantiate.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+namespace UseBeforeDefinition {
+ struct A {
+ template<typename T> static constexpr T get() { return T(); }
+ // ok, not a constant expression.
+ int n = get<int>();
+ };
+
+ // ok, constant expression.
+ constexpr int j = A::get<int>();
+
+ template<typename T> constexpr int consume(T);
+ // ok, not a constant expression.
+ const int k = consume(0); // expected-note {{here}}
+
+ template<typename T> constexpr int consume(T) { return 0; }
+ // ok, constant expression.
+ constexpr int l = consume(0);
+
+ constexpr int m = k; // expected-error {{constant expression}} expected-note {{initializer of 'k'}}
+}
+
+namespace IntegralConst {
+ template<typename T> constexpr T f(T n) { return n; }
+ enum E {
+ v = f(0), w = f(1) // ok
+ };
+ static_assert(w == 1, "");
+
+ char arr[f('x')]; // ok
+ static_assert(sizeof(arr) == 'x', "");
+}
+
+namespace ConvertedConst {
+ template<typename T> constexpr T f(T n) { return n; }
+ int f() {
+ switch (f()) {
+ case f(4): return 0;
+ }
+ return 1;
+ }
+}
+
+namespace OverloadResolution {
+ template<typename T> constexpr T f(T t) { return t; }
+
+ template<int n> struct S { };
+
+ template<typename T> auto g(T t) -> S<f(sizeof(T))> &;
+ char &f(...);
+
+ template<typename T> auto h(T t[f(sizeof(T))]) -> decltype(&*t) {
+ return t;
+ }
+
+ S<4> &k = g(0);
+ int *p, *q = h(p);
+}