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