9 #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
10 #define LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H
14 #include "clang/ASTMatchers/ASTMatchFinder.h"
15 #include "clang/Basic/Diagnostic.h"
16 #include "llvm/ADT/Optional.h"
17 #include "llvm/Support/Error.h"
18 #include <type_traits>
24 class CompilerInstance;
33 static ArrayRef<std::pair<T, StringRef>>
getEnumMapping() =
delete;
36 template <
typename T>
class OptionError :
public llvm::ErrorInfo<T> {
37 std::error_code convertToErrorCode()
const override {
38 return llvm::inconvertibleErrorCode();
42 void log(raw_ostream &
OS)
const override {
OS << this->message(); }
48 : OptionName(OptionName) {}
50 std::string
message()
const override;
53 const std::string OptionName;
60 std::string LookupValue)
61 : LookupName(LookupName), LookupValue(LookupValue) {}
63 std::string LookupValue,
64 std::string SuggestedValue)
65 : LookupName(LookupName), LookupValue(LookupValue),
66 SuggestedValue(SuggestedValue) {}
68 std::string
message()
const override;
72 const std::string LookupName;
73 const std::string LookupValue;
74 const llvm::Optional<std::string> SuggestedValue;
78 :
public OptionError<UnparseableIntegerOptionError> {
81 std::string LookupValue,
82 bool IsBoolean =
false)
83 : LookupName(LookupName), LookupValue(LookupValue), IsBoolean(IsBoolean) {
86 std::string
message()
const override;
90 const std::string LookupName;
91 const std::string LookupValue;
152 Preprocessor *ModuleExpanderPP) {}
173 virtual void check(
const ast_matchers::MatchFinder::MatchResult &Result) {}
202 llvm::Expected<std::string>
get(StringRef LocalName)
const;
209 std::string
get(StringRef LocalName, StringRef Default)
const {
210 if (llvm::Expected<std::string> Val =
get(LocalName))
213 llvm::consumeError(Val.takeError());
214 return Default.str();
235 llvm::consumeError(Val.takeError());
236 return Default.str();
246 template <
typename T>
247 std::enable_if_t<std::is_integral<T>::value, llvm::Expected<T>>
248 get(StringRef LocalName)
const {
249 if (llvm::Expected<std::string> Value =
get(LocalName)) {
251 if (!StringRef(*Value).getAsInteger(10, Result))
253 return llvm::make_error<UnparseableIntegerOptionError>(
254 (NamePrefix + LocalName).str(), *Value);
256 return std::move(Value.takeError());
265 template <
typename T>
266 std::enable_if_t<std::is_integral<T>::value, T>
get(StringRef LocalName,
268 if (llvm::Expected<T> ValueOr = get<T>(LocalName))
271 logErrToStdErr(ValueOr.takeError());
284 template <
typename T>
285 std::enable_if_t<std::is_integral<T>::value, llvm::Expected<T>>
287 llvm::Expected<std::string> ValueOr =
get(LocalName);
288 bool IsGlobal =
false;
291 llvm::consumeError(ValueOr.takeError());
294 return std::move(ValueOr.takeError());
297 if (!StringRef(*ValueOr).getAsInteger(10, Result))
299 return llvm::make_error<UnparseableIntegerOptionError>(
300 (IsGlobal ? LocalName.str() : (NamePrefix + LocalName).str()),
311 template <
typename T>
312 std::enable_if_t<std::is_integral<T>::value, T>
314 if (llvm::Expected<T> ValueOr = getLocalOrGlobal<T>(LocalName))
317 logErrToStdErr(ValueOr.takeError());
331 template <
typename T>
332 std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
333 get(StringRef LocalName,
bool IgnoreCase =
false) {
334 if (llvm::Expected<int64_t> ValueOr =
335 getEnumInt(LocalName, typeEraseMapping<T>(),
false, IgnoreCase))
336 return static_cast<T>(*ValueOr);
338 return std::move(ValueOr.takeError());
350 template <
typename T>
351 std::enable_if_t<std::is_enum<T>::value, T>
352 get(StringRef LocalName, T Default,
bool IgnoreCase =
false) {
353 if (
auto ValueOr = get<T>(LocalName, IgnoreCase))
356 logErrToStdErr(ValueOr.takeError());
371 template <
typename T>
372 std::enable_if_t<std::is_enum<T>::value, llvm::Expected<T>>
374 bool IgnoreCase =
false) {
375 if (llvm::Expected<int64_t> ValueOr =
376 getEnumInt(LocalName, typeEraseMapping<T>(),
true, IgnoreCase))
377 return static_cast<T>(*ValueOr);
379 return std::move(ValueOr.takeError());
392 template <
typename T>
393 std::enable_if_t<std::is_enum<T>::value, T>
395 if (
auto ValueOr = getLocalOrGlobal<T>(LocalName, IgnoreCase))
398 logErrToStdErr(ValueOr.takeError());
405 StringRef Value)
const;
409 template <
typename T>
410 std::enable_if_t<std::is_integral<T>::value>
413 storeInt(
Options, LocalName, Value);
421 template <
typename T>
422 std::enable_if_t<std::is_enum<T>::value>
424 ArrayRef<std::pair<T, StringRef>> Mapping =
426 auto Iter = llvm::find_if(
427 Mapping, [&](
const std::pair<T, StringRef> &NameAndEnum) {
428 return NameAndEnum.first == Value;
430 assert(Iter != Mapping.end() &&
"Unknown Case Value");
435 using NameAndValue = std::pair<int64_t, StringRef>;
437 llvm::Expected<int64_t> getEnumInt(StringRef LocalName,
438 ArrayRef<NameAndValue> Mapping,
439 bool CheckGlobal,
bool IgnoreCase);
441 template <
typename T>
442 std::enable_if_t<std::is_enum<T>::value, std::vector<NameAndValue>>
444 ArrayRef<std::pair<T, StringRef>> Mapping =
446 std::vector<NameAndValue> Result;
447 Result.reserve(Mapping.size());
448 for (
auto &MappedItem : Mapping) {
449 Result.emplace_back(static_cast<int64_t>(MappedItem.first),
456 int64_t Value)
const;
458 static void logErrToStdErr(llvm::Error &&Err);
460 std::string NamePrefix;
465 void run(
const ast_matchers::MatchFinder::MatchResult &Result)
override;
466 StringRef getID()
const override {
return CheckName; }
467 std::string CheckName;
468 ClangTidyContext *Context;
475 const LangOptions &
getLangOpts()
const {
return Context->getLangOpts(); }
486 ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName)
const;
494 bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName,
507 ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName)
const;
516 bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName,
522 void ClangTidyCheck::OptionsView::store<bool>(
529 #endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_TIDY_CLANGTIDYCHECK_H