Hi,
Daniel, while working on the SFINAE-friendly std::result_of, noticed one
more SFINAE bug: we weren't propagating complain from
tsubst_copy_and_build via build_offset_ref_call_from_tree. Fixed the
usual way.
Tested x86_64-linux.
Thanks,
Paolo.
///////////////////////////
/cp
2012-09-28 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/54738
* decl2.c (build_offset_ref_call_from_tree): Add tsubst_flags_t
parameter.
* pt.c (tsubst_copy_and_build): Adjust.
* parser.c (cp_parser_postfix_expression): Likewise.
* cp-tree.h: Adjust declaration.
/testsuite
2012-09-28 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/54738
* g++.dg/cpp0x/sfinae42.C: New.
Index: cp/pt.c
===================================================================
--- cp/pt.c (revision 191843)
+++ cp/pt.c (working copy)
@@ -13783,7 +13783,8 @@ tsubst_copy_and_build (tree t,
mark_used (function);
if (TREE_CODE (function) == OFFSET_REF)
- ret = build_offset_ref_call_from_tree (function, &call_args);
+ ret = build_offset_ref_call_from_tree (function, &call_args,
+ complain);
else if (TREE_CODE (function) == COMPONENT_REF)
{
tree instance = TREE_OPERAND (function, 0);
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 191843)
+++ cp/parser.c (working copy)
@@ -5749,7 +5749,8 @@ cp_parser_postfix_expression (cp_parser *parser, b
|| TREE_CODE (postfix_expression) == MEMBER_REF
|| TREE_CODE (postfix_expression) == DOTSTAR_EXPR)
postfix_expression = (build_offset_ref_call_from_tree
- (postfix_expression, &args));
+ (postfix_expression, &args,
+ tf_warning_or_error));
else if (idk == CP_ID_KIND_QUALIFIED)
/* A call to a static class member, or a namespace-scope
function. */
Index: cp/cp-tree.h
===================================================================
--- cp/cp-tree.h (revision 191843)
+++ cp/cp-tree.h (working copy)
@@ -5149,7 +5149,8 @@ extern void determine_visibility (tree);
extern void constrain_class_visibility (tree);
extern void import_export_decl (tree);
extern tree build_cleanup (tree);
-extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **);
+extern tree build_offset_ref_call_from_tree (tree, VEC(tree,gc) **,
+ tsubst_flags_t);
extern bool decl_constant_var_p (tree);
extern bool decl_maybe_constant_var_p (tree);
extern void check_default_args (tree);
Index: cp/decl2.c
===================================================================
--- cp/decl2.c (revision 191843)
+++ cp/decl2.c (working copy)
@@ -4087,7 +4087,8 @@ cp_write_global_declarations (void)
ARGS. */
tree
-build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args)
+build_offset_ref_call_from_tree (tree fn, VEC(tree,gc) **args,
+ tsubst_flags_t complain)
{
tree orig_fn;
VEC(tree,gc) *orig_args = NULL;
@@ -4115,7 +4116,7 @@ tree
if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE)
{
if (TREE_CODE (fn) == DOTSTAR_EXPR)
- object = cp_build_addr_expr (object, tf_warning_or_error);
+ object = cp_build_addr_expr (object, complain);
VEC_safe_insert (tree, gc, *args, 0, object);
}
/* Now that the arguments are done, transform FN. */
@@ -4130,17 +4131,17 @@ tree
void B::g() { (this->*p)(); } */
if (TREE_CODE (fn) == OFFSET_REF)
{
- tree object_addr = cp_build_addr_expr (object, tf_warning_or_error);
+ tree object_addr = cp_build_addr_expr (object, complain);
fn = TREE_OPERAND (fn, 1);
fn = get_member_function_from_ptrfunc (&object_addr, fn,
- tf_warning_or_error);
+ complain);
VEC_safe_insert (tree, gc, *args, 0, object_addr);
}
if (CLASS_TYPE_P (TREE_TYPE (fn)))
- expr = build_op_call (fn, args, tf_warning_or_error);
+ expr = build_op_call (fn, args, complain);
else
- expr = cp_build_function_call_vec (fn, args, tf_warning_or_error);
+ expr = cp_build_function_call_vec (fn, args, complain);
if (processing_template_decl && expr != error_mark_node)
expr = build_min_non_dep_call_vec (expr, orig_fn, orig_args);
Index: testsuite/g++.dg/cpp0x/sfinae42.C
===================================================================
--- testsuite/g++.dg/cpp0x/sfinae42.C (revision 0)
+++ testsuite/g++.dg/cpp0x/sfinae42.C (working copy)
@@ -0,0 +1,46 @@
+// PR c++/54738
+// { dg-do compile { target c++11 } }
+
+template<class T>
+T&& declval();
+
+template<class F, class T1, class... Ts>
+decltype(((*declval<T1>()).*declval<F>())(declval<Ts>()...))
+test1(int);
+
+template<class...>
+void test1(...);
+
+template<class F, class T1, class... Ts>
+decltype((declval<T1>().*declval<F>())(declval<Ts>()...))
+test2(int);
+
+template<class...>
+void test2(...);
+
+struct S {};
+
+typedef void (S::*Func)(int) const;
+typedef void (S::*Func2)(int);
+
+typedef decltype(test1<Func, S*>(0)) type1a;
+typedef decltype(test1<Func, S*&>(0)) type1b;
+typedef decltype(test1<Func, S*, int, int>(0)) type1c;
+typedef decltype(test1<Func, S*&, int, int>(0)) type1d;
+
+typedef decltype(test2<Func, S>(0)) type2a;
+typedef decltype(test2<Func, S&>(0)) type2b;
+typedef decltype(test2<Func, S, int, int>(0)) type2c;
+typedef decltype(test2<Func, S&, int, int>(0)) type2d;
+
+typedef decltype(test1<Func, S*, S>(0)) type3a;
+typedef decltype(test1<Func, S*&, S>(0)) type3b;
+
+typedef decltype(test2<Func, S, S>(0)) type4a;
+typedef decltype(test2<Func, S&, S>(0)) type4b;
+
+typedef decltype(test1<Func2, const S*, int>(0)) type5a;
+typedef decltype(test1<Func2, const S*&, int>(0)) type5b;
+
+typedef decltype(test2<Func2, const S, int>(0)) type6a;
+typedef decltype(test2<Func2, const S&, int>(0)) type6b;