From patchwork Tue Oct 20 02:08:53 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 532764 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 99C2C140180 for ; Tue, 20 Oct 2015 13:09:10 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=lQZfvild; 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:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=qvxIambcdX0hdLgTna5C00FiXnZJu6feurJey1hzQW8GphNb4W tlDJvnt9JFPvhTX3tIKw/rxcdRCMWCO45rxOL9xFuw8SboCrlARdvTMN/XYYY92i T4Q4xHIInPH4ygyjFOIuJMcedjh5M8z0IvS4re1y0fNHhKEMbBFlMR0u0= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=LfJ+h64Eip9XXd8v3Z8/Q26kLq0=; b=lQZfvild4OHoCziGIj6K 5J60eV3MI6oMnfSw5LKCT9yeMfx/MksdS/ljKjb71NQm6qIhLynq6UTxphb9Yd1Z AOlUBeDyS2+wR3iELkI5la+0BK7Iw2U46TaeJXR86CmF0xNiMYoDoLkaCVbCD59J 3Cu6E/rlQEjZP9EPD7PhGDU= Received: (qmail 51302 invoked by alias); 20 Oct 2015 02:09:01 -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 51002 invoked by uid 89); 20 Oct 2015 02:09:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.5 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=ham version=3.3.2 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Tue, 20 Oct 2015 02:08:58 +0000 Received: from int-mx11.intmail.prod.int.phx2.redhat.com (int-mx11.intmail.prod.int.phx2.redhat.com [10.5.11.24]) by mx1.redhat.com (Postfix) with ESMTPS id 999A68E716 for ; Tue, 20 Oct 2015 02:08:57 +0000 (UTC) Received: from [10.10.112.20] (ovpn-112-20.rdu2.redhat.com [10.10.112.20]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t9K28sjq020147 for ; Mon, 19 Oct 2015 22:08:56 -0400 To: gcc-patches List From: Jason Merrill Subject: C++ PATCH for N4268, constant evaluation of non-type template arguments Message-ID: <5625A235.5020800@redhat.com> Date: Mon, 19 Oct 2015 16:08:53 -1000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 N4268 is the last bullet point remaining for C++1z features until Saturday, when presumably more stuff will be added. The basic functionality is quite straightforward: first generalize parsing, then pass all arguments through maybe_constant_value. But to get correct handling of pointers to members, we need to prevent constexpr evaluation from lowering PTRMEM_CST until it's really needed, namely if we're trying to use one in a .* expression or we're handing off to the language-independent code. Tested x86_64-pc-linux-gnu, applying to trunk. commit fea6597952f6cb45b5751f1b2097a2092cb18b8d Author: Jason Merrill Date: Sun Oct 18 22:57:08 2015 -1000 Expand PTRMEM_CST only when necessary. * constexpr.c (cxx_eval_constant_expression): Expand PTRMEM_CST only when necessary. (cxx_eval_component_reference): Like here. * decl2.c (lower_var_init): And here. (c_parse_final_cleanups): Call it. * decl.c (complete_vars): Not here. * typeck2.c (digest_init_r): Or here. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 6619c42..dd27b99 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1873,6 +1873,8 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, tree whole = cxx_eval_constant_expression (ctx, orig_whole, lval, non_constant_p, overflow_p); + if (TREE_CODE (whole) == PTRMEM_CST) + whole = cplus_expand_constant (whole); if (whole == orig_whole) return t; if (lval) @@ -3139,9 +3141,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, } if (CONSTANT_CLASS_P (t)) { - if (TREE_CODE (t) == PTRMEM_CST) - t = cplus_expand_constant (t); - else if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet)) + if (TREE_OVERFLOW (t) && (!flag_permissive || ctx->quiet)) *overflow_p = true; return t; } @@ -3555,7 +3555,11 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, non_constant_p, overflow_p); if (*non_constant_p) return t; - if (POINTER_TYPE_P (TREE_TYPE (t)) + tree type = TREE_TYPE (t); + if (TREE_CODE (op) == PTRMEM_CST + && !TYPE_PTRMEM_P (type)) + op = cplus_expand_constant (op); + if (POINTER_TYPE_P (type) && TREE_CODE (op) == INTEGER_CST && !integer_zerop (op)) { @@ -3569,7 +3573,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, /* We didn't fold at the top so we could check for ptr-int conversion. */ return fold (t); - r = fold_build1 (TREE_CODE (t), TREE_TYPE (t), op); + r = fold_build1 (TREE_CODE (t), type, op); /* Conversion of an out-of-range value has implementation-defined behavior; the language considers it different from arithmetic overflow, which is undefined. */ diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 5716a13..50bb39c 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -6714,6 +6714,9 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p, to put statics on the list so we can deal with the label address extension. FIXME. */ add_local_decl (cfun, decl); + /* And make sure it's in the symbol table for + c_parse_final_cleanups to find. */ + varpool_node::get_create (decl); } /* Convert the initializer to the type of DECL, if we have not @@ -14887,10 +14890,6 @@ complete_vars (tree type) cp_apply_type_quals_to_decl (cp_type_quals (type), var); } - if (DECL_INITIAL (var) - && decl_constant_var_p (var)) - DECL_INITIAL (var) = cplus_expand_constant (DECL_INITIAL (var)); - /* Remove this entry from the list. */ incomplete_vars->unordered_remove (ix); } diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c index a5b44e0..3b3817e 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -4484,6 +4484,22 @@ maybe_warn_sized_delete () maybe_warn_sized_delete (VEC_DELETE_EXPR); } +/* Earlier we left PTRMEM_CST in variable initializers alone so that we could + look them up when evaluating non-type template parameters. Now we need to + lower them to something the back end can understand. */ + +static void +lower_var_init () +{ + varpool_node *node; + FOR_EACH_VARIABLE (node) + { + tree d = node->decl; + if (tree init = DECL_INITIAL (d)) + DECL_INITIAL (d) = cplus_expand_constant (init); + } +} + /* This routine is called at the end of compilation. Its job is to create all the code needed to initialize and destroy the global aggregates. We do the destruction @@ -4793,6 +4809,8 @@ c_parse_final_cleanups (void) } while (reconsider); + lower_var_init (); + generate_mangling_aliases (); /* All used inline functions must have a definition at this point. */ diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c index 2c9143e..e61a57f 100644 --- a/gcc/cp/typeck2.c +++ b/gcc/cp/typeck2.c @@ -1059,22 +1059,11 @@ digest_init_r (tree type, tree init, bool nested, int flags, || BRACE_ENCLOSED_INITIALIZER_P (init)) && (SCALAR_TYPE_P (type) || code == REFERENCE_TYPE)) { - tree *exp; - if (nested) flags |= LOOKUP_NO_NARROWING; init = convert_for_initialization (0, type, init, flags, ICR_INIT, NULL_TREE, 0, complain); - exp = &init; - - /* Skip any conversions since we'll be outputting the underlying - constant. */ - while (CONVERT_EXPR_P (*exp) - || TREE_CODE (*exp) == NON_LVALUE_EXPR) - exp = &TREE_OPERAND (*exp, 0); - - *exp = cplus_expand_constant (*exp); return init; }