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