summaryrefslogtreecommitdiffstats
path: root/clang/test
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2011-05-10 18:27:06 +0000
committerDouglas Gregor <dgregor@apple.com>2011-05-10 18:27:06 +0000
commit972fe534ed33dbb10a26b527f69f19c677722277 (patch)
tree3c3f607415fa0570cb33e60653c29a5cb9d7c501 /clang/test
parent62f1ab79ecc350021f0a986d3e2a03b172b24f80 (diff)
downloadbcm5719-llvm-972fe534ed33dbb10a26b527f69f19c677722277.tar.gz
bcm5719-llvm-972fe534ed33dbb10a26b527f69f19c677722277.zip
Reimplement Sema::MatchTemplateParametersToScopeSpecifier() based on
the semantic context referenced by the nested-name-specifier rather than the syntactic form of the nested-name-specifier. The previous incarnation was based on my complete misunderstanding of C++ [temp.expl.spec]. The latest C++0x working draft clarifies the requirements here, and this rewrite is intended to follow that. Along the way, improve source location information in the diagnostics. For example, if we report that a specific type needs or doesn't need a 'template<>' header, we dig out that type in the nested-name-specifier and highlight its range. Fixes: PR5907, PR9421, PR8277, PR8708, PR9482, PR9668, PR9877, and <rdar://problem/9135379>. llvm-svn: 131138
Diffstat (limited to 'clang/test')
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp167
-rw-r--r--clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp5
2 files changed, 169 insertions, 3 deletions
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
new file mode 100644
index 00000000000..733aaee7545
--- /dev/null
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/examples.cpp
@@ -0,0 +1,167 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+
+namespace PR5907 {
+ template<typename T> struct identity { typedef T type; };
+ struct A { A(); };
+ identity<A>::type::A() { }
+
+ struct B { void f(); };
+ template<typename T> struct C { typedef B type; };
+
+ void C<int>::type::f() { }
+}
+
+namespace PR9421 {
+ namespace N { template<typename T> struct S { void f(); }; }
+ typedef N::S<int> T;
+ namespace N { template<> void T::f() {} }
+}
+
+namespace PR8277 {
+ template< typename S >
+ struct C
+ {
+ template< int >
+ void F( void )
+ {
+ }
+ };
+
+ template< typename S >
+ struct D
+ {
+ typedef C< int > A;
+ };
+
+ typedef D< int >::A A;
+
+ template<>
+ template<>
+ void A::F< 0 >( void )
+ {
+ }
+}
+
+namespace PR8277b {
+ template<typename S> struct C {
+ void f();
+ };
+ template<typename S> struct D {
+ typedef C<int> A;
+ };
+ template<> void D<int>::A::f() {
+ }
+}
+
+namespace PR8708 {
+ template<typename T> struct A {
+ template<typename U> struct B {
+ // #2
+ void f();
+ };
+ };
+
+ // #A specialize the member template for
+ // implicit instantiation of A<int>,
+ // leaving the member template "unspecialized"
+ // (14.7.3/16). Specialization uses the syntax
+ // for explicit specialization (14.7.3/14)
+ template<> template<typename U>
+ struct A<int>::B {
+ // #1
+ void g();
+ };
+
+ // #1 define its function g. There is an enclosing
+ // class template, so we write template<> for each
+ // specialized template (14.7.3/15).
+ template<> template<typename U>
+ void A<int>::B<U>::g() { }
+
+ // #2 define the unspecialized member template's
+ // f
+ template<typename T> template<typename U>
+ void A<T>::B<U>::f() { }
+
+
+ // specialize the member template again, now
+ // specializing the member too. This specializes
+ // #A
+ template<> template<>
+ struct A<int>::B<int> {
+ // #3
+ void h();
+ };
+
+ // defines #3. There is no enclosing class template, so
+ // we write no "template<>".
+ void A<int>::B<int>::h() { }
+
+ void test() {
+ // calls #1
+ A<int>::B<float> a; a.g();
+
+ // calls #2
+ A<float>::B<int> b; b.f();
+
+ // calls #3
+ A<int>::B<int> c; c.h();
+ }
+}
+
+namespace PR9482 {
+ namespace N1 {
+ template <typename T> struct S {
+ void foo() {}
+ };
+ }
+
+ namespace N2 {
+ typedef N1::S<int> X;
+ }
+
+ namespace N1 {
+ template<> void N2::X::foo() {}
+ }
+}
+
+namespace PR9668 {
+ namespace First
+ {
+ template<class T>
+ class Bar
+ {
+ protected:
+
+ static const bool static_bool;
+ };
+ }
+
+ namespace Second
+ {
+ class Foo;
+ }
+
+ typedef First::Bar<Second::Foo> Special;
+
+ namespace
+ First
+ {
+ template<>
+ const bool Special::static_bool(false);
+ }
+}
+
+namespace PR9877 {
+ template<int>
+ struct X
+ {
+ struct Y;
+ };
+
+ template<> struct X<0>::Y { static const int Z = 1; };
+ template<> struct X<1>::Y { static const int Z = 1; };
+
+ const int X<0>::Y::Z;
+ template<> const int X<1>::Y::Z; // expected-error{{extraneous 'template<>' in declaration of variable 'Z'}}
+}
diff --git a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp
index 88cfc5d7c39..56231e2f725 100644
--- a/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp
+++ b/clang/test/CXX/temp/temp.spec/temp.expl.spec/p17.cpp
@@ -24,12 +24,11 @@ namespace test1 {
template <> class A<double> {
public:
- static int foo; // expected-note{{attempt to specialize}}
+ static int foo;
static int bar;
};
typedef A<double> AB;
- template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}} \
- // expected-error{{does not specialize}}
+ template <> int AB::foo = 0; // expected-error{{extraneous 'template<>'}}
int AB::bar = 1;
}
OpenPOWER on IntegriCloud