1 //===- CompilerInvocation.h - Compiler Invocation Helper Data ---*- C -*-===// 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 // Coding style: https://mlir.llvm.org/getting_started/DeveloperGuide/ 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef FORTRAN_FRONTEND_COMPILERINVOCATION_H 14 #define FORTRAN_FRONTEND_COMPILERINVOCATION_H 15 16 #include "flang/Frontend/FrontendOptions.h" 17 #include "flang/Frontend/PreprocessorOptions.h" 18 #include "flang/Frontend/TargetOptions.h" 19 #include "flang/Parser/parsing.h" 20 #include "flang/Semantics/semantics.h" 21 #include "clang/Basic/Diagnostic.h" 22 #include "clang/Basic/DiagnosticOptions.h" 23 #include "llvm/Option/ArgList.h" 24 #include <memory> 25 26 namespace Fortran::frontend { 27 28 /// Fill out Opts based on the options given in Args. 29 /// 30 /// When errors are encountered, return false and, if Diags is non-null, 31 /// report the error(s). 32 bool parseDiagnosticArgs(clang::DiagnosticOptions &opts, 33 llvm::opt::ArgList &args); 34 35 class CompilerInvocationBase { 36 public: 37 /// Options controlling the diagnostic engine. 38 llvm::IntrusiveRefCntPtr<clang::DiagnosticOptions> diagnosticOpts; 39 /// Options for the preprocessor. 40 std::shared_ptr<Fortran::frontend::PreprocessorOptions> preprocessorOpts; 41 42 CompilerInvocationBase(); 43 CompilerInvocationBase(const CompilerInvocationBase &x); 44 ~CompilerInvocationBase(); 45 46 clang::DiagnosticOptions &getDiagnosticOpts() { 47 return *diagnosticOpts.get(); 48 } 49 const clang::DiagnosticOptions &getDiagnosticOpts() const { 50 return *diagnosticOpts.get(); 51 } 52 53 PreprocessorOptions &getPreprocessorOpts() { return *preprocessorOpts; } 54 const PreprocessorOptions &getPreprocessorOpts() const { 55 return *preprocessorOpts; 56 } 57 }; 58 59 class CompilerInvocation : public CompilerInvocationBase { 60 /// Options for the frontend driver 61 // TODO: Merge with or translate to parserOpts_. We shouldn't need two sets of 62 // options. 63 FrontendOptions frontendOpts; 64 65 /// Options for Flang parser 66 // TODO: Merge with or translate to frontendOpts. We shouldn't need two sets 67 // of options. 68 Fortran::parser::Options parserOpts; 69 70 /// Options controlling the target. 71 Fortran::frontend::TargetOptions targetOpts; 72 73 // Semantics context 74 std::unique_ptr<Fortran::semantics::SemanticsContext> semanticsContext; 75 76 /// Semantic options 77 // TODO: Merge with or translate to frontendOpts. We shouldn't need two sets 78 // of options. 79 std::string moduleDir = "."; 80 81 std::string moduleFileSuffix = ".mod"; 82 83 bool debugModuleDir = false; 84 85 bool warnAsErr = false; 86 87 /// This flag controls the unparsing and is used to decide whether to print out 88 /// the semantically analyzed version of an object or expression or the plain 89 /// version that does not include any information from semantic analysis. 90 bool useAnalyzedObjectsForUnparse = true; 91 92 // Fortran Dialect options 93 Fortran::common::IntrinsicTypeDefaultKinds defaultKinds; 94 95 bool enableConformanceChecks = false; 96 97 /// Used in e.g. unparsing to dump the analyzed rather than the original 98 /// parse-tree objects. 99 Fortran::parser::AnalyzedObjectsAsFortran asFortran{ 100 [](llvm::raw_ostream &o, const Fortran::evaluate::GenericExprWrapper &x) { 101 if (x.v) { 102 x.v->AsFortran(o); 103 } else { 104 o << "(bad expression)"; 105 } 106 }, 107 [](llvm::raw_ostream &o, 108 const Fortran::evaluate::GenericAssignmentWrapper &x) { 109 if (x.v) { 110 x.v->AsFortran(o); 111 } else { 112 o << "(bad assignment)"; 113 } 114 }, 115 [](llvm::raw_ostream &o, const Fortran::evaluate::ProcedureRef &x) { 116 x.AsFortran(o << "CALL "); 117 }, 118 }; 119 120 public: 121 CompilerInvocation() = default; 122 123 FrontendOptions &getFrontendOpts() { return frontendOpts; } 124 const FrontendOptions &getFrontendOpts() const { return frontendOpts; } 125 126 Fortran::parser::Options &getFortranOpts() { return parserOpts; } 127 const Fortran::parser::Options &getFortranOpts() const { return parserOpts; } 128 129 TargetOptions &getTargetOpts() { return targetOpts; } 130 const TargetOptions &getTargetOpts() const { return targetOpts; } 131 132 Fortran::semantics::SemanticsContext &getSemanticsContext() { 133 return *semanticsContext; 134 } 135 const Fortran::semantics::SemanticsContext &getSemanticsContext() const { 136 return *semanticsContext; 137 } 138 139 std::string &getModuleDir() { return moduleDir; } 140 const std::string &getModuleDir() const { return moduleDir; } 141 142 std::string &getModuleFileSuffix() { return moduleFileSuffix; } 143 const std::string &getModuleFileSuffix() const { return moduleFileSuffix; } 144 145 bool &getDebugModuleDir() { return debugModuleDir; } 146 const bool &getDebugModuleDir() const { return debugModuleDir; } 147 148 bool &getWarnAsErr() { return warnAsErr; } 149 const bool &getWarnAsErr() const { return warnAsErr; } 150 151 bool &getUseAnalyzedObjectsForUnparse() { 152 return useAnalyzedObjectsForUnparse; 153 } 154 const bool &getUseAnalyzedObjectsForUnparse() const { 155 return useAnalyzedObjectsForUnparse; 156 } 157 158 bool &getEnableConformanceChecks() { return enableConformanceChecks; } 159 const bool &getEnableConformanceChecks() const { 160 return enableConformanceChecks; 161 } 162 163 Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() { 164 return asFortran; 165 } 166 const Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() const { 167 return asFortran; 168 } 169 170 Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() { 171 return defaultKinds; 172 } 173 const Fortran::common::IntrinsicTypeDefaultKinds &getDefaultKinds() const { 174 return defaultKinds; 175 } 176 177 /// Create a compiler invocation from a list of input options. 178 /// \returns true on success. 179 /// \returns false if an error was encountered while parsing the arguments 180 /// \param [out] res - The resulting invocation. 181 static bool createFromArgs(CompilerInvocation &res, 182 llvm::ArrayRef<const char *> commandLineArgs, 183 clang::DiagnosticsEngine &diags); 184 185 // Enables the std=f2018 conformance check 186 void setEnableConformanceChecks() { enableConformanceChecks = true; } 187 188 /// Useful setters 189 void setModuleDir(std::string &dir) { moduleDir = dir; } 190 191 void setModuleFileSuffix(const char *suffix) { 192 moduleFileSuffix = std::string(suffix); 193 } 194 195 void setDebugModuleDir(bool flag) { debugModuleDir = flag; } 196 197 void setWarnAsErr(bool flag) { warnAsErr = flag; } 198 199 void setUseAnalyzedObjectsForUnparse(bool flag) { 200 useAnalyzedObjectsForUnparse = flag; 201 } 202 203 /// Set the Fortran options to predefined defaults. 204 // TODO: We should map frontendOpts_ to parserOpts_ instead. For that, we 205 // need to extend frontendOpts_ first. Next, we need to add the corresponding 206 // compiler driver options in libclangDriver. 207 void setDefaultFortranOpts(); 208 209 /// Set the default predefinitions. 210 void setDefaultPredefinitions(); 211 212 /// Collect the macro definitions from preprocessorOpts_ and prepare them for 213 /// the parser (i.e. copy into parserOpts_) 214 void collectMacroDefinitions(); 215 216 /// Set the Fortran options to user-specified values. 217 /// These values are found in the preprocessor options. 218 void setFortranOpts(); 219 220 /// Set the Semantic Options 221 void setSemanticsOpts(Fortran::parser::AllCookedSources &); 222 }; 223 224 } // end namespace Fortran::frontend 225 #endif // FORTRAN_FRONTEND_COMPILERINVOCATION_H 226