1 //===--- FrontendActions.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/FrontendActions.h"
10 #include "flang/Common/default-kinds.h"
11 #include "flang/Frontend/CompilerInstance.h"
12 #include "flang/Parser/parsing.h"
13 #include "flang/Parser/provenance.h"
14 #include "flang/Parser/source.h"
15 #include "flang/Semantics/semantics.h"
16 
17 using namespace Fortran::frontend;
18 
19 void InputOutputTestAction::ExecuteAction() {
20 
21   // Get the name of the file from FrontendInputFile current.
22   std::string path{GetCurrentFileOrBufferName()};
23   std::string buf;
24   llvm::raw_string_ostream error_stream{buf};
25   bool binaryMode = true;
26 
27   // Set/store input file info into CompilerInstance.
28   CompilerInstance &ci = instance();
29   Fortran::parser::AllSources &allSources{ci.allSources()};
30   const Fortran::parser::SourceFile *sf;
31   sf = allSources.Open(path, error_stream);
32   llvm::ArrayRef<char> fileContent = sf->content();
33 
34   // Output file descriptor to receive the content of input file.
35   std::unique_ptr<llvm::raw_ostream> os;
36 
37   // Do not write on the output file if using outputStream_.
38   if (ci.IsOutputStreamNull()) {
39     os = ci.CreateDefaultOutputFile(
40         binaryMode, GetCurrentFileOrBufferName(), "txt");
41     if (!os)
42       return;
43     (*os) << fileContent.data();
44   } else {
45     ci.WriteOutputStream(fileContent.data());
46   }
47 }
48 
49 void PrintPreprocessedAction::ExecuteAction() {
50   std::string buf;
51   llvm::raw_string_ostream outForPP{buf};
52 
53   // Run the preprocessor
54   CompilerInstance &ci = this->instance();
55   ci.parsing().DumpCookedChars(outForPP);
56 
57   // If a pre-defined output stream exists, dump the preprocessed content there
58   if (!ci.IsOutputStreamNull()) {
59     // Send the output to the pre-defined output buffer.
60     ci.WriteOutputStream(outForPP.str());
61     return;
62   }
63 
64   // Create a file and save the preprocessed output there
65   if (auto os{ci.CreateDefaultOutputFile(
66           /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName())}) {
67     (*os) << outForPP.str();
68   } else {
69     llvm::errs() << "Unable to create the output file\n";
70     return;
71   }
72 }
73 
74 void ParseSyntaxOnlyAction::ExecuteAction() {
75   CompilerInstance &ci = this->instance();
76 
77   // TODO: These should be specifiable by users. For now just use the defaults.
78   common::LanguageFeatureControl features;
79   Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;
80 
81   // Parse
82   ci.parsing().Parse(llvm::outs());
83   auto &parseTree{*ci.parsing().parseTree()};
84 
85   // Prepare semantics
86   Fortran::semantics::SemanticsContext semanticsContext{
87       defaultKinds, features, ci.allCookedSources()};
88   Fortran::semantics::Semantics semantics{
89       semanticsContext, parseTree, ci.parsing().cooked().AsCharBlock()};
90 
91   // Run semantic checks
92   semantics.Perform();
93 
94   // Report the diagnostics from the semantic checks
95   semantics.EmitMessages(ci.semaOutputStream());
96 
97   if (semantics.AnyFatalError()) {
98     unsigned DiagID = ci.diagnostics().getCustomDiagID(
99         clang::DiagnosticsEngine::Error, "semantic errors in %0");
100     ci.diagnostics().Report(DiagID) << GetCurrentFileOrBufferName();
101   }
102 }
103