From patchwork Tue Jan 13 21:02:56 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 428692 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 E7B811401EB for ; Wed, 14 Jan 2015 08:03:17 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=ylKbnqmFNxNaUmZ2Nep8zHPCAoOSTTNl0veBmvaz6iy4cL nULJwF5mEmhemE63nPOlITD2AWYoSoFUayQkC8J7fEHx491T1MDW98k6CSX+O9Zv YxfXwqGFVxncY+RJbOLyMZDWuuX8p7OUi2asqBtHEd94UjTfQ6wqcop2qPf7E= 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 :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=ZSV4Jk48C56VOTi9sflRavEc8h4=; b=I0MlYTKfB0MHXkCjT13G zumbcKVSss4tS8c/Sf99iEhVs/owhdfrseZgPNwDLF+GjvDIoFK3LMH1roLJULsf vWEzpcZnfhjdtBMR4n6U6cK9nsuBXcZf5NP1zMn/wW+VeWwNSpl8ueEhgNapVvCV EsEZc3C9jbCr98U61+/37Es= Received: (qmail 22903 invoked by alias); 13 Jan 2015 21:03:11 -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 22884 invoked by uid 89); 13 Jan 2015 21:03:10 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-3.7 required=5.0 tests=AWL, BAYES_00, SPF_HELO_PASS, SPF_PASS, T_RP_MATCHES_RCVD 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, 13 Jan 2015 21:03:02 +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 (8.14.4/8.14.4) with ESMTP id t0DL30gd031082 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=FAIL) for ; Tue, 13 Jan 2015 16:03:00 -0500 Received: from [10.10.116.16] ([10.10.116.16]) by int-mx11.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id t0DL30cO000513 for ; Tue, 13 Jan 2015 16:03:00 -0500 Message-ID: <54B58800.2080601@redhat.com> Date: Tue, 13 Jan 2015 16:02:56 -0500 From: Jason Merrill User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.3.0 MIME-Version: 1.0 To: gcc-patches List Subject: C++ PATCH for c++/64356 and libstdc++/58777 (constexpr pointer arithmetic) In this testcase we are iterating through an array which is a local variable in a constexpr function. So its address is not constant, but we can still do arithmetic on it to get to the address of an element and then pull out the value of the element; we shouldn't reject the evaluation as non-constant unless the non-constant address is part of the value of the complete expression. This patch also fixes libstdc++/58777, another issue with giving up on an intermediate non-constant address even though the final value is constant. Tested x86_64-pc-linux-gnu, applying to trunk. commit 10760eb60bfd8f5de38ff1194718851a3d0f9073 Author: Jason Merrill Date: Tue Jan 13 07:45:03 2015 -0500 PR c++/64356 PR libstdc++/58777 * constexpr.c (cxx_eval_binary_expression): Don't VERIFY_CONSTANT pointer expressions. (cxx_eval_increment_expression): Likewise. diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 650250b..1432506 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -1616,10 +1616,15 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, tree lhs, rhs; lhs = cxx_eval_constant_expression (ctx, orig_lhs, /*lval*/false, non_constant_p, overflow_p); - VERIFY_CONSTANT (lhs); + /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to + a local array in a constexpr function. */ + bool ptr = POINTER_TYPE_P (TREE_TYPE (lhs)); + if (!ptr) + VERIFY_CONSTANT (lhs); rhs = cxx_eval_constant_expression (ctx, orig_rhs, /*lval*/false, non_constant_p, overflow_p); - VERIFY_CONSTANT (rhs); + if (!ptr) + VERIFY_CONSTANT (lhs); location_t loc = EXPR_LOCATION (t); enum tree_code code = TREE_CODE (t); @@ -1634,7 +1639,8 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t, } else if (cxx_eval_check_shift_p (loc, ctx, code, type, lhs, rhs)) *non_constant_p = true; - VERIFY_CONSTANT (r); + if (!ptr) + VERIFY_CONSTANT (lhs); return r; } @@ -2704,7 +2710,11 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, tree val = rvalue (op); val = cxx_eval_constant_expression (ctx, val, false, non_constant_p, overflow_p); - VERIFY_CONSTANT (val); + /* Don't VERIFY_CONSTANT if this might be dealing with a pointer to + a local array in a constexpr function. */ + bool ptr = POINTER_TYPE_P (TREE_TYPE (val)); + if (!ptr) + VERIFY_CONSTANT (val); /* The modified value. */ bool inc = (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR); @@ -2719,7 +2729,8 @@ cxx_eval_increment_expression (const constexpr_ctx *ctx, tree t, } else mod = fold_build2 (inc ? PLUS_EXPR : MINUS_EXPR, type, val, offset); - VERIFY_CONSTANT (mod); + if (!ptr) + VERIFY_CONSTANT (mod); /* Storing the modified value. */ tree store = build2 (MODIFY_EXPR, type, op, mod); diff --git a/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C b/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C new file mode 100644 index 0000000..fd6143b --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1y/constexpr-local2.C @@ -0,0 +1,22 @@ +// PR c++/64356 +// { dg-do compile { target c++14 } } + +typedef unsigned long size_t; + +template +constexpr size_t f(const char (&x)[N]) { + size_t s = 0; + for(size_t c : x) + s += c; + return s; +} + +template +constexpr size_t g(const char (&x)[N]) { + char y[N] = {0}; + for(size_t i = 0; i < N; ++i) + y[i] = x[i]; + return f(y); +} + +constexpr auto x = g(__DATE__); diff --git a/gcc/testsuite/g++.dg/cpp1y/pr63996.C b/gcc/testsuite/g++.dg/cpp1y/pr63996.C index d0bf9b5..8f66cdc 100644 --- a/gcc/testsuite/g++.dg/cpp1y/pr63996.C +++ b/gcc/testsuite/g++.dg/cpp1y/pr63996.C @@ -6,5 +6,5 @@ foo (int i) int a[i] = { }; // { dg-error "forbids variable length" } } -constexpr int j = foo (1); // { dg-error "is not a constant expression" } +constexpr int j = foo (1); // { dg-error "flows off the end" } diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc index f3b4388..d57cf5c 100644 --- a/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc +++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/make_optional.cc @@ -1,7 +1,4 @@ // { dg-options "-std=gnu++14" } -// XFAIL pending resolution of PR libstdc++/58777 -// { dg-do compile { xfail *-*-* } } -// { dg-excess-errors "" } // Copyright (C) 2013-2015 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc index 20c307d..803927b 100644 --- a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc +++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/2.cc @@ -1,7 +1,4 @@ // { dg-options "-std=gnu++14" } -// XFAIL pending resolution of PR libstdc++/58777 -// { dg-do compile { xfail *-*-* } } -// { dg-excess-errors "" } // Copyright (C) 2013-2015 Free Software Foundation, Inc. // diff --git a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc index 59b1bdd..be170f5 100644 --- a/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc +++ b/libstdc++-v3/testsuite/experimental/optional/constexpr/observers/3.cc @@ -1,7 +1,4 @@ // { dg-options "-std=gnu++14" } -// XFAIL pending resolution of PR libstdc++/58777 -// { dg-do compile { xfail *-*-* } } -// { dg-excess-errors "" } // Copyright (C) 2013-2015 Free Software Foundation, Inc. //