From 0dd48296433763ba6f3a1c9068ce3991fb71e9b9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 17 Dec 2020 00:15:00 +0000 Subject: [PATCH] Add an RAII class for managing obstacks This patch adds an RAII class for managing the lifetimes of objects on an obstack. See the comments in the patch for more details and example usage. gcc/ * obstack-utils.h: New file. --- gcc/obstack-utils.h | 86 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 gcc/obstack-utils.h diff --git a/gcc/obstack-utils.h b/gcc/obstack-utils.h new file mode 100644 index 00000000000..ee389f89923 --- /dev/null +++ b/gcc/obstack-utils.h @@ -0,0 +1,86 @@ +// Obstack-related utilities. +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. +// +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. +// +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#ifndef GCC_OBSTACK_UTILS_H +#define GCC_OBSTACK_UTILS_H + +// This RAII class automatically frees memory allocated on an obstack, +// unless told not to via keep (). It automatically converts to an +// obstack, so it can (optionally) be used in place of the obstack +// to make the scoping clearer. For example: +// +// obstack_watermark watermark (ob); +// auto *ptr1 = XOBNEW (watermark, struct1); +// if (...) +// // Frees ptr1. +// return false; +// +// auto *ptr2 = XOBNEW (watermark, struct2); +// if (...) +// // Frees ptr1 and ptr2. +// return false; +// +// // Retains ptr1 and ptr2. +// watermark.keep (); +// +// auto *ptr3 = XOBNEW (watermark, struct3); +// if (...) +// // Frees ptr3. +// return false; +// +// // Retains ptr3 (in addition to ptr1 and ptr2 above). +// watermark.keep (); +// return true; +// +// The move constructor makes it possible to transfer ownership to a caller: +// +// obstack_watermark +// foo () +// { +// obstack_watermark watermark (ob); +// ... +// return watermark; +// } +// +// void +// bar () +// { +// // Inherit ownership of everything that foo allocated. +// obstack_watermark watermark = foo (); +// ... +// } +class obstack_watermark +{ +public: + obstack_watermark (obstack *ob) : m_obstack (ob) { keep (); } + constexpr obstack_watermark (obstack_watermark &&) = default; + ~obstack_watermark () { obstack_free (m_obstack, m_start); } + + operator obstack *() const { return m_obstack; } + void keep () { m_start = XOBNEWVAR (m_obstack, char, 0); } + +private: + DISABLE_COPY_AND_ASSIGN (obstack_watermark); + +protected: + obstack *m_obstack; + char *m_start; +}; + +#endif -- 2.30.2