Implement CWG 941 - explicit specializations of deleted function templates
authorFaisal Vali <faisalv@yahoo.com>
Sun, 17 Apr 2016 17:32:04 +0000 (17:32 +0000)
committerFaisal Vali <faisalv@yahoo.com>
Sun, 17 Apr 2016 17:32:04 +0000 (17:32 +0000)
commit5e9e8ac4326b28ff5cc582f14c955391793a7e19
treec5da389eb8b1e1ac4db89f5e2ebc7e81715465fc
parent6ccbd2bdd2f7c247d79054f361a32b5f50539b3c
Implement CWG 941 - explicit specializations of deleted function templates

  template<class T> void f(T) = delete;
  template<> void f(int); // OK.

  f(3); // OK

Implementation strategy:

When an explicit specialization of a function template, a member function template or a member function of a class template is declared, clang first implicitly instantiates the declaration of a specialization from the templated-entity being explicitly specialized (since their signatures must be the same) and then links the explicit specialization being declared as a redeclaration of the aforementioned specialization.

The problem was that when clang 'implicitly instantiates' the initial specialization, it marks the corresponding FunctionDecl as deleted if the corresponding templated-entity was deleted, rather than waiting to see whether the explicit specialization being declared provides a non-deleted body. (The eager marking of delete has advantages during overload resolution I suppose, where we don't have to try and instantiate a definition of the function to see if it is deleted).

The present fix entails recognizing that when clang knows that an explicit specialization is being declared (for whichever templated-entity), the prior implicit instantiation should not inherit the 'deleted' status, and so we reset it to false.

I suppose an alternative fix (amongst others) could consider creating a new context (ExplicitSpecializationDeclarationSubstitution or some such) that is checked during template-argument-deduction and final substitution, and avoid inheriting the deleted status during declaration substitution.  But while conceptually cleaner, that would be a slightly more involved change (as could be some of the other alternatives: such as avoid tagging implicit specializations as deleted, and check their primary templates for the deleted status where needed), and so I chose a different path.  Hopefully it'll prove to not be a bad choice.

llvm-svn: 266561
clang/lib/Sema/SemaDecl.cpp
clang/lib/Sema/SemaTemplate.cpp
clang/test/SemaCXX/delete-and-function-templates.cpp [new file with mode: 0644]