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