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 "llvm/Support/Errc.h" 13 14 using namespace Fortran::frontend; 15 16 void FrontendAction::set_currentInput(const FrontendInputFile ¤tInput) { 17 this->currentInput_ = currentInput; 18 } 19 20 // Call this method if BeginSourceFile fails. 21 // Deallocate compiler instance, input and output descriptors 22 static void BeginSourceFileCleanUp(FrontendAction &fa, CompilerInstance &ci) { 23 ci.ClearOutputFiles(/*EraseFiles=*/true); 24 fa.set_currentInput(FrontendInputFile()); 25 fa.set_instance(nullptr); 26 } 27 28 bool FrontendAction::BeginSourceFile( 29 CompilerInstance &ci, const FrontendInputFile &realInput) { 30 31 FrontendInputFile input(realInput); 32 assert(!instance_ && "Already processing a source file!"); 33 assert(!realInput.IsEmpty() && "Unexpected empty filename!"); 34 set_currentInput(realInput); 35 set_instance(&ci); 36 if (!ci.HasAllSources()) { 37 BeginSourceFileCleanUp(*this, ci); 38 return false; 39 } 40 return true; 41 } 42 43 bool FrontendAction::ShouldEraseOutputFiles() { 44 return instance().diagnostics().hasErrorOccurred(); 45 } 46 47 llvm::Error FrontendAction::Execute() { 48 CompilerInstance &ci = this->instance(); 49 50 std::string currentInputPath{GetCurrentFileOrBufferName()}; 51 52 Fortran::parser::Options parserOptions = 53 this->instance().invocation().fortranOpts(); 54 55 // Prescan. In case of failure, report and return. 56 ci.parsing().Prescan(currentInputPath, parserOptions); 57 58 if (ci.parsing().messages().AnyFatalError()) { 59 const unsigned diagID = ci.diagnostics().getCustomDiagID( 60 clang::DiagnosticsEngine::Error, "Could not scan %0"); 61 ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName(); 62 ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources()); 63 64 return llvm::Error::success(); 65 } 66 67 ExecuteAction(); 68 69 return llvm::Error::success(); 70 } 71 72 void FrontendAction::EndSourceFile() { 73 CompilerInstance &ci = instance(); 74 75 // Cleanup the output streams, and erase the output files if instructed by the 76 // FrontendAction. 77 ci.ClearOutputFiles(/*EraseFiles=*/ShouldEraseOutputFiles()); 78 79 set_instance(nullptr); 80 set_currentInput(FrontendInputFile()); 81 } 82