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