File indexing completed on 2024-04-28 16:57:49
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 #include "AccessSpecifierManager.h" 0023 #include "checkmanager.h" 0024 #include "ClazyContext.h" 0025 #include "FixItExporter.h" 0026 #include "PreProcessorVisitor.h" 0027 0028 #include <clang/AST/ParentMap.h> 0029 #include <clang/Frontend/CompilerInstance.h> 0030 #include <clang/Lex/PreprocessorOptions.h> 0031 #include <clang/Rewrite/Frontend/FixItRewriter.h> 0032 #include <llvm/Support/Regex.h> 0033 0034 #include <stdlib.h> 0035 0036 using namespace std; 0037 using namespace clang; 0038 0039 0040 ClazyContext::ClazyContext(const clang::CompilerInstance &compiler, 0041 const string &headerFilter, const string &ignoreDirs, 0042 string exportFixesFilename, 0043 const std::vector<string> &translationUnitPaths, ClazyOptions opts) 0044 : ci(compiler) 0045 , astContext(ci.getASTContext()) 0046 , sm(ci.getSourceManager()) 0047 , m_noWerror(getenv("CLAZY_NO_WERROR") != nullptr) // Allows user to make clazy ignore -Werror 0048 , m_checksPromotedToErrors(CheckManager::instance()->checksAsErrors()) 0049 , options(opts) 0050 , extraOptions(clazy::splitString(getenv("CLAZY_EXTRA_OPTIONS"), ',')) 0051 , m_translationUnitPaths(translationUnitPaths) 0052 { 0053 if (!headerFilter.empty()) 0054 headerFilterRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(headerFilter)); 0055 0056 if (!ignoreDirs.empty()) 0057 ignoreDirsRegex = std::unique_ptr<llvm::Regex>(new llvm::Regex(ignoreDirs)); 0058 0059 if (exportFixesEnabled()) { 0060 if (exportFixesFilename.empty()) { 0061 // Only clazy-standalone sets the filename by argument. 0062 // clazy plugin sets it automatically here: 0063 const FileEntry *fileEntry = sm.getFileEntryForID(sm.getMainFileID()); 0064 exportFixesFilename = fileEntry->getName().str() + ".clazy.yaml"; 0065 } 0066 0067 const bool isClazyStandalone = !translationUnitPaths.empty(); 0068 exporter = new FixItExporter(ci.getDiagnostics(), sm, ci.getLangOpts(), 0069 exportFixesFilename, isClazyStandalone); 0070 } 0071 } 0072 0073 ClazyContext::~ClazyContext() 0074 { 0075 //delete preprocessorVisitor; // we don't own it 0076 delete accessSpecifierManager; 0077 delete parentMap; 0078 0079 static unsigned long count = 0; 0080 count++; 0081 0082 if (exporter) { 0083 // With clazy-standalone we use the same YAML file for all translation-units, so only 0084 // write out the last one. With clazy-plugin there's a YAML file per translation unit. 0085 const bool isClazyPlugin = m_translationUnitPaths.empty(); 0086 const bool isLast = count == m_translationUnitPaths.size(); 0087 if (isLast || isClazyPlugin) 0088 exporter->Export(); 0089 delete exporter; 0090 } 0091 0092 preprocessorVisitor = nullptr; 0093 accessSpecifierManager = nullptr; 0094 parentMap = nullptr; 0095 } 0096 0097 void ClazyContext::enableAccessSpecifierManager() 0098 { 0099 if (!accessSpecifierManager && !usingPreCompiledHeaders()) 0100 accessSpecifierManager = new AccessSpecifierManager(this); 0101 } 0102 0103 void ClazyContext::enablePreprocessorVisitor() 0104 { 0105 if (!preprocessorVisitor && !usingPreCompiledHeaders()) 0106 preprocessorVisitor = new PreProcessorVisitor(ci); 0107 } 0108 0109 void ClazyContext::enableVisitallTypeDefs() 0110 { 0111 // By default we only process decls from the .cpp file we're processing, not stuff included (for performance) 0112 /// But we might need to process all typedefs, not only the ones in our current .cpp files 0113 m_visitsAllTypeDefs = true; 0114 } 0115 0116 bool ClazyContext::visitsAllTypedefs() const 0117 { 0118 return m_visitsAllTypeDefs; 0119 } 0120 0121 bool ClazyContext::isQt() const 0122 { 0123 static const bool s_isQt = [this] { 0124 for (auto s : ci.getPreprocessorOpts().Macros) { 0125 if (s.first == "QT_CORE_LIB") 0126 return true; 0127 } 0128 return false; 0129 } (); 0130 0131 return s_isQt; 0132 }