A call that is the immediate operand of decltype has special semantics: no temporary is produced, so it's OK for the return type to be e.g. incomplete. But we were treating (e | f) the same way, which confused overload resolution when we then tried to evaluate ... | g.
Fixed by making build_temp do what its name says, and force the C++17 temporary materialization conversion. We could also handle this by making sure that tf_decltype is only set when appropriate, but we keep finding more cases where we aren't getting that right yet, and the approach of this patch is more consistent with the C++17 model. Tested x86_64-pc-linux-gnu, applying to trunk. gcc/cp/ChangeLog: PR c++/95675 * call.c (build_temp): Wrap a CALL_EXPR in a TARGET_EXPR if it didn't get one before. gcc/testsuite/ChangeLog: PR c++/95675 * g++.dg/cpp0x/decltype-call5.C: New test. * g++.dg/cpp0x/decltype-call6.C: New test. --- gcc/cp/call.c | 8 ++++++++ gcc/testsuite/g++.dg/cpp0x/decltype-call5.C | 7 +++++++ gcc/testsuite/g++.dg/cpp0x/decltype-call6.C | 12 ++++++++++++ 3 files changed, 27 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-call5.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/decltype-call6.C diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 0ba0e19ae08..b00334d0919 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -7291,6 +7291,14 @@ build_temp (tree expr, tree type, int flags, && !type_has_nontrivial_copy_init (TREE_TYPE (expr))) return get_target_expr_sfinae (expr, complain); + /* In decltype, we might have decided not to wrap this call in a TARGET_EXPR. + But it turns out to be a subexpression, so perform temporary + materialization now. */ + if (TREE_CODE (expr) == CALL_EXPR + && CLASS_TYPE_P (type) + && same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (expr))) + expr = build_cplus_new (type, expr, complain); + savew = warningcount + werrorcount, savee = errorcount; releasing_vec args (make_tree_vector_single (expr)); expr = build_special_member_call (NULL_TREE, complete_ctor_identifier, diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call5.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call5.C new file mode 100644 index 00000000000..81ef6e6f9c9 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call5.C @@ -0,0 +1,7 @@ +// PR c++/95675 +// { dg-do compile { target c++11 } } + +struct b {}; +b operator|(b, b) { return {}; } +b e, f, g; +using h = decltype(e | f | g); diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype-call6.C b/gcc/testsuite/g++.dg/cpp0x/decltype-call6.C new file mode 100644 index 00000000000..4173b607689 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/decltype-call6.C @@ -0,0 +1,12 @@ +// PR c++/95675 +// { dg-do compile { target c++11 } } + +struct a {}; +template <typename> struct b; +template <typename bq, typename br> struct b<bq(br)> { + decltype(bq()(br())) c; +}; +struct e { + operator a(); +}; +b<e (*(e))(a)> d; base-commit: f1b13064609a41fcaf4d1859663453bba237e277 -- 2.27.0