]> granicus.if.org Git - clang/commitdiff
PR12937: Explicitly deleting an explicit template specialization.
authorDavid Blaikie <dblaikie@gmail.com>
Mon, 25 Jun 2012 21:55:30 +0000 (21:55 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 25 Jun 2012 21:55:30 +0000 (21:55 +0000)
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
test/CXX/dcl.decl/dcl.fct.def/dcl.fct.def.delete/p4.cpp [new file with mode: 0644]
test/SemaCXX/deleted-function.cpp

index 828083527a7fb430e782f09cd14ec7138cc39e79..dab2d4de0925573bf6c960a185c0cdbffa0fb69b 100644 (file)
@@ -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 (file)
index 0000000..16fd5e6
--- /dev/null
@@ -0,0 +1,8 @@
+// RUN: %clang_cc1 -std=c++11 -fsyntax-only -verify %s
+
+template<typename> void func();
+template<> void func<int>() = delete;
+
+template<typename> void func2();
+template<> void func2<int>(); // expected-note {{previous declaration is here}}
+template<> void func2<int>() = delete; // expected-error {{deleted definition must be first declaration}}
index d13fd0eb7b4f61486caea76033651fd7fce1d3b7..2ee6064501963f0f80944c147cac5f85c04a9959 100644 (file)
@@ -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<typename> void test2() = delete;
+template void test2<int>();
+
+// test3 really shouldn't have behavior that differs from test2 above
+template<typename> void test3() = delete; // expected-note {{explicit instantiation refers here}}
+template<typename> void test3();
+template void test3<int>(); // expected-error {{explicit instantiation of undefined function template 'test3'}}