Commit e2e03032 by Paolo Carlini Committed by Paolo Carlini

re PR c++/54541 (SFINAE bug: handling incomplete return types)

/cp
2012-09-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54541
	PR c++/54542
	* call.c (build_cxx_call): Add tsubst_flags_t parameter, use
	require_complete_type_sfinae.
	(build_op_delete_call, build_over_call): Adjust.
	* typeck.c (build_x_compound_expr_from_vec): Add tsubst_flags_t
	parameter.
	(cp_build_function_call_vec): Adjust.
	* init.c (build_new_1): Likewise.
	* rtti.c (throw_bad_cast, throw_bad_typeid, build_dynamic_cast_1):
	Likewise.
	* optimize.c (build_delete_destructor_body): Likewise.
	* cp-tree.h: Adjust declarations.

	* call.c (convert_arg_to_ellipsis): Use require_complete_type_sfinae.

/testsuite
2012-09-10  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/54541
	PR c++/54542
	* g++.dg/cpp0x/sfinae40.C: New.
	* g++.dg/cpp0x/sfinae41.C: Likewise.

From-SVN: r191170
parent f0bdc1d2
2012-09-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54541
PR c++/54542
* call.c (build_cxx_call): Add tsubst_flags_t parameter, use
require_complete_type_sfinae.
(build_op_delete_call, build_over_call): Adjust.
* typeck.c (build_x_compound_expr_from_vec): Add tsubst_flags_t
parameter.
(cp_build_function_call_vec): Adjust.
* init.c (build_new_1): Likewise.
* rtti.c (throw_bad_cast, throw_bad_typeid, build_dynamic_cast_1):
Likewise.
* optimize.c (build_delete_destructor_body): Likewise.
* cp-tree.h: Adjust declarations.
* call.c (convert_arg_to_ellipsis): Use require_complete_type_sfinae.
2012-09-10 Jason Merrill <jason@redhat.com> 2012-09-10 Jason Merrill <jason@redhat.com>
PR c++/54538 PR c++/54538
...@@ -18,7 +36,7 @@ ...@@ -18,7 +36,7 @@
* decl.c (reshape_init_class): Avoid dereferencing a * decl.c (reshape_init_class): Avoid dereferencing a
past-the-end pointer. past-the-end pointer.
2012-09-07 Paolo Carlini <paolo.carlini@oracle.com> 2012-09-07 Paolo Carlini <paolo.carlini@oracle.com>
* pt.c (num_template_headers_for_class): Rework per the code * pt.c (num_template_headers_for_class): Rework per the code
......
...@@ -5525,7 +5525,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size, ...@@ -5525,7 +5525,7 @@ build_op_delete_call (enum tree_code code, tree addr, tree size,
for (i = 1; i < nargs; i++) for (i = 1; i < nargs; i++)
argarray[i] = CALL_EXPR_ARG (placement, i); argarray[i] = CALL_EXPR_ARG (placement, i);
mark_used (fn); mark_used (fn);
return build_cxx_call (fn, nargs, argarray); return build_cxx_call (fn, nargs, argarray, complain);
} }
else else
{ {
...@@ -6127,12 +6127,12 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain) ...@@ -6127,12 +6127,12 @@ convert_arg_to_ellipsis (tree arg, tsubst_flags_t complain)
arg = cp_perform_integral_promotions (arg, complain); arg = cp_perform_integral_promotions (arg, complain);
} }
arg = require_complete_type (arg); arg = require_complete_type_sfinae (arg, complain);
arg_type = TREE_TYPE (arg); arg_type = TREE_TYPE (arg);
if (arg != error_mark_node if (arg != error_mark_node
/* In a template (or ill-formed code), we can have an incomplete type /* In a template (or ill-formed code), we can have an incomplete type
even after require_complete_type, in which case we don't know even after require_complete_type_sfinae, in which case we don't know
whether it has trivial copy or not. */ whether it has trivial copy or not. */
&& COMPLETE_TYPE_P (arg_type)) && COMPLETE_TYPE_P (arg_type))
{ {
...@@ -6882,7 +6882,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -6882,7 +6882,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
return error_mark_node; return error_mark_node;
} }
return build_cxx_call (fn, nargs, argarray); return build_cxx_call (fn, nargs, argarray, complain);
} }
/* Build and return a call to FN, using NARGS arguments in ARGARRAY. /* Build and return a call to FN, using NARGS arguments in ARGARRAY.
...@@ -6890,7 +6890,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) ...@@ -6890,7 +6890,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
high-level operations. */ high-level operations. */
tree tree
build_cxx_call (tree fn, int nargs, tree *argarray) build_cxx_call (tree fn, int nargs, tree *argarray,
tsubst_flags_t complain)
{ {
tree fndecl; tree fndecl;
int optimize_sav; int optimize_sav;
...@@ -6923,12 +6924,12 @@ build_cxx_call (tree fn, int nargs, tree *argarray) ...@@ -6923,12 +6924,12 @@ build_cxx_call (tree fn, int nargs, tree *argarray)
if (VOID_TYPE_P (TREE_TYPE (fn))) if (VOID_TYPE_P (TREE_TYPE (fn)))
return fn; return fn;
fn = require_complete_type (fn); fn = require_complete_type_sfinae (fn, complain);
if (fn == error_mark_node) if (fn == error_mark_node)
return error_mark_node; return error_mark_node;
if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn))) if (MAYBE_CLASS_TYPE_P (TREE_TYPE (fn)))
fn = build_cplus_new (TREE_TYPE (fn), fn, tf_warning_or_error); fn = build_cplus_new (TREE_TYPE (fn), fn, complain);
return convert_from_reference (fn); return convert_from_reference (fn);
} }
......
...@@ -4918,7 +4918,8 @@ extern tree build_integral_nontype_arg_conv (tree, tree, tsubst_flags_t); ...@@ -4918,7 +4918,8 @@ extern tree build_integral_nontype_arg_conv (tree, tree, tsubst_flags_t);
extern tree perform_direct_initialization_if_possible (tree, tree, bool, extern tree perform_direct_initialization_if_possible (tree, tree, bool,
tsubst_flags_t); tsubst_flags_t);
extern tree in_charge_arg_for_name (tree); extern tree in_charge_arg_for_name (tree);
extern tree build_cxx_call (tree, int, tree *); extern tree build_cxx_call (tree, int, tree *,
tsubst_flags_t);
extern bool is_std_init_list (tree); extern bool is_std_init_list (tree);
extern bool is_list_ctor (tree); extern bool is_list_ctor (tree);
#ifdef ENABLE_CHECKING #ifdef ENABLE_CHECKING
...@@ -5851,7 +5852,8 @@ extern tree build_x_conditional_expr (location_t, tree, tree, tree, ...@@ -5851,7 +5852,8 @@ extern tree build_x_conditional_expr (location_t, tree, tree, tree,
tsubst_flags_t); tsubst_flags_t);
extern tree build_x_compound_expr_from_list (tree, expr_list_kind, extern tree build_x_compound_expr_from_list (tree, expr_list_kind,
tsubst_flags_t); tsubst_flags_t);
extern tree build_x_compound_expr_from_vec (VEC(tree,gc) *, const char *); extern tree build_x_compound_expr_from_vec (VEC(tree,gc) *, const char *,
tsubst_flags_t);
extern tree build_x_compound_expr (location_t, tree, tree, extern tree build_x_compound_expr (location_t, tree, tree,
tsubst_flags_t); tsubst_flags_t);
extern tree build_compound_expr (location_t, tree, tree); extern tree build_compound_expr (location_t, tree, tree);
......
...@@ -2739,7 +2739,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts, ...@@ -2739,7 +2739,8 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree nelts,
/* We are processing something like `new int (10)', which /* We are processing something like `new int (10)', which
means allocate an int, and initialize it with 10. */ means allocate an int, and initialize it with 10. */
ie = build_x_compound_expr_from_vec (*init, "new initializer"); ie = build_x_compound_expr_from_vec (*init, "new initializer",
complain);
init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie, init_expr = cp_build_modify_expr (init_expr, INIT_EXPR, ie,
complain); complain);
} }
......
...@@ -128,7 +128,8 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor) ...@@ -128,7 +128,8 @@ build_delete_destructor_body (tree delete_dtor, tree complete_dtor)
/* Call the corresponding complete destructor. */ /* Call the corresponding complete destructor. */
gcc_assert (complete_dtor); gcc_assert (complete_dtor);
call_dtor = build_cxx_call (complete_dtor, 1, &parm); call_dtor = build_cxx_call (complete_dtor, 1, &parm,
tf_warning_or_error);
add_stmt (call_dtor); add_stmt (call_dtor);
add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label)); add_stmt (build_stmt (0, LABEL_EXPR, cdtor_label));
......
...@@ -206,7 +206,7 @@ throw_bad_cast (void) ...@@ -206,7 +206,7 @@ throw_bad_cast (void)
fn = push_throw_library_fn (fn, build_function_type_list (ptr_type_node, fn = push_throw_library_fn (fn, build_function_type_list (ptr_type_node,
NULL_TREE)); NULL_TREE));
return build_cxx_call (fn, 0, NULL); return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
} }
/* Return an expression for "__cxa_bad_typeid()". The expression /* Return an expression for "__cxa_bad_typeid()". The expression
...@@ -225,7 +225,7 @@ throw_bad_typeid (void) ...@@ -225,7 +225,7 @@ throw_bad_typeid (void)
fn = push_throw_library_fn (fn, t); fn = push_throw_library_fn (fn, t);
} }
return build_cxx_call (fn, 0, NULL); return build_cxx_call (fn, 0, NULL, tf_warning_or_error);
} }
/* Return an lvalue expression whose type is "const std::type_info" /* Return an lvalue expression whose type is "const std::type_info"
...@@ -743,7 +743,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain) ...@@ -743,7 +743,7 @@ build_dynamic_cast_1 (tree type, tree expr, tsubst_flags_t complain)
pop_abi_namespace (); pop_abi_namespace ();
dynamic_cast_node = dcast_fn; dynamic_cast_node = dcast_fn;
} }
result = build_cxx_call (dcast_fn, 4, elems); result = build_cxx_call (dcast_fn, 4, elems, complain);
if (tc == REFERENCE_TYPE) if (tc == REFERENCE_TYPE)
{ {
......
...@@ -3373,7 +3373,7 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params, ...@@ -3373,7 +3373,7 @@ cp_build_function_call_vec (tree function, VEC(tree,gc) **params,
null parameters. */ null parameters. */
check_function_arguments (fntype, nargs, argarray); check_function_arguments (fntype, nargs, argarray);
ret = build_cxx_call (function, nargs, argarray); ret = build_cxx_call (function, nargs, argarray, complain);
if (allocated != NULL) if (allocated != NULL)
release_tree_vector (allocated); release_tree_vector (allocated);
...@@ -5719,7 +5719,8 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp, ...@@ -5719,7 +5719,8 @@ build_x_compound_expr_from_list (tree list, expr_list_kind exp,
/* Like build_x_compound_expr_from_list, but using a VEC. */ /* Like build_x_compound_expr_from_list, but using a VEC. */
tree tree
build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg) build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg,
tsubst_flags_t complain)
{ {
if (VEC_empty (tree, vec)) if (VEC_empty (tree, vec))
return NULL_TREE; return NULL_TREE;
...@@ -5732,14 +5733,19 @@ build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg) ...@@ -5732,14 +5733,19 @@ build_x_compound_expr_from_vec (VEC(tree,gc) *vec, const char *msg)
tree t; tree t;
if (msg != NULL) if (msg != NULL)
permerror (input_location, {
"%s expression list treated as compound expression", if (complain & tf_error)
msg); permerror (input_location,
"%s expression list treated as compound expression",
msg);
else
return error_mark_node;
}
expr = VEC_index (tree, vec, 0); expr = VEC_index (tree, vec, 0);
for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix) for (ix = 1; VEC_iterate (tree, vec, ix, t); ++ix)
expr = build_x_compound_expr (EXPR_LOCATION (t), expr, expr = build_x_compound_expr (EXPR_LOCATION (t), expr,
t, tf_warning_or_error); t, complain);
return expr; return expr;
} }
......
2012-09-10 Paolo Carlini <paolo.carlini@oracle.com>
PR c++/54541
PR c++/54542
* g++.dg/cpp0x/sfinae40.C: New.
* g++.dg/cpp0x/sfinae41.C: Likewise.
2012-09-10 Jason Merrill <jason@redhat.com> 2012-09-10 Jason Merrill <jason@redhat.com>
PR c++/54538 PR c++/54538
......
// PR c++/54541
// { dg-do compile { target c++11 } }
template <typename T> T&& declval();
struct X;
X f(int);
template <class T>
void g(decltype((void)f(declval<T>())) *)
{}
template <class T>
void g(...)
{}
int main()
{
g<int>(0);
}
// PR c++/54542
// { dg-do compile { target c++11 } }
template <class T>
void f(decltype(new T(1, 2)) *)
{
T(1, 2);
}
template <class T>
void f(...)
{}
int main()
{
f<int>(0);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment