From patchwork Tue Mar 5 22:17:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Merrill X-Patchwork-Id: 1052014 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-497409-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com 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 44DWTw0KHNz9s1B for ; Wed, 6 Mar 2019 09:17:18 +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:from :to:subject:date:message-id:mime-version :content-transfer-encoding; q=dns; s=default; b=QkJAT3WpMZXhfRCO hJPJMaoiA0kMARpBM+nlNLHU5uXCaG9nckTV7jJg/zU9bO2PjhF/mtVEbg52jXXV +00UeGNMeLLGloKl6nG8KqeKmlzrG9o3OO6aKrb6HxYlfGh1yF+goP0aHbI+jki/ M2edoIOyNlJHykmllhe+O2AKD84= 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:from :to:subject:date:message-id:mime-version :content-transfer-encoding; s=default; bh=+weuNJFhntjg4+gsKSGKvP DAhtY=; b=h1FGyxjFIkHl47UbyiiyibNxquHdN1YRO7lh30yHGSd31y/XrYhNen 41z6e0Pv1+Ql2bW8AtukuGZqcpgJl4Wo4IdZolbD2pECttcN8MDRU3jOIxsnNnCP SCWaA35Cas49AOkK0DFGUWDvWfdrLAOX/qvSuLM03bKMwQs8k52xU= Received: (qmail 79593 invoked by alias); 5 Mar 2019 22:17:10 -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 79584 invoked by uid 89); 5 Mar 2019 22:17:09 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KAM_LAZY_DOMAIN_SECURITY, RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.2 spammy=strict, DECL_CHAIN, field_decl, FIELD_DECL X-HELO: mail-qt1-f171.google.com Received: from mail-qt1-f171.google.com (HELO mail-qt1-f171.google.com) (209.85.160.171) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 05 Mar 2019 22:17:07 +0000 Received: by mail-qt1-f171.google.com with SMTP id j36so10696139qta.7 for ; Tue, 05 Mar 2019 14:17:07 -0800 (PST) Received: from localhost.localdomain (209-6-216-142.s141.c3-0.smr-cbr1.sbo-smr.ma.cable.rcncustomer.com. [209.6.216.142]) by smtp.gmail.com with ESMTPSA id e184sm11660164qka.31.2019.03.05.14.17.04 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Tue, 05 Mar 2019 14:17:05 -0800 (PST) From: Jason Merrill To: gcc-patches@gcc.gnu.org Subject: [C++ PATCH] * class.c (is_really_empty_class): Add ignore_vptr parm. Date: Tue, 5 Mar 2019 17:17:03 -0500 Message-Id: <20190305221703.29109-1-jason@redhat.com> MIME-Version: 1.0 X-IsSubscribed: yes While looking at PR86485, I noticed that many uses of is_really_empty_class were overlooking that it returned true for a class with only a vptr; initialization of such a class is not trivial. Marek's P1064 patch fixed one place in constexpr.c to also check for a vtable, but there are several others that still don't. This patch requires callers to explicitly choose which behavior they want. Currently the uses in constexpr.c want to consider the vptr, and other uses don't. So this is effectively just extending Marek's change to the other uses in constexpr.c. Tested x86_64-pc-linux-gnu, applying to trunk. * class.c (is_really_empty_class): Add ignore_vptr parm. (trivial_default_constructor_is_constexpr): Pass it. * call.c (build_over_call): Pass it. * constexpr.c (cxx_eval_constant_expression): Pass it instead of checking TYPE_POLYMORPHIC_P. (cxx_eval_component_reference, potential_constant_expression_1): Pass it. * cp-gimplify.c (simple_empty_class_p): Pass it. * init.c (expand_aggr_init_1): Pass it. --- gcc/cp/cp-tree.h | 2 +- gcc/cp/call.c | 2 +- gcc/cp/class.c | 18 ++++++++++++------ gcc/cp/constexpr.c | 12 ++++-------- gcc/cp/cp-gimplify.c | 2 +- gcc/cp/init.c | 2 +- gcc/cp/ChangeLog | 12 ++++++++++++ 7 files changed, 32 insertions(+), 18 deletions(-) base-commit: 07b089176a78b3025a3c033f97cda7c12ffcae52 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 663a23b4043..15e39e1b545 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6267,7 +6267,7 @@ extern void finish_struct_1 (tree); extern int resolves_to_fixed_type_p (tree, int *); extern void init_class_processing (void); extern int is_empty_class (tree); -extern bool is_really_empty_class (tree); +extern bool is_really_empty_class (tree, bool); extern void pushclass (tree); extern void popclass (void); extern void push_nested_class (tree); diff --git a/gcc/cp/call.c b/gcc/cp/call.c index 1a29eb7bb19..04516eb967c 100644 --- a/gcc/cp/call.c +++ b/gcc/cp/call.c @@ -8566,7 +8566,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain) tree arg = argarray[1]; location_t loc = cp_expr_loc_or_loc (arg, input_location); - if (is_really_empty_class (type)) + if (is_really_empty_class (type, /*ignore_vptr*/true)) { /* Avoid copying empty classes. */ val = build2 (COMPOUND_EXPR, type, arg, to); diff --git a/gcc/cp/class.c b/gcc/cp/class.c index f44acfd62b5..0d4d35bd690 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -5137,7 +5137,8 @@ trivial_default_constructor_is_constexpr (tree t) /* A defaulted trivial default constructor is constexpr if there is nothing to initialize. */ gcc_assert (!TYPE_HAS_COMPLEX_DFLT (t)); - return is_really_empty_class (t); + /* A class with a vptr doesn't have a trivial default ctor. */ + return is_really_empty_class (t, /*ignore_vptr*/true); } /* Returns true iff class T has a constexpr default constructor. */ @@ -8310,10 +8311,12 @@ is_empty_class (tree type) } /* Returns true if TYPE contains no actual data, just various - possible combinations of empty classes and possibly a vptr. */ + possible combinations of empty classes. If IGNORE_VPTR is true, + a vptr doesn't prevent the class from being considered empty. Typically + we want to ignore the vptr on assignment, and not on initialization. */ bool -is_really_empty_class (tree type) +is_really_empty_class (tree type, bool ignore_vptr) { if (CLASS_TYPE_P (type)) { @@ -8327,22 +8330,25 @@ is_really_empty_class (tree type) if (COMPLETE_TYPE_P (type) && is_empty_class (type)) return true; + if (!ignore_vptr && TYPE_CONTAINS_VPTR_P (type)) + return false; + for (binfo = TYPE_BINFO (type), i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i) - if (!is_really_empty_class (BINFO_TYPE (base_binfo))) + if (!is_really_empty_class (BINFO_TYPE (base_binfo), ignore_vptr)) return false; for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) if (TREE_CODE (field) == FIELD_DECL && !DECL_ARTIFICIAL (field) /* An unnamed bit-field is not a data member. */ && !DECL_UNNAMED_BIT_FIELD (field) - && !is_really_empty_class (TREE_TYPE (field))) + && !is_really_empty_class (TREE_TYPE (field), ignore_vptr)) return false; return true; } else if (TREE_CODE (type) == ARRAY_TYPE) return (integer_zerop (array_type_nelts_top (type)) - || is_really_empty_class (TREE_TYPE (type))); + || is_really_empty_class (TREE_TYPE (type), ignore_vptr)); return false; } diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index 65888b60d63..1c3c7252807 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -2714,7 +2714,7 @@ cxx_eval_component_reference (const constexpr_ctx *ctx, tree t, /* We only create a CONSTRUCTOR for a subobject when we modify it, so empty classes never get represented; throw together a value now. */ - if (is_really_empty_class (TREE_TYPE (t))) + if (is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) return build_constructor (TREE_TYPE (t), NULL); gcc_assert (DECL_CONTEXT (part) == TYPE_MAIN_VARIANT (TREE_TYPE (whole))); @@ -4427,12 +4427,8 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, CONST_DECL for aggregate constants. */ if (lval) return t; - /* is_really_empty_class doesn't take into account _vptr, so initializing - otherwise empty class with { } would overwrite the initializer that - initialize_vtable created for us. */ if (COMPLETE_TYPE_P (TREE_TYPE (t)) - && !TYPE_POLYMORPHIC_P (TREE_TYPE (t)) - && is_really_empty_class (TREE_TYPE (t))) + && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { /* If the class is empty, we aren't actually loading anything. */ r = build_constructor (TREE_TYPE (t), NULL); @@ -4480,7 +4476,7 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, else if (TYPE_REF_P (TREE_TYPE (t))) /* Defer, there's no lvalue->rvalue conversion. */; else if (COMPLETE_TYPE_P (TREE_TYPE (t)) - && is_really_empty_class (TREE_TYPE (t))) + && is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { /* If the class is empty, we aren't actually loading anything. */ r = build_constructor (TREE_TYPE (t), NULL); @@ -5956,7 +5952,7 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now, || (DECL_INITIAL (t) && !DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (t))) && COMPLETE_TYPE_P (TREE_TYPE (t)) - && !is_really_empty_class (TREE_TYPE (t))) + && !is_really_empty_class (TREE_TYPE (t), /*ignore_vptr*/false)) { if (flags & tf_error) non_const_var_error (t); diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c index 56f717de85d..26be1fd1522 100644 --- a/gcc/cp/cp-gimplify.c +++ b/gcc/cp/cp-gimplify.c @@ -584,7 +584,7 @@ simple_empty_class_p (tree type, tree op) && !TREE_CLOBBER_P (op)) || (TREE_CODE (op) == CALL_EXPR && !CALL_EXPR_RETURN_SLOT_OPT (op))) - && is_really_empty_class (type); + && is_really_empty_class (type, /*ignore_vptr*/true); } /* Returns true if evaluating E as an lvalue has side-effects; diff --git a/gcc/cp/init.c b/gcc/cp/init.c index 606d246ef94..eb3b504d708 100644 --- a/gcc/cp/init.c +++ b/gcc/cp/init.c @@ -2058,7 +2058,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, tree init, int flags, /* If the type has data but no user-provided ctor, we need to zero out the object. */ if (!type_has_user_provided_constructor (type) - && !is_really_empty_class (type)) + && !is_really_empty_class (type, /*ignore_vptr*/true)) { tree field_size = NULL_TREE; if (exp != true_exp && CLASSTYPE_AS_BASE (type) != type) diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 69971800099..d2cb7fd1132 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,15 @@ +2019-03-05 Jason Merrill + + * class.c (is_really_empty_class): Add ignore_vptr parm. + (trivial_default_constructor_is_constexpr): Pass it. + * call.c (build_over_call): Pass it. + * constexpr.c (cxx_eval_constant_expression): Pass it instead of + checking TYPE_POLYMORPHIC_P. + (cxx_eval_component_reference, potential_constant_expression_1): + Pass it. + * cp-gimplify.c (simple_empty_class_p): Pass it. + * init.c (expand_aggr_init_1): Pass it. + 2019-03-04 Paolo Carlini PR c++/84605