diff --git a/docs/man/clazy.pod b/docs/man/clazy.pod --- a/docs/man/clazy.pod +++ b/docs/man/clazy.pod @@ -202,6 +202,9 @@ even if the -Werror compiler option is specified. This is useful if you want to use -Werror only for the regular gcc/clang warnings but not for clazy warnings. +B - comma-separated list of checks that will be promoted +to compiler errors. Note that this does not enable the checks specified here. + =head1 COPYRIGHT AND LICENSE Copyright (C) 2015-2017 Klaralvdalens Datakonsult AB, a KDAB Group company, diff --git a/src/ClazyContext.h b/src/ClazyContext.h --- a/src/ClazyContext.h +++ b/src/ClazyContext.h @@ -156,6 +156,11 @@ return sm.isInFileID(loc, sm.getMainFileID()); } + bool treatAsError(const std::string &checkName) const + { + return clazy::contains(m_checksPromotedToErrors, checkName); + } + /** * We only enable it if a check needs it, for performance reasons */ @@ -174,6 +179,7 @@ PreProcessorVisitor *preprocessorVisitor = nullptr; SuppressionManager suppressionManager; const bool m_noWerror; + std::vector m_checksPromotedToErrors; bool m_visitsAllTypeDefs = false; clang::ParentMap *parentMap = nullptr; const ClazyOptions options; diff --git a/src/ClazyContext.cpp b/src/ClazyContext.cpp --- a/src/ClazyContext.cpp +++ b/src/ClazyContext.cpp @@ -20,6 +20,7 @@ */ #include "AccessSpecifierManager.h" +#include "checkmanager.h" #include "ClazyContext.h" #include "FixItExporter.h" #include "PreProcessorVisitor.h" @@ -44,6 +45,7 @@ , astContext(ci.getASTContext()) , sm(ci.getSourceManager()) , m_noWerror(getenv("CLAZY_NO_WERROR") != nullptr) // Allows user to make clazy ignore -Werror + , m_checksPromotedToErrors(CheckManager::instance()->checksAsErrors()) , options(opts) , extraOptions(clazy::splitString(getenv("CLAZY_EXTRA_OPTIONS"), ',')) , m_translationUnitPaths(translationUnitPaths) diff --git a/src/checkbase.cpp b/src/checkbase.cpp --- a/src/checkbase.cpp +++ b/src/checkbase.cpp @@ -251,8 +251,9 @@ { FullSourceLoc full(loc, sm()); auto &engine = m_context->ci.getDiagnostics(); - auto severity = (engine.getWarningsAsErrors() && !m_context->userDisabledWError()) ? DiagnosticIDs::Error - : DiagnosticIDs::Warning; + auto severity = (m_context->treatAsError(m_name) || (engine.getWarningsAsErrors() && !m_context->userDisabledWError())) + ? DiagnosticIDs::Error + : DiagnosticIDs::Warning; unsigned id = engine.getDiagnosticIDs()->getCustomDiagID(severity, error.c_str()); DiagnosticBuilder B = engine.Report(full, id); for (const FixItHint& fixit : fixits) { diff --git a/src/checkmanager.h b/src/checkmanager.h --- a/src/checkmanager.h +++ b/src/checkmanager.h @@ -93,6 +93,7 @@ static std::mutex &lock() { return m_lock; } RegisteredCheck::List availableChecks(CheckLevel maxLevel) const; RegisteredCheck::List requestedChecksThroughEnv(std::vector &userDisabledChecks) const; + std::vector checksAsErrors() const; RegisteredCheck::List::const_iterator checkForName(const RegisteredCheck::List &checks, const std::string &name) const; RegisteredCheck::List checksForCommaSeparatedString(const std::string &str) const; diff --git a/src/checkmanager.cpp b/src/checkmanager.cpp --- a/src/checkmanager.cpp +++ b/src/checkmanager.cpp @@ -317,3 +317,28 @@ return result; } + +vector CheckManager::checksAsErrors() const +{ + auto checksAsErrosEnv = getenv("CLAZY_CHECKS_AS_ERRORS"); + + if (checksAsErrosEnv) { + auto checkNames = clazy::splitString(checksAsErrosEnv, ','); + vector result; + + // Check whether all supplied check names are valid + for (const string &name : checkNames) { + auto it = clazy::find_if(m_registeredChecks, [&name](const RegisteredCheck &check) + { + return check.name == name; + }); + if (it == m_registeredChecks.end()) + llvm::errs() << "Invalid check: " << name << '\n'; + else + result.emplace_back(name); + } + return result; + } + else + return {}; +}