From patchwork Mon Jul 17 16:55:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nathan Sidwell X-Patchwork-Id: 789622 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 3xB8Yl3FSKz9s5L for ; Tue, 18 Jul 2017 02:55:38 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="tN73Z4Qs"; 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:to :from:subject:message-id:date:mime-version:content-type; q=dns; s=default; b=Fsz2539KRwSCkOuyVdATna0ASvz5E5ixc5taYYip1FSqV4VYm+ wbxkQaqQSXgPTBaPFP6w1HurgS8fhzwRCp6xukDcRMv5Gnue1VTLkqCuYJP68XAJ bN6jYF8AQJ7TA85h9j9ZFRe5Ju8V5YGivi3F26Wo8SUBxAF0k++VIeprQ= 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:to :from:subject:message-id:date:mime-version:content-type; s= default; bh=CwdCz7gwoHYWsjareaKYQ2f6o5U=; b=tN73Z4Qseazl4CpjLXLw P7moCjHuzMm1jS189lGvQ9EefSTtFi7vTJTc84VotisGTmy0e+VSTsKLQb25zs1D z7uI7n5/neXWLWbXKJXuVesvKZpqZOqX9uZ1O2t7G6hum18wmQiNSWW9KB85Y6WF VuyK9dmNny2AGrkgRm/u2ZI= Received: (qmail 47059 invoked by alias); 17 Jul 2017 16:55:29 -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 46216 invoked by uid 89); 17 Jul 2017 16:55:28 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.6 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy=generous, privacy X-HELO: mail-yb0-f181.google.com Received: from mail-yb0-f181.google.com (HELO mail-yb0-f181.google.com) (209.85.213.181) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 17 Jul 2017 16:55:27 +0000 Received: by mail-yb0-f181.google.com with SMTP id 70so2244300ybn.2 for ; Mon, 17 Jul 2017 09:55:26 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:to:from:subject:message-id:date :user-agent:mime-version:content-language; bh=tqcezhnyeoRjBz0ahQ0mgZIkBQsECptn6tu43E9ETRY=; b=CtCuoaHzl14QbBhd6cAJb6WGV4U1fmrhNfTjK1EOX7DVKy3mcIojwQ1pnMdo8a5QJX Cghj4A6nQMgg50U5PlvkX9Aj+MlKTmp0D1Hm0uhBSQkZ3IYPVejSKncJlGX25VlzZ6cq +AaZhtDD+Ur7hYHNNMbd14UrHAIk/CRBVM3uLYLG0M4WWSYDtYWc6XANBfECpdqW/ZRr h/1/VZpLc/unAzUWRA+zvefD1s97YDKu73tn+ZB83pX5PWq6QlBe6O5IbxDNM/vGV8kL A2Qz/L1ro+yk6aSbQi3N+u/UQ5DL8UEu8X9mZ7PXeenz+LefHqJ/9Bbn36cpB94RykJ3 h0yQ== X-Gm-Message-State: AIVw1132VAQA3iUqZ9badmPPL6yZlNnnABxMNmV1XI/nfPEjnM2fb9i5 e2FyybeGBZ9Hjg== X-Received: by 10.37.57.86 with SMTP id g83mr4961555yba.53.1500310525339; Mon, 17 Jul 2017 09:55:25 -0700 (PDT) Received: from ?IPv6:2620:10d:c0a3:20fb:7500:e7fb:4a6f:2254? ([2620:10d:c091:200::3:fb48]) by smtp.googlemail.com with ESMTPSA id v84sm5157383ywb.67.2017.07.17.09.55.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 17 Jul 2017 09:55:24 -0700 (PDT) To: GCC Patches From: Nathan Sidwell Subject: [C++ PATCH] ctor privacy Message-ID: <41d815d8-c023-b804-7d4e-f363b52958ce@acm.org> Date: Mon, 17 Jul 2017 12:55:22 -0400 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Thunderbird/52.2.1 MIME-Version: 1.0 While futzing around with ctor lookup I discovered this warning about overly-private classes. Originally we'd allow a public copy-ctor to be sufficiently public, but as the comment says, you need an already-constructed object for that to work. so this implements that check -- public copy or move ctors do not make the class sufficiently public. I didn't implement the further suggested check of ignoring a ctor that takes an already constructed object -- be it copy ctor or not. applied to trunk. nathan 2017-07-17 Nathan Sidwell * class.c (maybe_warn_about_overly_private_class): Ignore public copy ctors. * g++.dg/warn/ctor-dtor-privacy-3.C: New. Index: cp/class.c =================================================================== --- cp/class.c (revision 250280) +++ cp/class.c (working copy) @@ -2240,10 +2240,10 @@ maybe_warn_about_overly_private_class (t /* Warn about classes that have private constructors and no friends. */ if (TYPE_HAS_USER_CONSTRUCTOR (t) /* Implicitly generated constructors are always public. */ - && (!CLASSTYPE_LAZY_DEFAULT_CTOR (t) - || !CLASSTYPE_LAZY_COPY_CTOR (t))) + && !CLASSTYPE_LAZY_DEFAULT_CTOR (t)) { bool nonprivate_ctor = false; + tree copy_or_move = NULL_TREE; /* If a non-template class does not define a copy constructor, one is defined for it, enabling it to avoid @@ -2260,13 +2260,15 @@ maybe_warn_about_overly_private_class (t else for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); !nonprivate_ctor && iter; ++iter) - /* Ideally, we wouldn't count copy constructors (or, in - fact, any constructor that takes an argument of the class - type as a parameter) because such things cannot be used - to construct an instance of the class unless you already - have one. But, for now at least, we're more - generous. */ - if (! TREE_PRIVATE (*iter)) + if (TREE_PRIVATE (*iter)) + continue; + else if (copy_fn_p (*iter) || move_fn_p (*iter)) + /* Ideally, we wouldn't count any constructor that takes + an argument of the class type as a parameter, because + such things cannot be used to construct an instance of + the class unless you already have one. */ + copy_or_move = *iter; + else nonprivate_ctor = true; if (!nonprivate_ctor) @@ -2274,6 +2276,10 @@ maybe_warn_about_overly_private_class (t warning (OPT_Wctor_dtor_privacy, "%q#T only defines private constructors and has no friends", t); + if (copy_or_move) + inform (DECL_SOURCE_LOCATION (copy_or_move), + "%q#D is public, but requires an existing %q#T object", + copy_or_move, t); return; } } Index: testsuite/g++.dg/warn/ctor-dtor-privacy-3.C =================================================================== --- testsuite/g++.dg/warn/ctor-dtor-privacy-3.C (revision 0) +++ testsuite/g++.dg/warn/ctor-dtor-privacy-3.C (working copy) @@ -0,0 +1,20 @@ +// { dg-do compile { target c++11 } } +// { dg-additional-options "-Wctor-dtor-privacy" } + +class X // { dg-message "only defines private" } +{ +public: + X (X const &); // { dg-message "requires an existing" } +}; + +class Y // { dg-message "only defines private" } +{ +public: + Y (Y &&); // { dg-message "requires an existing" } +}; + +class Z +{ +public: + Z (int); +};