<div dir="ltr">In the last Flang technical call, I offered to check whether patches work under Windows. Turns out, Flang currently does not compile at all when using MSVC. Here are my notes for making is compile using the latest msvc compiler version 19.26.28806. I don't think we need to put effort into making it compile with older versions. <br><br>This is not a list of fixes. Some changes are not general purpose solutions, some break check-flang. However, I would gladly help working on fixing these upstream. However, with these changes f18 compiles and links successfully.<br><br><br><font size="4" face="arial, sans-serif">CMAKE_CXX_STANDARD=14</font><br><br><a href="https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html">https://cmake.org/cmake/help/latest/prop_tgt/CXX_STANDARD.html</a><br><br>Flang's CMakeLists.txt sets CMAKE_CXX_STANDARD=17. This is ignored when using a pre-configured llvm-prject build directory and adding flang to LLVM_ENABLED_PROJECTS. Maybe we can find a better solution such as setting CXX_STANDARD for flang targets only, but I am not sure whether the libraries are compatible when compiled for different versions of the C++ standard.<br><br><br><font size="4">flang\include\flang\Common\idioms.h(20,1): fatal error C1189: #error:  this is a C++17 program</font><br><br><a href="https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/">https://devblogs.microsoft.com/cppblog/msvc-now-correctly-reports-__cplusplus/</a><br><br>For historic reasons, msvc never bumped the value of the __cplusplus macro.<br>Adding /Zc:__cplusplus to CMAKE_CXX_FLAGS fixes this.<br><br>NOTE: When saying 'adding to CMAKE_CXX_FLAGS fixes this' I do not suggest to add<br>list(APPEND CMAKE_CXX_FLAGS "...")<br>into some CMakeLists.txt. A much better way is to use<br>add_compile_options(...)<br>CMAKE_CXX_FLAGS should be entirely under user control and never modified within the CMakeLists.txt.<br><br><br><font size="4">-Wno-unused-parameter -Wno-error</font><br><br>lib/Optimizer/CMakeLists.txt adds these unconditionally to CMAKE_CXX_FLAGS (which, as mentioned before, should not be done). Msvc does not understand these flags.<br>Also, -Werror is not used by default anymore. Adding -Wno-error to selected sources also seem to defeat the purpose of -Werror.<br><br><font face="monospace">--- a/flang/lib/Optimizer/CMakeLists.txt<br>+++ b/flang/lib/Optimizer/CMakeLists.txt<br>@@ -1,4 +1,4 @@<br>-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-error")<br> get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)<br><br> add_flang_library(FIROptimizer<br><br>--- a/flang/lib/Lower/CMakeLists.txt<br>+++ b/flang/lib/Lower/CMakeLists.txt<br>@@ -1,4 +1,3 @@<br>-set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-error -Wno-unused-parameter")<br> get_property(dialect_libs GLOBAL PROPERTY MLIR_DIALECT_LIBS)<br><br> add_flang_library(FortranLower</font><br><br><font size="4">llvm\include\llvm/ADT/iterator.h(68,19): warning C4996: 'std::iterator<IteratorCategoryT,T,DifferenceTypeT,PointerT,ReferenceT>': warning STL4015: The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17. (The <iterator> header is NOT deprecated.) The C++ Standard has never required user-defined iterators to derive from std::iterator.</font><br><br><a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r1.html#2.1">http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0174r1.html#2.1</a><br><br>When C++17 mode is enabled, msvc starts warning about deprecated features. Most prevalant is the warning to not derive from std::iterator, mostly in the LLVM support library. I.e. this will probably only fixed when LLVM itself bumps to C++17.<br>Adding /D_SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to CXX_CMAKE_FLAGS disables these warnings.<br><br><br><font size="4">fatal error C1128: number of sections exceeded object file format limit: compile with /bigobj</font><br><br><a href="https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1128?view=vs-2019">https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-1/fatal-error-c1128?view=vs-2019</a><br><br>Some files contain more symbols than the standard PE-COFF object format allows. <br>Adding /bigobj to CMAKE_CXX_FLAGS switches to a new object format.<br>Alternatively, /Gy- could be used, but that effectively disables COMDAT folding/pruning.<br><br><br><font size="4">INTERNAL COMPILER ERROR in 'C:\PROGRA~2\MICROS~1\2019\COMMUN~1\VC\Tools\MSVC\1426~1.288\bin\Hostx64\x64\cl.exe'</font><br><br><a href="https://developercommunity.visualstudio.com/content/problem/1067774/ice-internal-compiler-error-on-constexpr-range-bas.html">https://developercommunity.visualstudio.com/content/problem/1067774/ice-internal-compiler-error-on-constexpr-range-bas.html</a><br><br>This occurs when iterating over an std::initializer_list in a constexpr constructor. As a workaround, I replaced the std::initializer_list constructor with a variadic template constructor. Unfortunately, this also requires some other changes that rely on implicit conversion of std::initializer_list literals in the source.<br><font face="monospace"><br>--- a/flang/include/flang/Common/enum-set.h<br>+++ b/flang/include/flang/Common/enum-set.h<br>@@ -36,10 +36,10 @@ public:<br>   using enumerationType = ENUM;<br><br>   constexpr EnumSet() {}<br>-  constexpr EnumSet(const std::initializer_list<enumerationType> &enums) {<br>-    for (auto x : enums) {<br>-      set(x);<br>-    }<br>+  explicit constexpr EnumSet(enumerationType Singletpn) { set(Singletpn); }<br>+  template<typename... T><br>+  constexpr EnumSet(enumerationType a, T... Remaining) : EnumSet(Remaining...) {<br>+    set(a);<br>   }<br>   constexpr EnumSet(const EnumSet &) = default;<br>   constexpr EnumSet(EnumSet &&) = default;</font><br><br><font size="4">flang\lib\Semantics\symbol.cpp(258,1): error C2668: 'Fortran::semantics::Symbol::detailsIf': ambiguous call to overloaded function</font><br><br>Msvc is confused whether to call to const or non-const qualified method. Since the calling method is const-qualified, there really should not be such an ambiguity.<br>The following patch the issue:<br><font face="monospace"><br>--- a/flang/lib/Semantics/symbol.cpp<br>+++ b/flang/lib/Semantics/symbol.cpp<br>@@ -255,7 +255,7 @@ bool Symbol::CanReplaceDetails(const Details &details) const {<br>               return has<SubprogramNameDetails>() || has<EntityDetails>();<br>             },<br>             [&](const DerivedTypeDetails &) {<br>-              auto *derived{detailsIf<DerivedTypeDetails>()};<br>+              auto *derived{this->detailsIf<DerivedTypeDetails>()};<br>               return derived && derived->isForwardReferenced();<br>             },<br>             [](const auto &) { return false; },</font><br><br><br><font size="4">lang\runtime\file.cpp(186,19): error C2589: '(': illegal token on right side of '::'</font><br><br><a href="https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std">https://stackoverflow.com/questions/11544073/how-do-i-deal-with-the-max-macro-in-windows-h-colliding-with-max-in-std</a><br><br>windows.h defines macros min and max, conflicting with std::min. Defining NOMINMAX makes windows.h stop doing that:<br><br><font face="monospace">--- a/flang/runtime/file.cpp<br>+++ b/flang/runtime/file.cpp<br>@@ -15,6 +15,7 @@<br> #include <fcntl.h><br> #include <stdlib.h><br> #ifdef _WIN32<br>+#define NOMINMAX<br> #include <io.h><br> #include <windows.h><br> #else</font><br><br><br><font size="4">flang\include\flang\Evaluate\expression.h(646): warning C4099: 'Fortran::evaluate::Relational<Fortran::evaluate::SomeType>': type name first seen using 'class' now seen using 'struct'</font><br><br>When forward-declaring a class/struct, it should match struct/class with the keyword used to define the struct class.<br><br>Clang version of the same warning: <br>flang/include/flang/Evaluate/expression.h:646:17: warning: class template 'Relational' was previously declared as a struct template; this is valid, but may result in linker errors under the Microsoft C++ ABI [-Wmismatched-tags]<br><br><font face="monospace">--- a/flang/include/flang/Evaluate/expression.h<br>+++ b/flang/include/flang/Evaluate/expression.h<br>@@ -640,7 +643,7 @@ public:<br> FOR_EACH_INTEGER_KIND(extern template struct Relational, )<br> FOR_EACH_REAL_KIND(extern template struct Relational, )<br> FOR_EACH_CHARACTER_KIND(extern template struct Relational, )<br>-extern template struct Relational<SomeType>;<br>+extern template class Relational<SomeType>;<br><br> // Logical expressions of a kind bigger than LogicalResult<br> // do not include Relational<> operations as possibilities,<br></font><br><br><font size="4">include\flang/Decimal/decimal.h(109): error C2765: 'Fortran::decimal::ConvertToBinary': an explicit specialization or instantiation of a function template cannot have any default arguments</font><br> <br><a href="https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2765?view=vs-2019">https://docs.microsoft.com/en-us/cpp/error-messages/compiler-errors-2/compiler-error-c2765?view=vs-2019</a><br><br>Self explaining. Msvc is definitely right here:<br><br><a href="https://en.cppreference.com/w/cpp/language/template_specialization">https://en.cppreference.com/w/cpp/language/template_specialization</a><br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Default function arguments cannot be specified in explicit specializations of function templates, member function templates, and member functions of class templates when the class is implicitly instantiated.</blockquote><br><font face="monospace">--- a/flang/include/flang/Decimal/decimal.h<br>+++ b/flang/include/flang/Decimal/decimal.h<br>@@ -106,17 +106,17 @@ ConversionToBinaryResult<PREC> ConvertToBinary(<br>     const char *&, enum FortranRounding = RoundNearest);<br><br> extern template ConversionToBinaryResult<8> ConvertToBinary<8>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> extern template ConversionToBinaryResult<11> ConvertToBinary<11>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> extern template ConversionToBinaryResult<24> ConvertToBinary<24>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> extern template ConversionToBinaryResult<53> ConvertToBinary<53>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> extern template ConversionToBinaryResult<64> ConvertToBinary<64>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> extern template ConversionToBinaryResult<113> ConvertToBinary<113>(<br>-    const char *&, enum FortranRounding = RoundNearest);<br>+    const char *&, enum FortranRounding);<br> } // namespace Fortran::decimal<br> extern "C" {<br> #define NS(x) Fortran::decimal::x<br></font><br><font size="4"><br>include\flang/Evaluate/call.h(230): warning C4661: 'std::optional<Fortran::evaluate::Constant<Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,1>>> Fortran::evaluate::FunctionRef<Fortran::evaluate::Type<Fortran::common::TypeCategory::Integer,1>>::Fold(Fortran::evaluate::FoldingContext &)': no suitable definition provided for explicit template instantiation request</font><br><br>Some methods seem to not have any definitions. Seems they are never used, hence it still works.<br><br><br><font size="4">flang\include\flang\Evaluate\constant.h(102): error C2664: 'std::vector<Fortran::evaluate::value::Complex<Fortran::evaluate::value::Real<Fortran::evaluate::value::Integer<16,false,16,unsigned short,unsigned int>,8>>,std::allocator<Fortran::evaluate::value::Complex<Fortran::evaluate::value::Real<Fortran::evaluate::value::Integer<16,false,16,unsigned short,unsigned int>,8>>>>::vector(std::initializer_list<_Ty>,const _Alloc &)': cannot convert argument 1 from 'initializer list' to 'std::initializer_list<_Ty>'</font><br><br>Splitting the member initializer to the constructor body and making it more explicit works:<br><br><font face="monospace">--- a/flang/include/flang/Evaluate/constant.h<br>+++ b/flang/include/flang/Evaluate/constant.h<br>@@ -98,8 +98,11 @@ public:<br>   template <typename A><br>   ConstantBase(const A &x, Result res = Result{}) : result_{res}, values_{x} {}<br>   template <typename A, typename = common::NoLvalue<A>><br>-  ConstantBase(A &&x, Result res = Result{})<br>-      : result_{res}, values_{std::move(x)} {}<br>+  ConstantBase(A &&x, Result res /*= Result{}*/, int a, int b, int c)<br>+      : result_{res} {<br>+    Element y = std::move(x);<br>+    values_.push_back(std::move(y));<br>+  }<br></font><br><br><br><font size="4">flang\include\flang\Evaluate\expression.h(751): error C3200: 'Fortran::evaluate::Expr<Fortran::evaluate::SomeKind<Fortran::common::TypeCategory::Logical>>': invalid template argument for template parameter 'F', expected a class template</font><br><br>`Expr` inside the definition of `Expr` may be interpreted as the current instantiation (Same reason why template parameters do not need to be repeated for declaring its constructor). Declaring a forward declaration under a different name helps:<br><br><font face="monospace">--- a/flang/include/flang/Evaluate/expression.h<br>+++ b/flang/include/flang/Evaluate/expression.h<br>@@ -736,6 +739,9 @@ public:<br>       u;<br> };<br><br>+template <typename T><br>+using OtherExpr = Expr<T>;<br>+<br> // A polymorphic expression of known intrinsic type category, but dynamic<br> // kind, represented as a discriminated union over Expr<Type<CAT, K>><br> // for each supported kind K in the category.<br>@@ -745,7 +751,7 @@ public:<br>   using Result = SomeKind<CAT>;<br>   EVALUATE_UNION_CLASS_BOILERPLATE(Expr)<br>   int GetKind() const;<br>-  common::MapTemplate<Expr, CategoryTypes<CAT>> u;<br>+  common::MapTemplate<OtherExpr, CategoryTypes<CAT>> u;<br> };<br></font><br><br><font size="4">flang\lib\Evaluate\characteristics.cpp: error C2672: '_C_invoke': no matching overloaded function found</font><br><br>The `template <int KIND> Result operator()(const TypeParamInquiry<KIND> &)` is defined in evaluate::GetShapeHelper as well as in evaluate::Traverse that GetShapHelper derives from (indirectly through evaluate::AnyTraverse). Additionally, GetShapeHelper declares `using Base::operator();`, i.e. explicitly importing the overloads from the base class (Base is AnyTraverse which does not declare any operator() itself but inherits from Traverse).<br>Therefore there is an obvious ambiguity when calling GetShapeHelper::operator()(TypeParamInquiry) which stops a std::variant from forwarding a call to operator().<br><br>I removed the overloads in the derived classes (same issue applies not only to GetShapeHelper, but other classes as well). I assume this is responsible for 3 fails in check-clang. <br><font face="monospace"><br>--- a/flang/include/flang/Evaluate/shape.h<br>+++ b/flang/include/flang/Evaluate/shape.h<br>@@ -93,9 +93,6 @@ public:<br><br>   Result operator()(const ImpliedDoIndex &) const { return Scalar(); }<br>   Result operator()(const DescriptorInquiry &) const { return Scalar(); }<br>-  template <int KIND> Result operator()(const TypeParamInquiry<KIND> &) const {<br>-    return Scalar();<br>-  }<br>   Result operator()(const BOZLiteralConstant &) const { return Scalar(); }<br>   Result operator()(const StaticDataObject::Pointer &) const {<br>     return Scalar();<br></font><br><br><font size="4">flang\include\flang/Lower/PFTBuilder.h(59): error C2665: 'std::variant<Fortran::common::Reference<Fortran::lower::pft::Program>,Fortran::common::Reference<Fortran::lower::pft::ModuleLikeUnit>,Fortran::common::Reference<Fortran::lower::pft::FunctionLikeUnit>,Fortran::common::Reference<Fortran::lower::pft::Evaluation>>::variant': none of the 2 overloads could convert all the argument types</font><br><br>Msvc is confused whether to use std::variant's copy or move-constructur. Unfortunately, ReferenceVariantBase, std::variant and common::Reference all can only be set at initialization such that I did not manage to decompose the conversions into separate steps. <br>The only way I managed to still compile this is by only accepting the variants of a conversion-constructor and do the decomposition at the call sites. Two of 4 of these call sites in this patch:<br><br><font face="monospace">--- a/flang/include/flang/Lower/PFTBuilder.h<br>+++ b/flang/include/flang/Lower/PFTBuilder.h<br>@@ -55,8 +55,7 @@ public:<br>   using Ref = common::Reference<BaseType<B>>;<br><br>   ReferenceVariantBase() = delete;<br>-  template <typename B><br>-  ReferenceVariantBase(B &b) : u{Ref<B>{b}} {}<br>+  ReferenceVariantBase(std::variant<Ref<A>...> b): u(b) { }<br><br>   template <typename B><br>   constexpr BaseType<B> &get() const {<br><br>--- a/flang/lib/Lower/PFTBuilder.cpp<br>+++ b/flang/lib/Lower/PFTBuilder.cpp<br>@@ -65,7 +65,18 @@ class PFTBuilder {<br> public:<br>   PFTBuilder(const semantics::SemanticsContext &semanticsContext)<br>       : pgm{std::make_unique<lower::pft::Program>()},<br>-        parentVariantStack{*pgm.get()}, semanticsContext{semanticsContext} {}<br>+        semanticsContext{semanticsContext} {<br>+    lower::pft::Program &x = *pgm.get();<br>+    common::Reference<lower::pft::Program> z{x};<br>+    std::variant<<br>+      common::Reference<lower::pft::Program>,<br>+      common::Reference<lower::pft::ModuleLikeUnit>,<br>+      common::Reference<lower::pft::FunctionLikeUnit>,<br>+      common::Reference<lower::pft::Evaluation><br>+    > w = z;<br>+    lower::pft::ParentVariant y = w;<br>+    parentVariantStack.push_back(y);<br>+  }<br><br>   /// Get the result<br>   std::unique_ptr<lower::pft::Program> result() { return std::move(pgm); }<br>@@ -905,11 +916,17 @@ private:<br> template <typename A, typename T><br> static lower::pft::FunctionLikeUnit::FunctionStatement<br> getFunctionStmt(const T &func) {<br>-  return std::get<parser::Statement<A>>(func.t);<br>+  using StmtTy = parser::Statement<A>;<br>+  const StmtTy &Tmp = std::get<StmtTy>(func.t);<br>+  lower::pft::FunctionLikeUnit::FunctionStatement Result{ Tmp };<br>+  return Result;<br> }<br></font><br><br><font size="4">expr-parsers.cpp: error C2338: tuple index out of bounds</font><br><br>For some reason, Msvc still wants to build the AST for the `constexpr (sizeof...(PARSER) == 1)` body when the variadic template parameter PARSER is empty. As a result, std::get<0> fails.<br><br>The patch below obviously is incorrect, but I did not want to spend too much time finding a proper fix. Maybe hiding the `if constexpr` body in another function call?<br><br>--- a/flang/lib/Parser/basic-parsers.h<br>+++ b/flang/lib/Parser/basic-parsers.h<br>@@ -729,13 +729,6 @@ public:<br>       return RESULT{};<br>     } else {<br>       if constexpr (sizeof...(PARSER) == 1) {<br>-        if constexpr (std::is_same_v<Success, typename PARSER::resultType...>) {<br>-          if (std::get<0>(parsers_).Parse(state)) {<br>-            return RESULT{};<br>-          }<br>-        } else if (auto arg{std::get<0>(parsers_).Parse(state)}) {<br>-          return RESULT{std::move(*arg)};<br>-        }<br>       } else {<br>         ApplyArgs<PARSER...> results;<br>         using Sequence = std::index_sequence_for<PARSER...>;<br><br><br><font size="4">flang\lib\Parser\basic-parsers.h(790): error C2672: 'applyFunction': no matching overloaded function found</font><br><br>Msvc has trouble deriving the template arguments for the applyFunction call. Explicitly specifying the template argument and decomposing implicit conversions help here.<br><br><font face="monospace">--- a/flang/lib/Parser/basic-parsers.h<br>+++ b/flang/lib/Parser/basic-parsers.h<br>@@ -782,8 +775,17 @@ public:<br>   constexpr NonemptySeparated(const NonemptySeparated &) = default;<br>   constexpr NonemptySeparated(PA p, PB sep) : parser_{p}, separator_{sep} {}<br>   std::optional<resultType> Parse(ParseState &state) const {<br>-    return applyFunction(prepend<paType>, parser_, many(separator_ >> parser_))<br>-        .Parse(state);<br>+    std::list<paType> (*arg1)(paType &&, std::list<paType> &&) = prepend<paType>;<br>+    const PA &arg2 = parser_;<br>+    using SeqPA = SequenceParser<PB, PA>;<br>+    SeqPA Seq = separator_ >> parser_;<br>+    using ManyPA = ManyParser<SeqPA>;<br>+    ManyPA arg3 = many<SeqPA>(Seq);<br>+    using RESULT = std::list<paType>;<br>+    using PARSER1 = PA;<br>+    using PARSER2 = ManyParser<SeqPA>;<br>+    auto result{ applyFunction<RESULT, PA, ManyPA > (arg1, arg2, arg3) };<br>+    return result.Parse(state);<br>   }</font><br><br><font size="4">flang\lib\Parser\basic-parsers.h(830): error C2131: expression did not evaluate to a constant / note: failure was caused by call of undefined function or one not declared 'constexpr'</font><br><br>Msvc has trouble declaring a class and defining a constexpr symbol in the same declarator. Writing the items in different declarators helps.<br><br>This pattern is used for multiple singleton classes. One of the occurrences is fixed by the patch below.<br><br><font face="monospace">--- a/flang/lib/Parser/basic-parsers.h<br>+++ b/flang/lib/Parser/basic-parsers.h<br>@@ -800,13 +802,14 @@ inline constexpr auto nonemptySeparated(PA p, PB sep) {<br> // must discard its result in order to be compatible in type with other<br> // parsers in an alternative, e.g. "x >> ok || y >> ok" is type-safe even<br> // when x and y have distinct result types.<br>-constexpr struct OkParser {<br>+struct OkParser {<br>   using resultType = Success;<br>   constexpr OkParser() {}<br>   static constexpr std::optional<Success> Parse(ParseState &) {<br>     return Success{};<br>   }<br>-} ok;<br>+};<br>+constexpr OkParser ok;</font><br><br><font size="4">flang\lib\Parser\expr-parsers.cpp(383): error C2672: 'applyLambda': no matching overloaded function found</font><br><br>Another case where Msvc could not derive template arguments.<br><font face="monospace"><br>--- a/flang/lib/Parser/expr-parsers.cpp<br>+++ b/flang/lib/Parser/expr-parsers.cpp<br>@@ -371,8 +379,13 @@ template <> std::optional<Expr> Parser<Expr>::Parse(ParseState &state) {<br>           return Expr{Expr::DefinedBinary(<br>               std::move(op), std::move(result).value(), std::move(right))};<br>         }};<br>+    ApplicableFunctionObject<Expr, Parser<DefinedOpName>, Level5Expr> arg1 = defBinOp;<br>+    Parser<DefinedOpName> arg2 = definedOpName;<br>+    Level5Expr arg3 = level5Expr;<br>+    auto lr = applyLambda<Expr, Parser<DefinedOpName>, Level5Expr>(arg1, arg2, arg3);<br>     auto more{<br>-        attempt(sourced(applyLambda(defBinOp, definedOpName, level5Expr)))};<br>+        attempt(sourced(lr))};<br>     while (std::optional<Expr> next{more.Parse(state)}) {<br>       result = std::move(next);<br>       result->source.ExtendToCover(source);</font><br><br><font size="4"><br>Use of POSIX functions in f18.cpp / f18-parse-demo.cpp</font><br><br>The following headers do not exist on Windows:<br><br>#include <sys/wait.h><br>#include <unistd.h><br><br>The following functions have platform-independent versions in LLVMSupport:<br><br>unlink -> llvm::sys::fs::remove<br><br>std::snprintf(tmpSourcePath, sizeof tmpSourcePath, "/tmp/f18-%lx.f90",<br>      static_cast<unsigned long>(getpid()));<br>llvm::raw_fd_ostream tmpSource(tmpSourcePath, EC, llvm::sys::fs::F_None);<br> --><br>std::error_code EC = llvm::sys::fs::createUniqueFile("f18-%%%%.f90", fd, tmpSourcePath);<br><br>execvp -> llvm::sys::ExecuteAndWait<br><br>fork and wait (in ParentProcess) -> Call of llvm::sys::ExecuteAndWait will be blocking:<br><br><font face="monospace">--- a/flang/tools/f18/f18.cpp<br>+++ b/flang/tools/f18/f18.cpp<br>@@ -358,14 +354,11 @@ std::string CompileFortran(std::string path, Fortran::parser::Options options,<br><br> std::string CompileOtherLanguage(std::string path, DriverOptions &driver) {<br>   std::string relo{RelocatableName(driver, path)};<br>-  if (ParentProcess()) {<br>+  RunOtherCompiler(driver, path.data(), relo.data());<br>     if (!driver.compileOnly && driver.outputPath.empty()) {<br>       filesToDelete.push_back(relo);<br>     }<br>     return relo;<br>-  }<br>-  RunOtherCompiler(driver, path.data(), relo.data());<br>-  return {};<br> }<br><br></font><br><br><br>Michael<br><br></div>