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