Patchwork C++ PATCH for c++/17232 (abstract class, array and sfinae)

login
register
mail settings
Submitter Jason Merrill
Date March 16, 2013, 7:38 p.m.
Message ID <5144CA1F.8060605@redhat.com>
Download mbox | patch
Permalink /patch/228247/
State New
Headers show

Comments

Jason Merrill - March 16, 2013, 7:38 p.m.
In SFINAE context, we need to instantiate a class so that we can tell 
whether or not is abstract.  Doing this in non-SFINAE context caused 
problems, so I've made it conditional.

Tested x86_64-pc-linux-gnu, applying to trunk.

Patch

commit 02d2b645f935749d9f860cba2fab05656edbbce7
Author: Jason Merrill <jason@redhat.com>
Date:   Wed Feb 27 12:35:12 2013 -0500

    	DR 337
    	PR c++/17232
    	* pt.c (tsubst) [ARRAY_TYPE]: Use abstract_virtuals_error_sfinae.
    	* typeck2.c (abstract_virtuals_error_sfinae): Call complete_type.

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index cad1c60..ce07fa4 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -11653,13 +11653,9 @@  tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
 	      error ("creating array of %qT", type);
 	    return error_mark_node;
 	  }
-	if (ABSTRACT_CLASS_TYPE_P (type))
-	  {
-	    if (complain & tf_error)
-	      error ("creating array of %qT, which is an abstract class type",
-		     type);
-	    return error_mark_node;
-	  }
+
+	if (abstract_virtuals_error_sfinae (NULL_TREE, type, complain))
+	  return error_mark_node;
 
 	r = build_cplus_array_type (type, domain);
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 0e8c921..37c42e2 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -258,6 +258,10 @@  abstract_virtuals_error_sfinae (tree decl, tree type, tsubst_flags_t complain)
     return 0;
   type = TYPE_MAIN_VARIANT (type);
 
+  /* In SFINAE context, force instantiation.  */
+  if (!(complain & tf_error))
+    complete_type (type);
+
   /* If the type is incomplete, we register it within a hash table,
      so that we can check again once it is completed. This makes sense
      only for objects for which we have a declaration or at least a
diff --git a/gcc/testsuite/g++.dg/template/abstract-dr337.C b/gcc/testsuite/g++.dg/template/abstract-dr337.C
new file mode 100644
index 0000000..de84f90
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/abstract-dr337.C
@@ -0,0 +1,13 @@ 
+// PR c++/17232 (DR 337)
+
+template<typename T>
+class A {
+  virtual void f() = 0;
+};
+
+template<typename T>
+void g(T (*a)[1]) {}		// { dg-error "abstract" }
+
+int main() {
+  g<A<int> >(0);  // { dg-error "no matching function" }
+}