From patchwork Tue Jan 24 18:53:26 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 719321 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 3v7HQR2CTPz9ry7 for ; Wed, 25 Jan 2017 05:53:50 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="PGHdsq+V"; 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=MIIRrJ1on/Y/MTmb/ BNIgwuBYg0nQktECEOTOZrQ6gI62l9DYZwMUEH59NeGwgc1GnqlH6XsarJBvu6Pk 0nfEjeDMyWYotdCMgLHAAUb4vARhR43VmyrobrdYgo7byJkOTl/mQ/yS/ddX+tH+ 1LSwdkQA9Mat6Kpob8amw3rF64= 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=3N0CWLOkdKryzRyQgGSLptZ 4C+g=; b=PGHdsq+VcTizkqVvWe584aH0LTgpwpFp1COm+ZRLGo6IWgJmIhsPPF3 NYSber0t8rln9OgWpCZ1gYqOWYzycaHV9ef3G+hu5rqaNr7KmqvNz9hiewFXGbGn BTjn/ysmTFVb4UcRHFNKeQxrzpE8lJtXkdL4usfZkUJMoxwGttFM= Received: (qmail 13736 invoked by alias); 24 Jan 2017 18:53:41 -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 13704 invoked by uid 89); 24 Jan 2017 18:53:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=1.3 required=5.0 tests=BAYES_40, FREEMAIL_FROM, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=no version=3.3.2 spammy=8847, augments, FUN, no_zero_init X-HELO: mail-yw0-f193.google.com Received: from mail-yw0-f193.google.com (HELO mail-yw0-f193.google.com) (209.85.161.193) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 24 Jan 2017 18:53:30 +0000 Received: by mail-yw0-f193.google.com with SMTP id u68so21561486ywg.0 for ; Tue, 24 Jan 2017 10:53:30 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:subject:to:references:cc:from:message-id :date:user-agent:mime-version:in-reply-to; bh=FLGS5/Wk1JcLCGl9EoVkmZoGM5wM0+AWcDGrW2xHiTc=; b=br6XL1dcqIkkvJISKL9ynQdFYaevX4AAHfSyi6xfe3iJ+yA8NDafy9NKIGZcaXnIR/ Y0oQ9IdYu3I6MESyHCp533u5A2Tz9EnYZIcqV1mNiATFiTPuSAMyla+zVajz+7RwoxXP gXpxSTtw3OFKyX6g1+LZlnSuIxc4/QZ41W5yVch8iAs2jVziq+e8FSthN+EhfwRUUxmY 6NLqErsqNp1dZn1l3zU2dEw9BpKz+fGk7RyYRJis024Wpq2PbVBDKUQzpC16In1wSPNh 0OBvHjD6m5ltgjvgu/H0cjgZQMepB57Rt8BS/hUh/hRj1yoP9IXn1A+/JiWng6a4Q98J MbBg== X-Gm-Message-State: AIkVDXImHILcyS0dT8Zvoz9V/+ma60Wg98TQTyGCg2zDDwYATH0IIXdXIdVVDJrvBoINjQ== X-Received: by 10.129.46.213 with SMTP id u204mr26117138ywu.52.1485284008938; Tue, 24 Jan 2017 10:53:28 -0800 (PST) Received: from ?IPv6:2620:10d:c0a3:20fb:f6d0:5ac5:64cd:f102? ([2620:10d:c091:200::9:7c73]) by smtp.googlemail.com with ESMTPSA id x185sm10266720ywe.35.2017.01.24.10.53.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 24 Jan 2017 10:53:28 -0800 (PST) Subject: Re: [C++ PATCH] 79118 bitfields & constexpr To: Jason Merrill References: <9dc01f9e-6d84-0e30-0dac-56b52892042f@acm.org> <8df374e7-a828-05ae-c5bd-775735663d30@acm.org> Cc: GCC Patches , Jakub Jelinek From: Nathan Sidwell Message-ID: <1beb4ea3-2741-b293-c845-ced98bd8dd0e@acm.org> Date: Tue, 24 Jan 2017 13:53:26 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.6.0 MIME-Version: 1.0 In-Reply-To: On 01/24/2017 01:41 PM, Jason Merrill wrote: > On Tue, Jan 24, 2017 at 1:31 PM, Nathan Sidwell wrote: >> On 01/23/2017 04:06 PM, Jason Merrill wrote: >> >>>> In this particular case we've also made the base object the containing >>>> class, not the unnamed struct member. That means we're looking in the >>>> wrong >>>> CONSTRUCTOR and see CONSTRUCTOR_NO_IMPLICIT_ZERO is true. Whereas for >>>> the >>>> subobj's CONSTRUCTOR it is false. >>> >>> >>> Why is it false? >> >> >> I thought it was because we're looking at a different level of ctor, >> investigation shows there may be a bug there too. because in one place we >> do: >> if (*valp == NULL_TREE) >> { >> *valp = build_constructor (type, NULL); >> CONSTRUCTOR_NO_IMPLICIT_ZERO (*valp) = no_zero_init; >> and another we do: >> if (vec_safe_is_empty (*vec) >> || (*vec)->last().index != field) >> { >> ctor = build_constructor (TREE_TYPE (field), NULL); >> CONSTRUCTOR_APPEND_ELT (*vec, field, ctor); >> >> However, further looking at this problem, I discovered we're not properly >> checking the initialization of anonymous members. Once we do that, we >> reject the ctor as a constexpr, because it fails to initialize the 'type' >> member (regardless of bitfieldness). >> >> This patch augments cx_check_missing_mem_inits. I change the first parm to >> be the CTYPE not the FUN from whence we pull the CTYPE. That way we don't >> have to cons up an empty CONSTRUCTOR for the recursive case of discovering >> no initializer at all for the anon member. >> >> With this in place we don't try and evaluate the constexpr in the original >> testcase. >> >> ok? > > I'm not seeing the patch. d'oh! 2017-01-24 Nathan Sidwell PR c++/79118 - anon-members and constexpr * constexpr.c (cx_check_missing_mem_inits): Caller passes type not ctor decl. Recursively check anonymous members. (register_constexpr_fundef): Adjust cx_check_missing_mem_inits call. (explain_invalid_constexpr_fn): Likewise. PR c++/79118 * g++.dg/cpp0x/pr79118.C: New. Index: cp/constexpr.c =================================================================== --- cp/constexpr.c (revision 244874) +++ cp/constexpr.c (working copy) @@ -696,23 +696,21 @@ massage_constexpr_body (tree fun, tree b return body; } -/* FUN is a constexpr constructor with massaged body BODY. Return true - if some bases/fields are uninitialized, and complain if COMPLAIN. */ +/* CTYPE is a type constructed from BODY. Return true if some + bases/fields are uninitialized, and complain if COMPLAIN. */ static bool -cx_check_missing_mem_inits (tree fun, tree body, bool complain) +cx_check_missing_mem_inits (tree ctype, tree body, bool complain) { - bool bad; - tree field; - unsigned i, nelts; - tree ctype; - - if (TREE_CODE (body) != CONSTRUCTOR) - return false; - - nelts = CONSTRUCTOR_NELTS (body); - ctype = DECL_CONTEXT (fun); - field = TYPE_FIELDS (ctype); + unsigned nelts = 0; + + if (body) + { + if (TREE_CODE (body) != CONSTRUCTOR) + return false; + nelts = CONSTRUCTOR_NELTS (body); + } + tree field = TYPE_FIELDS (ctype); if (TREE_CODE (ctype) == UNION_TYPE) { @@ -726,13 +724,13 @@ cx_check_missing_mem_inits (tree fun, tr return false; } - bad = false; - for (i = 0; i <= nelts; ++i) + /* Iterate over the CONSTRUCTOR, checking any missing fields don't + need an explicit initialization. */ + bool bad = false; + for (unsigned i = 0; i <= nelts; ++i) { - tree index; - if (i == nelts) - index = NULL_TREE; - else + tree index = NULL_TREE; + if (i < nelts) { index = CONSTRUCTOR_ELT (body, i)->index; /* Skip base and vtable inits. */ @@ -740,13 +738,25 @@ cx_check_missing_mem_inits (tree fun, tr || DECL_ARTIFICIAL (index)) continue; } + for (; field != index; field = DECL_CHAIN (field)) { tree ftype; - if (TREE_CODE (field) != FIELD_DECL - || (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)) - || DECL_ARTIFICIAL (field)) + if (TREE_CODE (field) != FIELD_DECL) continue; + if (DECL_C_BIT_FIELD (field) && !DECL_NAME (field)) + continue; + if (DECL_ARTIFICIAL (field)) + continue; + if (ANON_AGGR_TYPE_P (TREE_TYPE (field))) + { + /* Recurse to check the anonummous aggregate member. */ + bad |= cx_check_missing_mem_inits + (TREE_TYPE (field), NULL_TREE, complain); + if (bad && !complain) + return true; + continue; + } ftype = strip_array_types (TREE_TYPE (field)); if (type_has_constexpr_default_constructor (ftype)) { @@ -766,6 +776,15 @@ cx_check_missing_mem_inits (tree fun, tr } if (field == NULL_TREE) break; + + if (ANON_AGGR_TYPE_P (TREE_TYPE (index))) + { + /* Check the anonymous aggregate initializer is valid. */ + bad |= cx_check_missing_mem_inits + (TREE_TYPE (index), CONSTRUCTOR_ELT (body, i)->value, complain); + if (bad && !complain) + return true; + } field = DECL_CHAIN (field); } @@ -803,7 +822,8 @@ register_constexpr_fundef (tree fun, tre } if (DECL_CONSTRUCTOR_P (fun) - && cx_check_missing_mem_inits (fun, massaged, !DECL_GENERATED_P (fun))) + && cx_check_missing_mem_inits (DECL_CONTEXT (fun), + massaged, !DECL_GENERATED_P (fun))) return NULL; /* Create the constexpr function table if necessary. */ @@ -864,7 +884,7 @@ explain_invalid_constexpr_fn (tree fun) body = massage_constexpr_body (fun, DECL_SAVED_TREE (fun)); require_potential_rvalue_constant_expression (body); if (DECL_CONSTRUCTOR_P (fun)) - cx_check_missing_mem_inits (fun, body, true); + cx_check_missing_mem_inits (DECL_CONTEXT (fun), body, true); } } input_location = save_loc; Index: testsuite/g++.dg/cpp0x/pr79118.C =================================================================== --- testsuite/g++.dg/cpp0x/pr79118.C (revision 0) +++ testsuite/g++.dg/cpp0x/pr79118.C (working copy) @@ -0,0 +1,42 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options { -Wno-pedantic } } +// PR c++/79118 failure to check initialization of anonymous members. + +struct One +{ + union + { + int a; + int b; + }; + + constexpr One () : a(), b() {} // { dg-error "multiple" } + constexpr One (int) : a() {} + constexpr One (unsigned) : b () {} + constexpr One (void *) {} // { dg-error "exactly one" } +}; + +One a (); +One b (0); +One c (0u); +One d ((void *)0); + +struct Two +{ + struct + { + int a; + int b; + }; + + constexpr Two () : a(), b() {} + constexpr Two (int) : a() {} // { dg-error "b' must be initialized" } + constexpr Two (unsigned) : b () {} // { dg-error "a' must be initialized" } + constexpr Two (void *) {} // { dg-error "a' must be initialized" } + // { dg-error "b' must be initialized" "" { target *-*-* } 35 } +}; + +Two e (); +Two f (0); +Two g (0u); +Two h ((void *)0);