File indexing completed on 2024-04-28 16:57:50
0001 /* 0002 This file is part of the clazy static checker. 0003 0004 Copyright (C) 2017 Sergio Martins <smartins@kde.org> 0005 0006 This library is free software; you can redistribute it and/or 0007 modify it under the terms of the GNU Library General Public 0008 License as published by the Free Software Foundation; either 0009 version 2 of the License, or (at your option) any later version. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LIB. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 0022 #ifndef CLAZY_CONTEXT_H 0023 #define CLAZY_CONTEXT_H 0024 0025 #include "SuppressionManager.h" 0026 #include "clazy_stl.h" 0027 0028 #include <clang/Frontend/CompilerInstance.h> 0029 #include <clang/Lex/PreprocessorOptions.h> 0030 #include <clang/Basic/FileManager.h> 0031 #include <clang/Basic/SourceLocation.h> 0032 #include <clang/Basic/SourceManager.h> 0033 #include <llvm/Support/Regex.h> 0034 #include <llvm/ADT/StringRef.h> 0035 0036 #include <string> 0037 #include <vector> 0038 #include <memory> 0039 #include <utility> 0040 0041 // ClazyContext is just a struct to share data and code between all checks 0042 0043 namespace clang { 0044 class CompilerInstance; 0045 class ASTContext; 0046 class ParentMap; 0047 class SourceManager; 0048 class CXXMethodDecl; 0049 class Decl; 0050 } 0051 0052 class AccessSpecifierManager; 0053 class PreProcessorVisitor; 0054 class FixItExporter; 0055 0056 class ClazyContext 0057 { 0058 public: 0059 enum ClazyOption { 0060 ClazyOption_None = 0, 0061 ClazyOption_ExportFixes = 1, 0062 ClazyOption_Qt4Compat = 2, 0063 ClazyOption_OnlyQt = 4, // Ignore non-Qt files. This is done by bailing out if QT_CORE_LIB is not set. 0064 ClazyOption_QtDeveloper = 8, // For running clazy on Qt itself, optional, but honours specific guidelines 0065 ClazyOption_VisitImplicitCode = 16, // Inspect compiler generated code aswell, useful for custom checks, if they need it 0066 ClazyOption_IgnoreIncludedFiles = 32 // Only warn for the current file being compiled, not on includes (useful for performance reasons) 0067 }; 0068 typedef int ClazyOptions; 0069 0070 explicit ClazyContext(const clang::CompilerInstance &ci, 0071 const std::string &headerFilter, 0072 const std::string &ignoreDirs, 0073 std::string exportFixesFilename, 0074 const std::vector<std::string> &translationUnitPaths, 0075 ClazyOptions = ClazyOption_None); 0076 ~ClazyContext(); 0077 0078 bool usingPreCompiledHeaders() const 0079 { 0080 return !ci.getPreprocessorOpts().ImplicitPCHInclude.empty(); 0081 } 0082 0083 bool userDisabledWError() const 0084 { 0085 return m_noWerror; 0086 } 0087 0088 bool exportFixesEnabled() const 0089 { 0090 return options & ClazyOption_ExportFixes; 0091 } 0092 0093 bool isQtDeveloper() const 0094 { 0095 return options & ClazyOption_QtDeveloper; 0096 } 0097 0098 bool ignoresIncludedFiles() const 0099 { 0100 return options & ClazyOption_IgnoreIncludedFiles; 0101 } 0102 0103 bool isVisitImplicitCode() const 0104 { 0105 return options & ClazyContext::ClazyOption_VisitImplicitCode; 0106 } 0107 0108 bool isOptionSet(const std::string &optionName) const 0109 { 0110 return clazy::contains(extraOptions, optionName); 0111 } 0112 0113 bool fileMatchesLoc(const std::unique_ptr<llvm::Regex> ®ex, clang::SourceLocation loc, const clang::FileEntry **file) const 0114 { 0115 if (!regex) 0116 return false; 0117 0118 if (!(*file)) { 0119 clang::FileID fid = sm.getDecomposedExpansionLoc(loc).first; 0120 *file = sm.getFileEntryForID(fid); 0121 if (!(*file)) { 0122 return false; 0123 } 0124 } 0125 0126 llvm::StringRef fileName((*file)->getName()); 0127 return regex->match(fileName); 0128 } 0129 0130 bool shouldIgnoreFile(clang::SourceLocation loc) const 0131 { 0132 // 1. Process the regexp that excludes files 0133 const clang::FileEntry *file = nullptr; 0134 if (ignoreDirsRegex) { 0135 const bool matches = fileMatchesLoc(ignoreDirsRegex, loc, &file); 0136 if (matches) 0137 return true; 0138 } 0139 0140 // 2. Process the regexp that includes files. Has lower priority. 0141 if (!headerFilterRegex || isMainFile(loc)) 0142 return false; 0143 0144 const bool matches = fileMatchesLoc(headerFilterRegex, loc, &file); 0145 if (!file) 0146 return false; 0147 0148 return !matches; 0149 } 0150 0151 bool isMainFile(clang::SourceLocation loc) const 0152 { 0153 if (loc.isMacroID()) 0154 loc = sm.getExpansionLoc(loc); 0155 0156 return sm.isInFileID(loc, sm.getMainFileID()); 0157 } 0158 0159 bool treatAsError(const std::string &checkName) const 0160 { 0161 return clazy::contains(m_checksPromotedToErrors, checkName); 0162 } 0163 0164 /** 0165 * We only enable it if a check needs it, for performance reasons 0166 */ 0167 void enableAccessSpecifierManager(); 0168 void enablePreprocessorVisitor(); 0169 void enableVisitallTypeDefs(); 0170 bool visitsAllTypedefs() const; 0171 0172 bool isQt() const; 0173 0174 // TODO: More things will follow 0175 const clang::CompilerInstance &ci; 0176 clang::ASTContext &astContext; 0177 clang::SourceManager &sm; 0178 AccessSpecifierManager *accessSpecifierManager = nullptr; 0179 PreProcessorVisitor *preprocessorVisitor = nullptr; 0180 SuppressionManager suppressionManager; 0181 const bool m_noWerror; 0182 std::vector<std::string> m_checksPromotedToErrors; 0183 bool m_visitsAllTypeDefs = false; 0184 clang::ParentMap *parentMap = nullptr; 0185 const ClazyOptions options; 0186 const std::vector<std::string> extraOptions; 0187 FixItExporter *exporter = nullptr; 0188 clang::CXXMethodDecl *lastMethodDecl = nullptr; 0189 clang::FunctionDecl *lastFunctionDecl = nullptr; 0190 clang::Decl *lastDecl = nullptr; 0191 std::unique_ptr<llvm::Regex> headerFilterRegex; 0192 std::unique_ptr<llvm::Regex> ignoreDirsRegex; 0193 const std::vector<std::string> m_translationUnitPaths; 0194 }; 0195 0196 #endif