/* This file is part of the clazy static checker. Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com Author: SĂ©rgio Martins Copyright (C) 2015-2017 Sergio Martins This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef CHECK_BASE_H #define CHECK_BASE_H #include "clazy_export.h" #include "clazy_stl.h" #include "SourceCompatibilityHelpers.h" #include #include #include #include #include "clang/ASTMatchers/ASTMatchers.h" #include "clang/ASTMatchers/ASTMatchFinder.h" #include namespace clang { class CXXMethodDecl; class Stmt; class Decl; class TranslationUnitDecl; class FixItHint; class PresumedLoc; class SourceLocation; class PreprocessorOptions; } class CheckBase; class ClazyContext; enum CheckLevel { // See README.md for what each level does CheckLevelUndefined = -1, CheckLevel0 = 0, CheckLevel1, CheckLevel2, CheckLevel3 = 3, ManualCheckLevel, MaxCheckLevel = CheckLevel3, DefaultCheckLevel = CheckLevel1 }; class ClazyPreprocessorCallbacks : public clang::PPCallbacks { public: ClazyPreprocessorCallbacks(const ClazyPreprocessorCallbacks &) = delete; explicit ClazyPreprocessorCallbacks(CheckBase *check); void MacroExpands(const clang::Token &MacroNameTok, const clang::MacroDefinition &, clang::SourceRange, const clang::MacroArgs *) override; void MacroDefined(const clang::Token &MacroNameTok, const clang::MacroDirective*) override; void Defined(const clang::Token &MacroNameTok, const clang::MacroDefinition &, clang::SourceRange Range) override; void Ifdef(clang::SourceLocation, const clang::Token &MacroNameTok, const clang::MacroDefinition &) override; private: CheckBase *const check; }; class ClazyAstMatcherCallback : public clang::ast_matchers::MatchFinder::MatchCallback { public: explicit ClazyAstMatcherCallback(CheckBase *check); protected: CheckBase *const m_check; }; class CLAZYLIB_EXPORT CheckBase { public: enum Option { Option_None = 0, Option_CanIgnoreIncludes = 1 }; typedef int Options; typedef std::vector List; explicit CheckBase(const std::string &name, const ClazyContext *context, Options = Option_None); CheckBase(const CheckBase &other) = delete; virtual ~CheckBase(); std::string name() const { return m_name; } void setEnabledFixits(int); bool isFixitEnabled(int fixit) const; bool isFixitEnabled() const; void emitWarning(const clang::Decl *, const std::string &error, bool printWarningTag = true); void emitWarning(const clang::Stmt *, const std::string &error, bool printWarningTag = true); void emitWarning(clang::SourceLocation loc, const std::string &error, bool printWarningTag = true); void emitWarning(clang::SourceLocation loc, std::string error, const std::vector &fixits, bool printWarningTag = true); void emitInternalError(clang::SourceLocation loc, std::string error); virtual void registerASTMatchers(clang::ast_matchers::MatchFinder &) {}; bool canIgnoreIncludes() const { return m_options & Option_CanIgnoreIncludes; } virtual void VisitStmt(clang::Stmt *stm); virtual void VisitDecl(clang::Decl *decl); protected: virtual void VisitMacroExpands(const clang::Token ¯oNameTok, const clang::SourceRange &, const clang::MacroInfo *minfo = nullptr); virtual void VisitMacroDefined(const clang::Token ¯oNameTok); virtual void VisitDefined(const clang::Token ¯oNameTok, const clang::SourceRange &); virtual void VisitIfdef(clang::SourceLocation, const clang::Token ¯oNameTok); void enablePreProcessorCallbacks(); bool shouldIgnoreFile(clang::SourceLocation) const; void reallyEmitWarning(clang::SourceLocation loc, const std::string &error, const std::vector &fixits); void queueManualFixitWarning(clang::SourceLocation loc, const std::string &message = {}, int fixitType = 1); bool warningAlreadyEmitted(clang::SourceLocation loc) const; bool manualFixitAlreadyQueued(clang::SourceLocation loc) const; bool isOptionSet(const std::string &optionName) const; // 3 shortcuts for stuff that litter the codebase all over. const clang::SourceManager &sm() const { return m_sm; } const clang::LangOptions &lo() const { return m_astContext.getLangOpts(); } const clang::SourceManager &m_sm; const std::string m_name; const ClazyContext *const m_context; clang::ASTContext &m_astContext; std::vector m_filesToIgnore; private: friend class ClazyPreprocessorCallbacks; friend class ClazyAstMatcherCallback; ClazyPreprocessorCallbacks *const m_preprocessorCallbacks; std::vector m_emittedWarningsInMacro; std::vector m_emittedManualFixItsWarningsInMacro; std::vector> m_queuedManualInterventionWarnings; int m_enabledFixits = 0; const Options m_options; const std::string m_tag; }; #endif