Implement explicit instantiations of member classes of class templates, e.g.,
template<typename T>
struct X {
struct Inner;
};
template struct X<int>::Inner;
This change is larger than it looks because it also fixes some
a problem with nested-name-specifiers and tags. We weren't requiring
the DeclContext associated with the scope specifier of a tag to be
complete. Therefore, when looking for something like "struct
X<int>::Inner", we weren't instantiating X<int>.
This, naturally, uncovered a problem with member pointers, where we
were requiring the left-hand side of a member pointer access
expression (e.g., x->*) to be a complete type. However, this is wrong:
the semantics of this expression does not require a complete type (EDG
agrees).
Stuart vouched for me. Blame him.
llvm-svn: 71756
diff --git a/clang/test/SemaTemplate/temp_explicit.cpp b/clang/test/SemaTemplate/temp_explicit.cpp
index 0b96c73..6394f1d 100644
--- a/clang/test/SemaTemplate/temp_explicit.cpp
+++ b/clang/test/SemaTemplate/temp_explicit.cpp
@@ -71,3 +71,41 @@
template struct X4<int&>; // expected-note{{instantiation}}
template struct X4<float&>; // expected-note{{instantiation}}
+
+// Check explicit instantiation of member classes
+namespace N2 {
+
+template<typename T>
+struct X5 {
+ struct Inner1 {
+ void f(T&);
+ };
+
+ struct Inner2 {
+ struct VeryInner { // expected-note 2{{instantiation}}
+ void g(T*); // expected-error 2{{pointer to a reference}}
+ };
+ };
+};
+
+}
+
+template struct N2::X5<void>::Inner2;
+
+using namespace N2;
+template struct X5<int&>::Inner2; // expected-note{{instantiation}}
+
+void f4(X5<float&>::Inner2);
+template struct X5<float&>::Inner2; // expected-note{{instantiation}}
+
+namespace N3 {
+ template struct N2::X5<int>::Inner2;
+}
+
+struct X6 {
+ struct Inner { // expected-note{{here}}
+ void f();
+ };
+};
+
+template struct X6::Inner; // expected-error{{non-templated}}