1 //===--- FrontendAction.cpp -----------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "flang/Frontend/FrontendAction.h" 10 #include "flang/Frontend/CompilerInstance.h" 11 #include "flang/Frontend/FrontendActions.h" 12 #include "flang/Frontend/FrontendOptions.h" 13 #include "flang/FrontendTool/Utils.h" 14 #include "clang/Basic/DiagnosticFrontend.h" 15 #include "llvm/Support/Errc.h" 16 #include "llvm/Support/VirtualFileSystem.h" 17 18 using namespace Fortran::frontend; 19 20 void FrontendAction::set_currentInput(const FrontendInputFile ¤tInput) { 21 this->currentInput_ = currentInput; 22 } 23 24 // Call this method if BeginSourceFile fails. 25 // Deallocate compiler instance, input and output descriptors 26 static void BeginSourceFileCleanUp(FrontendAction &fa, CompilerInstance &ci) { 27 ci.ClearOutputFiles(/*EraseFiles=*/true); 28 fa.set_currentInput(FrontendInputFile()); 29 fa.set_instance(nullptr); 30 } 31 32 bool FrontendAction::BeginSourceFile( 33 CompilerInstance &ci, const FrontendInputFile &realInput) { 34 35 FrontendInputFile input(realInput); 36 37 // Return immediately if the input file does not exist or is not a file. Note 38 // that we cannot check this for input from stdin. 39 if (input.file() != "-") { 40 if (!llvm::sys::fs::is_regular_file(input.file())) { 41 // Create an diagnostic ID to report 42 unsigned diagID; 43 if (llvm::vfs::getRealFileSystem()->exists(input.file())) { 44 ci.diagnostics().Report(clang::diag::err_fe_error_reading) 45 << input.file(); 46 diagID = ci.diagnostics().getCustomDiagID( 47 clang::DiagnosticsEngine::Error, "%0 is not a regular file"); 48 } else { 49 diagID = ci.diagnostics().getCustomDiagID( 50 clang::DiagnosticsEngine::Error, "%0 does not exist"); 51 } 52 53 // Report the diagnostic and return 54 ci.diagnostics().Report(diagID) << input.file(); 55 BeginSourceFileCleanUp(*this, ci); 56 return false; 57 } 58 } 59 60 assert(!instance_ && "Already processing a source file!"); 61 assert(!realInput.IsEmpty() && "Unexpected empty filename!"); 62 set_currentInput(realInput); 63 set_instance(&ci); 64 65 if (!ci.HasAllSources()) { 66 BeginSourceFileCleanUp(*this, ci); 67 return false; 68 } 69 70 if (!BeginSourceFileAction(ci)) { 71 BeginSourceFileCleanUp(*this, ci); 72 return false; 73 } 74 75 return true; 76 } 77 78 bool FrontendAction::ShouldEraseOutputFiles() { 79 return instance().diagnostics().hasErrorOccurred(); 80 } 81 82 llvm::Error FrontendAction::Execute() { 83 ExecuteAction(); 84 85 return llvm::Error::success(); 86 } 87 88 void FrontendAction::EndSourceFile() { 89 CompilerInstance &ci = instance(); 90 91 // Cleanup the output streams, and erase the output files if instructed by the 92 // FrontendAction. 93 ci.ClearOutputFiles(/*EraseFiles=*/ShouldEraseOutputFiles()); 94 95 set_instance(nullptr); 96 set_currentInput(FrontendInputFile()); 97 } 98