From patchwork Sun May 6 17:56:52 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 909352 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-477291-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="ETF5NFl0"; 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 40fD3R2Fbbz9s27 for ; Mon, 7 May 2018 03:57:06 +1000 (AEST) 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=y6U2gN0/ULrpLx6ERcB4es4tlQrnf gaYWvz+Cj3iKgTYt2/K7bxM+Mxh5Lfqe9UW4IBB0zvTH6xYuKpPFBZZgGiXJKUiq 6DcCx8MfY2fLsUmRYPSOHp5DNoCLzyyW1+niU0pprIjQh1VGSOPNJqQGiQxgpNnu 29TqKHWw5f/hUs= 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=R6Mm2Mv0wGcUVeQGvM3rGqM/Kqw=; b=ETF 5NFl0R5X/kI8LahvjqBschNuvs+5BpjercxXAtzS6VIBxxK9pvso0Q12rPmzF2PK Et50ZXMUZhGiNmhcMF2czebwESN8aV7ox5aBQ5J9Zga/dzas2yJFCIU5MgUcLIyC yINnAESbiyOvdZ9Z0NCkj+IWiM9UvYSgoqwxVNxY= Received: (qmail 88603 invoked by alias); 6 May 2018 17:56:59 -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 88591 invoked by uid 89); 6 May 2018 17:56:58 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-16.9 required=5.0 tests=BAYES_00, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy=gcc_unreachable, TREE_CODE, tree_code, fx 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; Sun, 06 May 2018 17:56:57 +0000 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id EA83B81129 for ; Sun, 6 May 2018 17:56:55 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.36.118.110]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7FA25600C9; Sun, 6 May 2018 17:56:55 +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 w46Hur5r019062; Sun, 6 May 2018 19:56:53 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id w46HuqpF019061; Sun, 6 May 2018 19:56:52 +0200 Date: Sun, 6 May 2018 19:56:52 +0200 From: Jakub Jelinek To: Jason Merrill Cc: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] Fix offsetof constexpr handling (PR c++/85662) Message-ID: <20180506175652.GA8577@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.2 (2017-12-15) X-IsSubscribed: yes Hi! fold_offsetof_1 builds the base as usually INTEGER_CST with pointer type and calls fold_build_pointer_plus with the offset gathered from the COMPONENT_REF field offset or ARRAY_REF index or combination of them. But most of the fold_* routines aren't recursive, they fold just one level, so if the expression is more complex and with delayed folding we actually can keep around POINTER_PLUS_EXPR of pointer-typed INTEGER_CST (usually 0) and some large expression computing the offset. In that case we reject it as constant expression though, because we don't allow such arithmetics on (null) pointers. The following patch fixes it by only doing the pointer arithmetics if the user actually wrote it that way (offsetof-like expression like &((struct S *)0)->foo.bar[idx * 3 + 2]), but if it is __builtin_offsetof, uses integral arithmetics from the beginning. I think we should e.g. reject offsetof when the expression inside of array index has undefined behavior, so we don't want to cp_fold the fold_offsetof_1 result. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? What about release branches? 2018-05-06 Jakub Jelinek PR c++/85662 * c-common.h (fold_offsetof_1): Add bool argument with false default argument. * c-common.c (fold_offsetof_1): Add NONPTR argument, if true, convert the pointer constant to sizetype and use size_binop with PLUS_EXPR instead of fold_build_pointer_plus. Adjust recursive calls. (fold_offsetof): Pass true as NONPTR to fold_offsetof_1. * g++.dg/ext/offsetof2.C: New test. Jakub --- gcc/c-family/c-common.h.jj 2018-03-13 00:38:23.846662269 +0100 +++ gcc/c-family/c-common.h 2018-05-05 10:43:53.069431079 +0200 @@ -1033,7 +1033,7 @@ extern bool c_dump_tree (void *, tree); extern void verify_sequence_points (tree); -extern tree fold_offsetof_1 (tree, tree_code ctx = ERROR_MARK); +extern tree fold_offsetof_1 (tree, bool = false, tree_code ctx = ERROR_MARK); extern tree fold_offsetof (tree); extern int complete_array_type (tree *, tree, bool); --- gcc/c-family/c-common.c.jj 2018-03-27 21:58:55.598502113 +0200 +++ gcc/c-family/c-common.c 2018-05-05 10:55:47.951600802 +0200 @@ -6171,7 +6171,7 @@ c_common_to_target_charset (HOST_WIDE_IN traditional rendering of offsetof as a macro. Return the folded result. */ tree -fold_offsetof_1 (tree expr, enum tree_code ctx) +fold_offsetof_1 (tree expr, bool nonptr, enum tree_code ctx) { tree base, off, t; tree_code code = TREE_CODE (expr); @@ -6196,10 +6196,12 @@ fold_offsetof_1 (tree expr, enum tree_co error ("cannot apply % to a non constant address"); return error_mark_node; } + if (nonptr) + return convert (sizetype, TREE_OPERAND (expr, 0)); return TREE_OPERAND (expr, 0); case COMPONENT_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof_1 (TREE_OPERAND (expr, 0), nonptr, code); if (base == error_mark_node) return base; @@ -6216,7 +6218,7 @@ fold_offsetof_1 (tree expr, enum tree_co break; case ARRAY_REF: - base = fold_offsetof_1 (TREE_OPERAND (expr, 0), code); + base = fold_offsetof_1 (TREE_OPERAND (expr, 0), nonptr, code); if (base == error_mark_node) return base; @@ -6273,12 +6275,14 @@ fold_offsetof_1 (tree expr, enum tree_co /* Handle static members of volatile structs. */ t = TREE_OPERAND (expr, 1); gcc_checking_assert (VAR_P (get_base_address (t))); - return fold_offsetof_1 (t); + return fold_offsetof_1 (t, nonptr); default: gcc_unreachable (); } + if (nonptr) + return size_binop (PLUS_EXPR, base, off); return fold_build_pointer_plus (base, off); } @@ -6287,7 +6291,7 @@ fold_offsetof_1 (tree expr, enum tree_co tree fold_offsetof (tree expr) { - return convert (size_type_node, fold_offsetof_1 (expr)); + return convert (size_type_node, fold_offsetof_1 (expr, true)); } --- gcc/testsuite/g++.dg/ext/offsetof2.C.jj 2018-05-05 10:58:22.796637643 +0200 +++ gcc/testsuite/g++.dg/ext/offsetof2.C 2018-05-05 10:57:24.281623720 +0200 @@ -0,0 +1,6 @@ +// PR c++/85662 +// { dg-do compile { target c++11 } } + +struct S { unsigned long x[31]; }; +struct T { bool b; S f; }; +static_assert (__builtin_offsetof (T, f.x[31 - 1]) == __builtin_offsetof (T, f.x[30]), "");