From d9cf8268dcd3f4d393b7a38fef7eb40c7e7f4d10 Mon Sep 17 00:00:00 2001 From: David Blaikie Date: Mon, 25 Jun 2012 21:55:30 +0000 Subject: [PATCH] PR12937: Explicitly deleting an explicit template specialization. This works around a quirk in the way that explicit template specializations are handled in Clang. We generate an implicit declaration from the original template which the explicit specialization is considered to redeclare. This trips up the explicit delete logic. This change only works around that strange representation. At some point it'd be nice to remove those extra declarations to make the AST more accurately reflect the C++ semantics. Review by Doug Gregor. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159167 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Sema/SemaDeclCXX.cpp | 9 +++++++-- test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp | 8 ++++++++ test/SemaCXX/deleted-function.cpp | 8 ++++++++ 3 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 828083527a..dab2d4de09 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/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. } diff --git a/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp new file mode 100644 index 0000000000..16fd5e6dbd --- /dev/null +++ b/test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s + +template void func(); +template<> void func() = delete; + +template void func2(); +template<> void func2(); // expected-note {{previous declaration is here}} +template<> void func2() = delete; // expected-error {{deleted definition must be first declaration}} diff --git a/test/SemaCXX/deleted-function.cpp b/test/SemaCXX/deleted-function.cpp index d13fd0eb7b..2ee6064501 100644 --- a/test/SemaCXX/deleted-function.cpp +++ b/test/SemaCXX/deleted-function.cpp @@ -55,3 +55,11 @@ struct Z : virtual DelDtor { ~Z() {} // expected-error {{attempt to use a deleted function}} }; DelDtor dd; // expected-error {{attempt to use a deleted function}} + +template void test2() = delete; +template void test2(); + +// test3 really shouldn't have behavior that differs from test2 above +template void test3() = delete; // expected-note {{explicit instantiation refers here}} +template void test3(); +template void test3(); // expected-error {{explicit instantiation of undefined function template 'test3'}} -- 2.50.1