[C++ Patch] PR 60753

Paolo Carlini paolo.carlini@oracle.com
Wed Jan 7 20:57:00 GMT 2015


Hi,

this is an accepts-invalid issue about an explicit specialization 
redeclared deleted. AFAICS, the problem is that start_decl sets 
DECL_DELETED_FN on the fndecl too late, that is, *after* calling 
grokdeclarator, whereas we want to have it set by the time the latter 
calls grokfndecl, because then the problem can be diagnosed by 
duplicate_decls (called by register_specialization via 
check_explicit_specialization). The below solves the issue by passing 
down the information about SD_DELETED from grokdeclator to grokfndecl.

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////
-------------- next part --------------
/cp
2015-01-07  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/60753
	* decl.c (grokfndecl): Add bool parameter.
	(grokdeclarator): Adjust calls.
	(start_decl): Don't set DECL_DELETED_FN here.

/testsuite
2015-01-07  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/60753
	* g++.dg/cpp0x/deleted10.C: New.
-------------- next part --------------
Index: cp/decl.c
===================================================================
--- cp/decl.c	(revision 219318)
+++ cp/decl.c	(working copy)
@@ -4631,27 +4631,16 @@ start_decl (const cp_declarator *declarator,
   if (context != global_namespace)
     *pushed_scope_p = push_scope (context);
 
-  if (initialized)
-    /* Is it valid for this decl to have an initializer at all?
-       If not, set INITIALIZED to zero, which will indirectly
-       tell `cp_finish_decl' to ignore the initializer once it is parsed.  */
-    switch (TREE_CODE (decl))
-      {
-      case TYPE_DECL:
-	error ("typedef %qD is initialized (use decltype instead)", decl);
-	return error_mark_node;
+  /* Is it valid for this decl to have an initializer at all?
+     If not, set INITIALIZED to zero, which will indirectly
+     tell `cp_finish_decl' to ignore the initializer once it is parsed.  */
+  if (initialized
+      && TREE_CODE (decl) == TYPE_DECL)
+    {
+      error ("typedef %qD is initialized (use decltype instead)", decl);
+      return error_mark_node;
+    }
 
-      case FUNCTION_DECL:
-	if (initialized == SD_DELETED)
-	  /* We'll handle the rest of the semantics later, but we need to
-	     set this now so it's visible to duplicate_decls.  */
-	  DECL_DELETED_FN (decl) = 1;
-	break;
-
-      default:
-	break;
-      }
-
   if (initialized)
     {
       if (! toplevel_bindings_p ()
@@ -7630,6 +7619,7 @@ grokfndecl (tree ctype,
 	    int friendp,
 	    int publicp,
 	    int inlinep,
+	    bool deletedp,
 	    special_function_kind sfk,
 	    bool funcdef_flag,
 	    int template_count,
@@ -7768,6 +7758,9 @@ grokfndecl (tree ctype,
       DECL_CONTEXT (decl) = ctype;
     }
 
+  if (deletedp)
+    DECL_DELETED_FN (decl) = 1;
+
   if (ctype)
     {
       DECL_CONTEXT (decl) = ctype;
@@ -10756,7 +10749,7 @@ grokdeclarator (const cp_declarator *declarator,
 			       virtualp, flags, memfn_quals, rqual, raises,
 			       friendp ? -1 : 0, friendp, publicp,
                                inlinep | (2 * constexpr_p),
-			       sfk,
+			       initialized == SD_DELETED, sfk,
 			       funcdef_flag, template_count, in_namespace,
 			       attrlist, declarator->id_loc);
             decl = set_virt_specifiers (decl, virt_specifiers);
@@ -10978,7 +10971,8 @@ grokdeclarator (const cp_declarator *declarator,
 	decl = grokfndecl (ctype, type, original_name, parms, unqualified_id,
 			   virtualp, flags, memfn_quals, rqual, raises,
 			   1, friendp,
-			   publicp, inlinep | (2 * constexpr_p), sfk,
+			   publicp, inlinep | (2 * constexpr_p),
+			   initialized == SD_DELETED, sfk,
                            funcdef_flag,
 			   template_count, in_namespace, attrlist,
 			   declarator->id_loc);
Index: testsuite/g++.dg/cpp0x/deleted10.C
===================================================================
--- testsuite/g++.dg/cpp0x/deleted10.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/deleted10.C	(working copy)
@@ -0,0 +1,15 @@
+// PR c++/60753
+// { dg-do compile { target c++11 } }
+
+template<class T> void foo (T);
+
+template<> void foo<int> (int);
+template<> void foo<int> (int) = delete;     // { dg-error "deleted" }
+
+struct S
+{
+  template<class T> void bar (T);
+};
+
+template<> void S::bar<int> (int);
+template<> void S::bar<int> (int) = delete;  // { dg-error "deleted" }


More information about the Gcc-patches mailing list