Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions libcxx/include/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,7 @@ set(files
__utility/priority_tag.h
__utility/private_constructor_tag.h
__utility/rel_ops.h
__utility/scope_guard.h
__utility/small_buffer.h
__utility/swap.h
__utility/to_underlying.h
Expand Down
1 change: 1 addition & 0 deletions libcxx/include/__flat_map/flat_map.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
#include <__type_traits/maybe_const.h>
#include <__utility/exception_guard.h>
#include <__utility/pair.h>
#include <__utility/scope_guard.h>
#include <__vector/vector.h>
#include <initializer_list>
#include <stdexcept>
Expand Down
6 changes: 0 additions & 6 deletions libcxx/include/__utility/exception_guard.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,6 @@ _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __exception_guard<_Rollback> __make_exce
return __exception_guard<_Rollback>(std::move(__rollback));
}

template <class _Rollback>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __exception_guard_exceptions<_Rollback>
__make_scope_guard(_Rollback __rollback) {
return __exception_guard_exceptions<_Rollback>(std::move(__rollback));
}

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS
Expand Down
60 changes: 60 additions & 0 deletions libcxx/include/__utility/scope_guard.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// -*- C++ -*-
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#ifndef _LIBCPP___UTILITY_SCOPE_GUARD_H
#define _LIBCPP___UTILITY_SCOPE_GUARD_H

#include <__assert>
#include <__config>
#include <__utility/move.h>

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif

_LIBCPP_PUSH_MACROS
#include <__undef_macros>

_LIBCPP_BEGIN_NAMESPACE_STD

template <class _Func>
class __scope_guard {
_Func __func_;
bool __moved_from_;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't this used uninitialized for C++14?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you are correct. @philnik777 Can you open a PR to fix that and #116204 ?


public:
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR __scope_guard(_Func __func) : __func_(std::move(__func)) {}
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 ~__scope_guard() { __func_(); }

__scope_guard(const __scope_guard&) = delete;

// C++17 has mandatory RVO, so we don't need the move constructor anymore to make __make_scope_guard work.
#if _LIBCPP_STD_VER <= 14
__scope_guard(__scope_guard&& __other) : __func_(__other.__func_) {
_LIBCPP_ASSERT_INTERNAL(!__other.__moved_from_, "Cannot move twice from __scope_guard");
__other.__moved_from_ = true;
}
#else
__scope_guard(__scope_guard&&) = delete;
#endif

__scope_guard& operator=(const __scope_guard&) = delete;
__scope_guard& operator=(__scope_guard&&) = delete;
};

template <class _Func>
_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 __scope_guard<_Func> __make_scope_guard(_Func __func) {
return __scope_guard<_Func>(std::move(__func));
}

_LIBCPP_END_NAMESPACE_STD

_LIBCPP_POP_MACROS

#endif // _LIBCPP___UTILITY_SCOPE_GUARD_H
1 change: 1 addition & 0 deletions libcxx/include/module.modulemap
Original file line number Diff line number Diff line change
Expand Up @@ -2003,6 +2003,7 @@ module std [system] {
module priority_tag { header "__utility/priority_tag.h" }
module private_constructor_tag { header "__utility/private_constructor_tag.h" }
module rel_ops { header "__utility/rel_ops.h" }
module scope_guard { header "__utility/scope_guard.h" }
module small_buffer { header "__utility/small_buffer.h" }
module swap { header "__utility/swap.h" }
module to_underlying { header "__utility/to_underlying.h" }
Expand Down
21 changes: 15 additions & 6 deletions libcxx/include/string
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,7 @@ basic_string<char32_t> operator""s( const char32_t *str, size_t len );
#include <__utility/forward.h>
#include <__utility/is_pointer_in_range.h>
#include <__utility/move.h>
#include <__utility/scope_guard.h>
#include <__utility/swap.h>
#include <__utility/unreachable.h>
#include <climits>
Expand Down Expand Up @@ -929,6 +930,15 @@ private:

_LIBCPP_COMPRESSED_PAIR(__rep, __rep_, allocator_type, __alloc_);

// annotate the string with its size() at scope exit. The string has to be in a valid state at that point.
struct __annotate_new_size {
basic_string& __str_;

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 __annotate_new_size(basic_string& __str) : __str_(__str) {}

_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void operator()() { __str_.__annotate_new(__str_.size()); }
};

// Construct a string with the given allocator and enough storage to hold `__size` characters, but
// don't initialize the characters. The contents of the string, including the null terminator, must be
// initialized separately.
Expand Down Expand Up @@ -2171,6 +2181,7 @@ private:
__alloc_ = __str.__alloc_;
} else {
__annotate_delete();
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
allocator_type __a = __str.__alloc_;
auto __allocation = std::__allocate_at_least(__a, __str.__get_long_cap());
__begin_lifetime(__allocation.ptr, __allocation.count);
Expand All @@ -2180,7 +2191,6 @@ private:
__set_long_pointer(__allocation.ptr);
__set_long_cap(__allocation.count);
__set_long_size(__str.size());
__annotate_new(__get_long_size());
}
}
}
Expand Down Expand Up @@ -2508,6 +2518,7 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
size_type __cap =
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
__annotate_delete();
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);
pointer __p = __allocation.ptr;
__begin_lifetime(__p, __allocation.count);
Expand All @@ -2526,7 +2537,6 @@ _LIBCPP_CONSTEXPR_SINCE_CXX20 void basic_string<_CharT, _Traits, _Allocator>::__
__old_sz = __n_copy + __n_add + __sec_cp_sz;
__set_long_size(__old_sz);
traits_type::assign(__p[__old_sz], value_type());
__annotate_new(__old_sz);
}

// __grow_by is deprecated because it does not set the size. It may not update the size when the size is changed, and it
Expand All @@ -2550,7 +2560,6 @@ _LIBCPP_DEPRECATED_("use __grow_by_without_replace") basic_string<_CharT, _Trait
pointer __old_p = __get_pointer();
size_type __cap =
__old_cap < __ms / 2 - __alignment ? __recommend(std::max(__old_cap + __delta_cap, 2 * __old_cap)) : __ms - 1;
__annotate_delete();
auto __allocation = std::__allocate_at_least(__alloc_, __cap + 1);
pointer __p = __allocation.ptr;
__begin_lifetime(__p, __allocation.count);
Expand All @@ -2575,11 +2584,12 @@ basic_string<_CharT, _Traits, _Allocator>::__grow_by_without_replace(
size_type __n_copy,
size_type __n_del,
size_type __n_add) {
__annotate_delete();
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
_LIBCPP_SUPPRESS_DEPRECATED_PUSH
__grow_by(__old_cap, __delta_cap, __old_sz, __n_copy, __n_del, __n_add);
_LIBCPP_SUPPRESS_DEPRECATED_POP
__set_long_size(__old_sz - __n_del + __n_add);
__annotate_new(__old_sz - __n_del + __n_add);
}

// assign
Expand Down Expand Up @@ -3364,6 +3374,7 @@ template <class _CharT, class _Traits, class _Allocator>
inline _LIBCPP_CONSTEXPR_SINCE_CXX20 void
basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target_capacity) {
__annotate_delete();
auto __guard = std::__make_scope_guard(__annotate_new_size(*this));
size_type __cap = capacity();
size_type __sz = size();

Expand Down Expand Up @@ -3395,7 +3406,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
// due to swapping the elements.
if (__allocation.count - 1 > __target_capacity) {
__alloc_traits::deallocate(__alloc_, __allocation.ptr, __allocation.count);
__annotate_new(__sz); // Undoes the __annotate_delete()
return;
}
__new_data = __allocation.ptr;
Expand All @@ -3420,7 +3430,6 @@ basic_string<_CharT, _Traits, _Allocator>::__shrink_or_extend(size_type __target
__set_long_pointer(__new_data);
} else
__set_short_size(__sz);
__annotate_new(__sz);
}

template <class _CharT, class _Traits, class _Allocator>
Expand Down
Loading