diff mbox

C++ PATCH for c++/52748 (N3276 change to decltype of function call)

Message ID 51548981.4090708@redhat.com
State New
Headers show

Commit Message

Jason Merrill March 28, 2013, 6:18 p.m. UTC
The change to force instantiation to check for abstract return types 
broke this change; until the core SG has a chance to discuss the 
language inconsistency, I'm going to disable that instantiation in 
decltype context.

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

Patch

commit d84445fd99912ad25589975f3d5f2fadb08ff9f6
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 28 11:21:47 2013 -0400

    	PR c++/17232
    	PR c++/52748
    	* typeck2.c (abstract_virtuals_error_sfinae): Don't complete
    	the type if tf_decltype is set.
    	* pt.c (fn_type_unification): Add decltype_p parm.
    	(get_bindings): Adjust.
    	* cp-tree.h: Adjust.
    	* class.c (resolve_address_of_overloaded_function): Adjust.
    	* call.c (add_template_candidate_real, print_z_candidate): Adjust.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cff653f..ba3de10 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -2905,7 +2905,8 @@  add_template_candidate_real (struct z_candidate **candidates, tree tmpl,
   fn = fn_type_unification (tmpl, explicit_targs, targs,
 			    args_without_in_chrg,
 			    nargs_without_in_chrg,
-			    return_type, strict, flags, false);
+			    return_type, strict, flags, false,
+			    complain & tf_decltype);
 
   if (fn == error_mark_node)
     {
@@ -3221,7 +3222,7 @@  print_z_candidate (location_t loc, const char *msgstr,
 			       r->u.template_unification.return_type,
 			       r->u.template_unification.strict,
 			       r->u.template_unification.flags,
-			       true);
+			       true, false);
 	  break;
 	case rr_invalid_copy:
 	  inform (cloc,
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index b48b353..956d5aa 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -7253,7 +7253,7 @@  resolve_address_of_overloaded_function (tree target_type,
 	  instantiation = fn_type_unification (fn, explicit_targs, targs, args,
 					      nargs, target_ret_type,
 					      DEDUCE_EXACT, LOOKUP_NORMAL,
-					       false);
+					       false, false);
 	  if (instantiation == error_mark_node)
 	    /* Instantiation failed.  */
 	    continue;
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 36671d5..4e60946 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -5419,7 +5419,7 @@  extern tree instantiate_template		(tree, tree, tsubst_flags_t);
 extern tree fn_type_unification			(tree, tree, tree,
 						 const tree *, unsigned int,
 						 tree, unification_kind_t, int,
-						 bool);
+						 bool, bool);
 extern void mark_decl_instantiated		(tree, int);
 extern int more_specialized_fn			(tree, tree, int);
 extern void do_decl_instantiation		(tree, tree);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 59ecdcb..27e3ff8 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -14935,7 +14935,8 @@  fn_type_unification (tree fn,
 		     tree return_type,
 		     unification_kind_t strict,
 		     int flags,
-		     bool explain_p)
+		     bool explain_p,
+		     bool decltype_p)
 {
   tree parms;
   tree fntype;
@@ -14949,6 +14950,9 @@  fn_type_unification (tree fn,
   tree tinst;
   tree r = error_mark_node;
 
+  if (decltype_p)
+    complain |= tf_decltype;
+
   /* In C++0x, it's possible to have a function template whose type depends
      on itself recursively.  This is most obvious with decltype, but can also
      occur with enumeration scope (c++/48969).  So we need to catch infinite
@@ -17626,7 +17630,8 @@  get_bindings (tree fn, tree decl, tree explicit_args, bool check_rettype)
 			   args, ix,
 			   (check_rettype || DECL_CONV_FN_P (fn)
 			    ? TREE_TYPE (decl_type) : NULL_TREE),
-			   DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false)
+			   DEDUCE_EXACT, LOOKUP_NORMAL, /*explain_p=*/false,
+			   /*decltype*/false)
       == error_mark_node)
     return NULL_TREE;
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index 52bc4ec..cf42958 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -265,15 +265,15 @@  abstract_virtuals_error_sfinae (tree decl, tree type, abstract_class_use use,
     return 0;
   type = TYPE_MAIN_VARIANT (type);
 
-  /* In SFINAE context, force instantiation.  */
-  if (!(complain & tf_error))
+  /* In SFINAE, non-N3276 context, force instantiation.  */
+  if (!(complain & (tf_error|tf_decltype)))
     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
      name.  */
-  if (!COMPLETE_TYPE_P (type))
+  if (!COMPLETE_TYPE_P (type) && (complain & tf_error))
     {
       void **slot;
       struct pending_abstract_type *pat;
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call2.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call2.C
new file mode 100644
index 0000000..ad23220
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call2.C
@@ -0,0 +1,7 @@ 
+// PR c++/52748
+// We don't want to instantiate A<T> here.
+// { dg-require-effective-target c++11 }
+
+template <class T> struct A: T { };
+template <class T> A<T> f(T);
+decltype(f(42)) *p;