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