Mercurial > hg > CbC > CbC_llvm
diff clang-tools-extra/clang-tidy/ClangTidyCheck.cpp @ 173:0572611fdcc8 llvm10 llvm12
reorgnization done
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 11:55:54 +0900 |
parents | 1d019706d866 |
children | 2e18cbf3894f |
line wrap: on
line diff
--- a/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp Mon May 25 11:50:15 2020 +0900 +++ b/clang-tools-extra/clang-tidy/ClangTidyCheck.cpp Mon May 25 11:55:54 2020 +0900 @@ -7,10 +7,44 @@ //===----------------------------------------------------------------------===// #include "ClangTidyCheck.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/raw_ostream.h" namespace clang { namespace tidy { +char MissingOptionError::ID; +char UnparseableEnumOptionError::ID; +char UnparseableIntegerOptionError::ID; + +std::string MissingOptionError::message() const { + llvm::SmallString<128> Buffer; + llvm::raw_svector_ostream Output(Buffer); + Output << "option not found '" << OptionName << '\''; + return std::string(Buffer); +} + +std::string UnparseableEnumOptionError::message() const { + llvm::SmallString<128> Buffer; + llvm::raw_svector_ostream Output(Buffer); + Output << "invalid configuration value '" << LookupValue << "' for option '" + << LookupName << '\''; + if (SuggestedValue) + Output << "; did you mean '" << *SuggestedValue << "'?"; + return std::string(Buffer); +} + +std::string UnparseableIntegerOptionError::message() const { + llvm::SmallString<128> Buffer; + llvm::raw_svector_ostream Output(Buffer); + Output << "invalid configuration value '" << LookupValue << "' for option '" + << LookupName << "'; expected " + << (IsBoolean ? "a bool" : "an integer value"); + return std::string(Buffer); +} + ClangTidyCheck::ClangTidyCheck(StringRef CheckName, ClangTidyContext *Context) : CheckName(CheckName), Context(Context), Options(CheckName, Context->getOptions().CheckOptions) { @@ -34,31 +68,87 @@ const ClangTidyOptions::OptionMap &CheckOptions) : NamePrefix(CheckName.str() + "."), CheckOptions(CheckOptions) {} -std::string ClangTidyCheck::OptionsView::get(StringRef LocalName, - StringRef Default) const { +llvm::Expected<std::string> +ClangTidyCheck::OptionsView::get(StringRef LocalName) const { const auto &Iter = CheckOptions.find(NamePrefix + LocalName.str()); if (Iter != CheckOptions.end()) - return Iter->second; - return std::string(Default); + return Iter->second.Value; + return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); +} + +llvm::Expected<std::string> +ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName) const { + auto IterLocal = CheckOptions.find(NamePrefix + LocalName.str()); + auto IterGlobal = CheckOptions.find(LocalName.str()); + if (IterLocal != CheckOptions.end() && + (IterGlobal == CheckOptions.end() || + IterLocal->second.Priority >= IterGlobal->second.Priority)) + return IterLocal->second.Value; + if (IterGlobal != CheckOptions.end()) + return IterGlobal->second.Value; + return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); +} + +static llvm::Expected<bool> getAsBool(StringRef Value, + const llvm::Twine &LookupName) { + if (Value == "true") + return true; + if (Value == "false") + return false; + bool Result; + if (!Value.getAsInteger(10, Result)) + return Result; + return llvm::make_error<UnparseableIntegerOptionError>(LookupName.str(), + Value.str(), true); } -std::string -ClangTidyCheck::OptionsView::getLocalOrGlobal(StringRef LocalName, - StringRef Default) const { - auto Iter = CheckOptions.find(NamePrefix + LocalName.str()); - if (Iter != CheckOptions.end()) - return Iter->second; - // Fallback to global setting, if present. - Iter = CheckOptions.find(LocalName.str()); - if (Iter != CheckOptions.end()) - return Iter->second; - return std::string(Default); +template <> +llvm::Expected<bool> +ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName) const { + llvm::Expected<std::string> ValueOr = get(LocalName); + if (ValueOr) + return getAsBool(*ValueOr, NamePrefix + LocalName); + return ValueOr.takeError(); +} + +template <> +bool ClangTidyCheck::OptionsView::get<bool>(StringRef LocalName, + bool Default) const { + llvm::Expected<bool> ValueOr = get<bool>(LocalName); + if (ValueOr) + return *ValueOr; + logErrToStdErr(ValueOr.takeError()); + return Default; +} + +template <> +llvm::Expected<bool> +ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName) const { + auto IterLocal = CheckOptions.find(NamePrefix + LocalName.str()); + auto IterGlobal = CheckOptions.find(LocalName.str()); + if (IterLocal != CheckOptions.end() && + (IterGlobal == CheckOptions.end() || + IterLocal->second.Priority >= IterGlobal->second.Priority)) + return getAsBool(IterLocal->second.Value, NamePrefix + LocalName); + if (IterGlobal != CheckOptions.end()) + return getAsBool(IterGlobal->second.Value, llvm::Twine(LocalName)); + return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); +} + +template <> +bool ClangTidyCheck::OptionsView::getLocalOrGlobal<bool>(StringRef LocalName, + bool Default) const { + llvm::Expected<bool> ValueOr = getLocalOrGlobal<bool>(LocalName); + if (ValueOr) + return *ValueOr; + logErrToStdErr(ValueOr.takeError()); + return Default; } void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, StringRef LocalName, StringRef Value) const { - Options[NamePrefix + LocalName.str()] = std::string(Value); + Options[NamePrefix + LocalName.str()] = Value; } void ClangTidyCheck::OptionsView::store(ClangTidyOptions::OptionMap &Options, @@ -67,5 +157,49 @@ store(Options, LocalName, llvm::itostr(Value)); } +llvm::Expected<int64_t> ClangTidyCheck::OptionsView::getEnumInt( + StringRef LocalName, ArrayRef<std::pair<StringRef, int64_t>> Mapping, + bool CheckGlobal, bool IgnoreCase) { + auto Iter = CheckOptions.find((NamePrefix + LocalName).str()); + if (CheckGlobal && Iter == CheckOptions.end()) + Iter = CheckOptions.find(LocalName.str()); + if (Iter == CheckOptions.end()) + return llvm::make_error<MissingOptionError>((NamePrefix + LocalName).str()); + + StringRef Value = Iter->second.Value; + StringRef Closest; + unsigned EditDistance = -1; + for (const auto &NameAndEnum : Mapping) { + if (IgnoreCase) { + if (Value.equals_lower(NameAndEnum.first)) + return NameAndEnum.second; + } else if (Value.equals(NameAndEnum.first)) { + return NameAndEnum.second; + } else if (Value.equals_lower(NameAndEnum.first)) { + Closest = NameAndEnum.first; + EditDistance = 0; + continue; + } + unsigned Distance = Value.edit_distance(NameAndEnum.first); + if (Distance < EditDistance) { + EditDistance = Distance; + Closest = NameAndEnum.first; + } + } + if (EditDistance < 3) + return llvm::make_error<UnparseableEnumOptionError>( + Iter->first, Iter->second.Value, std::string(Closest)); + return llvm::make_error<UnparseableEnumOptionError>(Iter->first, + Iter->second.Value); +} + +void ClangTidyCheck::OptionsView::logErrToStdErr(llvm::Error &&Err) { + llvm::logAllUnhandledErrors( + llvm::handleErrors(std::move(Err), + [](const MissingOptionError &) -> llvm::Error { + return llvm::Error::success(); + }), + llvm::errs(), "warning: "); +} } // namespace tidy } // namespace clang