aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDouglas Gregor <dgregor@apple.com>2009-10-06 21:27:51 +0000
committerDouglas Gregor <dgregor@apple.com>2009-10-06 21:27:51 +0000
commit13d2d6cfd6a0032402c98b4fa237526c5b40e3fb (patch)
treed42c66a21a40fd1459a9dd3a4d617bb58cef1fe9
parent07b1270f438292710466ca77a1ab83e74f1abebc (diff)
Test explicit specialization for all of the various cases where
explicit specializations can occur. Also, fix a minor recovery bug where we should allow declarations coming from the parser to be NULL. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@83416 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Sema/SemaTemplate.cpp2
-rw-r--r--test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp97
2 files changed, 98 insertions, 1 deletions
diff --git a/lib/Sema/SemaTemplate.cpp b/lib/Sema/SemaTemplate.cpp
index d12ec9318a..02c3e43b33 100644
--- a/lib/Sema/SemaTemplate.cpp
+++ b/lib/Sema/SemaTemplate.cpp
@@ -257,7 +257,7 @@ bool Sema::DiagnoseTemplateParameterShadow(SourceLocation Loc, Decl *PrevDecl) {
/// the parameter D to reference the templated declaration and return a pointer
/// to the template declaration. Otherwise, do nothing to D and return null.
TemplateDecl *Sema::AdjustDeclIfTemplate(DeclPtrTy &D) {
- if (TemplateDecl *Temp = dyn_cast<TemplateDecl>(D.getAs<Decl>())) {
+ if (TemplateDecl *Temp = dyn_cast_or_null<TemplateDecl>(D.getAs<Decl>())) {
D = DeclPtrTy::make(Temp->getTemplatedDecl());
return Temp;
}
diff --git a/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp
new file mode 100644
index 0000000000..f3d0709ef8
--- /dev/null
+++ b/test/CXX/temp/temp.spec/temp.expl.spec/p1.cpp
@@ -0,0 +1,97 @@
+// RUN: clang-cc -fsyntax-only %s
+
+// This test creates cases where implicit instantiations of various entities
+// would cause a diagnostic, but provides expliict specializations for those
+// entities that avoid the diagnostic. The intent is to verify that
+struct NonDefaultConstructible {
+ NonDefaultConstructible(int);
+};
+
+
+// C++ [temp.expl.spec]p1:
+// An explicit specialization of any of the following:
+
+// -- function template
+template<typename T> void f0(T) {
+ T t;
+}
+
+template<> void f0(NonDefaultConstructible) { }
+
+void test_f0(NonDefaultConstructible NDC) {
+ f0(NDC);
+}
+
+// -- class template
+template<typename T>
+struct X0 {
+ static T member;
+
+ void f1(T t) {
+ t = 17;
+ }
+
+ struct Inner : public T { };
+
+ template<typename U>
+ struct InnerTemplate : public T { };
+
+ template<typename U>
+ void ft1(T t, U u);
+};
+
+template<typename T>
+template<typename U>
+void X0<T>::ft1(T t, U u) {
+ t = u;
+}
+
+template<typename T> T X0<T>::member;
+
+template<> struct X0<void> { };
+X0<void> test_X0;
+
+
+// -- member function of a class template
+template<> void X0<void*>::f1(void *) { }
+
+void test_spec(X0<void*> xvp, void *vp) {
+ xvp.f1(vp);
+}
+
+// -- static data member of a class template
+template<>
+NonDefaultConstructible X0<NonDefaultConstructible>::member = 17;
+
+NonDefaultConstructible &get_static_member() {
+ return X0<NonDefaultConstructible>::member;
+}
+
+// -- member class of a class template
+template<>
+struct X0<void*>::Inner { };
+
+X0<void*>::Inner inner0;
+
+// -- member class template of a class template
+template<>
+template<>
+struct X0<void*>::InnerTemplate<int> { };
+
+X0<void*>::InnerTemplate<int> inner_template0;
+
+// -- member function template of a class template
+template<>
+template<>
+void X0<void*>::ft1(void*, const void*) { }
+
+void test_func_template(X0<void *> xvp, void *vp, const void *cvp) {
+ xvp.ft1(vp, cvp);
+}
+
+// example from the standard:
+template<class T> class stream;
+template<> class stream<char> { /* ... */ };
+template<class T> class Array { /* ... */ };
+template<class T> void sort(Array<T>& v) { /* ... */ }
+template<> void sort<char*>(Array<char*>&) ;