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/instantiate-complete.cpp b/clang/test/SemaTemplate/instantiate-complete.cpp
index 7b43735..babc552 100644
--- a/clang/test/SemaTemplate/instantiate-complete.cpp
+++ b/clang/test/SemaTemplate/instantiate-complete.cpp
@@ -11,8 +11,7 @@
// expected-error{{data member instantiated with function type 'int (int)'}} \
// expected-error{{data member instantiated with function type 'char (char)'}} \
// expected-error{{data member instantiated with function type 'short (short)'}} \
- // expected-error{{data member instantiated with function type 'float (float)'}} \
- // expected-error{{data member instantiated with function type 'long (long)'}}
+ // expected-error{{data member instantiated with function type 'float (float)'}}
};
X<int> f() { return 0; }
@@ -41,7 +40,8 @@
}
void test_memptr(X<long> *p1, long X<long>::*pm1,
- X<long(long)> *p2, long (X<long(long)>::*pm2)(long)) {
+ X<long(long)> *p2,
+ long (X<long(long)>::*pm2)(long)) {
(void)(p1->*pm1);
- (void)(p2->*pm2); // expected-note{{in instantiation of template class 'struct X<long (long)>' requested here}}
+ (void)((p2->*pm2)(0));
}