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