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.
commit d84445fd99912ad25589975f3d5f2fadb08ff9f6
Author: Jason Merrill <ja...@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;