aboutsummaryrefslogtreecommitdiffstats
path: root/src/Clazy.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Clazy.cpp')
-rw-r--r--src/Clazy.cpp139
1 files changed, 66 insertions, 73 deletions
diff --git a/src/Clazy.cpp b/src/Clazy.cpp
index c1ff2c67..0fcaed92 100644
--- a/src/Clazy.cpp
+++ b/src/Clazy.cpp
@@ -61,38 +61,56 @@ static void manuallyPopulateParentMap(ParentMap *map, Stmt *s)
ClazyASTConsumer::ClazyASTConsumer(ClazyContext *context)
: m_context(context)
- , m_matchFinder(nullptr)
{
- clang::ast_matchers::MatchFinder::MatchFinderOptions options;
#ifndef CLAZY_DISABLE_AST_MATCHERS
- m_matchFinder = new clang::ast_matchers::MatchFinder(options);
+ m_matchFinder = new clang::ast_matchers::MatchFinder();
#endif
}
-void ClazyASTConsumer::addCheck(CheckBase *check)
+void ClazyASTConsumer::addCheck(const std::pair<CheckBase *, RegisteredCheck> &check)
{
+ CheckBase *checkBase = check.first;
#ifndef CLAZY_DISABLE_AST_MATCHERS
- check->registerASTMatchers(*m_matchFinder);
+ checkBase->registerASTMatchers(*m_matchFinder);
#endif
- m_createdChecks.push_back(check);
+ //m_createdChecks.push_back(checkBase);
+
+ const RegisteredCheck &rcheck = check.second;
+
+ if (rcheck.options & RegisteredCheck::Option_VisitsStmts)
+ m_checksToVisitStmts.push_back(checkBase);
+
+ if (rcheck.options & RegisteredCheck::Option_VisitsDecls)
+ m_checksToVisitDecls.push_back(checkBase);
+
}
ClazyASTConsumer::~ClazyASTConsumer()
{
- delete m_context;
+#ifndef CLAZY_DISABLE_AST_MATCHERS
delete m_matchFinder;
+#endif
+ delete m_context;
}
bool ClazyASTConsumer::VisitDecl(Decl *decl)
{
- const bool isInSystemHeader = m_context->sm.isInSystemHeader(decl->getLocStart());
-
- if (AccessSpecifierManager *a = m_context->accessSpecifierManager)
+ if (AccessSpecifierManager *a = m_context->accessSpecifierManager) // Needs to visit system headers too (qobject.h for example)
a->VisitDeclaration(decl);
- if (!isInSystemHeader) {
- for (CheckBase *check : m_createdChecks)
- check->VisitDeclaration(decl);
+ const SourceLocation locStart = getLocStart(decl);
+ if (locStart.isInvalid() || m_context->sm.isInSystemHeader(locStart))
+ return true;
+
+ const bool isFromIgnorableInclude = m_context->ignoresIncludedFiles() && !Utils::isMainFile(m_context->sm, locStart);
+
+ m_context->lastDecl = decl;
+ if (auto mdecl = dyn_cast<CXXMethodDecl>(decl))
+ m_context->lastMethodDecl = mdecl;
+
+ for (CheckBase *check : m_checksToVisitDecls) {
+ if (!(isFromIgnorableInclude && check->canIgnoreIncludes()))
+ check->VisitDecl(decl);
}
return true;
@@ -100,6 +118,10 @@ bool ClazyASTConsumer::VisitDecl(Decl *decl)
bool ClazyASTConsumer::VisitStmt(Stmt *stm)
{
+ const SourceLocation locStart = getLocStart(stm);
+ if (locStart.isInvalid() || m_context->sm.isInSystemHeader(locStart))
+ return true;
+
if (!m_context->parentMap) {
if (m_context->ci.getDiagnostics().hasUnrecoverableErrorOccurred())
return false; // ParentMap sometimes crashes when there were errors. Doesn't like a botched AST.
@@ -122,10 +144,10 @@ bool ClazyASTConsumer::VisitStmt(Stmt *stm)
if (!parentMap->hasParent(stm))
parentMap->addStmt(stm);
- const bool isInSystemHeader = m_context->sm.isInSystemHeader(stm->getLocStart());
- if (!isInSystemHeader) {
- for (CheckBase *check : m_createdChecks)
- check->VisitStatement(stm);
+ const bool isFromIgnorableInclude = m_context->ignoresIncludedFiles() && !Utils::isMainFile(m_context->sm, locStart);
+ for (CheckBase *check : m_checksToVisitStmts) {
+ if (!(isFromIgnorableInclude && check->canIgnoreIncludes()))
+ check->VisitStmt(stm);
}
return true;
@@ -147,7 +169,7 @@ void ClazyASTConsumer::HandleTranslationUnit(ASTContext &ctx)
static bool parseArgument(const string &arg, vector<string> &args)
{
- auto it = clazy_std::find(args, arg);
+ auto it = clazy::find(args, arg);
if (it != args.end()) {
args.erase(it);
return true;
@@ -170,14 +192,22 @@ std::unique_ptr<clang::ASTConsumer> ClazyASTAction::CreateASTConsumer(CompilerIn
std::lock_guard<std::mutex> lock(CheckManager::lock());
auto astConsumer = std::unique_ptr<ClazyASTConsumer>(new ClazyASTConsumer(m_context));
- CheckBase::List createdChecks = m_checkManager->createChecks(m_checks, m_context);
- for (CheckBase *check : createdChecks) {
+ auto createdChecks = m_checkManager->createChecks(m_checks, m_context);
+ for (auto check : createdChecks) {
astConsumer->addCheck(check);
}
return std::unique_ptr<clang::ASTConsumer>(astConsumer.release());
}
+static std::string getEnvVariable(const char *name)
+{
+ const char *result = getenv(name);
+ if (result)
+ return result;
+ else return std::string();
+}
+
bool ClazyASTAction::ParseArgs(const CompilerInstance &ci, const std::vector<std::string> &args_)
{
// NOTE: This method needs to be kept reentrant (but not necessarily thread-safe)
@@ -186,14 +216,8 @@ bool ClazyASTAction::ParseArgs(const CompilerInstance &ci, const std::vector<std
std::vector<std::string> args = args_;
if (parseArgument("help", args)) {
- m_context = new ClazyContext(ci, ClazyContext::ClazyOption_None);
- PrintHelp(llvm::errs(), HelpMode_Normal);
- return true;
- }
-
- if (parseArgument("generateAnchorHeader", args)) {
- m_context = new ClazyContext(ci, ClazyContext::ClazyOption_None);
- PrintHelp(llvm::errs(), HelpMode_AnchorHeader);
+ m_context = new ClazyContext(ci, getEnvVariable("CLAZY_HEADER_FILTER"), getEnvVariable("CLAZY_IGNORE_DIRS"), ClazyContext::ClazyOption_None);
+ PrintHelp(llvm::errs());
return true;
}
@@ -222,7 +246,10 @@ bool ClazyASTAction::ParseArgs(const CompilerInstance &ci, const std::vector<std
if (parseArgument("visit-implicit-code", args))
m_options |= ClazyContext::ClazyOption_VisitImplicitCode;
- m_context = new ClazyContext(ci, m_options);
+ if (parseArgument("ignore-included-files", args))
+ m_options |= ClazyContext::ClazyOption_IgnoreIncludedFiles;
+
+ m_context = new ClazyContext(ci, /*headerFilter=*/ "", /*ignoreDirs=*/ "", m_options);
// This argument is for debugging purposes
const bool dbgPrintRequestedChecks = parseArgument("print-requested-checks", args);
@@ -269,48 +296,14 @@ void ClazyASTAction::printRequestedChecks() const
llvm::errs() << "\n";
}
-void ClazyASTAction::PrintAnchorHeader(llvm::raw_ostream &ros, RegisteredCheck::List &checks) const
-{
- // Generates ClazyAnchorHeader.h.
- // Needed so we can support a static build of clazy without the linker discarding our checks.
- // You can generate with:
- // $ echo | clang -Xclang -load -Xclang ClangLazy.so -Xclang -add-plugin -Xclang clang-lazy -Xclang -plugin-arg-clang-lazy -Xclang generateAnchorHeader -c -xc -
-
-
- ros << "// This file was autogenerated.\n\n";
- ros << "#ifndef CLAZY_ANCHOR_HEADER_H\n#define CLAZY_ANCHOR_HEADER_H\n\n";
-
- for (auto &check : checks) {
- ros << string("extern volatile int ClazyAnchor_") + check.className + ";\n";
- }
-
- ros << "\n";
- ros << "int clazy_dummy()\n{\n";
- ros << " return\n";
-
- for (auto &check : checks) {
- ros << string(" ClazyAnchor_") + check.className + " +\n";
- }
-
- ros << " 0;\n";
- ros << "}\n\n";
- ros << "#endif\n";
-}
-
-void ClazyASTAction::PrintHelp(llvm::raw_ostream &ros, HelpMode helpMode) const
+void ClazyASTAction::PrintHelp(llvm::raw_ostream &ros) const
{
std::lock_guard<std::mutex> lock(CheckManager::lock());
RegisteredCheck::List checks = m_checkManager->availableChecks(MaxCheckLevel);
- clazy_std::sort(checks, checkLessThanByLevel);
-
- if (helpMode == HelpMode_AnchorHeader) {
- PrintAnchorHeader(ros, checks);
- return;
- }
+ clazy::sort(checks, checkLessThanByLevel);
ros << "Available checks and FixIts:\n\n";
- const bool useMarkdown = getenv("CLAZY_HELP_USE_MARKDOWN");
int lastPrintedLevel = -1;
const auto numChecks = checks.size();
@@ -330,7 +323,7 @@ void ClazyASTAction::PrintHelp(llvm::raw_ostream &ros, HelpMode helpMode) const
auto padded = check.name;
padded.insert(padded.end(), 39 - padded.size(), ' ');
- ros << " - " << (useMarkdown ? "[" : "") << check.name << (useMarkdown ? "](" + relativeReadmePath + ")" : "");
+ ros << " - " << check.name;;
auto fixits = m_checkManager->availableFixIts(check.name);
if (!fixits.empty()) {
ros << " (";
@@ -361,19 +354,19 @@ void ClazyASTAction::PrintHelp(llvm::raw_ostream &ros, HelpMode helpMode) const
ros << "FixIts are experimental and rewrite your code therefore only one FixIt is allowed per build.\nSpecifying a list of different FixIts is not supported.\nBackup your code before running them.\n";
}
-ClazyStandaloneASTAction::ClazyStandaloneASTAction(const string &checkList,
+ClazyStandaloneASTAction::ClazyStandaloneASTAction(const string &checkList, const string &headerFilter, const string &ignoreDirs,
ClazyContext::ClazyOptions options)
: clang::ASTFrontendAction()
- , m_checkList(checkList)
+ , m_checkList(checkList.empty() ? "level1" : checkList)
+ , m_headerFilter(headerFilter.empty() ? getEnvVariable("CLAZY_HEADER_FILTER") : headerFilter)
+ , m_ignoreDirs(ignoreDirs.empty() ? getEnvVariable("CLAZY_IGNORE_DIRS") : ignoreDirs)
, m_options(options)
{
- if (m_checkList.empty())
- m_checkList = "level1";
}
unique_ptr<ASTConsumer> ClazyStandaloneASTAction::CreateASTConsumer(CompilerInstance &ci, llvm::StringRef)
{
- auto context = new ClazyContext(ci, m_options);
+ auto context = new ClazyContext(ci, m_headerFilter, m_ignoreDirs, m_options);
auto astConsumer = new ClazyASTConsumer(context);
auto cm = CheckManager::instance();
@@ -386,8 +379,8 @@ unique_ptr<ASTConsumer> ClazyStandaloneASTAction::CreateASTConsumer(CompilerInst
return nullptr;
}
- CheckBase::List createdChecks = cm->createChecks(requestedChecks, context);
- for (CheckBase *check : createdChecks) {
+ auto createdChecks = cm->createChecks(requestedChecks, context);
+ for (const auto &check : createdChecks) {
astConsumer->addCheck(check);
}