Author: rsmith
Date: Fri Dec 11 16:39:52 2015
New Revision: 255383

URL: http://llvm.org/viewvc/llvm-project?rev=255383&view=rev
Log:
Allow non-defining declarations of class template partial specializations to
have a nested name specifier. Strictly speaking, forward declarations of class
template partial specializations are not permitted at all, but that seems like
an obvious wording defect, and if we allow them without a nested name specifier
we should also allow them with a nested name specifier.

Added:
    cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p1.cpp
Modified:
    cfe/trunk/lib/Sema/SemaDecl.cpp
    cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h

Modified: cfe/trunk/lib/Sema/SemaDecl.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaDecl.cpp?rev=255383&r1=255382&r2=255383&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaDecl.cpp (original)
+++ cfe/trunk/lib/Sema/SemaDecl.cpp Fri Dec 11 16:39:52 2015
@@ -3780,10 +3780,15 @@ Decl *Sema::ParsedFreeStandingDeclSpec(S
   bool IsExplicitSpecialization =
     !TemplateParams.empty() && TemplateParams.back()->size() == 0;
   if (Tag && SS.isNotEmpty() && !Tag->isCompleteDefinition() &&
-      !IsExplicitInstantiation && !IsExplicitSpecialization) {
+      !IsExplicitInstantiation && !IsExplicitSpecialization &&
+      !isa<ClassTemplatePartialSpecializationDecl>(Tag)) {
     // Per C++ [dcl.type.elab]p1, a class declaration cannot have a
     // nested-name-specifier unless it is an explicit instantiation
     // or an explicit specialization.
+    //
+    // FIXME: We allow class template partial specializations here too, per the
+    // obvious intent of DR1819.
+    //
     // Per C++ [dcl.enum]p1, an opaque-enum-declaration can't either.
     Diag(SS.getBeginLoc(), diag::err_standalone_class_nested_name_specifier)
         << GetDiagnosticTypeSpecifierID(DS.getTypeSpecType()) << SS.getRange();

Added: cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p1.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p1.cpp?rev=255383&view=auto
==============================================================================
--- cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p1.cpp (added)
+++ cfe/trunk/test/CXX/dcl.dcl/dcl.spec/dcl.type/dcl.type.elab/p1.cpp Fri Dec 
11 16:39:52 2015
@@ -0,0 +1,26 @@
+// RUN: %clang_cc1 -verify %s -std=c++11
+
+namespace N {
+  struct A;
+  template<typename T> struct B {};
+}
+template<typename T> struct C {};
+struct D {
+  template<typename T> struct A {};
+};
+struct N::A; // expected-error {{cannot have a nested name specifier}}
+
+template<typename T> struct N::B; // expected-error {{cannot have a nested 
name specifier}}
+template<typename T> struct N::B<T*>; // FIXME: This is technically 
ill-formed, but that's not the intent.
+template<> struct N::B<int>;
+template struct N::B<float>;
+
+template<typename T> struct C;
+template<typename T> struct C<T*>; // FIXME: This is technically ill-formed, 
but that's not the intent.
+template<> struct C<int>;
+template struct C<float>;
+
+template<typename T> struct D::A; // expected-error {{cannot have a nested 
name specifier}}
+template<typename T> struct D::A<T*>; // FIXME: This is technically 
ill-formed, but that's not the intent.
+template<> struct D::A<int>;
+template struct D::A<float>;

Modified: cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h?rev=255383&r1=255382&r2=255383&view=diff
==============================================================================
--- cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h (original)
+++ cfe/trunk/test/Modules/Inputs/submodules-merge-defs/defs.h Fri Dec 11 
16:39:52 2015
@@ -131,3 +131,10 @@ namespace ClassTemplatePartialSpec {
   };
   template<typename A, int B> template<typename C> F<A[B]>::F() {}
 }
+
+struct MemberClassTemplate {
+  template<typename T> struct A;
+};
+template<typename T> struct MemberClassTemplate::A {};
+template<typename T> struct MemberClassTemplate::A<T*> {};
+template<> struct MemberClassTemplate::A<int> {};


_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to