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
ExecuteAction()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
ExecuteAction()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 // Print diagnostics from the preprocessor
65 ci.parsing().messages().Emit(llvm::errs(), ci.allCookedSources());
66
67 // Create a file and save the preprocessed output there
68 if (auto os{ci.CreateDefaultOutputFile(
69 /*Binary=*/true, /*InFile=*/GetCurrentFileOrBufferName())}) {
70 (*os) << outForPP.str();
71 } else {
72 llvm::errs() << "Unable to create the output file\n";
73 return;
74 }
75 }
76
ExecuteAction()77 void ParseSyntaxOnlyAction::ExecuteAction() {
78 CompilerInstance &ci = this->instance();
79
80 // TODO: These should be specifiable by users. For now just use the defaults.
81 common::LanguageFeatureControl features;
82 Fortran::common::IntrinsicTypeDefaultKinds defaultKinds;
83
84 // Parse. In case of failure, report and return.
85 ci.parsing().Parse(llvm::outs());
86
87 if (ci.parsing().messages().AnyFatalError()) {
88 unsigned diagID = ci.diagnostics().getCustomDiagID(
89 clang::DiagnosticsEngine::Error, "Could not parse %0");
90 ci.diagnostics().Report(diagID) << GetCurrentFileOrBufferName();
91
92 ci.parsing().messages().Emit(
93 llvm::errs(), this->instance().allCookedSources());
94 return;
95 }
96
97 auto &parseTree{*ci.parsing().parseTree()};
98
99 // Prepare semantics
100 Fortran::semantics::SemanticsContext semanticsContext{
101 defaultKinds, features, ci.allCookedSources()};
102 Fortran::semantics::Semantics semantics{
103 semanticsContext, parseTree, ci.parsing().cooked().AsCharBlock()};
104
105 // Run semantic checks
106 semantics.Perform();
107
108 // Report the diagnostics from the semantic checks
109 semantics.EmitMessages(ci.semaOutputStream());
110
111 if (semantics.AnyFatalError()) {
112 unsigned DiagID = ci.diagnostics().getCustomDiagID(
113 clang::DiagnosticsEngine::Error, "Semantic errors in %0");
114 ci.diagnostics().Report(DiagID) << GetCurrentFileOrBufferName();
115 }
116 }
117
ExecuteAction()118 void EmitObjAction::ExecuteAction() {
119 CompilerInstance &ci = this->instance();
120 unsigned DiagID = ci.diagnostics().getCustomDiagID(
121 clang::DiagnosticsEngine::Error, "code-generation is not available yet");
122 ci.diagnostics().Report(DiagID);
123 }
124