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