File indexing completed on 2024-05-19 05:42:03
0001 // ct_lvtclp_physicaldepscanner.cpp -*-C++-*- 0002 0003 /* 0004 // Copyright 2023 Codethink Ltd <codethink@codethink.co.uk> 0005 // SPDX-License-Identifier: Apache-2.0 0006 // 0007 // Licensed under the Apache License, Version 2.0 (the "License"); 0008 // you may not use this file except in compliance with the License. 0009 // You may obtain a copy of the License at 0010 // 0011 // http://www.apache.org/licenses/LICENSE-2.0 0012 // 0013 // Unless required by applicable law or agreed to in writing, software 0014 // distributed under the License is distributed on an "AS IS" BASIS, 0015 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 0016 // See the License for the specific language governing permissions and 0017 // limitations under the License. 0018 */ 0019 0020 #include <ct_lvtclp_clputil.h> 0021 #include <ct_lvtclp_physicaldepscanner.h> 0022 0023 #include <ct_lvtclp_diagnostic_consumer.h> 0024 0025 #include <clang/Frontend/CompilerInstance.h> 0026 #include <clang/Frontend/FrontendActions.h> 0027 0028 namespace { 0029 0030 using namespace Codethink; 0031 using namespace Codethink::lvtclp; 0032 0033 class FrontendAction : public clang::PreprocessOnlyAction { 0034 // Per-thread processing using only the clang preprocessor 0035 0036 private: 0037 lvtmdb::ObjectStore& d_memDb; 0038 std::filesystem::path d_prefix; 0039 std::vector<std::filesystem::path> d_nonLakosianDirs; 0040 std::vector<std::pair<std::string, std::string>> d_thirdPartyDirs; 0041 std::function<void(const std::string&)> d_filenameCallback; 0042 std::vector<llvm::GlobPattern> d_ignoreGlobs; 0043 std::optional<HeaderCallbacks::HeaderLocationCallback_f> d_headerLocationCallback; 0044 0045 public: 0046 FrontendAction(lvtmdb::ObjectStore& memDb, 0047 std::filesystem::path prefix, 0048 std::vector<std::filesystem::path> nonLakosians, 0049 std::vector<std::pair<std::string, std::string>> thirdPartyDirs, 0050 std::function<void(const std::string&)> filenameCallback, 0051 std::vector<llvm::GlobPattern> ignoreGlobs, 0052 std::optional<HeaderCallbacks::HeaderLocationCallback_f> headerLocationCallback): 0053 d_memDb(memDb), 0054 d_prefix(std::move(prefix)), 0055 d_nonLakosianDirs(std::move(nonLakosians)), 0056 d_thirdPartyDirs(std::move(thirdPartyDirs)), 0057 d_filenameCallback(std::move(filenameCallback)), 0058 d_ignoreGlobs(std::move(ignoreGlobs)), 0059 d_headerLocationCallback(std::move(headerLocationCallback)) 0060 { 0061 } 0062 0063 ~FrontendAction() noexcept override = default; 0064 0065 void ExecuteAction() override 0066 { 0067 auto realPathStr = getCurrentFile().str(); 0068 if (ClpUtil::isFileIgnored(realPathStr, d_ignoreGlobs)) { 0069 return; 0070 } 0071 0072 clang::CompilerInstance& compiler = getCompilerInstance(); 0073 clang::Preprocessor& pp = compiler.getPreprocessor(); 0074 0075 pp.addPPCallbacks(std::make_unique<lvtclp::HeaderCallbacks>(&compiler.getSourceManager(), 0076 d_memDb, 0077 d_prefix, 0078 d_nonLakosianDirs, 0079 d_thirdPartyDirs, 0080 d_ignoreGlobs, 0081 d_headerLocationCallback)); 0082 0083 // try our best not to bail on compilation errors 0084 clang::FrontendOptions& fOpts = compiler.getFrontendOpts(); 0085 fOpts.FixWhatYouCan = true; 0086 fOpts.FixAndRecompile = true; 0087 fOpts.FixToTemporaries = true; 0088 // skip parsing function bodies 0089 fOpts.SkipFunctionBodies = true; 0090 0091 // Attempt to obliterate any -Werror options 0092 clang::DiagnosticOptions& dOpts = compiler.getDiagnosticOpts(); 0093 dOpts.Warnings = {"-Wno-everything"}; 0094 0095 PreprocessOnlyAction::ExecuteAction(); 0096 } 0097 0098 bool BeginSourceFileAction(clang::CompilerInstance& ci) override 0099 { 0100 d_filenameCallback(getCurrentFile().str()); 0101 0102 auto realPathStr = getCurrentFile().str(); 0103 if (ClpUtil::isFileIgnored(realPathStr, d_ignoreGlobs)) { 0104 return false; 0105 } 0106 0107 return PreprocessOnlyAction::BeginSourceFileAction(ci); 0108 } 0109 }; 0110 0111 } // namespace 0112 0113 namespace Codethink::lvtclp { 0114 0115 struct DepScanActionFactory::Private { 0116 lvtmdb::ObjectStore& memDb; 0117 std::filesystem::path prefix; 0118 std::vector<std::filesystem::path> nonLakosianDirs; 0119 std::vector<std::pair<std::string, std::string>> thirdPartyDirs; 0120 std::function<void(const std::string&)> filenameCallback; 0121 std::vector<llvm::GlobPattern> ignoreGlobs; 0122 std::optional<HeaderCallbacks::HeaderLocationCallback_f> headerLocationCallback; 0123 0124 Private(lvtmdb::ObjectStore& memDb, 0125 std::filesystem::path prefix, 0126 std::vector<std::filesystem::path> nonLakosians, 0127 std::vector<std::pair<std::string, std::string>> thirdPartyDirs, 0128 std::function<void(const std::string&)> filenameCallback, 0129 std::vector<llvm::GlobPattern> ignoreGlobs, 0130 std::optional<HeaderCallbacks::HeaderLocationCallback_f> headerLocationCallback): 0131 memDb(memDb), 0132 prefix(std::move(prefix)), 0133 nonLakosianDirs(std::move(nonLakosians)), 0134 thirdPartyDirs(std::move(thirdPartyDirs)), 0135 filenameCallback(std::move(filenameCallback)), 0136 ignoreGlobs(std::move(ignoreGlobs)), 0137 headerLocationCallback(std::move(headerLocationCallback)) 0138 { 0139 } 0140 }; 0141 0142 DepScanActionFactory::DepScanActionFactory( 0143 lvtmdb::ObjectStore& memDb, 0144 const std::filesystem::path& prefix, 0145 const std::vector<std::filesystem::path>& nonLakosians, 0146 const std::vector<std::pair<std::string, std::string>>& thirdPartyDirs, 0147 std::function<void(const std::string&)> filenameCallback, 0148 std::vector<llvm::GlobPattern> ignoreGlobs, 0149 std::optional<HeaderCallbacks::HeaderLocationCallback_f> headerLocationCallback): 0150 d(std::make_unique<DepScanActionFactory::Private>(memDb, 0151 prefix, 0152 nonLakosians, 0153 thirdPartyDirs, 0154 std::move(filenameCallback), 0155 std::move(ignoreGlobs), 0156 std::move(headerLocationCallback))) 0157 { 0158 } 0159 0160 DepScanActionFactory::~DepScanActionFactory() noexcept = default; 0161 0162 std::unique_ptr<clang::FrontendAction> DepScanActionFactory::create() 0163 { 0164 return std::make_unique<FrontendAction>(d->memDb, 0165 d->prefix, 0166 d->nonLakosianDirs, 0167 d->thirdPartyDirs, 0168 d->filenameCallback, 0169 d->ignoreGlobs, 0170 d->headerLocationCallback); 0171 } 0172 0173 } // namespace Codethink::lvtclp