From patchwork Wed Jan 24 23:19:43 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 865561 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-471997-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="MUElAhVC"; dkim-atps=neutral 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 3zRh3G07M0z9s7n for ; Thu, 25 Jan 2018 10:20:09 +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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; q=dns; s=default; b=TkFwVaOG9kKzbCYgnSGkhGohD5YiE UAQCGiF0l86Ip/D0oUE79zlMAyV7Dr0Jhx+jgpyopo+AxfVx8a9m/5y5K/nF4Sb6 WY7Fj0ytq/yYBC47mobkzfGEkajYIaEcTaLLZXM+RJSVPSq0ivC8VnGr2VxNqAM6 H6oisYilccZeJc= 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:date :from:to:cc:subject:message-id:reply-to:mime-version :content-type; s=default; bh=sN/yIGfAsiVakBHoCMnIqF2ezIs=; b=MUE lAhVC+AKPHA7aSTUYAFQFZ7OTL6IT1TyZHZI33oHOLmQDgPGS0eeoPV136vebp5+ RYarjy/4TcWuEuuSrOBqqgtio9SnjkAkRDsFQvyCvK9XY6SC6uhpPTz2qocJyfa7 eijWWAtNnpvOq1wiMFOfxhlgFmpNLlhFggiptUG4= Received: (qmail 35108 invoked by alias); 24 Jan 2018 23:20: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 34292 invoked by uid 89); 24 Jan 2018 23:20:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=*d2 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 ESMTP; Wed, 24 Jan 2018 23:19:58 +0000 Received: from smtp.corp.redhat.com (int-mx05.intmail.prod.int.phx2.redhat.com [10.5.11.15]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 42E844E33A; Wed, 24 Jan 2018 23:19:57 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-117-22.ams2.redhat.com [10.36.117.22]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C784262674; Wed, 24 Jan 2018 23:19:49 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id w0ONJiw3008466; Thu, 25 Jan 2018 00:19:44 +0100 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id w0ONJhpn008465; Thu, 25 Jan 2018 00:19:43 +0100 Date: Thu, 25 Jan 2018 00:19:43 +0100 From: Jakub Jelinek To: Jason Merrill , Nathan Sidwell Cc: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] Fix constexpr handling of arrays with unknown bound (PR c++/83993) Message-ID: <20180124231943.GJ2063@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.1 (2017-09-22) X-IsSubscribed: yes Hi! In constexpr evaluation of array references for arrays with unknown bounds, we need to diagnose out of bounds accesses, but really don't know the bounds at compile time, right now GCC will see nelts as error_mark_node + 1 and will not consider them a constant expression at all. From the clang commit message it seems that CWG is leaning towards allowing &array_with_unknown_bound[0] and array_with_unknown_bound, but disallowing any other indexes (i.e. assume the array could have zero elements). The following patch implements that. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2018-01-24 Jakub Jelinek PR c++/83993 * constexpr.c (diag_array_subscript): Emit different diagnostics if TYPE_DOMAIN (arraytype) is NULL. (cxx_eval_array_reference, cxx_eval_store_expression): For arrays with NULL TYPE_DOMAIN use size_zero_node as nelts. * g++.dg/init/pr83993-1.C: New test. * g++.dg/cpp0x/pr83993.C: New test. Jakub --- gcc/cp/constexpr.c.jj 2018-01-19 23:34:04.897278768 +0100 +++ gcc/cp/constexpr.c 2018-01-24 13:38:40.572913190 +0100 @@ -2270,13 +2270,20 @@ diag_array_subscript (const constexpr_ct tree sidx = fold_convert (ssizetype, index); if (DECL_P (array)) { - error ("array subscript value %qE is outside the bounds " - "of array %qD of type %qT", sidx, array, arraytype); + if (TYPE_DOMAIN (arraytype)) + error ("array subscript value %qE is outside the bounds " + "of array %qD of type %qT", sidx, array, arraytype); + else + error ("array subscript value %qE used on array %qD of " + "type %qT with unknown bounds", sidx, array, arraytype); inform (DECL_SOURCE_LOCATION (array), "declared here"); } - else + else if (TYPE_DOMAIN (arraytype)) error ("array subscript value %qE is outside the bounds " "of array type %qT", sidx, arraytype); + else + error ("array subscript value %qE used on array of type %qT " + "with unknown bounds", sidx, arraytype); } } @@ -2361,7 +2368,12 @@ cxx_eval_array_reference (const constexp tree nelts; if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) - nelts = array_type_nelts_top (TREE_TYPE (ary)); + { + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; + } else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else @@ -3439,7 +3451,12 @@ cxx_eval_store_expression (const constex tree nelts, ary; ary = TREE_OPERAND (probe, 0); if (TREE_CODE (TREE_TYPE (ary)) == ARRAY_TYPE) - nelts = array_type_nelts_top (TREE_TYPE (ary)); + { + if (TYPE_DOMAIN (TREE_TYPE (ary))) + nelts = array_type_nelts_top (TREE_TYPE (ary)); + else + nelts = size_zero_node; + } else if (VECTOR_TYPE_P (TREE_TYPE (ary))) nelts = size_int (TYPE_VECTOR_SUBPARTS (TREE_TYPE (ary))); else --- gcc/testsuite/g++.dg/init/pr83993-1.C.jj 2018-01-24 13:45:43.430864528 +0100 +++ gcc/testsuite/g++.dg/init/pr83993-1.C 2018-01-24 13:44:59.352869530 +0100 @@ -0,0 +1,11 @@ +// PR c++/83993 +// { dg-do compile } + +extern const int a[]; +const int *const b = &a[0]; + +int +foo () +{ + return b[0]; +} --- gcc/testsuite/g++.dg/cpp0x/pr83993.C.jj 2018-01-24 14:09:01.846716177 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr83993.C 2018-01-24 14:08:41.246718212 +0100 @@ -0,0 +1,49 @@ +// PR c++/83993 +// { dg-do compile { target c++11 } } +// { dg-options "" } + +extern const int a[]; +const int b[5] = { 1, 2, 3, 4, 5 }; +extern const int c[4]; +constexpr const int *d = &a[0]; +constexpr const int *d2 = a; +constexpr const int *e = &a[1]; // { dg-error "array subscript value '1' used on array 'a' of type 'const int \\\[\\\]' with unknown bounds" } +constexpr const int *f = &b[0]; +constexpr const int *f2 = b; +constexpr const int *g = &b[5]; +constexpr const int *h = &b[6]; // { dg-error "array subscript value '6' is outside the bounds of array 'b' of type 'const int \\\[5\\\]'" } +constexpr const int *i = &c[0]; +constexpr const int *i2 = c; +constexpr const int *j = &c[4]; +constexpr const int *k = &c[5]; // { dg-error "array subscript value '5' is outside the bounds of array 'c' of type 'const int \\\[4\\\]'" } +extern const int l[]; + +void +foo () +{ + extern const int l[3]; + constexpr const int *m = &l[0]; + constexpr const int *m2 = l; + constexpr const int *n = &l[1]; + static_assert (m == m2, ""); +} + +constexpr const int *m = &l[0]; +constexpr const int *m2 = l; +constexpr const int *n = &l[1]; // { dg-error "array subscript value '1' used on array 'l' of type 'const int \\\[\\\]' with unknown bounds" } +static_assert (d == d2 && f == f2 && i == i2 && m == m2, ""); +const int o[] = { 1, 2 }; +constexpr const int *p = &o[0]; +constexpr const int *p2 = o; +constexpr const int *q = &o[2]; +constexpr const int *r = &o[3]; // { dg-error "array subscript value '3' is outside the bounds of array 'o' of type 'const int \\\[2\\\]'" } +struct S { char a; char b[]; } s; +constexpr const char *t = &s.b[0]; +constexpr const char *t2 = s.b; +constexpr const char *u = &s.b[1]; // { dg-error "array subscript value '1' used on array of type 'char \\\[\\\]' with unknown bounds" } +struct V { int a; }; +extern V v[]; +constexpr V *w = &v[0]; +constexpr V *w2 = v; +constexpr int *x = &v[0].a; +constexpr int y = a[0]; // { dg-error "the value of 'a' is not usable in a constant expression" }