[cfe-commits] PR12937 - explicitly deleting an explicit template specialization

David Blaikie dblaikie at gmail.com
Mon Jun 25 15:01:05 PDT 2012


On Mon, Jun 25, 2012 at 11:14 AM, Douglas Gregor <dgregor at apple.com> wrote:
>
> On Jun 25, 2012, at 11:08 AM, David Blaikie <dblaikie at gmail.com> wrote:
>
>> On Mon, Jun 25, 2012 at 8:52 AM, Douglas Gregor <dgregor at apple.com> wrote:
>>>
>>> On Jun 21, 2012, at 3:14 PM, David Blaikie wrote:
>>>
>>>> As per PR12937 Clang rejects valid code that attempts to explicitly
>>>> delete an explicit template specialization.
>>>>
>>>> This is due to the way Clang represents explicit template
>>>> specializations as redeclarations of an implicit specialization of the
>>>> original function template.
>>>>
>>>> The fix is a pretty vague workaround - I'm open to suggestions of how
>>>> to more deliberately test for the "magic" implicit declaration for an
>>>> explicit specialization but I couldn't find one - so for now I just
>>>> assume it's the first (getPreviousDecl() == nullptr) declaration of
>>>> any explicit specialization.
>>>
>>> diff --git lib/Sema/SemaDeclCXX.cpp lib/Sema/SemaDeclCXX.cpp
>>> index 8280835..dab2d4d 100644
>>> --- lib/Sema/SemaDeclCXX.cpp
>>> +++ lib/Sema/SemaDeclCXX.cpp
>>> @@ -10316,8 +10316,13 @@ void Sema::SetDeclDeleted(Decl *Dcl, SourceLocation DelLoc) {
>>>     return;
>>>   }
>>>   if (const FunctionDecl *Prev = Fn->getPreviousDecl()) {
>>> -    Diag(DelLoc, diag::err_deleted_decl_not_first);
>>> -    Diag(Prev->getLocation(), diag::note_previous_declaration);
>>> +    // Don't consider the implicit declaration we generate for explicit
>>> +    // specializations. FIXME: Do not generate these implicit declarations.
>>> +    if (Prev->getTemplateSpecializationKind() != TSK_ExplicitSpecialization
>>> +        || Prev->getPreviousDecl()) {
>>> +      Diag(DelLoc, diag::err_deleted_decl_not_first);
>>> +      Diag(Prev->getLocation(), diag::note_previous_declaration);
>>> +    }
>>>     // If the declaration wasn't the first, we delete the function anyway for
>>>     // recovery.
>>>   }
>>>
>>> I suggest checking that Prev->getTemplateSpecializationKind() == TSK_ImplicitInstantiation. The others (explicit instantiations) should still, presumably, cause us to complain.
>>
>> Just replacing my check with this would then cause us to lose the
>> normal (non-templated) case. Assuming you meant testing both
>> TSK_Undefined || TSK_ImplicitInstantiation, even then I'm a little
>> confused - what cases would this correctly error on that my version
>> did not?
>
> I was concerned with explicit instantiations, e.g.,
>
>        template void func2<int>();
>
>> If it's any clearer, the condition I meant to express was: "if this is
>> an explicit specialization with only one prior declaration, do not
>> error" - perhaps it would be more legible as
>> "!(Prev->getTemplateSpecializationKind() == TSK_ExplicitSpecalization
>> && !Prev->getPreviousDecl())" ?
>
> Okay. As long as the explicit instantiation example DTRT, either formulation is fine.

Committed as r159167. I added a test case for what I assume is the
explicit instantiation example you were interested in:

  template<typename> void test2() = delete;
  template void test2<int>();

Clang compiles this without diagnostics before & after my change.
Interestingly GCC rejects this ("explicit instantiation of ‘void
func(T) [with T = int]’ but no definition available") & Richard Smith
& I seem to agree that GCC is incorrect to reject such code.

Though I also found an extra case that's probably a Clang bug I'll
look at (I've committed the test case in the same revision along with
a comment explaining that it's probably not right):

  template<typename> void test2() = delete;
  template<typename> void test2();
  template void test2<int>();

Clang errors on this (with & without my change)

deleted.cpp:3:15: error: explicit instantiation of undefined function
template 'func'
template void func(int);
              ^
deleted.cpp:1:27: note: explicit instantiation refers here
template<typename T> void func(T) = delete;
                          ^




More information about the cfe-commits mailing list