This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/44967 (sfinae and variadic templates)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 20 Jul 2010 14:22:44 -0400
- Subject: C++ PATCH for c++/44967 (sfinae and variadic templates)
This testcase was running into problems because we were effectively
assuming that when we tsubst into a CALL_EXPR we're producing a
non-dependent result. This is not the case in this testcase, where we
do a partial substitution of the explicit template args but can deduce
more from the function arguments.
Fixed by adding early exit as in cp_parser_postfix_expression.
Tested x86_64-pc-linux-gnu, applied to trunk.
2010-07-20 Jason Merrill <jason@redhat.com>
PR c++/44967
* pt.c (tsubst_copy_and_build): Rework last change.
PR c++/44967
* pt.c (tsubst_copy_and_build): Handle partial substitution of
CALL_EXPR.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0ccd8d9..b618907 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -12531,15 +12531,24 @@ tsubst_copy_and_build (tree t,
ret = build_offset_ref_call_from_tree (function, &call_args);
else if (TREE_CODE (function) == COMPONENT_REF)
{
- if (!BASELINK_P (TREE_OPERAND (function, 1)))
+ tree instance = TREE_OPERAND (function, 0);
+ tree fn = TREE_OPERAND (function, 1);
+
+ if (processing_template_decl
+ && (type_dependent_expression_p (instance)
+ || (!BASELINK_P (fn)
+ && TREE_CODE (fn) != FIELD_DECL)
+ || type_dependent_expression_p (fn)
+ || any_type_dependent_arguments_p (call_args)))
+ ret = build_nt_call_vec (function, call_args);
+ else if (!BASELINK_P (fn))
ret = finish_call_expr (function, &call_args,
/*disallow_virtual=*/false,
/*koenig_p=*/false,
complain);
else
ret = (build_new_method_call
- (TREE_OPERAND (function, 0),
- TREE_OPERAND (function, 1),
+ (instance, fn,
&call_args, NULL_TREE,
qualified_p ? LOOKUP_NONVIRTUAL : LOOKUP_NORMAL,
/*fn_p=*/NULL,
diff --git a/gcc/testsuite/g++.dg/cpp0x/sfinae2.C b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C
new file mode 100644
index 0000000..b9ef70d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/sfinae2.C
@@ -0,0 +1,39 @@
+// PR c++/44967
+// { dg-options -std=c++0x }
+
+template <typename T> T&& declval();
+
+template<typename T1, typename T2, typename... Args>
+struct has_construct
+{
+ typedef char one;
+ typedef struct {char _m[2]; } two;
+
+ template<typename U1, typename U2, typename... Args2>
+ static decltype(declval<U1>().construct(declval<U2*>(), declval<Args2>()...), one()) test(int);
+ template<typename, typename, typename...>
+ static two test(...);
+
+ static const bool value = sizeof(test<T1, T2, Args...>(0)) == 1;
+};
+
+
+struct A0
+{};
+
+struct A1
+{
+ void construct(int*, int);
+};
+
+template<typename _Tp>
+struct A2
+{
+ template<typename _Tp1, typename... _Args>
+ void construct(_Tp1*, _Args&&...) {}
+};
+
+#define SA(X) static_assert(X,#X)
+SA((!has_construct<A0, int, int>::value)); // ok
+SA((has_construct<A1, int, int>::value)); // bang
+SA((has_construct<A2<int>, int>::value)); // bang