[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