summaryrefslogtreecommitdiff
path: root/clang/test/CXX/temp/temp.spec/temp.explicit
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/CXX/temp/temp.spec/temp.explicit')
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp24
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp29
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp89
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp33
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp18
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp6
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp43
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp65
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp81
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp48
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp17
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp35
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp36
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp40
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp66
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp59
16 files changed, 689 insertions, 0 deletions
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
new file mode 100644
index 0000000..80f0598
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-0x.cpp
@@ -0,0 +1,24 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+template<typename T>
+struct X {
+ void f() {}
+};
+
+template inline void X<int>::f(); // expected-error{{explicit instantiation cannot be 'inline'}}
+
+template<typename T>
+struct Y {
+ constexpr int f() { return 0; }
+};
+
+template constexpr int Y<int>::f(); // expected-error{{explicit instantiation cannot be 'constexpr'}}
+
+template<typename T>
+struct Z {
+ enum E : T { e1, e2 };
+ T t; // expected-note {{refers here}}
+};
+
+template enum Z<int>::E; // expected-error {{enumerations cannot be explicitly instantiated}}
+template int Z<int>::t; // expected-error {{explicit instantiation of 't' does not refer to}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
new file mode 100644
index 0000000..d0df305
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1-emit.cpp
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -emit-llvm -triple x86_64-apple-darwin10 -o - %s | FileCheck %s
+template<typename T>
+struct X {
+ static T member1;
+ static T member2;
+ static T member3;
+};
+
+template<typename T>
+T X<T>::member1;
+
+template<typename T>
+T X<T>::member2 = 17;
+
+// CHECK: @_ZN1XIiE7member1E = weak_odr global i32 0
+template int X<int>::member1;
+
+// CHECK: @_ZN1XIiE7member2E = weak_odr global i32 17
+template int X<int>::member2;
+
+// For implicit instantiation of
+long& get(bool Cond1, bool Cond2) {
+ // CHECK: @_ZN1XIlE7member1E = weak_odr global i64 0
+ // CHECK: @_ZN1XIlE7member2E = weak_odr global i64 17
+ // CHECK: @_ZN1XIlE7member3E = external global i64
+ return Cond1? X<long>::member1
+ : Cond2? X<long>::member2
+ : X<long>::member3;
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
new file mode 100644
index 0000000..b426339
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p1.cpp
@@ -0,0 +1,89 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+struct C { };
+
+template<typename T>
+struct X0 {
+ T value; // expected-error{{incomplete}}
+};
+
+// Explicitly instantiate a class template specialization
+template struct X0<int>;
+template struct X0<void>; // expected-note{{instantiation}}
+
+// Explicitly instantiate a function template specialization
+template<typename T>
+void f0(T t) {
+ ++t; // expected-error{{cannot increment}}
+}
+
+template void f0(int);
+template void f0<long>(long);
+template void f0<>(unsigned);
+template void f0(int C::*); // expected-note{{instantiation}}
+
+// Explicitly instantiate a member template specialization
+template<typename T>
+struct X1 {
+ template<typename U>
+ struct Inner {
+ T member1;
+ U member2; // expected-error{{incomplete}}
+ };
+
+ template<typename U>
+ void f(T& t, U u) {
+ t = u; // expected-error{{incompatible}}
+ }
+};
+
+template struct X1<int>::Inner<float>;
+template struct X1<int>::Inner<double>;
+template struct X1<int>::Inner<void>; // expected-note{{instantiation}}
+
+template void X1<int>::f(int&, float);
+template void X1<int>::f<long>(int&, long);
+template void X1<int>::f<>(int&, double);
+template void X1<int>::f<>(int&, int*); // expected-note{{instantiation}}
+
+// Explicitly instantiate members of a class template
+struct Incomplete; // expected-note{{forward declaration}}
+struct NonDefaultConstructible { // expected-note{{candidate constructor (the implicit copy constructor) not viable}}
+ NonDefaultConstructible(int); // expected-note{{candidate constructor}}
+};
+
+template<typename T, typename U>
+struct X2 {
+ void f(T &t, U u) {
+ t = u; // expected-error{{incompatible}}
+ }
+
+ struct Inner {
+ T member1;
+ U member2; // expected-error{{incomplete}}
+ };
+
+ static T static_member1;
+ static U static_member2;
+};
+
+template<typename T, typename U>
+T X2<T, U>::static_member1 = 17; // expected-error{{cannot initialize}}
+
+template<typename T, typename U>
+U X2<T, U>::static_member2; // expected-error{{no matching}}
+
+template void X2<int, float>::f(int &, float);
+template void X2<int, float>::f(int &, double); // expected-error{{does not refer}}
+template void X2<int, int*>::f(int&, int*); // expected-note{{instantiation}}
+
+template struct X2<int, float>::Inner;
+template struct X2<int, Incomplete>::Inner; // expected-note{{instantiation}}
+
+template int X2<int, float>::static_member1;
+template int* X2<int*, float>::static_member1; // expected-note{{instantiation}}
+template
+ NonDefaultConstructible X2<NonDefaultConstructible, int>::static_member1;
+
+template
+ NonDefaultConstructible X2<int, NonDefaultConstructible>::static_member2; // expected-note{{instantiation}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
new file mode 100644
index 0000000..290a874
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p10.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ void f(T&);
+
+ struct Inner;
+
+ static T static_var;
+};
+
+template<typename T>
+void X0<T>::f(T& t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+struct X0<T>::Inner {
+ T member;
+};
+
+template<typename T>
+T X0<T>::static_var = 1; // expected-error{{cannot initialize}}
+
+extern template struct X0<void*>;
+template struct X0<void*>; // expected-note 2{{instantiation}}
+
+template struct X0<int>; // expected-note 4{{explicit instantiation definition is here}}
+
+extern template void X0<int>::f(int&); // expected-error{{follows explicit instantiation definition}}
+extern template struct X0<int>::Inner; // expected-error{{follows explicit instantiation definition}}
+extern template int X0<int>::static_var; // expected-error{{follows explicit instantiation definition}}
+extern template struct X0<int>; // expected-error{{follows explicit instantiation definition}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
new file mode 100644
index 0000000..4ca5428
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p11.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+class X {
+ template <typename T> class Y {};
+};
+
+class A {
+ class B {};
+ class C {};
+};
+
+// C++0x [temp.explicit] 14.7.2/11:
+// The usual access checking rules do not apply to names used to specify
+// explicit instantiations.
+template class X::Y<A::B>;
+
+// As an extension, this rule is applied to explicit specializations as well.
+template <> class X::Y<A::C> {};
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp
new file mode 100644
index 0000000..c756486
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p12.cpp
@@ -0,0 +1,6 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+char* p = 0;
+template<class T> T g(T x = &p) { return x; }
+template int g<int>(int); // OK even though &p isn't an int.
+
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp
new file mode 100644
index 0000000..1dfcf0c
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p2.cpp
@@ -0,0 +1,43 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic -Wc++11-compat %s
+
+// Example from the standard
+template<class T> class Array { void mf() { } };
+
+template class Array<char>;
+template void Array<int>::mf();
+template<class T> void sort(Array<T>& v) { /* ... */ }
+template void sort(Array<char>&);
+namespace N {
+ template<class T> void f(T&) { }
+}
+template void N::f<int>(int&);
+
+
+template<typename T>
+struct X0 {
+ struct Inner {};
+ void f() { }
+ static T value;
+};
+
+template<typename T>
+T X0<T>::value = 17;
+
+typedef X0<int> XInt;
+
+template struct XInt::Inner; // expected-warning{{template-id}}
+template void XInt::f(); // expected-warning{{template-id}}
+template int XInt::value; // expected-warning{{template-id}}
+
+namespace N {
+ template<typename T>
+ struct X1 { // expected-note{{explicit instantiation refers here}}
+ };
+
+ template<typename T>
+ void f1(T) {} // expected-note{{explicit instantiation refers here}}
+}
+using namespace N;
+
+template struct X1<int>; // expected-warning{{must occur in}}
+template void f1(int); // expected-warning{{must occur in}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp
new file mode 100644
index 0000000..1028830
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3-0x.cpp
@@ -0,0 +1,65 @@
+// RUN: %clang_cc1 -std=c++11 -verify %s
+
+// If the name declared in the explicit instantiation is an
+// unqualified name, the explicit instantiation shall appear in the
+// namespace where its template is declared or, if that namespace is
+// inline (7.3.1), any namespace from its enclosing namespace set.
+
+namespace has_inline_namespaces {
+ inline namespace inner {
+ template<class T> void f(T&) {}
+
+ template<class T>
+ struct X0 {
+ struct MemberClass {};
+
+ void mem_func() {}
+
+ template<typename U>
+ struct MemberClassTemplate {};
+
+ template<typename U>
+ void mem_func_template(U&) {}
+
+ static int value;
+ };
+ }
+
+ template<typename T> int X0<T>::value = 17;
+
+ struct X1 {};
+ struct X2 {};
+
+ template void f(X1&);
+ template void f<X2>(X2&);
+
+ template struct X0<X1>;
+
+ template struct X0<X2>::MemberClass;
+
+ template void X0<X2>::mem_func();
+
+ template struct X0<X2>::MemberClassTemplate<X1>;
+
+ template void X0<X2>::mem_func_template(X1&);
+
+ template int X0<X2>::value;
+}
+
+struct X3;
+struct X4;
+
+template void has_inline_namespaces::f(X3&);
+template void has_inline_namespaces::f<X4>(X4&);
+
+template struct has_inline_namespaces::X0<X3>;
+
+template struct has_inline_namespaces::X0<X4>::MemberClass;
+
+template void has_inline_namespaces::X0<X4>::mem_func();
+
+template
+struct has_inline_namespaces::X0<X4>::MemberClassTemplate<X3>;
+
+template
+void has_inline_namespaces::X0<X4>::mem_func_template(X3&);
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
new file mode 100644
index 0000000..38ae768
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p3.cpp
@@ -0,0 +1,81 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s
+
+// A declaration of a function template shall be in scope at the point of the
+// explicit instantiation of the function template.
+template<typename T> void f0(T);
+template void f0(int); // okay
+template<typename T> void f0(T) { }
+
+// A definition of the class or class template containing a member function
+// template shall be in scope at the point of the explicit instantiation of
+// the member function template.
+struct X0; // expected-note {{forward declaration}}
+template<typename> struct X1; // expected-note 5{{declared here}}
+
+template void X0::f0<int>(int); // expected-error {{incomplete type}}
+template void X1<int>::f0<int>(int); // expected-error {{implicit instantiation of undefined template}}
+
+// A definition of a class template or class member template shall be in scope
+// at the point of the explicit instantiation of the class template or class
+// member template.
+template struct X1<float>; // expected-error{{explicit instantiation of undefined template}}
+
+template<typename T>
+struct X2 { // expected-note 4{{refers here}}
+ template<typename U>
+ struct Inner; // expected-note{{declared here}}
+
+ struct InnerClass; // expected-note{{forward declaration}}
+};
+
+template struct X2<int>::Inner<float>; // expected-error{{explicit instantiation of undefined template}}
+
+// A definition of a class template shall be in scope at the point of an
+// explicit instantiation of a member function or a static data member of the
+// class template.
+template void X1<int>::f1(int); // expected-error {{undefined template}}
+template void X1<int>::f1<int>(int); // expected-error {{undefined template}}
+
+template int X1<int>::member; // expected-error {{undefined template}}
+
+// A definition of a member class of a class template shall be in scope at the
+// point of an explicit instantiation of the member class.
+template struct X2<float>::InnerClass; // expected-error{{undefined member}}
+
+// If the declaration of the explicit instantiation names an implicitly-declared
+// special member function (Clause 12), the program is ill-formed.
+template X2<int>::X2(); // expected-error{{not an instantiation}}
+template X2<int>::X2(const X2&); // expected-error{{not an instantiation}}
+template X2<int>::~X2(); // expected-error{{not an instantiation}}
+template X2<int> &X2<int>::operator=(const X2<int>&); // expected-error{{not an instantiation}}
+
+
+// A definition of a class template is sufficient to explicitly
+// instantiate a member of the class template which itself is not yet defined.
+namespace PR7979 {
+ template <typename T> struct S {
+ void f();
+ static void g();
+ static int i;
+ struct S2 {
+ void h();
+ };
+ };
+
+ template void S<int>::f();
+ template void S<int>::g();
+ template int S<int>::i;
+ template void S<int>::S2::h();
+
+ template <typename T> void S<T>::f() {}
+ template <typename T> void S<T>::g() {}
+ template <typename T> int S<T>::i;
+ template <typename T> void S<T>::S2::h() {}
+}
+
+namespace PR11599 {
+ template <typename STRING_TYPE> class BasicStringPiece; // expected-note {{template is declared here}}
+
+ extern template class BasicStringPiece<int>; // expected-error{{explicit instantiation of undefined template 'PR11599::BasicStringPiece<int>}}
+ template class BasicStringPiece<int>;
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
new file mode 100644
index 0000000..09c428e
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p4.cpp
@@ -0,0 +1,48 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -pedantic %s
+
+template<typename T> void f0(T); // expected-note{{here}}
+template void f0(int); // expected-error{{explicit instantiation of undefined function template}}
+
+template<typename T>
+struct X0 {
+ struct Inner;
+
+ void f1(); // expected-note{{here}}
+
+ static T value; // expected-note{{here}}
+};
+
+template void X0<int>::f1(); // expected-error{{explicit instantiation of undefined member function}}
+
+template int X0<int>::value; // expected-error{{explicit instantiation of undefined static data member}}
+
+template<> void f0(long); // expected-note{{previous template specialization is here}}
+template void f0(long); // expected-warning{{explicit instantiation of 'f0<long>' that occurs after an explicit specialization will be ignored}}
+
+template<> void X0<long>::f1(); // expected-note{{previous template specialization is here}}
+template void X0<long>::f1(); // expected-warning{{explicit instantiation of 'f1' that occurs after an explicit specialization will be ignored}}
+
+template<> struct X0<long>::Inner; // expected-note{{previous template specialization is here}}
+template struct X0<long>::Inner; // expected-warning{{explicit instantiation of 'Inner' that occurs after an explicit specialization will be ignored}}
+
+template<> long X0<long>::value; // expected-note{{previous template specialization is here}}
+template long X0<long>::value; // expected-warning{{explicit instantiation of 'value' that occurs after an explicit specialization will be ignored}}
+
+template<> struct X0<double>; // expected-note{{previous template specialization is here}}
+template struct X0<double>; // expected-warning{{explicit instantiation of 'X0<double>' that occurs after an explicit specialization will be ignored}}
+
+// PR 6458
+namespace test0 {
+ template <class T> class foo {
+ int compare(T x, T y);
+ };
+
+ template <> int foo<char>::compare(char x, char y);
+ template <class T> int foo<T>::compare(T x, T y) {
+ // invalid at T=char; if we get a diagnostic here, we're
+ // inappropriately instantiating this template.
+ void *ptr = x;
+ }
+ extern template class foo<char>; // expected-warning {{extern templates are a C++11 extension}}
+ template class foo<char>;
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
new file mode 100644
index 0000000..8422c51
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p5.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -Wc++11-compat %s
+
+namespace N {
+ template<class T> class Y { // expected-note{{explicit instantiation refers here}}
+ void mf() { }
+ };
+}
+
+template class Z<int>; // expected-error{{explicit instantiation of non-template class 'Z'}}
+
+// FIXME: This example from the standard is wrong; note posted to CWG reflector
+// on 10/27/2009
+using N::Y;
+template class Y<int>; // expected-warning{{must occur in}}
+
+template class N::Y<char*>;
+template void N::Y<double>::mf();
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp
new file mode 100644
index 0000000..1382272
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p6.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<class T> class Array { /* ... */ };
+template<class T> void sort(Array<T>& v) { }
+
+// instantiate sort(Array<int>&) - template-argument deduced
+template void sort<>(Array<int>&);
+
+template void sort(Array<long>&);
+
+template<typename T, typename U> void f0(T, U*) { }
+
+template void f0<int>(int, float*);
+template void f0<>(double, float*);
+
+template<typename T> struct hash { };
+struct S {
+ bool operator==(const S&) const { return false; }
+};
+
+template<typename T> struct Hash_map {
+ void Method(const T& x) { h(x); }
+ hash<T> h;
+};
+
+Hash_map<S> *x;
+const Hash_map<S> *foo() {
+ return x;
+}
+
+template<> struct hash<S> {
+ int operator()(const S& k) const {
+ return 0;
+ }
+};
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp
new file mode 100644
index 0000000..7398dca
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p7.cpp
@@ -0,0 +1,36 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+template<typename T>
+struct X0 {
+ struct MemberClass {
+ T member; // expected-error{{with function type}}
+ };
+
+ T* f0(T* ptr) {
+ return ptr + 1; // expected-error{{pointer to the function}}
+ }
+
+ static T* static_member;
+};
+
+template<typename T>
+T* X0<T>::static_member = ((T*)0) + 1; // expected-error{{pointer to the function}}
+
+template class X0<int>; // okay
+
+template class X0<int(int)>; // expected-note 3{{requested here}}
+
+// Specialize everything, so that the explicit instantiation does not trigger
+// any diagnostics.
+template<>
+struct X0<int(long)>::MemberClass { };
+
+typedef int int_long_func(long);
+template<>
+int_long_func *X0<int_long_func>::f0(int_long_func *) { return 0; }
+
+template<>
+int_long_func *X0<int(long)>::static_member;
+
+template class X0<int(long)>;
+
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp
new file mode 100644
index 0000000..550078a
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p8.cpp
@@ -0,0 +1,40 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
+template<typename T>
+struct X0 {
+ struct MemberClass;
+
+ T* f0(T* ptr);
+
+ static T* static_member;
+};
+
+template class X0<int(int)>; // ok; nothing gets instantiated.
+
+template<typename T>
+struct X0<T>::MemberClass {
+ T member;
+};
+
+template<typename T>
+T* X0<T>::f0(T* ptr) {
+ return ptr + 1;
+}
+
+template<typename T>
+T* X0<T>::static_member = 0;
+
+template class X0<int>; // ok
+
+
+template<typename T>
+struct X1 {
+ enum class E {
+ e = T::error // expected-error 2{{no members}}
+ };
+};
+template struct X1<int>; // expected-note {{here}}
+
+extern template struct X1<char>; // ok
+
+template struct X1<char>; // expected-note {{here}}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
new file mode 100644
index 0000000..04e7df5
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9-linkage.cpp
@@ -0,0 +1,66 @@
+// RUN: %clang_cc1 -O1 -emit-llvm -std=c++11 -o - %s | FileCheck %s
+
+template<typename T>
+struct X0 {
+ void f(T &t) {
+ t = 0;
+ }
+
+ void g(T &t);
+
+ void h(T &t);
+
+ static T static_var;
+};
+
+template<typename T>
+inline void X0<T>::g(T & t) {
+ t = 0;
+}
+
+template<typename T>
+void X0<T>::h(T & t) {
+ t = 0;
+}
+
+template<typename T>
+T X0<T>::static_var = 0;
+
+extern template struct X0<int*>;
+
+int *&test(X0<int*> xi, int *ip) {
+ // CHECK: define available_externally void @_ZN2X0IPiE1fERS0_
+ xi.f(ip);
+ // CHECK: define available_externally void @_ZN2X0IPiE1gERS0_
+ xi.g(ip);
+ // CHECK: declare void @_ZN2X0IPiE1hERS0_
+ xi.h(ip);
+ return X0<int*>::static_var;
+}
+
+template<typename T>
+void f0(T& t) {
+ t = 0;
+}
+
+template<typename T>
+inline void f1(T& t) {
+ t = 0;
+}
+
+extern template void f0<>(int *&);
+extern template void f1<>(int *&);
+
+void test_f0(int *ip, float *fp) {
+ // CHECK: declare void @_Z2f0IPiEvRT_
+ f0(ip);
+ // CHECK: define linkonce_odr void @_Z2f0IPfEvRT_
+ f0(fp);
+}
+
+void test_f1(int *ip, float *fp) {
+ // CHECK: define available_externally void @_Z2f1IPiEvRT_
+ f1(ip);
+ // CHECK: define linkonce_odr void @_Z2f1IPfEvRT_
+ f1(fp);
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
new file mode 100644
index 0000000..8649017
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.explicit/p9.cpp
@@ -0,0 +1,59 @@
+// RUN: %clang_cc1 -fsyntax-only -std=c++11 -verify %s
+
+template<typename T>
+struct X0 {
+ void f(T &t) {
+ t = 1; // expected-error{{incompatible type}}
+ }
+
+ void g(T &t);
+
+ void h(T &t);
+
+ static T static_var;
+};
+
+template<typename T>
+inline void X0<T>::g(T & t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+void X0<T>::h(T & t) {
+ t = 1;
+}
+
+template<typename T>
+T X0<T>::static_var = 1;
+
+extern template struct X0<int*>;
+
+int *&test(X0<int*> xi, int *ip) {
+ xi.f(ip); // expected-note{{instantiation}}
+ xi.g(ip); // expected-note{{instantiation}}
+ xi.h(ip);
+ return X0<int*>::static_var;
+}
+
+template<typename T>
+void f0(T& t) {
+ t = 1; // expected-error{{incompatible type}}
+}
+
+template<typename T>
+inline void f1(T& t) {
+ t = 1; // expected-error 2{{incompatible type}}
+}
+
+extern template void f0<>(int *&);
+extern template void f1<>(int *&);
+
+void test_f0(int *ip, float *fp) {
+ f0(ip);
+ f0(fp); // expected-note{{instantiation}}
+}
+
+void test_f1(int *ip, float *fp) {
+ f1(ip); // expected-note{{instantiation}}
+ f1(fp); // expected-note{{instantiation}}
+}