Author: faisalv
Date: Mon Jun 13 22:23:15 2016
New Revision: 272631

URL: http://llvm.org/viewvc/llvm-project?rev=272631&view=rev
Log:
Fix PR28100 - Allow redeclarations of deleted explicit specializations.

See https://llvm.org/bugs/show_bug.cgi?id=28100.

In r266561 when I implemented allowing explicit specializations of function 
templates to override deleted status, I mistakenly assumed (and hence 
introduced a violable assertion) that when an explicit specialization was being 
declared, the corresponding specialization of the most specialized function 
template that it would get linked to would always be the one that was 
implicitly generated - and so if it was marked as 'deleted' it must have 
inherited it from the primary template and so should be safe to reset its 
deleted status, and set it to being an explicit specialization.  Obviously 
during redeclaration of a deleted explicit specialization, in order to avoid a 
recursive reset, we need to check that the previous specialization is not an 
explicit specialization (instead of assuming and asserting it) and that it 
hasn't been referenced, and so only then is it safe to reset its 'deleted' 
status.

All regression tests pass.

Thanks to Zhendong Su for reporting the bug and David Majnemer for tracking it 
to my commit r266561, and promptly bringing it to my attention.




Modified:
    cfe/trunk/lib/Sema/SemaTemplate.cpp
    cfe/trunk/test/SemaCXX/delete-and-function-templates.cpp

Modified: cfe/trunk/lib/Sema/SemaTemplate.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaTemplate.cpp?rev=272631&r1=272630&r2=272631&view=diff
==============================================================================
--- cfe/trunk/lib/Sema/SemaTemplate.cpp (original)
+++ cfe/trunk/lib/Sema/SemaTemplate.cpp Mon Jun 13 22:23:15 2016
@@ -6989,12 +6989,20 @@ bool Sema::CheckFunctionTemplateSpeciali
   // Mark the prior declaration as an explicit specialization, so that later
   // clients know that this is an explicit specialization.
   if (!isFriend) {
-    // Explicit specializations do not inherit '=delete' from their primary
-    // function template.
-    if (Specialization->isDeleted()) {
-      assert(!SpecInfo->isExplicitSpecialization());
-      assert(Specialization->getCanonicalDecl() == Specialization);
-      Specialization->setDeletedAsWritten(false);
+    // Since explicit specializations do not inherit '=delete' from their
+    // primary function template - check if the 'specialization' that was
+    // implicitly generated (during template argument deduction for partial
+    // ordering) from the most specialized of all the function templates that
+    // 'FD' could have been specializing, has a 'deleted' definition.  If so,
+    // first check that it was implicitly generated during template argument
+    // deduction by making sure it wasn't referenced, and then reset the 
deleted
+    // flag to not-deleted, so that we can inherit that information from 'FD'.
+    if (Specialization->isDeleted() && !SpecInfo->isExplicitSpecialization() &&
+        !Specialization->getCanonicalDecl()->isReferenced()) {
+      assert(
+          Specialization->getCanonicalDecl() == Specialization &&
+          "This must be the only existing declaration of this specialization");
+      Specialization->setDeletedAsWritten(false);
     }
     SpecInfo->setTemplateSpecializationKind(TSK_ExplicitSpecialization);
     MarkUnusedFileScopedDecl(Specialization);

Modified: cfe/trunk/test/SemaCXX/delete-and-function-templates.cpp
URL: 
http://llvm.org/viewvc/llvm-project/cfe/trunk/test/SemaCXX/delete-and-function-templates.cpp?rev=272631&r1=272630&r2=272631&view=diff
==============================================================================
--- cfe/trunk/test/SemaCXX/delete-and-function-templates.cpp (original)
+++ cfe/trunk/test/SemaCXX/delete-and-function-templates.cpp Mon Jun 13 
22:23:15 2016
@@ -112,4 +112,22 @@ void foo() {
 
 
 } // end ns3
+
+namespace ns4 {
+template < typename T> T* foo (T);
+template <> int* foo(int) = delete;
+template <> int* foo(int); //expected-note{{candidate}}
+
+int *IP = foo(2); //expected-error{{deleted}}
+double *DP = foo(3.14);
+} //end ns4
+
+namespace ns5 {
+template < typename T> T* foo (T);
+template <> int* foo(int); //expected-note{{previous}}
+template <> int* foo(int) = delete; //expected-error{{deleted definition must 
be first declaration}}
+
+} //end ns5
+
+
 } // end test_explicit_specializations_and_delete


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

Reply via email to