1// RUN: %check_clang_tidy -std=c++17-or-later %s cert-dcl58-cpp %t -- -- -I %clang_tidy_headers
2
3#include "system-header-simulation.h"
4
5namespace A {
6 namespace B {
7 int b;
8 }
9}
10
11namespace A {
12 namespace B {
13 int c;
14 }
15}
16
17namespace posix {
18// CHECK-MESSAGES: :[[@LINE+2]]:11: warning: modification of 'posix' namespace can result in undefined behavior [cert-dcl58-cpp]
19// CHECK-MESSAGES: :[[@LINE-2]]:11: note: 'posix' namespace opened here
20namespace foo {
21int foobar;
22}
23}
24
25namespace std {
26// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: modification of 'std' namespace
27// CHECK-MESSAGES: :[[@LINE-2]]:11: note: 'std' namespace opened here
28int stdInt;
29// CHECK-MESSAGES: :[[@LINE+2]]:5: warning: modification of 'std' namespace
30// CHECK-MESSAGES: :[[@LINE-5]]:11: note: 'std' namespace opened here
31int stdInt1;
32}
33
34namespace foobar {
35 namespace std {
36 int bar;
37 }
38}
39
40namespace posix {
41// CHECK-MESSAGES: :[[@LINE+2]]:11: warning: modification of 'posix' namespace
42// CHECK-MESSAGES: :[[@LINE-2]]:11: note: 'posix' namespace opened here
43namespace std {
44}
45} // namespace posix
46
47namespace posix::a {
48// CHECK-MESSAGES: :[[@LINE-1]]:18: warning: modification of 'posix' namespace
49// CHECK-MESSAGES: :[[@LINE-2]]:11: note: 'posix' namespace opened here
50}
51
52namespace std {
53// no-warning: empty
54} // namespace std
55
56namespace std {
57// Warn for non-NamedDecls as well.
58// CHECK-MESSAGES: :[[@LINE+2]]:1: warning: modification of 'std' namespace
59// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
60static_assert(1 == 1, "non-NamedDecl");
61} // namespace std
62
63enum class MyError {
64 ErrorA,
65 ErrorB
66};
67
68namespace std {
69// no-warning: Class template specialized by a program-defined type.
70template <>
71struct is_error_code_enum<MyError> : std::true_type {};
72
73// no-warning: Function template specialized by a program-defined type.
74template<>
75void swap<MyError>(MyError &a, MyError &b);
76}
77
78using ConstBoolPtr = const bool *;
79
80namespace std {
81// class template, builtin type
82// CHECK-MESSAGES: :[[@LINE+3]]:8: warning: modification of 'std' namespace
83// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
84template <>
85struct is_error_code_enum<bool> : std::true_type {};
86// function template, builtin type
87// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: modification of 'std' namespace
88// CHECK-MESSAGES: :[[@LINE-8]]:11: note: 'std' namespace opened here
89template <>
90void swap<bool>(bool &, bool &);
91// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: modification of 'std' namespace
92// CHECK-MESSAGES: :[[@LINE-12]]:11: note: 'std' namespace opened here
93template <>
94void swap<ConstBoolPtr>(ConstBoolPtr &, ConstBoolPtr &);
95} // namespace std
96
97namespace std {
98// class template, std type
99// CHECK-MESSAGES: :[[@LINE+3]]:8: warning: modification of 'std' namespace
100// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
101template <>
102struct is_error_code_enum<std::io_errc> : std::true_type {};
103// function template, std type
104// CHECK-MESSAGES: :[[@LINE+3]]:6: warning: modification of 'std' namespace
105// CHECK-MESSAGES: :[[@LINE-8]]:11: note: 'std' namespace opened here
106template <>
107void swap<std::io_errc>(std::io_errc &, std::io_errc &);
108} // namespace std
109
110// parameter pack, has program-defined type
111namespace std {
112// no-warning: there is one program-defined type.
113template <>
114class tuple<int, MyError, std::io_errc> {};
115} // namespace std
116
117// parameter pack, only builtin or std type
118namespace std {
119// Forbid variadic specializations over only `std::` or builtin types.
120// CHECK-MESSAGES: :[[@LINE+3]]:7: warning: modification of 'std' namespace
121// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
122template <>
123class tuple<int, const std::io_errc, float> {};
124} // namespace std
125
126namespace std {
127// Test nested standard declarations.
128// CHECK-MESSAGES: :[[@LINE+3]]:8: warning: modification of 'std' namespace
129// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
130template <>
131struct is_error_code_enum<std::Outer::Inner> : std::true_type {};
132} // namespace std
133
134namespace std {
135// Test nested namespace.
136// CHECK-MESSAGES: :[[@LINE+3]]:8: warning: modification of 'std' namespace
137// CHECK-MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
138template <>
139struct is_error_code_enum<std::detail::X> : std::true_type {};
140} // namespace std
141
142// Test member function template specializations.
143namespace std {
144// CHECK-MESSAGES: :[[@LINE+3]]:18: warning: modification of 'std' namespace
145// CHECK_MESSAGES: :[[@LINE-2]]:11: note: 'std' namespace opened here
146template <>
147bool less<void>::operator()<int &&, float &&>(int &&, float &&) const {
148 return true;
149}
150// CHECK-MESSAGES: :[[@LINE+3]]:18: warning: modification of 'std' namespace
151// CHECK_MESSAGES: :[[@LINE-8]]:11: note: 'std' namespace opened here
152template <>
153bool less<void>::operator()<MyError &&, MyError &&>(MyError &&, MyError &&) const {
154 return true;
155}
156} // namespace std
157
158// Test member class template specializations.
159namespace std {
160// CHECK-MESSAGES: :[[@LINE+3]]:20: warning: modification of 'std' namespace
161// CHECK_MESSAGES: :[[@LINE-2]]:11: note: 'std' namespace opened here
162template <>
163struct less<void>::X<bool> {};
164// CHECK-MESSAGES: :[[@LINE+3]]:20: warning: modification of 'std' namespace
165// CHECK_MESSAGES: :[[@LINE-6]]:11: note: 'std' namespace opened here
166template <>
167struct less<void>::X<MyError> {};
168// CHECK-MESSAGES: :[[@LINE+3]]:20: warning: modification of 'std' namespace
169// CHECK_MESSAGES: :[[@LINE-10]]:11: note: 'std' namespace opened here
170template <typename T>
171struct less<void>::X<MyError, T> {};
172} // namespace std
173
174// We did not open the 'std' namespace, but still specialized the member
175// function of 'std::less'.
176// CHECK-MESSAGES: :[[@LINE+3]]:23: warning: modification of 'std' namespace
177// no-note: There is no opening of 'std' namespace, hence no note emitted.
178template <>
179bool std::less<void>::operator()<int &&, int &&>(int &&, int &&) const {
180 return true;
181}
182
183namespace SpaceA {
184namespace SpaceB {
185class MapKey {
186 int Type = 0;
187
188public:
189 MapKey() = default;
190 int getType() const { return Type; }
191};
192} // namespace SpaceB
193} // namespace SpaceA
194
195// no-warning: Specializing for 'std::hash' for a program-defined type.
196template <>
197struct std::hash<::SpaceA::SpaceB::MapKey> {
198 // no-warning
199 unsigned long operator()(const ::SpaceA::SpaceB::MapKey &K) const {
200 return K.getType();
201 }
202 // no-warning
203 bool operator()(const ::SpaceA::SpaceB::MapKey &K1,
204 const ::SpaceA::SpaceB::MapKey &K2) const {
205 return K1.getType() < K2.getType();
206 }
207};
208
209using myint = int;
210
211// The type alias declaration is the same as typedef, does not introduce a
212// program-defined type.
213// CHECK-MESSAGES: :[[@LINE+2]]:13: warning: modification of 'std' namespace
214template <>
215struct std::hash<myint> {
216 // no-warning: The warning was already reported for the struct itself.
217 unsigned long operator()(const myint &K) const {
218 return K;
219 }
220 // no-warning: The warning was already reported for the struct itself.
221 bool operator()(const myint &K1,
222 const myint &K2) const {
223 return K1 < K2;
224 }
225};
226
227// CHECK-MESSAGES: :[[@LINE+2]]:15: warning: modification of 'std' namespace
228template <>
229struct ::std::hash<long> {
230 unsigned long operator()(const long &K) const {
231 return K;
232 }
233};
234
235namespace ranges {
236namespace detail {
237struct diffmax_t {};
238using LongT = long;
239} // namespace detail
240} // namespace ranges
241
242namespace std {
243// no-warning: specialization with an user-defined type
244template <>
245struct numeric_limits<::ranges::detail::diffmax_t> {
246 static constexpr bool is_signed = true;
247 static constexpr bool is_integer = true;
248 static constexpr ::ranges::detail::diffmax_t max() noexcept {
249 return {};
250 }
251};
252inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_signed;
253inline constexpr bool numeric_limits<::ranges::detail::diffmax_t>::is_integer;
254} // namespace std
255
256namespace std {
257// specialization with type alias to non-program-defined-type
258// CHECK-MESSAGES: :[[@LINE+3]]:8: warning: modification of 'std' namespace
259// CHECK_MESSAGES: :[[@LINE-3]]:11: note: 'std' namespace opened here
260template <>
261struct numeric_limits<::ranges::detail::LongT> {
262 static constexpr bool is_signed = true;
263 static constexpr bool is_integer = true;
264 static constexpr ::ranges::detail::LongT max() noexcept {
265 return 1;
266 }
267};
268inline constexpr bool numeric_limits<::ranges::detail::LongT>::is_signed;
269inline constexpr bool numeric_limits<::ranges::detail::LongT>::is_integer;
270} // namespace std
271
272namespace no_crash {
273struct A
274{
275 friend struct B;
276};
277
278struct B;
279
280template<typename> struct T {};
281
282T<B> b;
283}
284

source code of clang-tools-extra/test/clang-tidy/checkers/cert/dcl58-cpp.cpp