[clang] [flang] [flang] Add -fhermetic-module-files (PR #98083)

2024-07-08 Thread Peter Klausler via cfe-commits

https://github.com/klausler created 
https://github.com/llvm/llvm-project/pull/98083

Module files emitted by this Fortran compiler are valid Fortran source files.  
Symbols that are USE-associated into modules are represented in their module 
files with USE statements and special comments with hash codes in them to 
ensure that those USE statements resolve to the same modules that were used to 
build the module when its module file was generated.

This scheme prevents unchecked module file growth in large applications by not 
emitting USE-associated symbols redundantly.  This problem can be especially 
bad when derived type definitions must be repeated in the module files of their 
clients, and the clients of those modules, and so on.  However, this scheme has 
the disadvantage that clients of modules must be compiled with dependent 
modules in the module search path.

This new -fhermetic-module-files option causes module file output to be free of 
dependences on any non-intrinsic module files; dependent modules are instead 
emitted as part of the module file, rather than being USE-associated.  It is 
intended for top level library module files that are shipped with binary 
libraries when it is not convenient to collect and ship their dependent module 
files as well.

Fixes https://github.com/llvm/llvm-project/issues/97398.

>From e85b374f3f78090daf0293b6ed6258bf91fb7b95 Mon Sep 17 00:00:00 2001
From: Peter Klausler 
Date: Mon, 8 Jul 2024 14:27:02 -0700
Subject: [PATCH] [flang] Add -fhermetic-module-files

Module files emitted by this Fortran compiler are valid Fortran source
files.  Symbols that are USE-associated into modules are represented
in their module files with USE statements and special comments with
hash codes in them to ensure that those USE statements resolve to
the same modules that were used to build the module when its module
file was generated.

This scheme prevents unchecked module file growth in large applications
by not emitting USE-associated symbols redundantly.  This problem can
be especially bad when derived type definitions must be repeated in
the module files of their clients, and the clients of those modules,
and so on.  However, this scheme has the disadvantage that clients of
modules must be compiled with dependent modules in the module search path.

This new -fhermetic-module-files option causes module file output to
be free of dependences on any non-intrinsic module files; dependent
modules are instead emitted as part of the module file, rather than
being USE-associated.  It is intended for top level library module files
that are shipped with binary libraries when it is not convenient to collect
and ship their dependent module files as well.

Fixes https://github.com/llvm/llvm-project/issues/97398.
---
 clang/include/clang/Driver/Options.td |  3 ++
 clang/lib/Driver/ToolChains/Flang.cpp | 32 ++-
 .../flang/Frontend/CompilerInvocation.h   |  9 
 flang/include/flang/Semantics/semantics.h | 10 ++--
 flang/lib/Frontend/CompilerInvocation.cpp |  5 ++
 flang/lib/Frontend/FrontendAction.cpp |  7 ++-
 flang/lib/Semantics/mod-file.cpp  | 42 +++
 flang/lib/Semantics/mod-file.h|  7 ++-
 flang/lib/Semantics/semantics.cpp |  4 +-
 flang/test/Semantics/modfile65.f90| 53 +++
 10 files changed, 142 insertions(+), 30 deletions(-)
 create mode 100644 flang/test/Semantics/modfile65.f90

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 1c2b8cfeef6ce6..f3488c27ca1532 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6667,6 +6667,9 @@ defm stack_arrays : BoolOptionWithoutMarshalling<"f", 
"stack-arrays",
 defm loop_versioning : BoolOptionWithoutMarshalling<"f", 
"version-loops-for-stride",
   PosFlag,
NegFlag>;
+
+def fhermetic_module_files : Flag<["-"], "fhermetic-module-files">, 
Group,
+  HelpText<"Emit hermetic module files (no nested USE association)">;
 } // let Visibility = [FC1Option, FlangOption]
 
 def J : JoinedOrSeparate<["-"], "J">,
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index 42b45dba2bd311..f9d4704dbb7bdf 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -35,18 +35,26 @@ static void addDashXForInput(const ArgList , const 
InputInfo ,
 
 void Flang::addFortranDialectOptions(const ArgList ,
  ArgStringList ) const {
-  Args.addAllArgs(
-  CmdArgs, {options::OPT_ffixed_form, options::OPT_ffree_form,
-options::OPT_ffixed_line_length_EQ, options::OPT_fopenacc,
-options::OPT_finput_charset_EQ, options::OPT_fimplicit_none,
-options::OPT_fno_implicit_none, options::OPT_fbackslash,
-options::OPT_fno_backslash, 
options::OPT_flogical_abbreviations,
-  

[clang] [flang] [flang] New -fdebug-unparse-with-modules option (PR #91660)

2024-05-15 Thread Peter Klausler via cfe-commits

https://github.com/klausler closed 
https://github.com/llvm/llvm-project/pull/91660
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang] New -fdebug-unparse-with-modules option (PR #91660)

2024-05-09 Thread Peter Klausler via cfe-commits

https://github.com/klausler created 
https://github.com/llvm/llvm-project/pull/91660

This option is a compilation action that parses a source file and performs 
semantic analysis on it, like the existing -fdebug-unparse option does.  Its 
output, however, is preceded by the effective contents of all of the 
non-intrinsic modules on which it depends but does not define, transitively 
preceded by the closure of all of those modules' dependencies.

The output from this option is therefore the analyzed parse tree for a source 
file encapsulated with all of its non-intrinsic module dependencies.  This 
output may be useful for extracting code from large applications for use as an 
attachment to a bug report, or as input to a test case reduction tool for 
problem isolation.

>From f56d89ab6ff37d974a3081792422a69d89266c38 Mon Sep 17 00:00:00 2001
From: Peter Klausler 
Date: Thu, 9 May 2024 14:27:02 -0700
Subject: [PATCH] [flang] New -fdebug-unparse-with-modules option

This option is a compilation action that parses a source file
and performs semantic analysis on it, like the existing -fdebug-unparse
option does.  Its output, however, is preceded by the effective
contents of all of the non-intrinsic modules on which it depends
but does not define, transitively preceded by the closure of all of
those modules' dependencies.

The output from this option is therefore the analyzed parse tree
for a source file encapsulated with all of its non-intrinsic module
dependencies.  This output may be useful for extracting code from
large applications for use as an attachment to a bug report, or
as input to a test case reduction tool for problem isolation.
---
 clang/include/clang/Driver/Options.td |  4 +-
 .../include/flang/Frontend/FrontendActions.h  |  4 ++
 .../include/flang/Frontend/FrontendOptions.h  |  4 ++
 .../flang/Semantics/unparse-with-symbols.h|  4 ++
 flang/lib/Frontend/CompilerInvocation.cpp |  3 ++
 flang/lib/Frontend/FrontendActions.cpp|  9 +
 .../ExecuteCompilerInvocation.cpp |  2 +
 flang/lib/Semantics/mod-file.cpp  | 20 +-
 flang/lib/Semantics/mod-file.h|  3 ++
 flang/lib/Semantics/unparse-with-symbols.cpp  | 38 +++
 flang/test/Driver/unparse-with-modules.f90| 34 +
 11 files changed, 122 insertions(+), 3 deletions(-)
 create mode 100644 flang/test/Driver/unparse-with-modules.f90

diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 73a2518480e9b..2e6db8d5ebd56 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6644,7 +6644,9 @@ def fdebug_unparse : Flag<["-"], "fdebug-unparse">, 
Group,
   DocBrief<[{Run the parser and the semantic checks. Then unparse the
 parse-tree and output the generated Fortran source file.}]>;
 def fdebug_unparse_with_symbols : Flag<["-"], "fdebug-unparse-with-symbols">, 
Group,
-  HelpText<"Unparse and stop.">;
+  HelpText<"Unparse with symbols and stop.">;
+def fdebug_unparse_with_modules : Flag<["-"], "fdebug-unparse-with-modules">, 
Group,
+  HelpText<"Unparse with dependent modules and stop.">;
 def fdebug_dump_symbols : Flag<["-"], "fdebug-dump-symbols">, 
Group,
   HelpText<"Dump symbols after the semantic analysis">;
 def fdebug_dump_parse_tree : Flag<["-"], "fdebug-dump-parse-tree">, 
Group,
diff --git a/flang/include/flang/Frontend/FrontendActions.h 
b/flang/include/flang/Frontend/FrontendActions.h
index e2e859f3a81bd..7823565eb815f 100644
--- a/flang/include/flang/Frontend/FrontendActions.h
+++ b/flang/include/flang/Frontend/FrontendActions.h
@@ -108,6 +108,10 @@ class DebugUnparseWithSymbolsAction : public 
PrescanAndSemaAction {
   void executeAction() override;
 };
 
+class DebugUnparseWithModulesAction : public PrescanAndSemaAction {
+  void executeAction() override;
+};
+
 class DebugUnparseAction : public PrescanAndSemaAction {
   void executeAction() override;
 };
diff --git a/flang/include/flang/Frontend/FrontendOptions.h 
b/flang/include/flang/Frontend/FrontendOptions.h
index 06b1318f243b0..82ca99672ec61 100644
--- a/flang/include/flang/Frontend/FrontendOptions.h
+++ b/flang/include/flang/Frontend/FrontendOptions.h
@@ -63,6 +63,10 @@ enum ActionKind {
   /// Fortran source file
   DebugUnparseWithSymbols,
 
+  /// Parse, run semantics, and output a Fortran source file preceded
+  /// by all the necessary modules (transitively)
+  DebugUnparseWithModules,
+
   /// Parse, run semantics and then output symbols from semantics
   DebugDumpSymbols,
 
diff --git a/flang/include/flang/Semantics/unparse-with-symbols.h 
b/flang/include/flang/Semantics/unparse-with-symbols.h
index d70110245e2b2..5e18b3fc3063d 100644
--- a/flang/include/flang/Semantics/unparse-with-symbols.h
+++ b/flang/include/flang/Semantics/unparse-with-symbols.h
@@ -21,8 +21,12 @@ struct Program;
 }
 
 namespace Fortran::semantics {
+class SemanticsContext;
 void UnparseWithSymbols(llvm::raw_ostream &, 

[clang] [flang] [Flang] RFC: Add support for -w option (PR #90420)

2024-04-29 Thread Peter Klausler via cfe-commits

klausler wrote:

See https://github.com/llvm/llvm-project/pull/90518, which I think would 
greatly ease implementation of `-w`.

https://github.com/llvm/llvm-project/pull/90420
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [Flang] RFC: Add support for -w option (PR #90420)

2024-04-29 Thread Peter Klausler via cfe-commits

klausler wrote:

I am finishing up a patch that ensures that all warning messages are 
conditional in Semantics.

https://github.com/llvm/llvm-project/pull/90420
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [lld] [flang] Generate main only when a Fortran program statement is present (PR #89938)

2024-04-24 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,63 @@
+//===-- Main.cpp - generate main runtime API calls *- C++

klausler wrote:

This header comment needs to be cleaned up.

https://github.com/llvm/llvm-project/pull/89938
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [lld] [flang] Generate main only when a Fortran program statement is present (PR #89938)

2024-04-24 Thread Peter Klausler via cfe-commits

https://github.com/klausler edited 
https://github.com/llvm/llvm-project/pull/89938
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [lld] [flang] Generate main only when a Fortran program statement is present (PR #89938)

2024-04-24 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/89938
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang][Frontend] Implement printing defined macros via -dM (PR #87627)

2024-04-10 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/87627
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang][Frontend] Implement printing defined macros via -dM (PR #87627)

2024-04-09 Thread Peter Klausler via cfe-commits

klausler wrote:

> How is this code used outside of LLVM? Why do people want to use _without_ 
> LLVM? Just curious.

There are people who want to construct tools to analyze or restructure Fortran 
programs outside of the context of compilation, and need to have access to a 
good parse tree or symbol table.  Unlike most other languages, Fortran is 
weirdly hard to lex & parse, and tool writers would rather use an existing 
parser than do a partial job with something custom.  So as a general rule, I 
avoid using llvm utilities in parsing and semantics (esp. parsing) when the 
facilities in `std::` are capable and portable, and try to encourage others to 
do the same.

https://github.com/llvm/llvm-project/pull/87627
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang][Frontend] Implement printing defined macros via -dM (PR #87627)

2024-04-09 Thread Peter Klausler via cfe-commits


@@ -46,6 +49,38 @@ bool Definition::set_isDisabled(bool disable) {
   return was;
 }
 
+void Definition::Print(
+llvm::raw_ostream , llvm::StringRef macroName) const {
+  if (!isFunctionLike_) {
+// If it's not a function-like macro, then just print the replacement.
+out << ' ' << replacement_.ToString();
+return;
+  }
+
+  size_t argCount{argumentCount()};
+
+  out << '(';
+  for (size_t i{0}; i != argCount; ++i) {
+if (i != 0) {
+  out << ", ";
+}
+out << argNames_[i];
+  }
+  if (isVariadic_) {
+out << ", ...";
+  }
+  out << ") ";
+
+  for (size_t i{0}, e{replacement_.SizeInTokens()}; i != e; ++i) {
+std::string tok{replacement_.TokenAt(i).ToString()};
+if (size_t idx = getArgumentIndex(tok); idx < argCount) {

klausler wrote:

`std::size_t idx {GetArgumentIndex(Tok)}; ...`

https://github.com/llvm/llvm-project/pull/87627
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang][Frontend] Implement printing defined macros via -dM (PR #87627)

2024-04-09 Thread Peter Klausler via cfe-commits


@@ -49,15 +51,21 @@ class Definition {
 
   TokenSequence Apply(const std::vector , Prescanner &);
 
+  void Print(llvm::raw_ostream , llvm::StringRef macroName = "") const;

klausler wrote:

`const char *` would be a more portable type for `macroName` for those who use 
this code outside llvm.

https://github.com/llvm/llvm-project/pull/87627
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [flang][Frontend] Implement printing defined macros via -dM (PR #87627)

2024-04-09 Thread Peter Klausler via cfe-commits


@@ -49,15 +51,21 @@ class Definition {
 
   TokenSequence Apply(const std::vector , Prescanner &);
 
+  void Print(llvm::raw_ostream , llvm::StringRef macroName = "") const;
+
 private:
   static TokenSequence Tokenize(const std::vector ,
   const TokenSequence , std::size_t firstToken, std::size_t tokens);
+  // For a given token, return the index of the argument to which the token
+  // corresponds, or `argumentCount` if the token does not correspond to any
+  // argument.
+  std::size_t getArgumentIndex(const CharBlock ) const;

klausler wrote:

Capitalize function and member function names for consistency in the parser, 
please.

https://github.com/llvm/llvm-project/pull/87627
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [RFC][flang][runtime] Add FortranFloat128Math wrapper library. (PR #81971)

2024-02-20 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/81971
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[libc] [llvm] [clang] [clang-tools-extra] [flang] [compiler-rt] Apply kind code check on exitstat and cmdstat (PR #78286)

2024-01-23 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/78286
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [libc] [clang] [compiler-rt] [llvm] [flang] Apply kind code check on exitstat and cmdstat (PR #78286)

2024-01-23 Thread Peter Klausler via cfe-commits


@@ -122,10 +122,22 @@ void RTNAME(ExecuteCommandLine)(const Descriptor 
, bool wait,
 
   if (exitstat) {
 RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
+auto exitstatKind{exitstat->type().GetCategoryAndKind()->second};
+if (exitstatKind < 4) {

klausler wrote:

The runtime code doesn't need to check these descriptors -- that will have been 
done statically when the intrinsic procedure reference was analyzed!

What has to be done in the runtime is using those descriptors to store the 
integer result values properly, and I think that the code already does that.

https://github.com/llvm/llvm-project/pull/78286
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang] [compiler-rt] [llvm] [clang-tools-extra] [libc] Apply kind code check on exitstat and cmdstat (PR #78286)

2024-01-23 Thread Peter Klausler via cfe-commits

https://github.com/klausler commented:

Is there another patch that adds integer kind handling for these two arguments 
to the runtime implementation?

https://github.com/llvm/llvm-project/pull/78286
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang-tools-extra] [flang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2024-01-04 Thread Peter Klausler via cfe-commits

https://github.com/klausler edited 
https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [llvm] [clang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2024-01-04 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,72 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, std::size_t length, Terminator ) {
+  const void *nullTerminatorPos{std::memchr(str, '\0', length)};
+
+  if (nullTerminatorPos == nullptr) {

klausler wrote:

`if (std::memchr(str, '\0', length) == nullptr) {`

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [flang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2024-01-04 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [flang] [clang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2024-01-04 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,206 @@
+//===-- runtime/execute.cpp 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "flang/Runtime/execute.h"
+#include "environment.h"
+#include "stat.h"
+#include "terminator.h"
+#include "tools.h"
+#include "flang/Runtime/descriptor.h"
+#include 
+#include 
+#include 
+#ifdef _WIN32
+#define LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+#else
+#include 
+#include 
+#endif
+
+namespace Fortran::runtime {
+
+// cmdstat specified in 16.9.73
+// −1 if the processor does not support command line execution,
+// a processor-dependent positive value if an error condition occurs
+// −2 if no error condition occurs but WAIT is present with the value false
+// and the processor does not support asynchronous execution. Otherwise it is
+// assigned the value 0
+enum CMD_STAT {
+  ASYNC_NO_SUPPORT_ERR = -2,
+  NO_SUPPORT_ERR = -1,
+  CMD_EXECUTED = 0,
+  FORK_ERR = 1,
+  EXECL_ERR = 2,
+  INVALID_CL_ERR = 3,
+  SIGNAL_ERR = 4
+};
+
+// Override CopyCharsToDescriptor in tools.h, pass string directly
+void CopyCharsToDescriptor(const Descriptor , const char *rawValue) {
+  CopyCharsToDescriptor(value, rawValue, std::strlen(rawValue));
+}
+
+void CheckAndCopyCharsToDescriptor(
+const Descriptor *value, const char *rawValue) {
+  if (value) {
+CopyCharsToDescriptor(*value, rawValue);
+  }
+}
+
+void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator ) {
+  if (intVal) {
+StoreIntToDescriptor(intVal, value, terminator);
+  }
+}
+
+// If a condition occurs that would assign a nonzero value to CMDSTAT but
+// the CMDSTAT variable is not present, error termination is initiated.
+int TerminationCheck(int status, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, Terminator ) {
+  if (status == -1) {
+if (!cmdstat) {
+  terminator.Crash("Execution error with system status code: %d", status);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Execution error");
+}
+  }
+#ifdef _WIN32
+  // On WIN32 API std::system returns exit status directly
+  int exitStatusVal{status};
+  if (exitStatusVal == 1) {
+#else
+  int exitStatusVal{WEXITSTATUS(status)};
+  if (exitStatusVal == 127 || exitStatusVal == 126) {
+#endif
+if (!cmdstat) {
+  terminator.Crash(
+  "Invalid command quit with exit status code: %d", exitStatusVal);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Invalid command line");
+}
+  }
+#if defined(WIFSIGNALED) && defined(WTERMSIG)
+  if (WIFSIGNALED(status)) {
+if (!cmdstat) {
+  terminator.Crash("killed by signal: %d", WTERMSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "killed by signal");
+}
+  }
+#endif
+#if defined(WIFSTOPPED) && defined(WSTOPSIG)
+  if (WIFSTOPPED(status)) {
+if (!cmdstat) {
+  terminator.Crash("stopped by signal: %d", WSTOPSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "stopped by signal");
+}
+  }
+#endif
+  return exitStatusVal;
+}
+
+void RTNAME(ExecuteCommandLine)(const Descriptor , bool wait,
+const Descriptor *exitstat, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, const char *sourceFile, int line) {
+  Terminator terminator{sourceFile, line};
+  const char *newCmd{EnsureNullTerminated(
+  command.OffsetElement(), command.ElementBytes(), terminator)};
+
+  if (exitstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
+  }
+
+  if (cmdstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(cmdstat));
+// Assigned 0 as specifed in standard, if error then overwrite
+StoreIntToDescriptor(cmdstat, CMD_EXECUTED, terminator);
+  }
+
+  if (cmdmsg) {
+RUNTIME_CHECK(terminator, IsValidCharDescriptor(cmdmsg));
+  }
+
+  if (wait) {
+// either wait is not specified or wait is true: synchronous mode
+int status{std::system(newCmd)};
+int exitStatusVal{TerminationCheck(status, cmdstat, cmdmsg, terminator)};
+// If sync, assigned processor-dependent exit status. Otherwise unchanged
+CheckAndStoreIntToDescriptor(exitstat, exitStatusVal, terminator);
+  } else {
+// Asynchronous mode
+#ifdef _WIN32
+STARTUPINFO si;
+PROCESS_INFORMATION pi;
+ZeroMemory(, sizeof(si));
+si.cb = sizeof(si);
+ZeroMemory(, sizeof(pi));
+
+// append "cmd.exe /c " to the beginning of command
+const char *prefix{"cmd.exe /c "};
+char *newCmdWin{(char 

[flang] [clang-tools-extra] [llvm] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2024-01-04 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,206 @@
+//===-- runtime/execute.cpp 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "flang/Runtime/execute.h"
+#include "environment.h"
+#include "stat.h"
+#include "terminator.h"
+#include "tools.h"
+#include "flang/Runtime/descriptor.h"
+#include 
+#include 
+#include 
+#ifdef _WIN32
+#define LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+#else
+#include 
+#include 
+#endif
+
+namespace Fortran::runtime {
+
+// cmdstat specified in 16.9.73
+// −1 if the processor does not support command line execution,
+// a processor-dependent positive value if an error condition occurs
+// −2 if no error condition occurs but WAIT is present with the value false
+// and the processor does not support asynchronous execution. Otherwise it is
+// assigned the value 0
+enum CMD_STAT {
+  ASYNC_NO_SUPPORT_ERR = -2,
+  NO_SUPPORT_ERR = -1,
+  CMD_EXECUTED = 0,
+  FORK_ERR = 1,
+  EXECL_ERR = 2,
+  INVALID_CL_ERR = 3,
+  SIGNAL_ERR = 4
+};
+
+// Override CopyCharsToDescriptor in tools.h, pass string directly
+void CopyCharsToDescriptor(const Descriptor , const char *rawValue) {
+  CopyCharsToDescriptor(value, rawValue, std::strlen(rawValue));
+}
+
+void CheckAndCopyCharsToDescriptor(
+const Descriptor *value, const char *rawValue) {
+  if (value) {
+CopyCharsToDescriptor(*value, rawValue);
+  }
+}
+
+void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator ) {
+  if (intVal) {
+StoreIntToDescriptor(intVal, value, terminator);
+  }
+}
+
+// If a condition occurs that would assign a nonzero value to CMDSTAT but
+// the CMDSTAT variable is not present, error termination is initiated.
+int TerminationCheck(int status, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, Terminator ) {
+  if (status == -1) {
+if (!cmdstat) {
+  terminator.Crash("Execution error with system status code: %d", status);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Execution error");
+}
+  }
+#ifdef _WIN32
+  // On WIN32 API std::system returns exit status directly
+  int exitStatusVal{status};
+  if (exitStatusVal == 1) {
+#else
+  int exitStatusVal{WEXITSTATUS(status)};
+  if (exitStatusVal == 127 || exitStatusVal == 126) {
+#endif
+if (!cmdstat) {
+  terminator.Crash(
+  "Invalid command quit with exit status code: %d", exitStatusVal);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Invalid command line");
+}
+  }
+#if defined(WIFSIGNALED) && defined(WTERMSIG)
+  if (WIFSIGNALED(status)) {
+if (!cmdstat) {
+  terminator.Crash("killed by signal: %d", WTERMSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "killed by signal");
+}
+  }
+#endif
+#if defined(WIFSTOPPED) && defined(WSTOPSIG)
+  if (WIFSTOPPED(status)) {
+if (!cmdstat) {
+  terminator.Crash("stopped by signal: %d", WSTOPSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "stopped by signal");
+}
+  }
+#endif
+  return exitStatusVal;
+}
+
+void RTNAME(ExecuteCommandLine)(const Descriptor , bool wait,
+const Descriptor *exitstat, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, const char *sourceFile, int line) {
+  Terminator terminator{sourceFile, line};
+  const char *newCmd{EnsureNullTerminated(
+  command.OffsetElement(), command.ElementBytes(), terminator)};
+
+  if (exitstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
+  }
+
+  if (cmdstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(cmdstat));
+// Assigned 0 as specifed in standard, if error then overwrite
+StoreIntToDescriptor(cmdstat, CMD_EXECUTED, terminator);
+  }
+
+  if (cmdmsg) {
+RUNTIME_CHECK(terminator, IsValidCharDescriptor(cmdmsg));
+  }
+
+  if (wait) {
+// either wait is not specified or wait is true: synchronous mode
+int status{std::system(newCmd)};
+int exitStatusVal{TerminationCheck(status, cmdstat, cmdmsg, terminator)};
+// If sync, assigned processor-dependent exit status. Otherwise unchanged
+CheckAndStoreIntToDescriptor(exitstat, exitStatusVal, terminator);
+  } else {
+// Asynchronous mode
+#ifdef _WIN32
+STARTUPINFO si;
+PROCESS_INFORMATION pi;
+ZeroMemory(, sizeof(si));
+si.cb = sizeof(si);
+ZeroMemory(, sizeof(pi));
+
+// append "cmd.exe /c " to the beginning of command

klausler wrote:

"append" means adding on to the end of 

[libcxx] [clang-tools-extra] [flang] [lldb] [clang] [libc] [compiler-rt] [llvm] [flang] FDATE extension implementation: get date and time in ctime format (PR #71222)

2024-01-03 Thread Peter Klausler via cfe-commits


@@ -22,6 +22,9 @@ extern "C" {
 // CALL FLUSH(n) antedates the Fortran 2003 FLUSH statement.
 void FORTRAN_PROCEDURE_NAME(flush)(const int );
 
+// GNU extension subroutine FDATE
+void FORTRAN_PROCEDURE_NAME(fdate)(std::byte *string, std::int64_t length);

klausler wrote:

Like what?

https://github.com/llvm/llvm-project/pull/71222
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [flang] [llvm] [libc] [compiler-rt] [lldb] [clang] [libcxx] [flang] FDATE extension implementation: get date and time in ctime format (PR #71222)

2024-01-03 Thread Peter Klausler via cfe-commits


@@ -43,6 +66,26 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int ) {
 }
 } // namespace io
 
+// CALL FDATE(DATE)
+void FORTRAN_PROCEDURE_NAME(fdate)(std::byte *arg, std::int64_t length) {
+  // Day Mon dd hh:mm:ss \n\0 is 26 characters, e.g.
+  // Tue May 26 21:51:03 2015\n\0
+  char str[26];
+  // Insufficient space, fill with spaces and return.
+  if (length < 24) {
+std::memset(reinterpret_cast(arg), ' ', length);
+return;
+  }
+
+  Terminator terminator{__FILE__, __LINE__};
+  std::time_t current_time;
+  std::time(_time);
+  CtimeBuffer(str, sizeof(str), current_time, terminator);
+
+  // Pad space on \n\0 as well, start at index 24 (included).

klausler wrote:

Do you mean that the last two bytes will be replaced with spaces?

https://github.com/llvm/llvm-project/pull/71222
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [flang] [llvm] [libc] [compiler-rt] [lldb] [clang] [libcxx] [flang] FDATE extension implementation: get date and time in ctime format (PR #71222)

2024-01-03 Thread Peter Klausler via cfe-commits


@@ -43,6 +66,26 @@ void FORTRAN_PROCEDURE_NAME(flush)(const int ) {
 }
 } // namespace io
 
+// CALL FDATE(DATE)
+void FORTRAN_PROCEDURE_NAME(fdate)(std::byte *arg, std::int64_t length) {
+  // Day Mon dd hh:mm:ss \n\0 is 26 characters, e.g.
+  // Tue May 26 21:51:03 2015\n\0
+  char str[26];
+  // Insufficient space, fill with spaces and return.
+  if (length < 24) {
+std::memset(reinterpret_cast(arg), ' ', length);
+return;
+  }
+
+  Terminator terminator{__FILE__, __LINE__};
+  std::time_t current_time;
+  std::time(_time);
+  CtimeBuffer(str, sizeof(str), current_time, terminator);
+
+  // Pad space on \n\0 as well, start at index 24 (included).

klausler wrote:

What does "Pad space on \n\0 as well" mean?

https://github.com/llvm/llvm-project/pull/71222
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang] [libcxx] [lldb] [clang-tools-extra] [llvm] [compiler-rt] [libc] [flang] FDATE extension implementation: get date and time in ctime format (PR #71222)

2024-01-03 Thread Peter Klausler via cfe-commits


@@ -22,6 +22,9 @@ extern "C" {
 // CALL FLUSH(n) antedates the Fortran 2003 FLUSH statement.
 void FORTRAN_PROCEDURE_NAME(flush)(const int );
 
+// GNU extension subroutine FDATE
+void FORTRAN_PROCEDURE_NAME(fdate)(std::byte *string, std::int64_t length);

klausler wrote:

Why `std::byte` here instead of the usual `char`?

https://github.com/llvm/llvm-project/pull/71222
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [flang] [llvm] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,70 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {

klausler wrote:

`std::size_t`

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [flang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,31 @@
+//===-- include/flang/Runtime/command.h -*- C++ 
-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef FORTRAN_RUNTIME_EXECUTE_H_
+#define FORTRAN_RUNTIME_EXECUTE_H_
+
+#include "flang/Runtime/entry-names.h"
+
+#include 

klausler wrote:

Is this `#include` necessary to define anything in this header?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [flang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,203 @@
+//===-- runtime/execute.cpp 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "flang/Runtime/execute.h"
+#include "environment.h"
+#include "stat.h"
+#include "terminator.h"
+#include "tools.h"
+#include "flang/Runtime/descriptor.h"
+#include 
+#include 
+#include 
+#ifdef _WIN32
+#define LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+#include 
+#else
+#include 
+#include 
+#endif
+
+namespace Fortran::runtime {
+
+// cmdstat specified in 16.9.73
+// −1 if the processor does not support command line execution,
+// a processor-dependent positive value if an error condition occurs
+// −2 if no error condition occurs but WAIT is present with the value false
+// and the processor does not support asynchronous execution. Otherwise it is
+// assigned the value 0
+enum CMD_STAT {
+  ASYNC_NO_SUPPORT_ERR = -2,
+  NO_SUPPORT_ERR = -1,
+  CMD_EXECUTED = 0,
+  FORK_ERR = 1,
+  EXECL_ERR = 2,
+  INVALID_CL_ERR = 3,
+  SIGNAL_ERR = 4
+};
+
+// Override CopyCharsToDescriptor in tools.h, pass string directly
+void CopyCharsToDescriptor(const Descriptor , const char *rawValue) {
+  CopyCharsToDescriptor(value, rawValue, std::strlen(rawValue));
+}
+
+void CheckAndCopyCharsToDescriptor(
+const Descriptor *value, const char *rawValue) {
+  if (value) {
+CopyCharsToDescriptor(*value, rawValue);
+  }
+}
+
+void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator ) {
+  if (intVal) {
+StoreIntToDescriptor(intVal, value, terminator);
+  }
+}
+
+// If a condition occurs that would assign a nonzero value to CMDSTAT but
+// the CMDSTAT variable is not present, error termination is initiated.
+int TerminationCheck(int status, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, Terminator ) {
+  if (status == -1) {
+if (!cmdstat) {
+  terminator.Crash("Execution error with system status code: %d", status);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Execution error");
+}
+  }
+#ifdef _WIN32
+  // On WIN32 API std::system returns exit status directly
+  int exitStatusVal{status};
+  if (exitStatusVal == 1) {
+#else
+  int exitStatusVal{WEXITSTATUS(status)};
+  if (exitStatusVal == 127 || exitStatusVal == 126) {
+#endif
+if (!cmdstat) {
+  terminator.Crash(
+  "Invalid command quit with exit status code: %d", exitStatusVal);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Invalid command line");
+}
+  }
+#if defined(WIFSIGNALED) && defined(WTERMSIG)
+  if (WIFSIGNALED(status)) {
+if (!cmdstat) {
+  terminator.Crash("killed by signal: %d", WTERMSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "killed by signal");
+}
+  }
+#endif
+#if defined(WIFSTOPPED) && defined(WSTOPSIG)
+  if (WIFSTOPPED(status)) {
+if (!cmdstat) {
+  terminator.Crash("stopped by signal: %d", WSTOPSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "stopped by signal");
+}
+  }
+#endif
+  return exitStatusVal;
+}
+
+void RTNAME(ExecuteCommandLine)(const Descriptor , bool wait,
+const Descriptor *exitstat, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, const char *sourceFile, int line) {
+  Terminator terminator{sourceFile, line};
+  const char *newCmd{EnsureNullTerminated(
+  command.OffsetElement(), command.ElementBytes(), terminator)};
+
+  if (exitstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
+  }
+
+  if (cmdstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(cmdstat));
+// Assigned 0 as specifed in standard, if error then overwrite
+StoreIntToDescriptor(cmdstat, CMD_EXECUTED, terminator);
+  }
+
+  if (cmdmsg) {
+RUNTIME_CHECK(terminator, IsValidCharDescriptor(cmdmsg));
+  }
+
+  if (wait) {
+// either wait is not specified or wait is true: synchronous mode
+int status{std::system(newCmd)};
+int exitStatusVal{TerminationCheck(status, cmdstat, cmdmsg, terminator)};
+// If sync, assigned processor-dependent exit status. Otherwise unchanged
+CheckAndStoreIntToDescriptor(exitstat, exitStatusVal, terminator);
+  } else {
+// Asynchronous mode
+#ifdef _WIN32
+STARTUPINFO si;
+PROCESS_INFORMATION pi;
+ZeroMemory(, sizeof(si));
+si.cb = sizeof(si);
+ZeroMemory(, sizeof(pi));
+
+// append "cmd.exe /c " to the beginning of command
+const char *prefix{"cmd.exe /c "};
+char 

[llvm] [clang-tools-extra] [flang] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -411,6 +412,24 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ,
 bool toIsContiguous, bool fromIsContiguous);
 RT_API_ATTRS void ShallowCopy(const Descriptor , const Descriptor );
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator );
+
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value);
+
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal);
+
+// Copy a null-terminated character array \p rawValue to descriptor \p value.
+// The copy starts at the given \p offset, if not present then start at 0.
+// If descriptor `errmsg` is provided, error messages will be stored to it.
+// Returns stats specified in standard.
+RT_API_ATTRS std::int32_t CopyCharsToDescriptor(const Descriptor ,
+const char *rawValue, std::int64_t rawValueLength,

klausler wrote:

`rawValueLength` should probably be `std::size_t`.

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [flang] [clang-tools-extra] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -0,0 +1,203 @@
+//===-- runtime/execute.cpp 
---===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#include "flang/Runtime/execute.h"
+#include "environment.h"
+#include "stat.h"
+#include "terminator.h"
+#include "tools.h"
+#include "flang/Runtime/descriptor.h"
+#include 
+#include 
+#include 
+#ifdef _WIN32
+#define LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+#include 
+#else
+#include 
+#include 
+#endif
+
+namespace Fortran::runtime {
+
+// cmdstat specified in 16.9.73
+// −1 if the processor does not support command line execution,
+// a processor-dependent positive value if an error condition occurs
+// −2 if no error condition occurs but WAIT is present with the value false
+// and the processor does not support asynchronous execution. Otherwise it is
+// assigned the value 0
+enum CMD_STAT {
+  ASYNC_NO_SUPPORT_ERR = -2,
+  NO_SUPPORT_ERR = -1,
+  CMD_EXECUTED = 0,
+  FORK_ERR = 1,
+  EXECL_ERR = 2,
+  INVALID_CL_ERR = 3,
+  SIGNAL_ERR = 4
+};
+
+// Override CopyCharsToDescriptor in tools.h, pass string directly
+void CopyCharsToDescriptor(const Descriptor , const char *rawValue) {
+  CopyCharsToDescriptor(value, rawValue, std::strlen(rawValue));
+}
+
+void CheckAndCopyCharsToDescriptor(
+const Descriptor *value, const char *rawValue) {
+  if (value) {
+CopyCharsToDescriptor(*value, rawValue);
+  }
+}
+
+void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator ) {
+  if (intVal) {
+StoreIntToDescriptor(intVal, value, terminator);
+  }
+}
+
+// If a condition occurs that would assign a nonzero value to CMDSTAT but
+// the CMDSTAT variable is not present, error termination is initiated.
+int TerminationCheck(int status, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, Terminator ) {
+  if (status == -1) {
+if (!cmdstat) {
+  terminator.Crash("Execution error with system status code: %d", status);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, EXECL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Execution error");
+}
+  }
+#ifdef _WIN32
+  // On WIN32 API std::system returns exit status directly
+  int exitStatusVal{status};
+  if (exitStatusVal == 1) {
+#else
+  int exitStatusVal{WEXITSTATUS(status)};
+  if (exitStatusVal == 127 || exitStatusVal == 126) {
+#endif
+if (!cmdstat) {
+  terminator.Crash(
+  "Invalid command quit with exit status code: %d", exitStatusVal);
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, INVALID_CL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "Invalid command line");
+}
+  }
+#if defined(WIFSIGNALED) && defined(WTERMSIG)
+  if (WIFSIGNALED(status)) {
+if (!cmdstat) {
+  terminator.Crash("killed by signal: %d", WTERMSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "killed by signal");
+}
+  }
+#endif
+#if defined(WIFSTOPPED) && defined(WSTOPSIG)
+  if (WIFSTOPPED(status)) {
+if (!cmdstat) {
+  terminator.Crash("stopped by signal: %d", WSTOPSIG(status));
+} else {
+  CheckAndStoreIntToDescriptor(cmdstat, SIGNAL_ERR, terminator);
+  CopyCharsToDescriptor(*cmdmsg, "stopped by signal");
+}
+  }
+#endif
+  return exitStatusVal;
+}
+
+void RTNAME(ExecuteCommandLine)(const Descriptor , bool wait,
+const Descriptor *exitstat, const Descriptor *cmdstat,
+const Descriptor *cmdmsg, const char *sourceFile, int line) {
+  Terminator terminator{sourceFile, line};
+  const char *newCmd{EnsureNullTerminated(
+  command.OffsetElement(), command.ElementBytes(), terminator)};
+
+  if (exitstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(exitstat));
+  }
+
+  if (cmdstat) {
+RUNTIME_CHECK(terminator, IsValidIntDescriptor(cmdstat));
+// Assigned 0 as specifed in standard, if error then overwrite
+StoreIntToDescriptor(cmdstat, CMD_EXECUTED, terminator);
+  }
+
+  if (cmdmsg) {
+RUNTIME_CHECK(terminator, IsValidCharDescriptor(cmdmsg));
+  }
+
+  if (wait) {
+// either wait is not specified or wait is true: synchronous mode
+int status{std::system(newCmd)};
+int exitStatusVal{TerminationCheck(status, cmdstat, cmdmsg, terminator)};
+// If sync, assigned processor-dependent exit status. Otherwise unchanged
+CheckAndStoreIntToDescriptor(exitstat, exitStatusVal, terminator);
+  } else {
+// Asynchronous mode
+#ifdef _WIN32
+STARTUPINFO si;
+PROCESS_INFORMATION pi;
+ZeroMemory(, sizeof(si));
+si.cb = sizeof(si);
+ZeroMemory(, sizeof(pi));
+
+// append "cmd.exe /c " to the beginning of command
+const char *prefix{"cmd.exe /c "};
+char 

[clang-tools-extra] [flang] [clang] [llvm] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-27 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,70 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {
+  if (length <= std::strlen(str)) {

klausler wrote:

Do not call `std::strlen()` on a string that is not known to be NUL terminated. 
 Use `std::memchr` instead.

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [llvm] [flang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,141 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {
+  if (length <= std::strlen(str)) {
+char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
+std::memcpy(newCmd, str, length);
+newCmd[length] = '\0';
+return newCmd;
+  } else {
+return str;
+  }
+}
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor ) {
+  std::size_t s{d.ElementBytes() - 1};
+  while (*d.OffsetElement(s) == ' ') {
+--s;
+  }
+  return s + 1;
+}
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string) {
+  return static_cast(std::strlen(string));
+}
+
+// Assumes Descriptor \p value is not nullptr.
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value) {
+  return value && value->IsAllocated() &&
+  value->type() == TypeCode(TypeCategory::Character, 1) &&
+  value->rank() == 0;
+}
+
+// Assumes Descriptor \p intVal is not nullptr.
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal) {
+  auto typeCode{intVal->type().GetCategoryAndKind()};
+  // Check that our descriptor is allocated and is a scalar integer with
+  // kind != 1 (i.e. with a large enough decimal exponent range).
+  return intVal->IsAllocated() && intVal->rank() == 0 &&
+  intVal->type().IsInteger() && typeCode && typeCode->second != 1;
+}
+
+// Assume Descriptor \p value is valid: pass IsValidCharDescriptor check.
+RT_API_ATTRS void FillWithSpaces(const Descriptor , std::size_t offset) {

klausler wrote:

What if `offset` is larger than `ElementBytes()`?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang-tools-extra] [flang] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,145 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {
+  if (length <= std::strlen(str)) {
+char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
+std::memcpy(newCmd, str, length);
+newCmd[length] = '\0';
+return newCmd;
+  } else {
+return str;
+  }
+}
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor ) {
+  std::size_t s{d.ElementBytes() - 1};
+  while (*d.OffsetElement(s) == ' ') {
+--s;
+  }
+  return s + 1;
+}
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string) {
+  std::size_t length{std::strlen(string)};
+  if constexpr (sizeof(std::size_t) < sizeof(std::int64_t)) {
+return static_cast(length);
+  } else {
+std::size_t max{std::numeric_limits::max()};
+return length > max ? 0 // Just fail.
+: static_cast(length);
+  }
+}
+
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value) {
+  return value && value->IsAllocated() &&
+  value->type() == TypeCode(TypeCategory::Character, 1) &&
+  value->rank() == 0;
+}
+
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *length) {
+  auto typeCode{length->type().GetCategoryAndKind()};
+  // Check that our descriptor is allocated and is a scalar integer with
+  // kind != 1 (i.e. with a large enough decimal exponent range).
+  return length->IsAllocated() && length->rank() == 0 &&
+  length->type().IsInteger() && typeCode && typeCode->second != 1;
+}
+
+RT_API_ATTRS void FillWithSpaces(const Descriptor , std::size_t offset) {
+  if (offset < value.ElementBytes()) {

klausler wrote:

If it's not a safe general-purpose utility routine, then don't put it into 
`tools.cpp`.  Or leave it here and add some checking.

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang-tools-extra] [clang] [llvm] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -411,6 +412,48 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ,
 bool toIsContiguous, bool fromIsContiguous);
 RT_API_ATTRS void ShallowCopy(const Descriptor , const Descriptor );
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator );
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor );
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string);
+
+// Assumes Descriptor \p value is not nullptr.
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value);
+
+// Assumes Descriptor \p intVal is not nullptr.
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal);
+
+// Assume Descriptor \p value is valid: pass IsValidCharDescriptor check.
+RT_API_ATTRS void FillWithSpaces(
+const Descriptor , std::size_t offset = 0);
+
+RT_API_ATTRS std::int32_t CopyToDescriptor(const Descriptor ,
+const char *rawValue, std::int64_t rawValueLength, const Descriptor 
*errmsg,
+std::size_t offset = 0);
+
+void CopyCharToDescriptor(
+const Descriptor , const char *rawValue, std::size_t offset = 0);
+
+RT_API_ATTRS std::int32_t CheckAndCopyToDescriptor(const Descriptor *value,
+const char *rawValue, const Descriptor *errmsg, std::size_t );
+
+RT_API_ATTRS void CheckAndCopyCharToDescriptor(
+const Descriptor *value, const char *rawValue, std::size_t offset = 0);
+
+RT_API_ATTRS void StoreIntToDescriptor(
+const Descriptor *length, std::int64_t value, Terminator );
+
+RT_API_ATTRS void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator );
+
+template  struct FitsInIntegerKind;
+
+RT_API_ATTRS bool FitsInDescriptor(

klausler wrote:

This routine looks like a Boolean predicate but why does it require a 
`Terminator`?  Can it crash?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang] [clang-tools-extra] [llvm] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,141 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {
+  if (length <= std::strlen(str)) {
+char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
+std::memcpy(newCmd, str, length);
+newCmd[length] = '\0';
+return newCmd;
+  } else {
+return str;
+  }
+}
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor ) {
+  std::size_t s{d.ElementBytes() - 1};
+  while (*d.OffsetElement(s) == ' ') {
+--s;
+  }
+  return s + 1;
+}
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string) {
+  return static_cast(std::strlen(string));
+}
+
+// Assumes Descriptor \p value is not nullptr.

klausler wrote:

The comment is incorrect; the code works fine if `value` is null.

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang-tools-extra] [llvm] [clang] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -173,5 +173,141 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ) {
   ShallowCopy(to, from, to.IsContiguous(), from.IsContiguous());
 }
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator ) {
+  if (length <= std::strlen(str)) {
+char *newCmd{(char *)AllocateMemoryOrCrash(terminator, length + 1)};
+std::memcpy(newCmd, str, length);
+newCmd[length] = '\0';
+return newCmd;
+  } else {
+return str;
+  }
+}
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor ) {
+  std::size_t s{d.ElementBytes() - 1};
+  while (*d.OffsetElement(s) == ' ') {
+--s;
+  }
+  return s + 1;
+}
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string) {
+  return static_cast(std::strlen(string));
+}
+
+// Assumes Descriptor \p value is not nullptr.
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value) {
+  return value && value->IsAllocated() &&
+  value->type() == TypeCode(TypeCategory::Character, 1) &&
+  value->rank() == 0;
+}
+
+// Assumes Descriptor \p intVal is not nullptr.
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal) {

klausler wrote:

This function could easily accommodate a null `value`.

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [clang-tools-extra] [llvm] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -411,6 +412,48 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ,
 bool toIsContiguous, bool fromIsContiguous);
 RT_API_ATTRS void ShallowCopy(const Descriptor , const Descriptor );
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator );
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor );
+
+// Returns the length of the \p string. Assumes \p string is valid.

klausler wrote:

The comment doesn't specify how the length of the string is defined.  If it is 
NUL terminated, how is this different from `std::strlen()`?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [flang] [clang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -411,6 +412,48 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ,
 bool toIsContiguous, bool fromIsContiguous);
 RT_API_ATTRS void ShallowCopy(const Descriptor , const Descriptor );
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator );
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor );
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string);
+
+// Assumes Descriptor \p value is not nullptr.
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value);
+
+// Assumes Descriptor \p intVal is not nullptr.
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal);
+
+// Assume Descriptor \p value is valid: pass IsValidCharDescriptor check.
+RT_API_ATTRS void FillWithSpaces(
+const Descriptor , std::size_t offset = 0);
+
+RT_API_ATTRS std::int32_t CopyToDescriptor(const Descriptor ,
+const char *rawValue, std::int64_t rawValueLength, const Descriptor 
*errmsg,
+std::size_t offset = 0);
+
+void CopyCharToDescriptor(

klausler wrote:

Does this routine copy a single character, or some kind of NUL terminated 
string, or something else?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [flang] [clang-tools-extra] [flang] Add EXECUTE_COMMAND_LINE runtime and lowering intrinsics implementation (PR #74077)

2023-12-21 Thread Peter Klausler via cfe-commits


@@ -411,6 +412,48 @@ RT_API_ATTRS void ShallowCopy(const Descriptor , const 
Descriptor ,
 bool toIsContiguous, bool fromIsContiguous);
 RT_API_ATTRS void ShallowCopy(const Descriptor , const Descriptor );
 
+RT_API_ATTRS const char *EnsureNullTerminated(
+const char *str, size_t length, Terminator );
+
+RT_API_ATTRS std::size_t LengthWithoutTrailingSpaces(const Descriptor );
+
+// Returns the length of the \p string. Assumes \p string is valid.
+RT_API_ATTRS std::int64_t StringLength(const char *string);
+
+// Assumes Descriptor \p value is not nullptr.
+RT_API_ATTRS bool IsValidCharDescriptor(const Descriptor *value);
+
+// Assumes Descriptor \p intVal is not nullptr.
+RT_API_ATTRS bool IsValidIntDescriptor(const Descriptor *intVal);
+
+// Assume Descriptor \p value is valid: pass IsValidCharDescriptor check.
+RT_API_ATTRS void FillWithSpaces(
+const Descriptor , std::size_t offset = 0);
+
+RT_API_ATTRS std::int32_t CopyToDescriptor(const Descriptor ,
+const char *rawValue, std::int64_t rawValueLength, const Descriptor 
*errmsg,
+std::size_t offset = 0);
+
+void CopyCharToDescriptor(
+const Descriptor , const char *rawValue, std::size_t offset = 0);
+
+RT_API_ATTRS std::int32_t CheckAndCopyToDescriptor(const Descriptor *value,
+const char *rawValue, const Descriptor *errmsg, std::size_t );
+
+RT_API_ATTRS void CheckAndCopyCharToDescriptor(
+const Descriptor *value, const char *rawValue, std::size_t offset = 0);
+
+RT_API_ATTRS void StoreIntToDescriptor(
+const Descriptor *length, std::int64_t value, Terminator );
+
+RT_API_ATTRS void CheckAndStoreIntToDescriptor(
+const Descriptor *intVal, std::int64_t value, Terminator );
+
+template  struct FitsInIntegerKind;

klausler wrote:

What does this do?

https://github.com/llvm/llvm-project/pull/74077
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [flang] [llvm] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-20 Thread Peter Klausler via cfe-commits

https://github.com/klausler approved this pull request.


https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang-tools-extra] [flang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-13 Thread Peter Klausler via cfe-commits


@@ -10,13 +10,29 @@
 // extensions that will eventually be implemented in Fortran.
 
 #include "flang/Runtime/extensions.h"
+#include "flang/Runtime/character.h"
 #include "flang/Runtime/command.h"
 #include "flang/Runtime/descriptor.h"
 #include "flang/Runtime/io-api.h"
 
+#if _REENTRANT || _POSIX_C_SOURCE >= 199506L
+// System is posix-compliant and has getlogin_r
+#include 
+#endif
+
 extern "C" {
 
 namespace Fortran::runtime {
+
+void GetUsernameEnvVar(
+const char *envName, std::byte *arg, std::int64_t length) {
+  Descriptor name{
+  *Descriptor::Create(1, sizeof(envName), const_cast(envName), 0)};

klausler wrote:

Exactly.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [clang-tools-extra] [flang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-13 Thread Peter Klausler via cfe-commits


@@ -6,6 +6,37 @@
 //
 
//===--===//
 
+// Defines a utility function for copying and padding characters
+#ifndef CHARACTER_H
+#define CHARACTER_H

klausler wrote:

Either way, the name of the guard macro is wrong.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [llvm] [flang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -37,5 +79,34 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
   (void)RTNAME(GetCommandArgument)(
   n, , nullptr, nullptr, __FILE__, __LINE__);
 }
+
+// CALL GETLOG(USRNAME)
+void FORTRAN_PROCEDURE_NAME(getlog)(std::int8_t *arg, std::int64_t length) {
+  const int nameMaxLen{LOGIN_NAME_MAX + 1};
+  char str[nameMaxLen];
+
+  int error{getlogin_r(str, nameMaxLen)};
+  Terminator terminator{__FILE__, __LINE__};
+  if (error != 0) {
+// if there is error, then get username from environment variable
+#ifdef _WIN32
+const int charLen = 9;
+char envName[charLen] = "USERNAME";
+#else
+const int charLen = 8;
+char envName[charLen] = "LOGNAME";
+#endif
+std::size_t n{std::strlen(envName)};

klausler wrote:

It is generally more error-prone to use explicit integer counts for things that 
the compiler can count correctly for you.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [llvm] [clang] [flang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -37,5 +79,34 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
   (void)RTNAME(GetCommandArgument)(
   n, , nullptr, nullptr, __FILE__, __LINE__);
 }
+
+// CALL GETLOG(USRNAME)
+void FORTRAN_PROCEDURE_NAME(getlog)(std::int8_t *arg, std::int64_t length) {
+  const int nameMaxLen{LOGIN_NAME_MAX + 1};
+  char str[nameMaxLen];
+
+  int error{getlogin_r(str, nameMaxLen)};
+  Terminator terminator{__FILE__, __LINE__};
+  if (error != 0) {
+// if there is error, then get username from environment variable
+#ifdef _WIN32
+const int charLen = 9;

klausler wrote:

It needn't be `static` or `const`.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [flang] [llvm] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -10,10 +10,52 @@
 // extensions that will eventually be implemented in Fortran.
 
 #include "flang/Runtime/extensions.h"
+#include "terminator.h"
+#include "flang/Runtime/character.h"
 #include "flang/Runtime/command.h"
 #include "flang/Runtime/descriptor.h"
 #include "flang/Runtime/io-api.h"
 
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+
+#include  // wcstombs_s
+#include  // UNLEN=256
+#include  // wchar_t cast to LPWSTR
+#pragma comment(lib, "Advapi32.lib") // Link Advapi32.lib for GetUserName
+#define LOGIN_NAME_MAX UNLEN
+
+inline int getlogin_r(char *buf, size_t bufSize) {
+  wchar_t w_username[UNLEN + 1];
+  DWORD nameLen{UNLEN + 1};
+
+  if (GetUserName(w_username, )) {
+// Convert the wchar_t string to a regular C string using wcstombs_s
+if (wcstombs_s(nullptr, buf, bufSize, w_username, _TRUNCATE) != 0) {
+  // Conversion failed
+  return -1;
+}
+return (buf[0] == 0 ? -1 : 0);

klausler wrote:

Please write the NUL character as a character literal (`'\0'`).

The parentheses are needless.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang] [clang-tools-extra] [flang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -37,5 +79,34 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
   (void)RTNAME(GetCommandArgument)(
   n, , nullptr, nullptr, __FILE__, __LINE__);
 }
+
+// CALL GETLOG(USRNAME)
+void FORTRAN_PROCEDURE_NAME(getlog)(std::int8_t *arg, std::int64_t length) {
+  const int nameMaxLen{LOGIN_NAME_MAX + 1};
+  char str[nameMaxLen];
+
+  int error{getlogin_r(str, nameMaxLen)};
+  Terminator terminator{__FILE__, __LINE__};
+  if (error != 0) {
+// if there is error, then get username from environment variable
+#ifdef _WIN32
+const int charLen = 9;

klausler wrote:

`static const char envName[]{"USERNAME"};`

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [flang] [clang-tools-extra] [clang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -37,5 +79,34 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
   (void)RTNAME(GetCommandArgument)(
   n, , nullptr, nullptr, __FILE__, __LINE__);
 }
+
+// CALL GETLOG(USRNAME)
+void FORTRAN_PROCEDURE_NAME(getlog)(std::int8_t *arg, std::int64_t length) {
+  const int nameMaxLen{LOGIN_NAME_MAX + 1};
+  char str[nameMaxLen];
+
+  int error{getlogin_r(str, nameMaxLen)};
+  Terminator terminator{__FILE__, __LINE__};
+  if (error != 0) {
+// if there is error, then get username from environment variable
+#ifdef _WIN32
+const int charLen = 9;
+char envName[charLen] = "USERNAME";
+#else
+const int charLen = 8;
+char envName[charLen] = "LOGNAME";
+#endif
+std::size_t n{std::strlen(envName)};

klausler wrote:

`const std::size_t n{sizeof envName};` or just use `sizeof envName` below in 
place of `n`.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[llvm] [clang-tools-extra] [flang] [clang] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -10,10 +10,52 @@
 // extensions that will eventually be implemented in Fortran.
 
 #include "flang/Runtime/extensions.h"
+#include "terminator.h"
+#include "flang/Runtime/character.h"
 #include "flang/Runtime/command.h"
 #include "flang/Runtime/descriptor.h"
 #include "flang/Runtime/io-api.h"
 
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#define NOMINMAX
+#include 
+
+#include  // wcstombs_s
+#include  // UNLEN=256
+#include  // wchar_t cast to LPWSTR
+#pragma comment(lib, "Advapi32.lib") // Link Advapi32.lib for GetUserName
+#define LOGIN_NAME_MAX UNLEN
+
+inline int getlogin_r(char *buf, size_t bufSize) {
+  wchar_t w_username[UNLEN + 1];
+  DWORD nameLen{UNLEN + 1};
+
+  if (GetUserName(w_username, )) {
+// Convert the wchar_t string to a regular C string using wcstombs_s
+if (wcstombs_s(nullptr, buf, bufSize, w_username, _TRUNCATE) != 0) {
+  // Conversion failed
+  return -1;
+}
+return (buf[0] == 0 ? -1 : 0);
+  } else {
+return -1;
+  }
+  return -1;

klausler wrote:

This line will never be reached.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [flang] [clang-tools-extra] [flang] GETLOG runtime and extension implementation: get login username (PR #74628)

2023-12-06 Thread Peter Klausler via cfe-commits


@@ -657,6 +657,11 @@ CALL CO_REDUCE
 CALL CO_SUM
 ```
 
+### Library subroutine 

klausler wrote:

Please put this new section later, after all of the non-standard intrinsics, so 
the actual intrinsic procedures appear together.

https://github.com/llvm/llvm-project/pull/74628
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [clang] [flang] [llvm] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-12-04 Thread Peter Klausler via cfe-commits


@@ -37,5 +80,17 @@ void FORTRAN_PROCEDURE_NAME(getarg)(
   (void)RTNAME(GetCommandArgument)(
   n, , nullptr, nullptr, __FILE__, __LINE__);
 }
+
+void FORTRAN_PROCEDURE_NAME(getlog)(std::int8_t *arg, std::int64_t length) {
+  std::array str;

klausler wrote:

Why not just `char str[LOGIN_NAME_MAX+1];`?

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [clang-tools-extra] [flang] [llvm] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-12-04 Thread Peter Klausler via cfe-commits


@@ -39,6 +39,17 @@
 // overload will have a dummy parameter whose type indicates whether or not it
 // should be preferred. Any other parameters required for SFINAE should have
 // default values provided.
+
+// outside anonymous namespace, function reused

klausler wrote:

There's a `CopyAndPad()` template function in flang/runtime/character.cpp that 
could be moved to a header file and used here.

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [llvm] [clang] [flang] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-12-04 Thread Peter Klausler via cfe-commits


@@ -751,7 +751,7 @@ This phase currently supports all the intrinsic procedures 
listed above but the
 | Object characteristic inquiry functions | ALLOCATED, ASSOCIATED, 
EXTENDS_TYPE_OF, IS_CONTIGUOUS, PRESENT, RANK, SAME_TYPE, STORAGE_SIZE |
 | Type inquiry intrinsic functions | BIT_SIZE, DIGITS, EPSILON, HUGE, KIND, 
MAXEXPONENT, MINEXPONENT, NEW_LINE, PRECISION, RADIX, RANGE, TINY|
 | Non-standard intrinsic functions | AND, OR, XOR, SHIFT, ZEXT, IZEXT, COSD, 
SIND, TAND, ACOSD, ASIND, ATAND, ATAN2D, COMPL, EQV, NEQV, INT8, JINT, JNINT, 
KNINT, QCMPLX, DREAL, DFLOAT, QEXT, QFLOAT, QREAL, DNUM, NUM, JNUM, KNUM, QNUM, 
RNUM, RAN, RANF, ILEN, SIZEOF, MCLOCK, SECNDS, COTAN, IBCHNG, ISHA, ISHC, ISHL, 
IXOR, IARG, IARGC, NARGS, GETPID, NUMARG, BADDRESS, IADDR, CACHESIZE, EOF, 
FP_CLASS, INT_PTR_KIND, ISNAN, MALLOC |
-| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, 
EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, 
GET_ENVIRONMENT_VARIABLE, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, RANDOM_SEED, 
SYSTEM_CLOCK |
+| Intrinsic subroutines |MVBITS (elemental), CPU_TIME, DATE_AND_TIME, 
EVENT_QUERY, EXECUTE_COMMAND_LINE, GET_COMMAND, GET_COMMAND_ARGUMENT, 
GET_ENVIRONMENT_VARIABLE, GETLOG, MOVE_ALLOC, RANDOM_INIT, RANDOM_NUMBER, 
RANDOM_SEED, SYSTEM_CLOCK |

klausler wrote:

You are not really implementing `GETLOG` here as an intrinsic subroutine, but 
as a library subroutine.  (There is no interface exposed to user programs in 
the intrinsic procedure tables.)

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [flang] [llvm] [clang] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-11-27 Thread Peter Klausler via cfe-commits


@@ -9,6 +9,17 @@
 // Defines the API between compiled code and the implementations of 
time-related
 // intrinsic subroutines in the runtime library.
 
+// time-intrinsic.h
+#ifndef TIME_INTRINSIC_H
+#define TIME_INTRINSIC_H
+
+#include 
+
+void copyBufferAndPad(

klausler wrote:

Function names are capitalized in flang/runtime.

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang-tools-extra] [llvm] [flang] [clang] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-11-27 Thread Peter Klausler via cfe-commits


@@ -9,6 +9,17 @@
 // Defines the API between compiled code and the implementations of 
time-related
 // intrinsic subroutines in the runtime library.
 
+// time-intrinsic.h
+#ifndef TIME_INTRINSIC_H
+#define TIME_INTRINSIC_H
+
+#include 
+
+void copyBufferAndPad(
+char *dest, std::size_t destChars, char *buffer, std::size_t len);

klausler wrote:

`buffer` can be `const char *`, yes?

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [clang] [llvm] [clang-tools-extra] [flang ]GETLOG runtime and extension implementation: get login username (PR #70917)

2023-11-21 Thread Peter Klausler via cfe-commits

klausler wrote:

> Hello @klausler, could you please share your thoughts or comments on this 
> patch, particularly with regard to the Windows side? Thanks in advance.

You should use modern C++ braced initialization in flang/runtime.

https://github.com/llvm/llvm-project/pull/70917
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[flang] [llvm] [clang] [mlir] [libc] [flang] Fold MATMUL() (PR #72176)

2023-11-14 Thread Peter Klausler via cfe-commits

https://github.com/klausler closed 
https://github.com/llvm/llvm-project/pull/72176
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [llvm] [flang] [libc] [mlir] [flang] Fold MATMUL() (PR #72176)

2023-11-14 Thread Peter Klausler via cfe-commits

klausler wrote:

ping!

https://github.com/llvm/llvm-project/pull/72176
___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[clang] [flang] [llvm] [libc] [mlir] [flang] Fold MATMUL() (PR #72176)

2023-11-13 Thread Peter Klausler via cfe-commits

https://github.com/klausler updated 
https://github.com/llvm/llvm-project/pull/72176

>From e2e0e60c5cf01b5e99cb2494e2444b91d1f6605d Mon Sep 17 00:00:00 2001
From: Peter Klausler 
Date: Fri, 3 Nov 2023 13:04:01 -0700
Subject: [PATCH] [flang] Fold MATMUL()

Implements constant folding for matrix multiplication for
all four accepted type categories.
---
 flang/lib/Evaluate/fold-complex.cpp |   4 +-
 flang/lib/Evaluate/fold-integer.cpp |   4 +-
 flang/lib/Evaluate/fold-logical.cpp |   4 +-
 flang/lib/Evaluate/fold-matmul.h| 103 
 flang/lib/Evaluate/fold-real.cpp|   4 +-
 flang/lib/Evaluate/fold-reduction.h |   4 +-
 flang/test/Evaluate/fold-matmul.f90 |  41 +++
 7 files changed, 158 insertions(+), 6 deletions(-)
 create mode 100644 flang/lib/Evaluate/fold-matmul.h
 create mode 100644 flang/test/Evaluate/fold-matmul.f90

diff --git a/flang/lib/Evaluate/fold-complex.cpp 
b/flang/lib/Evaluate/fold-complex.cpp
index e40e3a37df14948..3260f82ffe8d734 100644
--- a/flang/lib/Evaluate/fold-complex.cpp
+++ b/flang/lib/Evaluate/fold-complex.cpp
@@ -7,6 +7,7 @@
 
//===--===//
 
 #include "fold-implementation.h"
+#include "fold-matmul.h"
 #include "fold-reduction.h"
 
 namespace Fortran::evaluate {
@@ -64,13 +65,14 @@ Expr> 
FoldIntrinsicFunction(
 }
   } else if (name == "dot_product") {
 return FoldDotProduct(context, std::move(funcRef));
+  } else if (name == "matmul") {
+return FoldMatmul(context, std::move(funcRef));
   } else if (name == "product") {
 auto one{Scalar::FromInteger(value::Integer<8>{1}).value};
 return FoldProduct(context, std::move(funcRef), Scalar{one});
   } else if (name == "sum") {
 return FoldSum(context, std::move(funcRef));
   }
-  // TODO: matmul
   return Expr{std::move(funcRef)};
 }
 
diff --git a/flang/lib/Evaluate/fold-integer.cpp 
b/flang/lib/Evaluate/fold-integer.cpp
index dedfc20a491cd88..2882369105f6626 100644
--- a/flang/lib/Evaluate/fold-integer.cpp
+++ b/flang/lib/Evaluate/fold-integer.cpp
@@ -7,6 +7,7 @@
 
//===--===//
 
 #include "fold-implementation.h"
+#include "fold-matmul.h"
 #include "fold-reduction.h"
 #include "flang/Evaluate/check-expression.h"
 
@@ -1042,6 +1043,8 @@ Expr> 
FoldIntrinsicFunction(
 ScalarFunc([](const Scalar ) -> Scalar {
   return fptr(static_cast(places.ToInt64()));
 }));
+  } else if (name == "matmul") {
+return FoldMatmul(context, std::move(funcRef));
   } else if (name == "max") {
 return FoldMINorMAX(context, std::move(funcRef), Ordering::Greater);
   } else if (name == "max0" || name == "max1") {
@@ -1279,7 +1282,6 @@ Expr> 
FoldIntrinsicFunction(
   } else if (name == "ubound") {
 return UBOUND(context, std::move(funcRef));
   }
-  // TODO: dot_product, matmul, sign
   return Expr{std::move(funcRef)};
 }
 
diff --git a/flang/lib/Evaluate/fold-logical.cpp 
b/flang/lib/Evaluate/fold-logical.cpp
index bfedc32a33a8bad..82a5cb20db9e409 100644
--- a/flang/lib/Evaluate/fold-logical.cpp
+++ b/flang/lib/Evaluate/fold-logical.cpp
@@ -7,6 +7,7 @@
 
//===--===//
 
 #include "fold-implementation.h"
+#include "fold-matmul.h"
 #include "fold-reduction.h"
 #include "flang/Evaluate/check-expression.h"
 #include "flang/Runtime/magic-numbers.h"
@@ -231,6 +232,8 @@ Expr> 
FoldIntrinsicFunction(
 if (auto *expr{UnwrapExpr>(args[0])}) {
   return Fold(context, ConvertToType(std::move(*expr)));
 }
+  } else if (name == "matmul") {
+return FoldMatmul(context, std::move(funcRef));
   } else if (name == "out_of_range") {
 if (Expr * cx{UnwrapExpr>(args[0])}) {
   auto restorer{context.messages().DiscardMessages()};
@@ -367,7 +370,6 @@ Expr> 
FoldIntrinsicFunction(
   name == "__builtin_ieee_support_underflow_control") {
 return Expr{true};
   }
-  // TODO: logical, matmul, parity
   return Expr{std::move(funcRef)};
 }
 
diff --git a/flang/lib/Evaluate/fold-matmul.h b/flang/lib/Evaluate/fold-matmul.h
new file mode 100644
index 000..27b6db1fd8bf025
--- /dev/null
+++ b/flang/lib/Evaluate/fold-matmul.h
@@ -0,0 +1,103 @@
+//===-- lib/Evaluate/fold-matmul.h 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===--===//
+
+#ifndef FORTRAN_EVALUATE_FOLD_MATMUL_H_
+#define FORTRAN_EVALUATE_FOLD_MATMUL_H_
+
+#include "fold-implementation.h"
+
+namespace Fortran::evaluate {
+
+template 
+static Expr FoldMatmul(FoldingContext , FunctionRef &) {
+  using Element = typename Constant::Element;
+  auto args{funcRef.arguments()};
+  CHECK(args.size() == 2);
+  Folder 

[clang] 996ef89 - [flang] Add -fno-automatic, refine IsSaved()

2021-11-22 Thread Peter Klausler via cfe-commits

Author: Peter Klausler
Date: 2021-11-22T10:06:38-08:00
New Revision: 996ef895cd3d1313665a42fc8e20d1d4e1cf2a28

URL: 
https://github.com/llvm/llvm-project/commit/996ef895cd3d1313665a42fc8e20d1d4e1cf2a28
DIFF: 
https://github.com/llvm/llvm-project/commit/996ef895cd3d1313665a42fc8e20d1d4e1cf2a28.diff

LOG: [flang] Add -fno-automatic, refine IsSaved()

This legacy option (available in other Fortran compilers with various
spellings) implies the SAVE attribute for local variables on subprograms
that are not explicitly RECURSIVE.  The SAVE attribute essentially implies
static rather than stack storage.  This was the default setting in Fortran
until surprisingly recently, so explicit SAVE statements & attributes
could be and often were omitted from older codes.  Note that initialized
objects already have an implied SAVE attribute, and objects in COMMON
effectively do too, as data overlays are extinct; and since objects that are
expected to survive from one invocation of a procedure to the next in static
storage should probably be explicit initialized in the first place, so the
use cases for this option are somewhat rare, and all of them could be
handled with explicit SAVE statements or attributes.

This implicit SAVE attribute must not apply to automatic (in the Fortran sense)
local objects, whose sizes cannot be known at compilation time.  To get the
semantics of IsSaved() right, the IsAutomatic() predicate was moved into
Evaluate/tools.cpp to allow for dynamic linking of the compiler.  The
redundant predicate IsAutomatic() was noticed, removed, and its uses replaced.

GNU Fortran's spelling of the option (-fno-automatic) was added to
the clang-based driver and used for basic sanity testing.

Differential Revision: https://reviews.llvm.org/D114209

Added: 
flang/test/Semantics/save02.f90

Modified: 
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
flang/include/flang/Common/Fortran-features.h
flang/include/flang/Evaluate/tools.h
flang/include/flang/Semantics/tools.h
flang/lib/Evaluate/tools.cpp
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Semantics/resolve-names-utils.cpp
flang/lib/Semantics/runtime-type-info.cpp
flang/lib/Semantics/tools.cpp
flang/test/Driver/driver-help-hidden.f90
flang/test/Driver/driver-help.f90
flang/test/Semantics/entry01.f90
flang/test/Semantics/save01.f90

Removed: 




diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 9bde64cf49fd7..7730b7d1915e4 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -4519,7 +4519,7 @@ def frecord_marker_EQ : Joined<["-"], "frecord-marker=">, 
Group;
 defm aggressive_function_elimination : 
BooleanFFlag<"aggressive-function-elimination">, Group;
 defm align_commons : BooleanFFlag<"align-commons">, Group;
 defm all_intrinsics : BooleanFFlag<"all-intrinsics">, Group;
-defm automatic : BooleanFFlag<"automatic">, Group;
+def fautomatic : Flag<["-"], "fautomatic">; // -fno-automatic is significant
 defm backtrace : BooleanFFlag<"backtrace">, Group;
 defm bounds_check : BooleanFFlag<"bounds-check">, Group;
 defm check_array_temporaries : BooleanFFlag<"check-array-temporaries">, 
Group;
@@ -4616,6 +4616,9 @@ defm backslash : OptInFC1FFlag<"backslash", "Specify that 
backslash in string in
 defm xor_operator : OptInFC1FFlag<"xor-operator", "Enable .XOR. as a synonym 
of .NEQV.">;
 defm logical_abbreviations : OptInFC1FFlag<"logical-abbreviations", "Enable 
logical abbreviations">;
 defm implicit_none : OptInFC1FFlag<"implicit-none", "No implicit typing 
allowed unless overridden by IMPLICIT statements">;
+
+def fno_automatic : Flag<["-"], "fno-automatic">, Group,
+  HelpText<"Implies the SAVE attribute for non-automatic local objects in 
subprograms unless RECURSIVE">;
 }
 
 def J : JoinedOrSeparate<["-"], "J">,

diff  --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index b82c5d7600df2..c169e3d457938 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -32,7 +32,8 @@ void Flang::AddFortranDialectOptions(const ArgList ,
 options::OPT_fxor_operator, options::OPT_fno_xor_operator,
 options::OPT_falternative_parameter_statement,
 options::OPT_fdefault_real_8, options::OPT_fdefault_integer_8,
-options::OPT_fdefault_double_8, options::OPT_flarge_sizes});
+options::OPT_fdefault_double_8, options::OPT_flarge_sizes,
+options::OPT_fno_automatic});
 }
 
 void Flang::AddPreprocessingOptions(const ArgList ,

diff  --git a/flang/include/flang/Common/Fortran-features.h 
b/flang/include/flang/Common/Fortran-features.h
index ddce794056320..f5fe2b5de475e 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ 

[clang] 3338ef9 - [flang] Produce proper "preprocessor output" for -E option

2021-07-30 Thread peter klausler via cfe-commits

Author: peter klausler
Date: 2021-07-30T15:13:56-07:00
New Revision: 3338ef93b02837edf69abc203e15a42fa55aa1b3

URL: 
https://github.com/llvm/llvm-project/commit/3338ef93b02837edf69abc203e15a42fa55aa1b3
DIFF: 
https://github.com/llvm/llvm-project/commit/3338ef93b02837edf69abc203e15a42fa55aa1b3.diff

LOG: [flang] Produce proper "preprocessor output" for -E option

Rename the current -E option to "-E -Xflang -fno-reformat".

Add a new Parsing::EmitPreprocessedSource() routine to convert the
cooked character stream output of the prescanner back to something
more closely resembling output from a traditional preprocessor;
call this new routine when -E appears.

The new -E output is suitable for use as fixed form Fortran source to
compilation by (one hopes) any Fortran compiler.  If the original
top-level source file had been free form source, the output will be
suitable for use as free form source as well; otherwise there may be
diagnostics about missing spaces if they were indeed absent in the
original fixed form source.

Unless the -P option appears, #line directives are interspersed
with the output (but be advised, f18 will ignore these if presented
with them in a later compilation).

An effort has been made to preserve original alphabetic character case
and source indentation.

Add -P and -fno-reformat to the new drivers.

Tweak test options to avoid confusion with prior -E output; use
-fno-reformat where needed, but prefer to keep -E, sometimes
in concert with -P, on most, updating expected results accordingly.

Differential Revision: https://reviews.llvm.org/D106727

Added: 
flang/test/Preprocessing/dash-E.F90

Modified: 
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/Flang.cpp
flang/include/flang/Frontend/FrontendOptions.h
flang/include/flang/Frontend/PreprocessorOptions.h
flang/include/flang/Parser/parsing.h
flang/lib/Frontend/CompilerInvocation.cpp
flang/lib/Frontend/FrontendActions.cpp
flang/lib/Frontend/FrontendOptions.cpp
flang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
flang/lib/Parser/parsing.cpp
flang/lib/Parser/provenance.cpp
flang/lib/Parser/token-sequence.cpp
flang/lib/Parser/token-sequence.h
flang/test/Driver/cpp-nocpp-command-line-macro.f90
flang/test/Driver/driver-help-hidden.f90
flang/test/Driver/driver-help.f90
flang/test/Driver/escaped-backslash.f90
flang/test/Driver/fixed-free-detection.f90
flang/test/Driver/fixed-line-length.f90
flang/test/Driver/frontend-forwarding.f90
flang/test/Driver/include-header.f90
flang/test/Driver/input-from-stdin.f90
flang/test/Driver/macro-def-undef.F90
flang/test/Driver/macro-multiline.F90
flang/test/Parser/badlabel.f
flang/test/Preprocessing/assert.F90
flang/test/Preprocessing/fixed-rescan.F
flang/test/Preprocessing/hollerith.f
flang/test/Preprocessing/pp001.F
flang/test/Preprocessing/pp002.F
flang/test/Preprocessing/pp003.F
flang/test/Preprocessing/pp004.F
flang/test/Preprocessing/pp005.F
flang/test/Preprocessing/pp006.F
flang/test/Preprocessing/pp007.F
flang/test/Preprocessing/pp008.F
flang/test/Preprocessing/pp009.F
flang/test/Preprocessing/pp010.F
flang/test/Preprocessing/pp011.F
flang/test/Preprocessing/pp012.F
flang/test/Preprocessing/pp013.F
flang/test/Preprocessing/pp014.F
flang/test/Preprocessing/pp015.F
flang/test/Preprocessing/pp016.F
flang/test/Preprocessing/pp017.F
flang/test/Preprocessing/pp018.F
flang/test/Preprocessing/pp019.F
flang/test/Preprocessing/pp020.F
flang/test/Preprocessing/pp021.F
flang/test/Preprocessing/pp022.F
flang/test/Preprocessing/pp023.F
flang/test/Preprocessing/pp024.F
flang/test/Preprocessing/pp025.F
flang/test/Preprocessing/pp026.F
flang/test/Preprocessing/pp027.F
flang/test/Preprocessing/pp028.F
flang/test/Preprocessing/pp029.F
flang/test/Preprocessing/pp030.F
flang/test/Preprocessing/pp031.F
flang/test/Preprocessing/pp032.F
flang/test/Preprocessing/pp033.F
flang/test/Preprocessing/pp034.F
flang/test/Preprocessing/pp035.F
flang/test/Preprocessing/pp036.F
flang/test/Preprocessing/pp037.F
flang/test/Preprocessing/pp038.F
flang/test/Preprocessing/pp039.F
flang/test/Preprocessing/pp041.F
flang/test/Preprocessing/pp043.F
flang/test/Preprocessing/pp044.F
flang/test/Preprocessing/pp101.F90
flang/test/Preprocessing/pp102.F90
flang/test/Preprocessing/pp104.F90
flang/test/Preprocessing/pp107.F90
flang/test/Preprocessing/pp108.F90
flang/test/Preprocessing/pp111.F90
flang/test/Preprocessing/pp112.F90
flang/test/Preprocessing/pp115.F90
flang/test/Preprocessing/pp116.F90
flang/test/Preprocessing/pp117.F90
flang/test/Preprocessing/pp118.F90
flang/test/Preprocessing/pp121.F90
flang/test/Preprocessing/pp123.F90
flang/test/Preprocessing/pp124.F90