From patchwork Thu Jul 13 13:03:48 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 787714 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3x7bcn0b6sz9s4q for ; Thu, 13 Jul 2017 23:04:24 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="tMhs+8U9"; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; q= dns; s=default; b=fJf+ChuGrIAKfq43ML7g86KwVPXBGXnjjq22OmUz0MoVCa Onb5iE5oG8ughMvvRilG0e51zO6LEKNYBN6KbH5IUPwUd4onvphadcfGjnfuXhFZ RMcmJzNqiEhCw4vsMlNIj58FcethVf/4LplrGgBpWBmh7fyXtVLRHyiodjnyY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:from:date:message-id:subject:to:content-type; s= default; bh=fwtAdNji3W+CCifKUBJitgaDuSw=; b=tMhs+8U9gX5MeGqTh0RE 2lL1bQQO/QfBrb7K4JJw5Y7RLettew0gPsTGAuRniPpiRNSoXtUQl3Rd+C1Mxb4L expuz5CEovgiJfGgX22p+pbqVvB0wgw1Bkx7naF0sYx+nk9DHI8Q+xiSN17ZNz7Z a9ZKcwocw8L4ynhWOdK91Ag= Received: (qmail 106461 invoked by alias); 13 Jul 2017 13:04:14 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 105244 invoked by uid 89); 13 Jul 2017 13:04:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM autolearn=ham version=3.3.2 spammy=tt X-HELO: mail-it0-f51.google.com Received: from mail-it0-f51.google.com (HELO mail-it0-f51.google.com) (209.85.214.51) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 13 Jul 2017 13:04:11 +0000 Received: by mail-it0-f51.google.com with SMTP id k192so43929804ith.1 for ; Thu, 13 Jul 2017 06:04:11 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=7m+52zsv41CAnkJULNIMxpX58GesG+uYCV2c7V8PbJY=; b=BTYc9Cg2MRkc4W4vumEmQeD8wFTaSdI149I8qv8/8qALWOalrGQ5Gf54833gwndBQ6 nXN6fv59mqQFtXY3lWfLk65wD8eeei3EU1uOt2xDlY1jr2wMsgz2UApQm/2/NvLRFjwh 0k0OPwZMIpDryXmKfY27sWPrX6yM8AqndQ/4gzM/XB0fyPPXsja86EmFu0PesBRW4Tp/ 1/283a61t5WD51q+sKKyvMc76R6Gg9xLU1kl/yqhVx5ec+nZbSrb5eFcezGz8eMJQ6Cz OdEe7LioFuzhkZW2hzbMbtYIXuUgJNGde7IAAL93zwnOWJ9Hnhx0SOD5o5vCAUI5Dvsy VmHQ== X-Gm-Message-State: AIVw112dk4I6WdAC6ODC3f8qT+lR85IWUEI+8HfzNw0kOhjqr331EQwg BGP9+QVVFqpt/FyKLt3dgl4d6JM1O4XNcgXYUA== X-Received: by 10.36.107.80 with SMTP id v77mr25963879itc.4.1499951049251; Thu, 13 Jul 2017 06:04:09 -0700 (PDT) MIME-Version: 1.0 Received: by 10.107.11.105 with HTTP; Thu, 13 Jul 2017 06:03:48 -0700 (PDT) From: Jason Merrill Date: Thu, 13 Jul 2017 09:03:48 -0400 Message-ID: Subject: C++ PATCH to C++17 class deduction from init-list To: gcc-patches List X-IsSubscribed: yes P0512 corrected the specification of C++17 class template argument deduction to work more like constructor overload resolution in initialization; in particular, this means that we should do the same two-phase overload resolution for a class with a list constructor. This patch implements that, so that e.g. #include int a[1]; std::vector v{a, a, std::allocator()}; will now work. Tested x86_64-pc-linux-gnu, applying to trunk. commit 7cede2ad071dbd7ab1f174465305e5568b5d311a Author: Jason Merrill Date: Wed Jul 12 12:53:23 2017 -0400 P0512R0 - Deduction from an initializer list. * pt.c (do_class_deduction): Do list deduction in two phases. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index bd02951..0df6854 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -25329,14 +25329,20 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, tree type = TREE_TYPE (tmpl); + bool try_list_ctor = false; + vec *args; if (init == NULL_TREE || TREE_CODE (init) == TREE_LIST) args = make_tree_vector_from_list (init); - else if (BRACE_ENCLOSED_INITIALIZER_P (init) - && !TYPE_HAS_LIST_CTOR (type) - && !is_std_init_list (type)) - args = make_tree_vector_from_ctor (init); + else if (BRACE_ENCLOSED_INITIALIZER_P (init)) + { + try_list_ctor = TYPE_HAS_LIST_CTOR (type); + if (try_list_ctor || is_std_init_list (type)) + args = make_tree_vector_single (init); + else + args = make_tree_vector_from_ctor (init); + } else args = make_tree_vector_single (init); @@ -25391,13 +25397,43 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, saw_ctor = true; } - if (args->length () < 2) + tree call = error_mark_node; + + /* If this is list-initialization and the class has a list constructor, first + try deducing from the list as a single argument, as [over.match.list]. */ + tree list_cands = NULL_TREE; + if (try_list_ctor && cands) + for (lkp_iterator iter (cands); iter; ++iter) + { + tree dg = *iter; + if (is_list_ctor (dg)) + list_cands = lookup_add (dg, list_cands); + } + if (list_cands) + { + ++cp_unevaluated_operand; + call = build_new_function_call (list_cands, &args, tf_decltype); + --cp_unevaluated_operand; + + if (call == error_mark_node) + { + /* That didn't work, now try treating the list as a sequence of + arguments. */ + release_tree_vector (args); + args = make_tree_vector_from_ctor (init); + } + } + + /* Maybe generate an implicit deduction guide. */ + if (call == error_mark_node && args->length () < 2) { tree gtype = NULL_TREE; if (args->length () == 1) + /* Generate a copy guide. */ gtype = build_reference_type (type); else if (!saw_ctor) + /* Generate a default guide. */ gtype = type; if (gtype) @@ -25419,22 +25455,29 @@ do_class_deduction (tree ptype, tree tmpl, tree init, int flags, return error_mark_node; } - ++cp_unevaluated_operand; - tree t = build_new_function_call (cands, &args, tf_decltype); + if (call == error_mark_node) + { + ++cp_unevaluated_operand; + call = build_new_function_call (cands, &args, tf_decltype); + --cp_unevaluated_operand; + } - if (t == error_mark_node && (complain & tf_warning_or_error)) + if (call == error_mark_node && (complain & tf_warning_or_error)) { error ("class template argument deduction failed:"); - t = build_new_function_call (cands, &args, complain | tf_decltype); + + ++cp_unevaluated_operand; + call = build_new_function_call (cands, &args, complain | tf_decltype); + --cp_unevaluated_operand; + if (elided) inform (input_location, "explicit deduction guides not considered " "for copy-initialization"); } - --cp_unevaluated_operand; release_tree_vector (args); - return cp_build_qualified_type (TREE_TYPE (t), cp_type_quals (ptype)); + return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype)); } /* Replace occurrences of 'auto' in TYPE with the appropriate type deduced diff --git a/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C new file mode 100644 index 0000000..5e7fa3a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/class-deduction41.C @@ -0,0 +1,19 @@ +// { dg-options -std=c++1z } + +#include + +struct B { }; + +template +struct A +{ + A(std::initializer_list); + A(T, B); +}; + +A a { 1, B() }; + +template struct same; +template struct same { }; + +same> s;