Message ID | 1511368867-19365-5-git-send-email-simon.marchi@ericsson.com |
---|---|
State | New, archived |
Headers |
Received: (qmail 17442 invoked by alias); 22 Nov 2017 16:42:19 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: <gdb-patches.sourceware.org> List-Unsubscribe: <mailto:gdb-patches-unsubscribe-##L=##H@sourceware.org> List-Subscribe: <mailto:gdb-patches-subscribe@sourceware.org> List-Archive: <http://sourceware.org/ml/gdb-patches/> List-Post: <mailto:gdb-patches@sourceware.org> List-Help: <mailto:gdb-patches-help@sourceware.org>, <http://sourceware.org/ml/#faqs> Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 16792 invoked by uid 89); 22 Nov 2017 16:42:18 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, KB_WAM_FROM_NAME_SINGLEWORD, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: sesbmg22.ericsson.net Received: from sesbmg22.ericsson.net (HELO sesbmg22.ericsson.net) (193.180.251.48) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 22 Nov 2017 16:42:16 +0000 Received: from ESESSHC023.ericsson.se (Unknown_Domain [153.88.183.87]) by sesbmg22.ericsson.net (Symantec Mail Security) with SMTP id 0D.DA.09556.5E8A51A5; Wed, 22 Nov 2017 17:42:14 +0100 (CET) Received: from EUR01-DB5-obe.outbound.protection.outlook.com (153.88.183.145) by oa.msg.ericsson.com (153.88.183.87) with Microsoft SMTP Server (TLS) id 14.3.352.0; Wed, 22 Nov 2017 17:42:13 +0100 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=simon.marchi@ericsson.com; Received: from elxacz23q12.ericsson.se (129.192.64.65) by AMSPR07MB312.eurprd07.prod.outlook.com (2a01:111:e400:802f::24) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256) id 15.20.260.2; Wed, 22 Nov 2017 16:41:59 +0000 From: Simon Marchi <simon.marchi@ericsson.com> To: <gdb-patches@sourceware.org> CC: Simon Marchi <simon.marchi@polymtl.ca> Subject: [PATCH 4/4] Poison XNEW and friends for types that should use new/delete Date: Wed, 22 Nov 2017 11:41:07 -0500 Message-ID: <1511368867-19365-5-git-send-email-simon.marchi@ericsson.com> In-Reply-To: <1511368867-19365-1-git-send-email-simon.marchi@ericsson.com> References: <1511368867-19365-1-git-send-email-simon.marchi@ericsson.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-ClientProxiedBy: MWHPR17CA0061.namprd17.prod.outlook.com (2603:10b6:300:93::23) To AMSPR07MB312.eurprd07.prod.outlook.com (2a01:111:e400:802f::24) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-Correlation-Id: 92057144-1c92-440e-34ff-08d531c7f628 X-Microsoft-Antispam: UriScan:; BCL:0; PCL:0; RULEID:(5600022)(4604075)(4534020)(4602075)(4627115)(201703031133081)(201702281549075)(2017052603258); SRVR:AMSPR07MB312; X-Microsoft-Exchange-Diagnostics: 1; AMSPR07MB312; 3:aShW3AzDeqPafZhOHoqcEvfOv08PBuCkmmKuIEg/Y5oCVjmOFPOMDbLbGevizEyjN0pbCT1jduof4c/9QB0skatvz8mfJml1zD+iy1vrzIJZSrFTSl2dxJrEcCwmzhB55R4HY6xeHDkXwIPwzDJ0mm56ohlTaPFx3/xYSa5b1DcXD+7LRkkFQSGaqJoOV7kKCfjVQ3DLh3ZIWbHweBKdW+0coL9RbeK5+7q+BN2Yz4PdB1hxTSWYGe2ACq2Q5vTE; 25:HEwVIcwF3VMKl4cmoY+gAFS2CyK4J8tatYscQyyEhlHkBxSthsonZ4PDK4lCC7T85z8RTxyR5xqmeWbRoOvqkICYQoeZ+3/hmm/OiqZ8FBb3+EirYhd73PfK8w/6PVXHcwDnHQTyQ7urgMzJM3Z0sckTic8GukShQf69FbtNTI5OVC5wZI8KhGW1jb6eMQ7+dVnquMDXPHI4xaCDTlJKsA1sCXeP/2f+JGlkaCfFG16wELbCo7MCmw984LtVGNNqaYIpjUAvYufkSQNKrQR3ypBePfDf62Tf2MvpYUt9yfvkHnSCDqZtf7nb58/v7doD1Qq0Nx6HFyMGSM8xsIOFmaxvnUVVopSXNjK3cpclxp4=; 31:tWNYZUCd3QgUdFf9K+7LsFTy8C95imaRlsK1HIMFSOdAaEJCQC7ITC3sifqR0kJbyNtBYTf2OVIhXQXwskqE9HGYCy9WC7C5vyCvsjPFgSVin0nL+fVtuD89ct/E7tDXCITRVWwbt2eU47yYffrmaixV3MKz2sQ09XGkPuTlfVE26f5VEhQFR1b++JKpYp5vFQEdqtCK4ts3OA9R+iQRp8yFIdgXCqGP3sJHdTL8yQA= X-MS-TrafficTypeDiagnostic: AMSPR07MB312: X-Microsoft-Exchange-Diagnostics: 1; AMSPR07MB312; 20:reZhJGyKL6jCfH2pNtuxCRuXGMV+kFPoHYM6vTW/5+YQQuDNh3Pg4BikbkcU7PRl7ikhp8TuRtWESaXK6W7eiPDqAJzaKLxKzKRX+fWK9943kophrW0qU9ghX+J24X5ISmJJxCucQTgMZm3IlK87784VCsc6EPC6/9XAA8x/AnO/ibati8d2GVZsGaTmKAdQPSXuMYbJBSBjuu2MOe3wiAbI7veRyT2PquffOHbsmPA4nF+JdwpIKCoobT1JP07y0eE1LhEPmLvlDagvD8b8EvF4bULZlemA4ssx5B/QGAHSicoHxMnbbkOcowc6XZugfePig806DM8RHfem+EEF8GicmkY9VzPX1DRAFyj7xvfM5ycef01c/E2F0M0HYucB0xBFSLI8NEIcZROjF/bC3uDNa3L9VgqLZa1n3A6l7NAWwSK0B1Ny8LTwHW4wZv1thrfZIJnAi/ufd2MKlMb9Hi1V6FRg7yl7TwXGA52PZ/A7A756E/8zZBOUf1morLKb; 4:46PH73lX5xbbhg5yVXylHzdKSKsaZDpOZ7Er00ZisZXkyNKmNA4SXHWZcgBs/VuI/34QblK8UURj68PF4YE4SUHN8wYS54OED0j8JkX5mxoSa2nfN+UJ6iLmEKEvBN+yugIoqm6ZIZv3hVFVSKSw8Sglbeh+suf46oZB6fwqOBub1a9tcNzWEyMMPOTHtnMoiL3lYY1ddtKXsg2b4G9xPMQraIOXx75b05bX1QOvbHhAXf9wFe8vHqyMlkU78sx1ayDbeNludnm46L/dmaqD+A== X-Microsoft-Antispam-PRVS: <AMSPR07MB312575533CDB301426E899AED200@AMSPR07MB312.eurprd07.prod.outlook.com> X-Exchange-Antispam-Report-Test: UriScan:; X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(100000700101)(100105000095)(100000701101)(100105300095)(100000702101)(100105100095)(6040450)(2401047)(5005006)(8121501046)(100000703101)(100105400095)(10201501046)(3002001)(3231022)(93006095)(93001095)(6041248)(20161123560025)(20161123558100)(20161123555025)(20161123562025)(20161123564025)(201703131423075)(201702281528075)(201703061421075)(201703061406153)(6072148)(201708071742011)(100000704101)(100105200095)(100000705101)(100105500095); SRVR:AMSPR07MB312; BCL:0; PCL:0; RULEID:(100000800101)(100110000095)(100000801101)(100110300095)(100000802101)(100110100095)(100000803101)(100110400095)(100000804101)(100110200095)(100000805101)(100110500095); SRVR:AMSPR07MB312; X-Forefront-PRVS: 0499DAF22A X-Forefront-Antispam-Report: SFV:NSPM; SFS:(10009020)(6009001)(346002)(376002)(39860400002)(199003)(189002)(54534003)(4326008)(2351001)(81166006)(97736004)(2361001)(5660300001)(25786009)(7736002)(106356001)(2870700001)(50466002)(66066001)(23676004)(189998001)(50226002)(33646002)(68736007)(305945005)(101416001)(16526018)(8676002)(36756003)(53936002)(6512007)(316002)(69596002)(81156014)(53416004)(6506006)(2950100002)(6116002)(6486002)(2906002)(50986999)(47776003)(76176999)(105586002)(86362001)(478600001)(6916009)(8936002)(3846002)(6666003); DIR:OUT; SFP:1101; SCL:1; SRVR:AMSPR07MB312; H:elxacz23q12.ericsson.se; FPR:; SPF:None; PTR:InfoNoRecords; A:1; MX:1; LANG:en; Received-SPF: None (protection.outlook.com: ericsson.com does not designate permitted sender hosts) X-Microsoft-Exchange-Diagnostics: =?utf-8?B?MTtBTVNQUjA3TUIzMTI7MjM6K1ZEbzhieGpZNjNYYzQwYy9jSUxVTmF4emY2?= =?utf-8?B?VFRyS1VVOFRRWTdIUHRPZENYUkNPQlFKaDNSZ01CQTVFeUNHelIxVklBS2xr?= =?utf-8?B?VThPc3ZnMnpmcU1lMnBrZHBZZkxFZDhGWUUrNlljZFZpRjErR2NkQ09ERVNQ?= =?utf-8?B?KzlHZkhLeldLZG8wZzV3ckQ1VVd2bEw5bDBubENuellhUFFGbkloT0JlVVgx?= =?utf-8?B?WVZtVk9JSlI1MmU3Z2ZjcFI2SS9GUXVYbzhZK2VrV1Z5K2xsSnI1YXgwWVE1?= =?utf-8?B?b2liT1pWVkVKS25JSUlxQ1pXNm1tUGxmYXBWN2xIQXFFVUpNUWhrcFhtZU82?= =?utf-8?B?RWMvTzRXWHhzbnp5QkpqeXlTODVnSlliOG1xSW81V2ZSbEYrTEZtdlBoMXNS?= =?utf-8?B?VmRsZGdmWnVhc0JOQUFjSmlnd2lLb3FsdHd3SWpFT0tpQUtZSS81R2I4UExV?= =?utf-8?B?ZEdHbzNUd2c5SUphR1V4YzF5OEt1bWVFSmNTWm1qOWFEL0tHQjdRdE9aSU1p?= =?utf-8?B?L3RHL0t5dTZxSy90dll4L0JUQVlFbzgwM3MxR0hpWmt3SE05OWJPUWVZSHBO?= =?utf-8?B?VEFHdCtXUnhHazNrUFQvK3U1UnZ4VHowSFMrSlArRTczd21BVFZ4TnhvdWY0?= =?utf-8?B?QXJUSzMxZFpNazZqM3pPSDRNcmlHTFBpT25FUVFlVVpPMEZJZ1FabGhjZHpI?= =?utf-8?B?S21IcUk4S2tyajZEOWhqQWZ2d2ZrU1VPWUNyeXB3dkxPKzFyRE52L2tLdGsx?= =?utf-8?B?ZmZRNGdhN2NuR1F5YUo3V0lOZDYzRHF2MGRvekpvLy9FNEpFaC9LZDhWQ2ow?= =?utf-8?B?U2crZk9tOXphbUswV1NtdVFUdVBiS0dCdXVPU2NjMU9yemtaOW0rQ1k1dEZl?= =?utf-8?B?ZCt4L0pqcGtRY0NuSkliSUtHOWRRZmtCVG80UFZuL3RiTXUrZ0ZRVEdpVnJo?= =?utf-8?B?dnlOUkpETXFWU0RFbDdGb1JJTDNRV283K0VuRUhNV0xWUzJTMWlpUGhWcW55?= =?utf-8?B?UW13bWpOSDZ1T1l2SUtJcWpvaEtDaURzdEd5QVpnL2pBRElJT2tyR0x0Z2dY?= =?utf-8?B?NnNPWEN3U0Y3bGh0c3Fqay9VQ1lSWWtXNHA2NTJCVU5kRmsxdEFWMDE0RFRH?= =?utf-8?B?TGJjNnBPV2M5cXJvcThHeG1EUi9iU3E5K0NCVVJld0JGUm8wZm5tU2YwUHp5?= =?utf-8?B?VVdabVMzNGE1WnZDZGNCc3NpUzV0QmJGbVZtZDdKZzlJamFkTGNtaTRLMzE0?= =?utf-8?B?QUVOUTR3SC9mcmFoRm1OWHNJeUluS0k1YkhuQmwyVk5tRzJnUjBOOFI4cEtm?= =?utf-8?B?dnQyZ3JTdmFTbTA0d1l1QjlhYjVWazBLN1hmQXNPeGpUVk82RTNZeWFDcXlM?= =?utf-8?B?NVJhUFpBdk05YmhQMnpXRDc3NHdMRFlVY3RUWi9tcU0vOXJLOU55NXNSWmRq?= =?utf-8?B?NkpSV3NyZTZMUHdUVWNWOEtvUXdQU3ZmU1RBK0dGc0FwbXgvL2hIR1ZFT2E0?= =?utf-8?B?eTRZR08vc242L2U2M09QQzIrRm1yQ2FhOUlmZnJ4c1lMaUhXMENMV3ZpMmVD?= =?utf-8?B?ZTdDdW96RWtUZFJNQnFhTjFncHpDUT09?= X-Microsoft-Exchange-Diagnostics: 1; AMSPR07MB312; 6:TTy2lu63BodDeAJy+/zdcoJnKE+jLKZTUOUAayraIrY0DON2164A+HYtvMl1MZfMSAdue6aJmP9l10jGoPsVg2Q2teBxiE5SuNzBUPZAzA4fN1ks/F7KQnQIZ6WskgPjQSa2Av3SPazg5TertkqkQ8OWcUXfJeHbVzXTj9ksZR6X6U00wg/31bF8BwhoXO5J2jo3usjIBPdwy1SdwKgtLMC1v9IUoieu8oaSiUJ/hWG1V2qijuPJYYSBXMs+NzpXRZDEGUkib1dpXPU92FZEZ7mjVE7brHpDZ1XT6LmFfnQ7X0r+Bq/Z4M9QWRhqfAFvMbk1PHocGRR149Ewp5SDizvoHoNXm9JPTgaBp5SvNBw=; 5:cEjPGlFLWeVhpPNtqqN3EUBfxUG4c1AhX3otWFJ+P+TSElJ8fiGNZgus5uYlEUOLTFlbAmz/ykvC34Z39Zi4KJ4pIsgjnQ2+ZQO4714eXUW7X+sNNeWSyai8x41bPqNUE+2Pd5eIReMZxAlO0eFxkHiMk9lBKckSFQO0eTy7wtY=; 24:02Rbg7g/04ApkLL355YUKFAACoBxmEUYd8vcrX9QHO0mE7qNzto4BLc0C7lDMP0DLL1NPCjWTNXPM4uIpjJre1YU3HrQXkbmtEWbHgQyM7Y=; 7:Hs7ZW0DydJckBYQ+g5vVLrPgwWg/IORf8HvceCBeSUuEAxxcyn2KrqyUhTqnrtbZAT02mImH6ECD/RXNhm9Zb5+jSzwULi3LuHZJSj/ErGhKygBq2IEyFY6prR9VOz3kMnIbCtvpW/kHVbGDjFZFm3unwxC46psirhwzcojpt3xSpIaXY2C1vVXLVyNx9CfzW8jh0hJpJ3+WiNyR99ajv+S9Fs4IxIIhglz/6Mnq+xSy1PhyrXzjvrm22OMR8xES SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-MS-Exchange-CrossTenant-OriginalArrivalTime: 22 Nov 2017 16:41:59.7126 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 92057144-1c92-440e-34ff-08d531c7f628 X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-Transport-CrossTenantHeadersStamped: AMSPR07MB312 X-OriginatorOrg: ericsson.com X-IsSubscribed: yes |
Commit Message
Simon Marchi
Nov. 22, 2017, 4:41 p.m. UTC
From: Simon Marchi <simon.marchi@polymtl.ca>
This patch (finally!) makes it so that trying to use XNEW with a type
that requires "new" will cause a compilation error. The criterion I
initially used to allow a type to use XNEW (which calls malloc in the
end) was std::is_trivially_constructible, but then realized that gcc 4.8
did not have it. Instead, I went with:
using IsMallocatable = std::is_pod<T>;
which is just a bit more strict, which doesn't hurt. A similar thing is
done for macros that free instead of allocated, the criterion is:
using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>;
For simplicity, we could also do for std::is_pod for IsFreeable as well,
if you prefer.
I chose to put static_assert in the functions, instead of using
gdb::Requires in the template as SFINAE, because it allows to put a
message, which I think makes the compiler error more understandable.
With gdb::Requires, the error is:
In file included from /home/simark/src/binutils-gdb/gdb/common/common-utils.h:26:0,
from /home/simark/src/binutils-gdb/gdb/common/common-defs.h:78,
from /home/simark/src/binutils-gdb/gdb/defs.h:28,
from /home/simark/src/binutils-gdb/gdb/lala.c:1:
/home/simark/src/binutils-gdb/gdb/lala.c: In function ‘void foo()’:
/home/simark/src/binutils-gdb/gdb/common/poison.h:108:25: error: no matching function for call to ‘xnew<bar>()’
#define XNEW(T) xnew<T>()
^
/home/simark/src/binutils-gdb/gdb/lala.c:13:3: note: in expansion of macro ‘XNEW’
XNEW(bar);
^~~~
/home/simark/src/binutils-gdb/gdb/common/poison.h:101:1: note: candidate: template<class T, typename std::enable_if<std::is_trivially_constructible<_Tp>::value, void>::type <anonymous> > T* xnew()
xnew ()
^~~~
/home/simark/src/binutils-gdb/gdb/common/poison.h:101:1: note: template argument deduction/substitution failed:
/home/simark/src/binutils-gdb/gdb/common/poison.h:108:25: note: couldn't deduce template parameter ‘<anonymous>’
#define XNEW(T) xnew<T>()
^
/home/simark/src/binutils-gdb/gdb/lala.c:13:3: note: in expansion of macro ‘XNEW’
XNEW(bar);
^~~~
and with static_assert:
In file included from /home/simark/src/binutils-gdb/gdb/common/common-utils.h:26:0,
from /home/simark/src/binutils-gdb/gdb/common/common-defs.h:78,
from /home/simark/src/binutils-gdb/gdb/defs.h:28,
from /home/simark/src/binutils-gdb/gdb/lala.c:1:
/home/simark/src/binutils-gdb/gdb/common/poison.h: In instantiation of ‘T* xnew() [with T = bar]’:
/home/simark/src/binutils-gdb/gdb/lala.c:13:3: required from here
/home/simark/src/binutils-gdb/gdb/common/poison.h:103:3: error: static assertion failed: Trying to use XNEW with a non-POD data type. Use operator new instead.
static_assert (IsMallocatable<T>::value, "Trying to use XNEW with a non-POD\
^~~~~~~~~~~~~
I think the first one is more likely to just make people yell at their
screen, especially those less used to C++.
Generated-code-wise, it adds one more function call (xnew<T>) when using
XNEW and building with -O0, but it all goes away with optimizations
enabled.
gdb/ChangeLog:
* common/common-utils.h: Include poison.h.
(xfree): Remove declaration, add definition with static_assert.
* common/common-utils.c (xfree): Remove.
* common/poison.h (IsMallocatable): Define.
(IsFreeable): Define.
(free): Delete for non-freeable types.
(xnew): New.
(XNEW): Undef and redefine.
(xcnew): New.
(XCNEW): Undef and redefine.
(xdelete): New.
(XDELETE): Undef and redefine.
(xnewvec): New.
(XNEWVEC): Undef and redefine.
(xcnewvec): New.
(XCNEWVEC): Undef and redefine.
(xresizevec): New.
(XRESIZEVEC): Undef and redefine.
(xdeletevec): New.
(XDELETEVEC): Undef and redefine.
(xnewvar): New.
(XNEWVAR): Undef and redefine.
(xcnewvar): New.
(XCNEWVAR): Undef and redefine.
(xresizevar): New.
(XRESIZEVAR): Undef and redefine.
---
gdb/common/common-utils.c | 7 ---
gdb/common/common-utils.h | 14 ++++-
gdb/common/poison.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 145 insertions(+), 8 deletions(-)
Comments
On 11/22/2017 04:41 PM, Simon Marchi wrote: > From: Simon Marchi <simon.marchi@polymtl.ca> > > This patch (finally!) makes it so that trying to use XNEW with a type > that requires "new" will cause a compilation error. Yay! The criterion I > initially used to allow a type to use XNEW (which calls malloc in the > end) was std::is_trivially_constructible, but then realized that gcc 4.8 > did not have it. Instead, I went with: > Yeah, in the memset poisoning I just disabled the poisoning on older compilers. This is the "#if HAVE_IS_TRIVIALLY_COPYABLE" check in poison.h. > using IsMallocatable = std::is_pod<T>; > Nit, I think "malloc-able" is more common than "malloc-atable". At least, the latter sounds odd to me. Or sounds like "m-allocatable", which is a different thing. :-) > which is just a bit more strict, which doesn't hurt. A similar thing is > done for macros that free instead of allocated, the criterion is: > > using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>; > > For simplicity, we could also do for std::is_pod for IsFreeable as well, > if you prefer. > > I chose to put static_assert in the functions, instead of using > gdb::Requires in the template as SFINAE, because it allows to put a > message, which I think makes the compiler error more understandable. > With gdb::Requires, the error is: Right, I think static_assert is what I had suggest initially too. SFINAE alone wouldn't sound right to me here. The right alternative to static_assert would be SFINAE+"=delete;", which is what we do for the memcpy/memcpy poisoning, and what you're doing to "free". =delete keeps the function/overload in the overload set, serving as "honeypot", so you get an error about trying to call a deleted function. You could do that to xfree instead of the static_assert, but I guess inlining xfree ends up being a good thing. > I think the first one is more likely to just make people yell at their > screen, especially those less used to C++. Yes, don't do that. :-) > > Generated-code-wise, it adds one more function call (xnew<T>) when using > XNEW and building with -O0, but it all goes away with optimizations > enabled. Good. > > gdb/ChangeLog: > > * common/common-utils.h: Include poison.h. > (xfree): Remove declaration, add definition with static_assert. > * common/common-utils.c (xfree): Remove. > * common/poison.h (IsMallocatable): Define. > (IsFreeable): Define. > (free): Delete for non-freeable types. > (xnew): New. > (XNEW): Undef and redefine. > (xcnew): New. > (XCNEW): Undef and redefine. > (xdelete): New. > (XDELETE): Undef and redefine. > (xnewvec): New. > (XNEWVEC): Undef and redefine. > (xcnewvec): New. > (XCNEWVEC): Undef and redefine. > (xresizevec): New. > (XRESIZEVEC): Undef and redefine. > (xdeletevec): New. > (XDELETEVEC): Undef and redefine. > (xnewvar): New. > (XNEWVAR): Undef and redefine. > (xcnewvar): New. > (XCNEWVAR): Undef and redefine. > (xresizevar): New. > (XRESIZEVAR): Undef and redefine. > --- > gdb/common/common-utils.c | 7 --- > gdb/common/common-utils.h | 14 ++++- > gdb/common/poison.h | 132 ++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 145 insertions(+), 8 deletions(-) > > diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c > index 7139302..66d6161 100644 > --- a/gdb/common/common-utils.c > +++ b/gdb/common/common-utils.c > @@ -95,13 +95,6 @@ xzalloc (size_t size) > } > > void > -xfree (void *ptr) > -{ > - if (ptr != NULL) > - free (ptr); /* ARI: free */ > -} > - > -void > xmalloc_failed (size_t size) > { > malloc_failure (size); > diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h > index 4926a32..feb4790 100644 > --- a/gdb/common/common-utils.h > +++ b/gdb/common/common-utils.h > @@ -23,6 +23,8 @@ > #include <string> > #include <vector> > > +#include "poison.h" > + > /* If possible, define FUNCTION_NAME, a macro containing the name of > the function being defined. Since this macro may not always be > defined, all uses must be protected by appropriate macro definition > @@ -47,7 +49,17 @@ > /* Like xmalloc, but zero the memory. */ > void *xzalloc (size_t); > > -void xfree (void *); > +template <typename T> > +static void > +xfree (T *ptr) > +{ > + static_assert (IsFreeable<T>::value, "Trying to use xfree with a non-POD \ > +data type. Use operator delete instead."); > + > + if (ptr != NULL) > + free (ptr); /* ARI: free */ > +} > + > > /* Like asprintf and vasprintf, but return the string, throw an error > if no memory. */ > diff --git a/gdb/common/poison.h b/gdb/common/poison.h > index 37dd35e..de4cefa 100644 > --- a/gdb/common/poison.h > +++ b/gdb/common/poison.h > @@ -84,4 +84,136 @@ void *memmove (D *dest, const S *src, size_t n) = delete; > > #endif /* HAVE_IS_TRIVIALLY_COPYABLE */ > > +/* Poison XNEW and friends to catch usages of malloc-style allocations on > + objects that require new/delete. */ > + > +template<typename T> > +using IsMallocatable = std::is_pod<T>; > + > +template<typename T> > +using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>; > + > +template <typename T, typename = gdb::Requires<gdb::Not<IsFreeable<T>>>> > +void free (T *ptr) = delete; > + > +template<typename T> > +static T * > +xnew () > +{ > + static_assert (IsMallocatable<T>::value, "Trying to use XNEW with a non-POD \ > +data type. Use operator new instead."); > + return XNEW (T); > +} > + > +#undef XNEW > +#define XNEW(T) xnew<T>() > + > +template<typename T> > +static T * > +xcnew () > +{ > + static_assert (IsMallocatable<T>::value, "Trying to use XCNEW with a non-POD \ > +data type. Use operator new instead."); > + return XCNEW (T); > +} > + > +#undef XCNEW > +#define XCNEW(T) xcnew<T>() > + > +template<typename T> > +static void > +xdelete (T *p) > +{ > + static_assert (IsFreeable<T>::value, "Trying to use XDELETE with a non-POD \ > +data type. Use operator delete instead."); > + XDELETE (p); > +} > + > +#undef XDELETE > +#define XDELETE(P) xdelete (p) > + > +template<typename T> > +static T* Missing space after T in several of these functions. > +xnewvec (size_t n) > +{ > + static_assert (IsMallocatable<T>::value, "Trying to use XNEWVEC with a \ > +non-POD data type. Use operator new[] (or std::vector) instead."); > + return XNEWVEC (T, n); > +} > + Other than the formatting, this LGTM. Thanks a lot for doing this. Thanks, Pedro Alves
On 2017-11-23 10:02, Pedro Alves wrote: > On 11/22/2017 04:41 PM, Simon Marchi wrote: >> From: Simon Marchi <simon.marchi@polymtl.ca> >> >> This patch (finally!) makes it so that trying to use XNEW with a type >> that requires "new" will cause a compilation error. > > Yay! > > The criterion I >> initially used to allow a type to use XNEW (which calls malloc in the >> end) was std::is_trivially_constructible, but then realized that gcc >> 4.8 >> did not have it. Instead, I went with: >> > > Yeah, in the memset poisoning I just disabled the poisoning on older > compilers. This is the "#if HAVE_IS_TRIVIALLY_COPYABLE" check in > poison.h. I'm not sure if you are suggesting adding HAVE_IS_TRIVIALLY_CONSTRUCTIBLE, but since we can use std::is_pod easily, I think it's simpler just to use that (even if it's a bit more strict than needed). >> using IsMallocatable = std::is_pod<T>; >> > > Nit, I think "malloc-able" is more common than "malloc-atable". > At least, the latter sounds odd to me. Or sounds like > "m-allocatable", which is a different thing. :-) Agreed. > >> which is just a bit more strict, which doesn't hurt. A similar thing >> is >> done for macros that free instead of allocated, the criterion is: >> >> using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, >> std::is_void<T>>; >> >> For simplicity, we could also do for std::is_pod for IsFreeable as >> well, >> if you prefer. >> >> I chose to put static_assert in the functions, instead of using >> gdb::Requires in the template as SFINAE, because it allows to put a >> message, which I think makes the compiler error more understandable. >> With gdb::Requires, the error is: > > Right, I think static_assert is what I had suggest initially too. > SFINAE alone wouldn't sound right to me here. > > The right alternative to static_assert would be SFINAE+"=delete;", > which is what we do for the memcpy/memcpy poisoning, and what > you're doing to "free". > > =delete keeps the function/overload in the overload set, serving > as "honeypot", so you get an error about trying to call a > deleted function. > > You could do that to xfree instead > of the static_assert, but I guess inlining xfree ends up being > a good thing. Ah yeah, it would probably make the message a bit clearer. Instead of saying "I can't find a function that matches", it would say "I found a function that matches, but you can't use it". I'll just keep static_assert for xfree as well, since it ends up clearer anyway. >> I think the first one is more likely to just make people yell at their >> screen, especially those less used to C++. > > Yes, don't do that. :-) > >> >> Generated-code-wise, it adds one more function call (xnew<T>) when >> using >> XNEW and building with -O0, but it all goes away with optimizations >> enabled. > > Good. > >> >> gdb/ChangeLog: >> >> * common/common-utils.h: Include poison.h. >> (xfree): Remove declaration, add definition with static_assert. >> * common/common-utils.c (xfree): Remove. >> * common/poison.h (IsMallocatable): Define. >> (IsFreeable): Define. >> (free): Delete for non-freeable types. >> (xnew): New. >> (XNEW): Undef and redefine. >> (xcnew): New. >> (XCNEW): Undef and redefine. >> (xdelete): New. >> (XDELETE): Undef and redefine. >> (xnewvec): New. >> (XNEWVEC): Undef and redefine. >> (xcnewvec): New. >> (XCNEWVEC): Undef and redefine. >> (xresizevec): New. >> (XRESIZEVEC): Undef and redefine. >> (xdeletevec): New. >> (XDELETEVEC): Undef and redefine. >> (xnewvar): New. >> (XNEWVAR): Undef and redefine. >> (xcnewvar): New. >> (XCNEWVAR): Undef and redefine. >> (xresizevar): New. >> (XRESIZEVAR): Undef and redefine. >> --- >> gdb/common/common-utils.c | 7 --- >> gdb/common/common-utils.h | 14 ++++- >> gdb/common/poison.h | 132 >> ++++++++++++++++++++++++++++++++++++++++++++++ >> 3 files changed, 145 insertions(+), 8 deletions(-) >> >> diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c >> index 7139302..66d6161 100644 >> --- a/gdb/common/common-utils.c >> +++ b/gdb/common/common-utils.c >> @@ -95,13 +95,6 @@ xzalloc (size_t size) >> } >> >> void >> -xfree (void *ptr) >> -{ >> - if (ptr != NULL) >> - free (ptr); /* ARI: free */ >> -} >> - >> -void >> xmalloc_failed (size_t size) >> { >> malloc_failure (size); >> diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h >> index 4926a32..feb4790 100644 >> --- a/gdb/common/common-utils.h >> +++ b/gdb/common/common-utils.h >> @@ -23,6 +23,8 @@ >> #include <string> >> #include <vector> >> >> +#include "poison.h" >> + >> /* If possible, define FUNCTION_NAME, a macro containing the name of >> the function being defined. Since this macro may not always be >> defined, all uses must be protected by appropriate macro >> definition >> @@ -47,7 +49,17 @@ >> /* Like xmalloc, but zero the memory. */ >> void *xzalloc (size_t); >> >> -void xfree (void *); >> +template <typename T> >> +static void >> +xfree (T *ptr) >> +{ >> + static_assert (IsFreeable<T>::value, "Trying to use xfree with a >> non-POD \ >> +data type. Use operator delete instead."); >> + >> + if (ptr != NULL) >> + free (ptr); /* ARI: free */ >> +} >> + >> >> /* Like asprintf and vasprintf, but return the string, throw an error >> if no memory. */ >> diff --git a/gdb/common/poison.h b/gdb/common/poison.h >> index 37dd35e..de4cefa 100644 >> --- a/gdb/common/poison.h >> +++ b/gdb/common/poison.h >> @@ -84,4 +84,136 @@ void *memmove (D *dest, const S *src, size_t n) = >> delete; >> >> #endif /* HAVE_IS_TRIVIALLY_COPYABLE */ >> >> +/* Poison XNEW and friends to catch usages of malloc-style >> allocations on >> + objects that require new/delete. */ >> + >> +template<typename T> >> +using IsMallocatable = std::is_pod<T>; >> + >> +template<typename T> >> +using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, >> std::is_void<T>>; >> + >> +template <typename T, typename = >> gdb::Requires<gdb::Not<IsFreeable<T>>>> >> +void free (T *ptr) = delete; >> + >> +template<typename T> >> +static T * >> +xnew () >> +{ >> + static_assert (IsMallocatable<T>::value, "Trying to use XNEW with a >> non-POD \ >> +data type. Use operator new instead."); >> + return XNEW (T); >> +} >> + >> +#undef XNEW >> +#define XNEW(T) xnew<T>() >> + >> +template<typename T> >> +static T * >> +xcnew () >> +{ >> + static_assert (IsMallocatable<T>::value, "Trying to use XCNEW with >> a non-POD \ >> +data type. Use operator new instead."); >> + return XCNEW (T); >> +} >> + >> +#undef XCNEW >> +#define XCNEW(T) xcnew<T>() >> + >> +template<typename T> >> +static void >> +xdelete (T *p) >> +{ >> + static_assert (IsFreeable<T>::value, "Trying to use XDELETE with a >> non-POD \ >> +data type. Use operator delete instead."); >> + XDELETE (p); >> +} >> + >> +#undef XDELETE >> +#define XDELETE(P) xdelete (p) >> + >> +template<typename T> >> +static T* > > Missing space after T in several of these functions. Oops, thanks. >> +xnewvec (size_t n) >> +{ >> + static_assert (IsMallocatable<T>::value, "Trying to use XNEWVEC >> with a \ >> +non-POD data type. Use operator new[] (or std::vector) instead."); >> + return XNEWVEC (T, n); >> +} >> + > > Other than the formatting, this LGTM. Thanks a lot for doing this. Thanks, I'm glad that I won't have to carry that branch on the side anymore :) Simon
On 11/23/2017 05:27 PM, Simon Marchi wrote: > On 2017-11-23 10:02, Pedro Alves wrote: >> On 11/22/2017 04:41 PM, Simon Marchi wrote: >>> From: Simon Marchi <simon.marchi@polymtl.ca> >> The criterion I >>> initially used to allow a type to use XNEW (which calls malloc in the >>> end) was std::is_trivially_constructible, but then realized that gcc 4.8 >>> did not have it. Instead, I went with: >>> >> >> Yeah, in the memset poisoning I just disabled the poisoning on older >> compilers. This is the "#if HAVE_IS_TRIVIALLY_COPYABLE" check in >> poison.h. > > I'm not sure if you are suggesting adding > HAVE_IS_TRIVIALLY_CONSTRUCTIBLE, but since we can use std::is_pod > easily, I think it's simpler just to use that (even if it's a bit more > strict than needed). Nope, I was really just stating a fact. >>> which is just a bit more strict, which doesn't hurt. A similar thing is >>> done for macros that free instead of allocated, the criterion is: >>> >>> using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, >>> std::is_void<T>>; >>> >>> For simplicity, we could also do for std::is_pod for IsFreeable as well, >>> if you prefer. >>> >>> I chose to put static_assert in the functions, instead of using >>> gdb::Requires in the template as SFINAE, because it allows to put a >>> message, which I think makes the compiler error more understandable. >>> With gdb::Requires, the error is: >> >> Right, I think static_assert is what I had suggest initially too. >> SFINAE alone wouldn't sound right to me here. >> >> The right alternative to static_assert would be SFINAE+"=delete;", >> which is what we do for the memcpy/memcpy poisoning, and what >> you're doing to "free". >> >> =delete keeps the function/overload in the overload set, serving >> as "honeypot", so you get an error about trying to call a >> deleted function. >> >> You could do that to xfree instead >> of the static_assert, but I guess inlining xfree ends up being >> a good thing. > > Ah yeah, it would probably make the message a bit clearer. Instead of > saying "I can't find a function that matches", it would say "I found a > function that matches, but you can't use it". Exactly. > I'll just keep > static_assert for xfree as well, since it ends up clearer anyway. *nod* >> Other than the formatting, this LGTM. Thanks a lot for doing this. > > Thanks, I'm glad that I won't have to carry that branch on the side > anymore :) > :-) Thanks, Pedro Alves
diff --git a/gdb/common/common-utils.c b/gdb/common/common-utils.c index 7139302..66d6161 100644 --- a/gdb/common/common-utils.c +++ b/gdb/common/common-utils.c @@ -95,13 +95,6 @@ xzalloc (size_t size) } void -xfree (void *ptr) -{ - if (ptr != NULL) - free (ptr); /* ARI: free */ -} - -void xmalloc_failed (size_t size) { malloc_failure (size); diff --git a/gdb/common/common-utils.h b/gdb/common/common-utils.h index 4926a32..feb4790 100644 --- a/gdb/common/common-utils.h +++ b/gdb/common/common-utils.h @@ -23,6 +23,8 @@ #include <string> #include <vector> +#include "poison.h" + /* If possible, define FUNCTION_NAME, a macro containing the name of the function being defined. Since this macro may not always be defined, all uses must be protected by appropriate macro definition @@ -47,7 +49,17 @@ /* Like xmalloc, but zero the memory. */ void *xzalloc (size_t); -void xfree (void *); +template <typename T> +static void +xfree (T *ptr) +{ + static_assert (IsFreeable<T>::value, "Trying to use xfree with a non-POD \ +data type. Use operator delete instead."); + + if (ptr != NULL) + free (ptr); /* ARI: free */ +} + /* Like asprintf and vasprintf, but return the string, throw an error if no memory. */ diff --git a/gdb/common/poison.h b/gdb/common/poison.h index 37dd35e..de4cefa 100644 --- a/gdb/common/poison.h +++ b/gdb/common/poison.h @@ -84,4 +84,136 @@ void *memmove (D *dest, const S *src, size_t n) = delete; #endif /* HAVE_IS_TRIVIALLY_COPYABLE */ +/* Poison XNEW and friends to catch usages of malloc-style allocations on + objects that require new/delete. */ + +template<typename T> +using IsMallocatable = std::is_pod<T>; + +template<typename T> +using IsFreeable = gdb::Or<std::is_trivially_destructible<T>, std::is_void<T>>; + +template <typename T, typename = gdb::Requires<gdb::Not<IsFreeable<T>>>> +void free (T *ptr) = delete; + +template<typename T> +static T * +xnew () +{ + static_assert (IsMallocatable<T>::value, "Trying to use XNEW with a non-POD \ +data type. Use operator new instead."); + return XNEW (T); +} + +#undef XNEW +#define XNEW(T) xnew<T>() + +template<typename T> +static T * +xcnew () +{ + static_assert (IsMallocatable<T>::value, "Trying to use XCNEW with a non-POD \ +data type. Use operator new instead."); + return XCNEW (T); +} + +#undef XCNEW +#define XCNEW(T) xcnew<T>() + +template<typename T> +static void +xdelete (T *p) +{ + static_assert (IsFreeable<T>::value, "Trying to use XDELETE with a non-POD \ +data type. Use operator delete instead."); + XDELETE (p); +} + +#undef XDELETE +#define XDELETE(P) xdelete (p) + +template<typename T> +static T* +xnewvec (size_t n) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XNEWVEC with a \ +non-POD data type. Use operator new[] (or std::vector) instead."); + return XNEWVEC (T, n); +} + +#undef XNEWVEC +#define XNEWVEC(T, N) xnewvec<T> (N) + +template<typename T> +static T* +xcnewvec (size_t n) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XCNEWVEC with a \ +non-POD data type. Use operator new[] (or std::vector) instead."); + return XCNEWVEC (T, n); +} + +#undef XCNEWVEC +#define XCNEWVEC(T, N) xcnewvec<T> (N) + +template<typename T> +static T* +xresizevec (T *p, size_t n) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XRESIZEVEC with a \ +non-POD data type."); + return XRESIZEVEC (T, p, n); +} + +#undef XRESIZEVEC +#define XRESIZEVEC(T, P, N) xresizevec<T> (P, N) + +template<typename T> +static void +xdeletevec (T *p) +{ + static_assert (IsFreeable<T>::value, "Trying to use XDELETEVEC with a \ +non-POD data type. Use operator delete[] (or std::vector) instead."); + XDELETEVEC (p); +} + +#undef XDELETEVEC +#define XDELETEVEC(P) xdeletevec (P) + +template<typename T> +static T* +xnewvar (size_t s) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XNEWVAR with a \ +non-POD data type."); + return XNEWVAR (T, s);; +} + +#undef XNEWVAR +#define XNEWVAR(T, S) xnewvar<T> (S) + +template<typename T> +static T* +xcnewvar (size_t s) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XCNEWVAR with a \ +non-POD data type."); + return XCNEWVAR (T, s); +} + +#undef XCNEWVAR +#define XCNEWVAR(T, S) xcnewvar<T> (S) + +template<typename T> +static T* +xresizevar (T *p, size_t s) +{ + static_assert (IsMallocatable<T>::value, "Trying to use XRESIZEVAR with a \ +non-POD data type."); + return XRESIZEVAR (T, p, s); +} + +#undef XRESIZEVAR +#define XRESIZEVAR(T, P, S) xresizevar<T> (P, S) + #endif /* COMMON_POISON_H */