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