@@ -184,13 +184,13 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
184184 // / integral type ``T``.
185185 // /
186186 // / Reads the option with the check-local name \p LocalName from the
187- // / ``CheckOptions``. If the corresponding key is not present, return
188- // / ``std::nullopt``.
187+ // / ``CheckOptions``. If the corresponding key is not present,
188+ // / return ``std::nullopt``.
189189 // /
190190 // / If the corresponding key can't be parsed as a ``T``, emit a
191191 // / diagnostic and return ``std::nullopt``.
192192 template <typename T>
193- std::enable_if_t <std::is_integral <T>::value , std::optional<T>>
193+ std::enable_if_t <std::is_integral_v <T>, std::optional<T>>
194194 get (StringRef LocalName) const {
195195 if (std::optional<StringRef> Value = get (LocalName)) {
196196 T Result{};
@@ -201,6 +201,31 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
201201 return std::nullopt ;
202202 }
203203
204+ // / Read a named option from the ``Context`` and parse it as an
205+ // / integral type ``T``.
206+ // /
207+ // / Reads the option with the check-local name \p LocalName from the
208+ // / ``CheckOptions``. If the corresponding key is `none`, `null`,
209+ // / `-1` or empty, return ``std::nullopt``. If the corresponding
210+ // / key is not present, return \p Default.
211+ // /
212+ // / If the corresponding key can't be parsed as a ``T``, emit a
213+ // / diagnostic and return \p Default.
214+ template <typename T>
215+ std::enable_if_t <std::is_integral_v<T>, std::optional<T>>
216+ get (StringRef LocalName, std::optional<T> Default) const {
217+ if (std::optional<StringRef> Value = get (LocalName)) {
218+ if (Value == " " || Value == " none" || Value == " null" ||
219+ (std::is_unsigned_v<T> && Value == " -1" ))
220+ return std::nullopt ;
221+ T Result{};
222+ if (!StringRef (*Value).getAsInteger (10 , Result))
223+ return Result;
224+ diagnoseBadIntegerOption (NamePrefix + LocalName, *Value);
225+ }
226+ return Default;
227+ }
228+
204229 // / Read a named option from the ``Context`` and parse it as an
205230 // / integral type ``T``.
206231 // /
@@ -211,8 +236,8 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
211236 // / If the corresponding key can't be parsed as a ``T``, emit a
212237 // / diagnostic and return \p Default.
213238 template <typename T>
214- std::enable_if_t <std::is_integral <T>::value , T> get (StringRef LocalName,
215- T Default) const {
239+ std::enable_if_t <std::is_integral_v <T>, T> get (StringRef LocalName,
240+ T Default) const {
216241 return get<T>(LocalName).value_or (Default);
217242 }
218243
@@ -227,7 +252,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
227252 // / If the corresponding key can't be parsed as a ``T``, emit a
228253 // / diagnostic and return ``std::nullopt``.
229254 template <typename T>
230- std::enable_if_t <std::is_integral <T>::value , std::optional<T>>
255+ std::enable_if_t <std::is_integral_v <T>, std::optional<T>>
231256 getLocalOrGlobal (StringRef LocalName) const {
232257 std::optional<StringRef> ValueOr = get (LocalName);
233258 bool IsGlobal = false ;
@@ -245,6 +270,39 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
245270 return std::nullopt ;
246271 }
247272
273+ // / Read a named option from the ``Context`` and parse it as an
274+ // / integral type ``T``.
275+ // /
276+ // / Reads the option with the check-local name \p LocalName from local or
277+ // / global ``CheckOptions``. Gets local option first. If local is not
278+ // / present, falls back to get global option. If global option is not
279+ // / present either, return \p Default. If the value value was found
280+ // / and equals ``none``, ``null``, ``-1`` or empty, return ``std::nullopt``.
281+ // /
282+ // / If the corresponding key can't be parsed as a ``T``, emit a
283+ // / diagnostic and return \p Default.
284+ template <typename T>
285+ std::enable_if_t <std::is_integral_v<T>, std::optional<T>>
286+ getLocalOrGlobal (StringRef LocalName, std::optional<T> Default) const {
287+ std::optional<StringRef> ValueOr = get (LocalName);
288+ bool IsGlobal = false ;
289+ if (!ValueOr) {
290+ IsGlobal = true ;
291+ ValueOr = getLocalOrGlobal (LocalName);
292+ if (!ValueOr)
293+ return Default;
294+ }
295+ T Result{};
296+ if (ValueOr == " " || ValueOr == " none" || ValueOr == " null" ||
297+ (std::is_unsigned_v<T> && ValueOr == " -1" ))
298+ return std::nullopt ;
299+ if (!StringRef (*ValueOr).getAsInteger (10 , Result))
300+ return Result;
301+ diagnoseBadIntegerOption (
302+ IsGlobal ? Twine (LocalName) : NamePrefix + LocalName, *ValueOr);
303+ return Default;
304+ }
305+
248306 // / Read a named option from the ``Context`` and parse it as an
249307 // / integral type ``T``.
250308 // /
@@ -256,7 +314,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
256314 // / If the corresponding key can't be parsed as a ``T``, emit a
257315 // / diagnostic and return \p Default.
258316 template <typename T>
259- std::enable_if_t <std::is_integral <T>::value , T>
317+ std::enable_if_t <std::is_integral_v <T>, T>
260318 getLocalOrGlobal (StringRef LocalName, T Default) const {
261319 return getLocalOrGlobal<T>(LocalName).value_or (Default);
262320 }
@@ -274,7 +332,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
274332 // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
275333 // / supply the mapping required to convert between ``T`` and a string.
276334 template <typename T>
277- std::enable_if_t <std::is_enum <T>::value , std::optional<T>>
335+ std::enable_if_t <std::is_enum_v <T>, std::optional<T>>
278336 get (StringRef LocalName, bool IgnoreCase = false ) const {
279337 if (std::optional<int64_t > ValueOr =
280338 getEnumInt (LocalName, typeEraseMapping<T>(), false , IgnoreCase))
@@ -286,17 +344,17 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
286344 // / enum type ``T``.
287345 // /
288346 // / Reads the option with the check-local name \p LocalName from the
289- // / ``CheckOptions``. If the corresponding key is not present, return
290- // / \p Default.
347+ // / ``CheckOptions``. If the corresponding key is not present,
348+ // / return \p Default.
291349 // /
292350 // / If the corresponding key can't be parsed as a ``T``, emit a
293351 // / diagnostic and return \p Default.
294352 // /
295353 // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
296354 // / supply the mapping required to convert between ``T`` and a string.
297355 template <typename T>
298- std::enable_if_t <std::is_enum <T>::value , T>
299- get (StringRef LocalName, T Default, bool IgnoreCase = false ) const {
356+ std::enable_if_t <std::is_enum_v <T>, T> get (StringRef LocalName, T Default,
357+ bool IgnoreCase = false ) const {
300358 return get<T>(LocalName, IgnoreCase).value_or (Default);
301359 }
302360
@@ -314,7 +372,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
314372 // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
315373 // / supply the mapping required to convert between ``T`` and a string.
316374 template <typename T>
317- std::enable_if_t <std::is_enum <T>::value , std::optional<T>>
375+ std::enable_if_t <std::is_enum_v <T>, std::optional<T>>
318376 getLocalOrGlobal (StringRef LocalName, bool IgnoreCase = false ) const {
319377 if (std::optional<int64_t > ValueOr =
320378 getEnumInt (LocalName, typeEraseMapping<T>(), true , IgnoreCase))
@@ -336,7 +394,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
336394 // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
337395 // / supply the mapping required to convert between ``T`` and a string.
338396 template <typename T>
339- std::enable_if_t <std::is_enum <T>::value , T>
397+ std::enable_if_t <std::is_enum_v <T>, T>
340398 getLocalOrGlobal (StringRef LocalName, T Default,
341399 bool IgnoreCase = false ) const {
342400 return getLocalOrGlobal<T>(LocalName, IgnoreCase).value_or (Default);
@@ -350,19 +408,32 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
350408 // / Stores an option with the check-local name \p LocalName with
351409 // / integer value \p Value to \p Options.
352410 template <typename T>
353- std::enable_if_t <std::is_integral <T>::value >
411+ std::enable_if_t <std::is_integral_v <T>>
354412 store (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
355413 T Value) const {
356414 storeInt (Options, LocalName, Value);
357415 }
358416
417+ // / Stores an option with the check-local name \p LocalName with
418+ // / integer value \p Value to \p Options. If the value is empty
419+ // / stores ``
420+ template <typename T>
421+ std::enable_if_t <std::is_integral_v<T>>
422+ store (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
423+ std::optional<T> Value) const {
424+ if (Value)
425+ storeInt (Options, LocalName, *Value);
426+ else
427+ store (Options, LocalName, " none" );
428+ }
429+
359430 // / Stores an option with the check-local name \p LocalName as the string
360431 // / representation of the Enum \p Value to \p Options.
361432 // /
362433 // / \ref clang::tidy::OptionEnumMapping must be specialized for ``T`` to
363434 // / supply the mapping required to convert between ``T`` and a string.
364435 template <typename T>
365- std::enable_if_t <std::is_enum <T>::value >
436+ std::enable_if_t <std::is_enum_v <T>>
366437 store (ClangTidyOptions::OptionMap &Options, StringRef LocalName,
367438 T Value) const {
368439 ArrayRef<std::pair<T, StringRef>> Mapping =
@@ -383,7 +454,7 @@ class ClangTidyCheck : public ast_matchers::MatchFinder::MatchCallback {
383454 bool CheckGlobal, bool IgnoreCase) const ;
384455
385456 template <typename T>
386- std::enable_if_t <std::is_enum <T>::value , std::vector<NameAndValue>>
457+ std::enable_if_t <std::is_enum_v <T>, std::vector<NameAndValue>>
387458 typeEraseMapping () const {
388459 ArrayRef<std::pair<T, StringRef>> Mapping =
389460 OptionEnumMapping<T>::getEnumMapping ();
0 commit comments