Skip to content

Commit cf383e0

Browse files
authored
Merge branch 'main' into peg2pegtl
2 parents 1277923 + 54a2e32 commit cf383e0

File tree

3 files changed

+120
-53
lines changed

3 files changed

+120
-53
lines changed

.clang-tidy

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Checks: >-
3535
-readability-identifier-length,
3636
-readability-magic-numbers,
3737
-readability-static-accessed-through-instance,
38+
-llvm-header-guard,
3839
3940
CheckOptions:
4041
- { key: readability-identifier-naming.ClassCase, value: lower_case }

.github/workflows/clang-tidy.yml

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,20 @@ jobs:
1515
runs-on: ubuntu-latest
1616

1717
steps:
18-
- uses: actions/checkout@v3
18+
- uses: actions/checkout@v4
1919

20-
- run: sudo apt-get update -yq
20+
- name: Install Dependencies
21+
run: |
22+
sudo apt-get -qq update -yq
23+
sudo apt-get -qq install -y clang-tidy --no-install-recommends --no-install-suggests
2124
22-
- run: sudo apt-get install -yq clang-tidy
25+
- name: Generate Compilation Database
26+
run: cmake -S . -B build -DCMAKE_EXPORT_COMPILE_COMMANDS=ON
2327

24-
- run: find include/ -name '*.hpp' | grep -vF mmap_file_win32.hpp | grep -vF endian_win.hpp | xargs -I '{}' clang-tidy --quiet '{}' -- --std=c++17 -Iinclude
28+
- name: Run clang-tidy on Header Files
29+
continue-on-error: true
30+
run: find include/ -type f \( -name "*.hpp" -a ! -name "endian_win.hpp" -a ! -name "mmap_file_win32.hpp" \) | xargs -P $(nproc) -I {} clang-tidy -quiet -p build {} -- -std=c++17 -Iinclude
2531

26-
- run: find src/ -name '*.cpp' | xargs -I '{}' clang-tidy --quiet '{}' -- --std=c++17 -Iinclude
32+
- name: Run clang-tidy on tests and examples files
33+
continue-on-error: true
34+
run: find src/ -type f -name "*.cpp" | xargs -P $(nproc) -I {} clang-tidy -quiet -p build {} -- -std=c++17 -Iinclude

include/tao/pegtl/internal/resize_uninitialized.hpp

Lines changed: 106 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2021-2023 Dr. Colin Hirsch and Daniel Frey
1+
// Copyright (c) 2021-2025 Daniel Frey and Dr. Colin Hirsch
22
// Distributed under the Boost Software License, Version 1.0.
33
// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
44

@@ -7,111 +7,169 @@
77

88
#include <cstddef>
99
#include <string>
10-
11-
#include "../config.hpp"
10+
#include <vector>
1211

1312
namespace TAO_PEGTL_NAMESPACE::internal
1413
{
15-
// the below uses a hack to call private member functions of a class, described here:
14+
// This uses a hack to call private member functions of a class, described here:
1615
// https://github.com/facebook/folly/blob/master/folly/memory/UninitializedMemoryHacks.h
1716

1817
namespace // NOLINT(google-build-namespaces)
1918
{
20-
// declare some functions...
21-
void resize_uninitialized_proxy( std::string& v, const std::size_t n );
22-
void resize_uninitialized_proxy( std::basic_string< unsigned char >& v, const std::size_t n );
23-
void resize_uninitialized_proxy( std::basic_string< std::byte >& v, const std::size_t n );
19+
struct odr_helper;
20+
21+
void resize_uninitialized_proxy( std::string& v, const std::size_t n ) noexcept;
2422

2523
#if defined( _LIBCPP_STRING )
2624

27-
// ...create a proxy to generate the actual implementation of the above function...
28-
template< typename T, void ( T::*F )( std::size_t ) >
29-
struct proxy
25+
// Create a proxy to generate the actual implementation of the above function...
26+
27+
template< typename T, auto F >
28+
struct string_proxy
3029
{
3130
// ...define the function declared above...
32-
friend void resize_uninitialized_proxy( T& v, const std::size_t n )
31+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
3332
{
3433
( v.*F )( n ); // v.__set_size( n );
3534
v[ v.size() ] = typename T::value_type( 0 );
3635
}
3736
};
3837

39-
// ...and here's the actual "trick": an explicit template instantiation skips the access checks,
38+
// ...the actual "trick": an explicit template instantiation skips the access checks,
4039
// so you can reference private members and forward them to the above proxy!
41-
template struct proxy< std::string, &std::string::__set_size >;
42-
template struct proxy< std::basic_string< unsigned char >, &std::basic_string< unsigned char >::__set_size >;
43-
template struct proxy< std::basic_string< std::byte >, &std::basic_string< std::byte >::__set_size >;
4440

45-
#elif defined( _GLIBCXX_STRING ) && _GLIBCXX_USE_CXX11_ABI
41+
template struct string_proxy< std::string, &std::string::__set_size >;
4642

47-
template< typename T, void ( T::*F )( std::size_t ) >
48-
struct proxy
43+
#elif defined( _GLIBCXX_STRING ) && _GLIBCXX_USE_CXX11_ABI // NOLINT(misc-include-cleaner)
44+
45+
template< typename T, auto F >
46+
struct string_proxy
4947
{
50-
friend void resize_uninitialized_proxy( T& v, const std::size_t n )
48+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
5149
{
5250
( v.*F )( n ); // v._M_set_length( n );
5351
}
5452
};
5553

56-
template struct proxy< std::string, &std::string::_M_set_length >;
57-
template struct proxy< std::basic_string< unsigned char >, &std::basic_string< unsigned char >::_M_set_length >;
58-
template struct proxy< std::basic_string< std::byte >, &std::basic_string< std::byte >::_M_set_length >;
54+
template struct string_proxy< std::string, &std::string::_M_set_length >;
5955

6056
#elif defined( _GLIBCXX_STRING )
6157

62-
template< typename T,
63-
typename R,
64-
R* ( T::*F )() const >
65-
struct proxy
58+
template< typename T, auto F >
59+
struct string_proxy
6660
{
67-
friend void resize_uninitialized_proxy( T& v, const std::size_t n )
61+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
6862
{
6963
// v._M_rep()->_M_set_length_and_sharable( n );
7064
( v.*F )()->_M_set_length_and_sharable( n );
7165
}
7266
};
7367

74-
template struct proxy< std::string,
75-
std::string::_Rep,
76-
&std::string::_M_rep >;
68+
template struct string_proxy< std::string, &std::string::_M_rep >;
69+
70+
#elif defined( _MSC_VER )
71+
72+
template< typename T, auto F >
73+
struct string_proxy
74+
{
75+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
76+
{
77+
( v.*F )( n ); // v._Eos( n );
78+
}
79+
};
7780

78-
template struct proxy< std::basic_string< unsigned char >,
79-
std::basic_string< unsigned char >::_Rep,
80-
&std::basic_string< unsigned char >::_M_rep >;
81+
template struct string_proxy< std::string, &std::string::_Eos >;
82+
83+
#else
84+
#error "No implementation for resize_uninitialized for std::string available on this platform."
85+
#endif
86+
87+
#if defined( _LIBCPP_VECTOR )
88+
89+
void resize_uninitialized_proxy( std::vector< std::byte >& v, const std::size_t n ) noexcept;
90+
91+
template< typename T, auto M >
92+
struct vector_proxy
93+
{
94+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
95+
{
96+
// v.__end_ = v.data() + n;
97+
v.*M = v.data() + n;
98+
99+
#ifndef _LIBCPP_HAS_NO_ASAN
100+
__sanitizer_annotate_contiguous_container( v.data(),
101+
v.data() + v.capacity(),
102+
v.data() + v.size(),
103+
v.data() + n );
104+
#endif
105+
}
106+
};
81107

82-
template struct proxy< std::basic_string< std::byte >,
83-
std::basic_string< std::byte >::_Rep,
84-
&std::basic_string< std::byte >::_M_rep >;
108+
template struct vector_proxy< std::vector< std::byte >, &std::vector< std::byte >::__end_ >;
85109

86110
#elif defined( _MSC_VER )
87111

88-
template< typename T, void ( T::*F )( std::size_t ) >
89-
struct proxy
112+
void resize_uninitialized_proxy( std::vector< std::byte >& v, const std::size_t n ) noexcept;
113+
114+
template< typename T, auto Mypair, auto Myval2, auto Mylast >
115+
struct vector_proxy
90116
{
91-
friend void resize_uninitialized_proxy( T& v, const std::size_t n )
117+
friend void resize_uninitialized_proxy( T& v, const std::size_t n ) noexcept
92118
{
93-
( v.*F )( n ); // v._Eos( n );
119+
// v._Mypair._Myval2._Mylast = v.data() + n;
120+
v.*Mypair.*Myval2.*Mylast = v.data() + n;
94121
}
95122
};
96123

97-
template struct proxy< std::string, &std::string::_Eos >;
98-
template struct proxy< std::basic_string< unsigned char >, &std::basic_string< unsigned char >::_Eos >;
99-
template struct proxy< std::basic_string< std::byte >, &std::basic_string< std::byte >::_Eos >;
124+
template struct vector_proxy< std::vector< std::byte >,
125+
&std::vector< std::byte >::_Mypair,
126+
&decltype( std::declval< std::vector< std::byte > >()._Mypair )::_Myval2,
127+
&decltype( std::declval< std::vector< std::byte > >()._Mypair._Myval2 )::_Mylast >;
100128

101129
#else
102-
#error "No implementation for resize_uninitialized available."
130+
131+
// generic version
132+
133+
struct no_init_byte
134+
{
135+
std::byte b;
136+
no_init_byte() noexcept {} // NOLINT(modernize-use-equals-default)
137+
};
138+
139+
static_assert( sizeof( std::vector< std::byte > ) == sizeof( std::vector< no_init_byte > ) );
140+
static_assert( alignof( std::vector< std::byte > ) == alignof( std::vector< no_init_byte > ) );
141+
142+
inline void resize_uninitialized_proxy( std::vector< std::byte >& v, const std::size_t n ) noexcept
143+
{
144+
// undefined behaviour?
145+
reinterpret_cast< std::vector< no_init_byte >& >( v ).resize( n );
146+
}
147+
103148
#endif
104149

105150
} // namespace
106151

107-
template< typename T >
108-
void resize_uninitialized( std::basic_string< T >& v, const std::size_t n )
152+
template< typename = odr_helper >
153+
void resize_uninitialized( std::string& v, const std::size_t n )
154+
{
155+
if( n <= v.size() ) {
156+
v.resize( n );
157+
}
158+
else {
159+
if( n > v.capacity() ) {
160+
v.reserve( n );
161+
}
162+
internal::resize_uninitialized_proxy( v, n );
163+
}
164+
}
165+
166+
template< typename = odr_helper >
167+
void resize_uninitialized( std::vector< std::byte >& v, const std::size_t n )
109168
{
110169
if( n <= v.size() ) {
111170
v.resize( n );
112171
}
113172
else {
114-
// careful not to call reserve() unless necessary, as it causes shrink_to_fit() on many platforms
115173
if( n > v.capacity() ) {
116174
v.reserve( n );
117175
}

0 commit comments

Comments
 (0)