Implement restriction that a partial specialization must actually specialize
something, for variable templates.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@191278 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
new file mode 100644
index 0000000..24513b7
--- /dev/null
+++ b/test/CXX/temp/temp.decls/temp.class.spec/p8-1y.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -std=c++1y -fsyntax-only -verify %s
+
+// -- The argument list of the specialization shall not be identical
+// to the implicit argument list of the primary template.
+
+template<typename T, int N, template<typename> class X> int v1;
+template<typename T, int N, template<typename> class X> int v1<T, N, X>;
+// expected-error@-1{{variable template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+
+template<typename...T> int v2;
+template<typename...T> int v2<T...>;
+// expected-error@-1{{variable template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+
+template<int...N> int v3;
+template<int...N> int v3<N...>;
+// expected-error@-1{{variable template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+
+template<template<typename> class...X> int v4;
+template<template<typename> class...X> int v4<X...>;
+// expected-error@-1{{variable template partial specialization does not specialize any template argument; to define the primary template, remove the template argument list}}
+
+template<typename Outer> struct X {
+ template<typename Inner> static int y;
+ template<typename Inner> static int y<Outer>; // expected-warning {{can not be deduced}} expected-note {{'Inner'}}
+ template<typename Inner> static int y<Inner>; // expected-error {{does not specialize}}
+};
+template<typename Outer> template<typename Inner> int X<Outer>::y<Outer>; // expected-warning {{can not be deduced}} expected-note {{'Inner'}}
+template<typename Outer> template<typename Inner> int X<Outer>::y<Inner>; // expected-error {{does not specialize}}
+template<> template<typename Inner> int X<int>::y<Inner>; // expected-error {{does not specialize}}
diff --git a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
index f4b7246..50772bf 100644
--- a/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
+++ b/test/CodeGenCXX/static-member-variable-explicit-specialization.cpp
@@ -49,7 +49,7 @@
struct b {
template <typename T> static T i;
};
-template<typename T> T b::i<T> = foo();
+template<typename T> T b::i = foo();
template int b::i<int>;
}
// CHECK: define internal void @[[unordered1]]
diff --git a/test/PCH/cxx1y-variable-templates.cpp b/test/PCH/cxx1y-variable-templates.cpp
index 0c600b2..77eeea2 100644
--- a/test/PCH/cxx1y-variable-templates.cpp
+++ b/test/PCH/cxx1y-variable-templates.cpp
@@ -58,7 +58,7 @@
template<typename T> T vc = T();
template<typename T> constexpr T vd = T(10);
- template<typename T> T* vd<T> = new T();
+ template<typename T> T* vd<T*> = new T();
}
namespace spec_join1 {
@@ -72,7 +72,7 @@
template<typename T> T vc = T(10);
template<typename T> T vd = T(10);
- template<typename T> extern T* vd<T>;
+ template<typename T> extern T* vd<T*>;
}
#endif
@@ -108,7 +108,7 @@
template int vc<int>;
template<typename T> extern T vd;
- template<typename T> T* vd<T> = new T();
+ template<typename T> T* vd<T*> = new T();
}
#endif
@@ -146,16 +146,16 @@
static_assert(va<float> == 1.5, "");
static_assert(va<int> == 10, "");
- template<typename T> T* vb<T> = new T();
- int* intpb = vb<int>;
+ template<typename T> T* vb<T*> = new T();
+ int* intpb = vb<int*>;
static_assert(vb<float> == 1.5, "");
- template<typename T> T* vc<T> = new T();
+ template<typename T> T* vc<T*> = new T();
template<> constexpr float vc<float> = 1.5;
- int* intpc = vc<int>;
+ int* intpc = vc<int*>;
static_assert(vc<float> == 1.5, "");
- char* intpd = vd<char>;
+ char* intpd = vd<char*>;
}
namespace spec_join1 {
@@ -165,7 +165,7 @@
template<typename T> extern T vb;
int b = vb<int>;
- int* intpb = vd<int>;
+ int* intpb = vd<int*>;
}
#endif
diff --git a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
index 139dd98..0058c90 100644
--- a/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_in_class.cpp
@@ -101,29 +101,29 @@
struct C1a {
template<typename U> static U Data;
- template<typename U> static U* Data<U>; // Okay, with out-of-line definition
+ template<typename U> static U* Data<U*>; // Okay, with out-of-line definition
};
- template<typename T> T* C1a::Data<T> = new T();
- template int* C1a::Data<int>;
+ template<typename T> T* C1a::Data<T*> = new T();
+ template int* C1a::Data<int*>;
struct C1b {
template<typename U> static U Data;
- template<typename U> static CONST U* Data<U>; // Okay, with out-of-line definition
+ template<typename U> static CONST U* Data<U*>; // Okay, with out-of-line definition
};
- template<typename T> CONST T* C1b::Data<T> = (T*)(0);
- template CONST int* C1b::Data<int>;
+ template<typename T> CONST T* C1b::Data<T*> = (T*)(0);
+ template CONST int* C1b::Data<int*>;
struct C2a {
- template<typename U> static U Data;
- template<typename U> static U* Data<U> = new U(); // expected-error {{non-const static data member must be initialized out of line}}
+ template<typename U> static int Data;
+ template<typename U> static U* Data<U*> = new U(); // expected-error {{non-const static data member must be initialized out of line}}
};
- template int* C2a::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int>' requested here}}
+ template int* C2a::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2a::Data<int *>' requested here}}
struct C2b { // FIXME: ?!? Should this be an error? pointer-types are automatically non-const?
- template<typename U> static U Data;
- template<typename U> static CONST U* Data<U> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
+ template<typename U> static int Data;
+ template<typename U> static CONST U* Data<U*> = (U*)(0); // expected-error {{non-const static data member must be initialized out of line}}
};
- template CONST int* C2b::Data<int>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int>' requested here}}
+ template CONST int* C2b::Data<int*>; // expected-note {{in instantiation of static data member 'non_const_init::pointers::C2b::Data<int *>' requested here}}
}
}
@@ -211,16 +211,17 @@
}
namespace other_bugs {
- // FIXME: This fails to properly initialize the variable 'k'.
-
+ // FIXME: This fails to properly initialize the variables 'k1' and 'k2'.
+
template<typename A> struct S {
- template<typename B> static int V;
template<typename B> static int V0;
+ template<typename B> static int V1;
};
template struct S<int>;
template<typename A> template<typename B> int S<A>::V0 = 123;
- template<typename A> template<typename B> int S<A>::V<B> = 123;
- int k = S<int>::V<void>;
+ template<typename A> template<typename B> int S<A>::V1<B*> = 123;
+ int k1 = S<int>::V0<void>;
+ int k2 = S<int>::V1<void*>;
}
namespace incomplete_array {
@@ -244,7 +245,7 @@
// FIXME: These cases should be accepted.
int *use_before_definition = A<int>::x<char>;
- template<typename T> template<typename U> T A<T>::x<U>[sizeof(U)];
+ template<typename T> template<typename U> T A<T>::x[sizeof(U)];
static_assert(sizeof(A<int>::x<char>) == 1, ""); // expected-error {{incomplete}}
template<typename T> template<typename...U> T A<T>::y<tuple<U...> >[] = { U()... };
diff --git a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
index c98400c..b6e8762 100644
--- a/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
+++ b/test/SemaCXX/cxx1y-variable-templates_top_level.cpp
@@ -315,8 +315,7 @@
namespace diff_type {
// TODO:
- template<typename T> T var = T();
- template<typename T> T* var<T> = new T();
+ template<typename T> T* var = new T();
#ifndef PRECXX11
template<typename T> auto var<T*> = T(); // expected-note {{previous definition is here}}
template<typename T> T var<T*> = T(); // expected-error {{redefinition of 'var' with a different type: 'T' vs 'auto'}}