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 
set_currentInput(const FrontendInputFile & currentInput)16 void FrontendAction::set_currentInput(const FrontendInputFile &currentInput) {
17   this->currentInput_ = currentInput;
18 }
19 
20 // Call this method if BeginSourceFile fails.
21 // Deallocate compiler instance, input and output descriptors
BeginSourceFileCleanUp(FrontendAction & fa,CompilerInstance & ci)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 
BeginSourceFile(CompilerInstance & ci,const FrontendInputFile & realInput)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 
ShouldEraseOutputFiles()43 bool FrontendAction::ShouldEraseOutputFiles() {
44   return instance().diagnostics().hasErrorOccurred();
45 }
46 
Execute()47 llvm::Error FrontendAction::Execute() {
48   std::string currentInputPath{GetCurrentFileOrBufferName()};
49 
50   Fortran::parser::Options parserOptions =
51       this->instance().invocation().fortranOpts();
52 
53   this->instance().parsing().Prescan(currentInputPath, parserOptions);
54 
55   ExecuteAction();
56 
57   return llvm::Error::success();
58 }
59 
EndSourceFile()60 void FrontendAction::EndSourceFile() {
61   CompilerInstance &ci = instance();
62 
63   // Cleanup the output streams, and erase the output files if instructed by the
64   // FrontendAction.
65   ci.ClearOutputFiles(/*EraseFiles=*/ShouldEraseOutputFiles());
66 
67   set_instance(nullptr);
68   set_currentInput(FrontendInputFile());
69 }
70