[flang-commits] [clang] [flang] [flang] Add checks for Fortran 2023 system clock and add f2023/f202Y to valid arguments of -std= (PR #205938)

via flang-commits flang-commits at lists.llvm.org
Wed Aug 12 10:04:27 PDT 2026


https://github.com/chris-earl updated https://github.com/llvm/llvm-project/pull/205938

>From 8edfde8339e283482fd0605a690639fd4953184a Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Wed, 24 Jun 2026 17:44:36 -0500
Subject: [PATCH 1/6] [flang] Remove unused flags and accessor functions

---
 .../flang/Frontend/CompilerInvocation.h       | 24 -------------------
 .../include/flang/Support/Fortran-features.h  | 17 ++-----------
 flang/lib/Frontend/CompilerInvocation.cpp     |  4 ----
 flang/lib/Support/Fortran-features.cpp        |  4 ----
 4 files changed, 2 insertions(+), 47 deletions(-)

diff --git a/flang/include/flang/Frontend/CompilerInvocation.h b/flang/include/flang/Frontend/CompilerInvocation.h
index d294955af780e..6a94ee1bb47eb 100644
--- a/flang/include/flang/Frontend/CompilerInvocation.h
+++ b/flang/include/flang/Frontend/CompilerInvocation.h
@@ -117,10 +117,6 @@ class CompilerInvocation : public CompilerInvocationBase {
   // Fortran Error options
   size_t maxErrors = 0;
   bool warnAsErr = false;
-  // Fortran Warning options
-  bool enableConformanceChecks = false;
-  bool enableUsageChecks = false;
-  bool disableWarnings = false;
 
   /// Used in e.g. unparsing to dump the analyzed rather than the original
   /// parse-tree objects.
@@ -203,19 +199,8 @@ class CompilerInvocation : public CompilerInvocationBase {
     return useAnalyzedObjectsForUnparse;
   }
 
-  bool &getEnableConformanceChecks() { return enableConformanceChecks; }
-  const bool &getEnableConformanceChecks() const {
-    return enableConformanceChecks;
-  }
-
   const char *getArgv0() { return argv0; }
 
-  bool &getEnableUsageChecks() { return enableUsageChecks; }
-  const bool &getEnableUsageChecks() const { return enableUsageChecks; }
-
-  bool &getDisableWarnings() { return disableWarnings; }
-  const bool &getDisableWarnings() const { return disableWarnings; }
-
   Fortran::parser::AnalyzedObjectsAsFortran &getAsFortran() {
     return asFortran;
   }
@@ -241,15 +226,6 @@ class CompilerInvocation : public CompilerInvocationBase {
                              clang::DiagnosticsEngine &diags,
                              const char *argv0 = nullptr);
 
-  // Enables the std=f2018 conformance check
-  void setEnableConformanceChecks() { enableConformanceChecks = true; }
-
-  // Enables the usage checks
-  void setEnableUsageChecks() { enableUsageChecks = true; }
-
-  // Disables all Warnings
-  void setDisableWarnings() { disableWarnings = true; }
-
   /// Useful setters
   void setArgv0(const char *dir) { argv0 = dir; }
 
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index ebc6f495e59ba..b5e46ca7e095e 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -114,23 +114,13 @@ class LanguageFeatureControl {
     }
   }
   void WarnOnAllNonstandard(bool yes = true);
-  bool IsWarnOnAllNonstandard() const { return warnAllLanguage_; }
   void WarnOnAllUsage(bool yes = true);
-  bool IsWarnOnAllUsage() const { return warnAllUsage_; }
-  void DisableAllNonstandardWarnings() {
-    warnAllLanguage_ = false;
-    warnLanguage_.clear();
-  }
-  void DisableAllUsageWarnings() {
-    warnAllUsage_ = false;
-    warnUsage_.clear();
-  }
+  void DisableAllNonstandardWarnings() { warnLanguage_.clear(); }
+  void DisableAllUsageWarnings() { warnUsage_.clear(); }
   void DisableAllWarnings() {
-    disableAllWarnings_ = true;
     DisableAllNonstandardWarnings();
     DisableAllUsageWarnings();
   }
-  bool AreWarningsDisabled() const { return disableAllWarnings_; }
   bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
   bool ShouldWarn(LanguageFeature f) const { return warnLanguage_.test(f); }
   bool ShouldWarn(UsageWarning w) const { return warnUsage_.test(w); }
@@ -190,10 +180,7 @@ class LanguageFeatureControl {
       usageWarningCliCanonicalSpelling_;
   LanguageFeatures disable_;
   LanguageFeatures warnLanguage_;
-  bool warnAllLanguage_{false};
   UsageWarnings warnUsage_;
-  bool warnAllUsage_{false};
-  bool disableAllWarnings_{false};
 };
 } // namespace Fortran::common
 #endif // FORTRAN_SUPPORT_FORTRAN_FEATURES_H_
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 0f1ace5d62667..a0ead8e16925f 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1057,8 +1057,6 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
   if (args.hasArg(clang::options::OPT_pedantic)) {
     features.WarnOnAllNonstandard();
     features.WarnOnAllUsage();
-    res.setEnableConformanceChecks();
-    res.setEnableUsageChecks();
   }
 
   // -Werror option
@@ -1097,7 +1095,6 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
   // -w
   if (args.hasArg(clang::options::OPT_w)) {
     features.DisableAllWarnings();
-    res.setDisableWarnings();
   }
 
   // Default to off for `flang -fc1`.
@@ -1204,7 +1201,6 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     auto standard = args.getLastArgValue(clang::options::OPT_std_EQ);
     // We only allow f2018 as the given standard
     if (standard == "f2018") {
-      res.setEnableConformanceChecks();
       res.getFrontendOpts().features.WarnOnAllNonstandard();
     } else {
       const unsigned diagID =
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index b8d71867da85d..7cb2eeaa3dbe0 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -326,10 +326,8 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
 }
 
 void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {
-  warnAllLanguage_ = yes;
   warnLanguage_.reset();
   if (yes) {
-    disableAllWarnings_ = false;
     warnLanguage_.flip();
     // These three features do not need to be warned about,
     // but we do want their feature flags.
@@ -340,10 +338,8 @@ void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {
 }
 
 void LanguageFeatureControl::WarnOnAllUsage(bool yes) {
-  warnAllUsage_ = yes;
   warnUsage_.reset();
   if (yes) {
-    disableAllWarnings_ = false;
     warnUsage_.flip();
   }
 }

>From 12509fc3a107b9a7adcf69270bc27071d77ba297 Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Wed, 24 Jun 2026 17:58:14 -0500
Subject: [PATCH 2/6] [flang] Add f2023 and f202Y to valid options for -std=

---
 flang/include/flang/Support/LangOptions.def    |  2 ++
 flang/include/flang/Support/LangOptions.h      |  7 +++++++
 flang/lib/Frontend/CompilerInvocation.cpp      | 18 +++++++++++++-----
 .../{std2018-wrong.f90 => std20XX-wrong.f90}   |  4 ++--
 flang/test/Driver/{std2018.f90 => std20XX.f90} |  4 +++-
 5 files changed, 27 insertions(+), 8 deletions(-)
 rename flang/test/Driver/{std2018-wrong.f90 => std20XX-wrong.f90} (61%)
 rename flang/test/Driver/{std2018.f90 => std20XX.f90} (75%)

diff --git a/flang/include/flang/Support/LangOptions.def b/flang/include/flang/Support/LangOptions.def
index 7ae73c6755b57..10532f61036ce 100644
--- a/flang/include/flang/Support/LangOptions.def
+++ b/flang/include/flang/Support/LangOptions.def
@@ -22,6 +22,8 @@ LANGOPT(Name, Bits, Default)
 ENUM_LANGOPT(FPContractMode, FPModeKind, 2, FPM_Fast) ///< FP Contract Mode (off/fast)
 /// signed integer overflow handling
 ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 1, SOB_Undefined)
+/// Specify Fortran standard
+ENUM_LANGOPT(FortranStandard, FortranStandardTy, 3, FortranUnspecified)
 
 /// Indicate a build without the standard GPU libraries.
 LANGOPT(NoGPULib  , 1, false)
diff --git a/flang/include/flang/Support/LangOptions.h b/flang/include/flang/Support/LangOptions.h
index 1dd676e62a9e5..7c320a66f18ea 100644
--- a/flang/include/flang/Support/LangOptions.h
+++ b/flang/include/flang/Support/LangOptions.h
@@ -43,6 +43,13 @@ class LangOptionsBase {
     FPM_Fast,
   };
 
+  enum FortranStandardTy {
+    FortranUnspecified, // default
+    Fortran2018,
+    Fortran2023,
+    Fortran202Y,
+  };
+
 #define LANGOPT(Name, Bits, Default) unsigned Name : Bits;
 #define ENUM_LANGOPT(Name, Type, Bits, Default)
 #include "LangOptions.def"
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index a0ead8e16925f..ca7c10e04c2ea 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1194,18 +1194,26 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
         Fortran::common::LanguageFeature::OpenACC);
   }
 
-  // -std=f2018
-  // TODO: Set proper options when more fortran standards
-  // are supported.
+  // -std=f20**
   if (args.hasArg(clang::options::OPT_std_EQ)) {
     auto standard = args.getLastArgValue(clang::options::OPT_std_EQ);
-    // We only allow f2018 as the given standard
     if (standard == "f2018") {
       res.getFrontendOpts().features.WarnOnAllNonstandard();
+      res.getLangOpts().setFortranStandard(
+          Fortran::common::LangOptions::Fortran2018);
+    } else if (standard == "f2023") {
+      res.getFrontendOpts().features.WarnOnAllNonstandard();
+      res.getLangOpts().setFortranStandard(
+          Fortran::common::LangOptions::Fortran2023);
+    } else if (standard == "f202Y") {
+      res.getFrontendOpts().features.WarnOnAllNonstandard();
+      res.getLangOpts().setFortranStandard(
+          Fortran::common::LangOptions::Fortran202Y);
     } else {
       const unsigned diagID =
           diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                "Only -std=f2018 is allowed currently.");
+                                "Only 'f2018', 'f2023', or 'f202Y' are "
+                                "accepted to -std= currently.");
       diags.Report(diagID);
     }
   }
diff --git a/flang/test/Driver/std2018-wrong.f90 b/flang/test/Driver/std20XX-wrong.f90
similarity index 61%
rename from flang/test/Driver/std2018-wrong.f90
rename to flang/test/Driver/std20XX-wrong.f90
index 93ba153d75f7f..227bf59e45acb 100644
--- a/flang/test/Driver/std2018-wrong.f90
+++ b/flang/test/Driver/std20XX-wrong.f90
@@ -1,8 +1,8 @@
-! Ensure argument -std=f2018 works as expected.
+! Ensure argument -std=f20XX works as expected.
 
 !-----------------------------------------
 ! FRONTEND FLANG DRIVER (flang -fc1)
 !-----------------------------------------
 ! RUN: not %flang_fc1 -std=90 %s  2>&1 | FileCheck %s --check-prefix=WRONG
 
-! WRONG: Only -std=f2018 is allowed currently.
+! WRONG: Only 'f2018', 'f2023', or 'f202Y' are accepted to -std= currently.
diff --git a/flang/test/Driver/std2018.f90 b/flang/test/Driver/std20XX.f90
similarity index 75%
rename from flang/test/Driver/std2018.f90
rename to flang/test/Driver/std20XX.f90
index 1727f92127b71..afec991d1e1a6 100644
--- a/flang/test/Driver/std2018.f90
+++ b/flang/test/Driver/std20XX.f90
@@ -1,10 +1,12 @@
-! Ensure argument -std=f2018 works as expected.
+! Ensure argument -std=f20XX works as expected.
 
 !-----------------------------------------
 ! FRONTEND FLANG DRIVER (flang -fc1)
 !-----------------------------------------
 ! RUN: %flang_fc1 -fsyntax-only %s  2>&1 | FileCheck %s --allow-empty --check-prefix=WITHOUT
 ! RUN: %flang_fc1 -fsyntax-only -std=f2018 %s  2>&1 | FileCheck %s --check-prefix=GIVEN
+! RUN: %flang_fc1 -fsyntax-only -std=f2023 %s  2>&1 | FileCheck %s --check-prefix=GIVEN
+! RUN: %flang_fc1 -fsyntax-only -std=f202Y %s  2>&1 | FileCheck %s --check-prefix=GIVEN
 ! RUN: %flang_fc1 -fsyntax-only -pedantic %s  2>&1 | FileCheck %s --check-prefix=GIVEN
 
 ! WITHOUT-NOT: A DO loop should terminate with an END DO or CONTINUE

>From dbb0724476f0f6dfcc8e8d3f7905c676a1fc991b Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Thu, 25 Jun 2026 16:01:04 -0500
Subject: [PATCH 3/6] [flang] Add checks for F2023 SYSTEM_CLOCK restrictions

Add checks for the restrictions on SYSTEM_CLOCK arguments in Fortran
2023, and issue warnings for violations.

These checks are enabled by default. These warnings are disabled under
two conditions:
 - One or more of -fno-system-clock-strict or -fsystem-clock-strict
   appears, and -fno-system-clock-strict appears last.
 - If -f{no-}system-clock-strict flags do not appear, and if the Fortran
   standard is set (via -std=f20XX), the standard is set to f2018.
---
 clang/include/clang/Options/FlangOptions.td   |   4 +
 .../include/flang/Support/Fortran-features.h  |   3 +-
 flang/lib/Frontend/CompilerInvocation.cpp     |  36 +++++
 flang/lib/Semantics/check-call.cpp            |  57 ++++++++
 flang/lib/Support/Fortran-features.cpp        |   7 +
 flang/test/Semantics/system_clock.f90         | 123 ++++++++++++++++++
 6 files changed, 229 insertions(+), 1 deletion(-)
 create mode 100644 flang/test/Semantics/system_clock.f90

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 9d163ba0626ba..5a7652fffd0ae 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -318,6 +318,10 @@ def fno_realloc_lhs : Flag<["-"], "fno-realloc-lhs">, Group<f_Group>,
 def frealloc_lhs : Flag<["-"], "frealloc-lhs">, Group<f_Group>,
   HelpText<"If an allocatable left-hand side of an intrinsic assignment is unallocated or its shape/type does not match the right-hand side, then it is automatically (re)allocated">;
 
+defm system_clock_strict : OptOutFC1FFlag<"system-clock-strict",
+  "Issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023 (default)",
+  "Do not issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023">;
+
 //===----------------------------------------------------------------------===//
 // Coarray Options
 //===----------------------------------------------------------------------===//
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index b5e46ca7e095e..3bc0f5418a85c 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -60,7 +60,8 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
     DefaultStructConstructorNullPointer, AssumedRankIoItem,
     MultipleProgramUnitsOnSameLine, AllocatedForAssociated,
     OpenMPThreadprivateEquivalence, RelaxedCLocChecks, CudaPinned,
-    OpenAccDefaultNoneScalarsStrict, OpenACCMultipleNamesInRoutine)
+    OpenAccDefaultNoneScalarsStrict, OpenACCMultipleNamesInRoutine,
+    SystemClockStrict)
 
 // Portability and suspicious usage warnings
 ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index ca7c10e04c2ea..491c4c5f4c2d5 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1217,6 +1217,42 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
       diags.Report(diagID);
     }
   }
+
+  // -f{no-}system-clock-strict
+  {
+    // Fortran 2023 introduced restrictions to the arguements of SYSTEM_CLOCK.
+    // Since violations of these restrictions can cause unexpected or incorrect
+    // runtime results, violations should be reported to users at compile time
+    // by default. However, since these restrictions are not in Fortran 2018,
+    // these reports should be warnings and not errors. There are two ways to
+    // enable/disable these warnings:
+    //  -f{no-}system-clock-strict
+    //  -std=f20{18,23}
+    // Rules for enabling/disabling these warnings:
+    //  - If one or more of `-f{no-}system-clock-strict` appear, then the last
+    //    dictates whether or not the warnings are enabled.
+    //  - If no `-f{no-}system-clock-strict` flags appear and Fortran 2018 has
+    //    been set as the Fortran standard to follow, that is `-std=f2018` is
+    //    the last `std` flag, then the warnings are disabled.
+    //  - Otherwise, the warnings are enabled.
+    auto last = args.getLastArg(clang::options::OPT_fsystem_clock_strict,
+        clang::options::OPT_fno_system_clock_strict);
+    if (last) {
+      if (last->getOption().matches(clang::options::OPT_fno_system_clock_strict)) {
+        // If the last of these args is `-fno-system-clock-strict`, disable the
+        // warnings. Otherwise leave the warnings enabled.
+        res.getFrontendOpts().features.EnableWarning(
+            Fortran::common::LanguageFeature::SystemClockStrict, false);
+      }
+    } else if (res.getLangOpts().getFortranStandard() ==
+               Fortran::common::LangOptions::Fortran2018) {
+      // If the Fortran standard is set to `f2018`, disable the warnings.
+      // Otherwise, leave the warnings enabled.
+      res.getFrontendOpts().features.EnableWarning(
+          Fortran::common::LanguageFeature::SystemClockStrict, false);
+    }
+  }
+
   // -fcoarray
   if (args.hasArg(clang::options::OPT_fcoarray)) {
     res.getFrontendOpts().features.Enable(
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index f91b9b1d0b67d..736b901f8535c 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -2038,6 +2038,61 @@ static void CheckFree(evaluate::ActualArguments &arguments,
   }
 }
 
+static void CheckSystemClockIntArgsSameKind(
+    evaluate::ActualArguments &arguments,
+    evaluate::FoldingContext &foldingContext) {
+  std::optional<int> commonKind;
+  if (arguments.size() < 2) {
+    return;
+  }
+  for (const auto &arg : arguments) {
+    if (arg) {
+      auto dyType{arg->GetType()};
+      if (dyType && dyType->category() == TypeCategory::Integer) {
+        if (!commonKind) {
+          commonKind = dyType->kind();
+        } else if (*commonKind != dyType->kind()) {
+          foldingContext.Warn(common::LanguageFeature::SystemClockStrict,
+              arg->sourceLocation(),
+              "Integer arguments to SYSTEM_CLOCK should have the same kind. Given %d and %d."_warn_en_US,
+              *commonKind, dyType->kind());
+        }
+      }
+    }
+  }
+}
+
+static void CheckSystemClockMinSize(evaluate::ActualArguments &arguments,
+    evaluate::FoldingContext &foldingContext) {
+  int defaultInt{
+      foldingContext.defaults().GetDefaultKind(TypeCategory::Integer)};
+  for (const auto &arg : arguments) {
+    if (arg) {
+      auto dyType{arg->GetType()};
+      if (dyType && dyType->category() == TypeCategory::Integer &&
+          dyType->kind() < defaultInt) {
+        foldingContext.Warn(common::LanguageFeature::SystemClockStrict,
+            arg->sourceLocation(),
+            "Integer argument to SYSTEM_CLOCK should be an integer with kind >= %d. Given %d."_warn_en_US,
+            defaultInt, dyType->kind());
+      }
+    }
+  }
+}
+
+static void CheckSystemClock(
+    evaluate::ActualArguments &arguments, SemanticsContext &context) {
+  if (context.ShouldWarn(common::LanguageFeature::SystemClockStrict)) {
+    // Fortran 2023 limits integer arguments to SYSTEM_CLOCK to all having the
+    // same kind.
+    CheckSystemClockIntArgsSameKind(arguments, context.foldingContext());
+
+    // Fortran 2023 limits integer arguments to SYSTEM_CLOCK to having kind as
+    // least as large as the default integer.
+    CheckSystemClockMinSize(arguments, context.foldingContext());
+  }
+}
+
 // MOVE_ALLOC (F'2023 16.9.147)
 static void CheckMove_Alloc(evaluate::ActualArguments &arguments,
     parser::ContextualMessages &messages) {
@@ -2339,6 +2394,8 @@ static void CheckSpecificIntrinsic(const characteristics::Procedure &proc,
     CheckTransfer(arguments, context, scope);
   } else if (intrinsic.name == "free") {
     CheckFree(arguments, context.foldingContext().messages());
+  } else if (intrinsic.name == "system_clock") {
+    CheckSystemClock(arguments, context);
   }
 }
 
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 7cb2eeaa3dbe0..651844ec6f869 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -218,6 +218,7 @@ LanguageFeatureControl::LanguageFeatureControl() {
   warnUsage_.set(UsageWarning::IoImpliedDoIndexConflict);
   warnLanguage_.set(LanguageFeature::OpenMPThreadprivateEquivalence);
   warnLanguage_.set(LanguageFeature::OpenACCMultipleNamesInRoutine);
+  warnLanguage_.set(LanguageFeature::SystemClockStrict);
 }
 
 std::optional<LanguageControlFlag> LanguageFeatureControl::FindWarning(
@@ -326,6 +327,9 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
 }
 
 void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {
+  // This feature is set independently and is on by default:
+  bool clockStrict = warnLanguage_.test(LanguageFeature::SystemClockStrict);
+
   warnLanguage_.reset();
   if (yes) {
     warnLanguage_.flip();
@@ -335,6 +339,9 @@ void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {
     warnLanguage_.set(LanguageFeature::OpenACC, false);
     warnLanguage_.set(LanguageFeature::CUDA, false);
   }
+
+  // This feature is set independently and is on by default:
+  warnLanguage_.set(LanguageFeature::SystemClockStrict, clockStrict);
 }
 
 void LanguageFeatureControl::WarnOnAllUsage(bool yes) {
diff --git a/flang/test/Semantics/system_clock.f90 b/flang/test/Semantics/system_clock.f90
new file mode 100644
index 0000000000000..04b03c7ed1698
--- /dev/null
+++ b/flang/test/Semantics/system_clock.f90
@@ -0,0 +1,123 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+
+! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+
+! RUN: %flang_fc1 -fsyntax-only -fdefault-integer-8 %s 2>&1 | FileCheck --check-prefix=STRICT-8 %s
+! RUN: %flang_fc1 -fsyntax-only -fdefault-integer-8 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+
+! RUN: %flang_fc1 -fsyntax-only -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang_fc1 -fsyntax-only -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang_fc1 -fsyntax-only -std=f202Y %s 2>&1 | FileCheck --check-prefix=STRICT %s
+
+! RUN: %flang_fc1 -fsyntax-only -std=f2023 -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang_fc1 -fsyntax-only -std=f2018 -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+
+! RUN: %flang_fc1 -fsyntax-only -std=f2023 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict -std=f2023 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict -std=f2018 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+
+! Tests for SYSTEM_CLOCK argument warnings
+
+program test_system_clock
+  implicit none
+
+  integer(8) :: count8, rate8, max8
+  integer(4) :: count4, rate4, max4
+  integer(2) :: count2, rate2, max2
+  integer(1) :: count1, rate1, max1
+  real(8) :: rate_real8
+  real(4) :: rate_real4
+
+  call system_clock()
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate_real4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate4, max4)
+
+  call system_clock(count8, rate8, max8)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count=count4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count_rate=rate4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count_max=max4)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate_real4, max4)
+
+  call system_clock(count8, rate_real8, max8)
+
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count=count4, count_rate=rate4, count_max=max4)
+
+  !STRICT: Integer arguments to SYSTEM_CLOCK should have the same kind.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate8)
+
+  !STRICT: Integer arguments to SYSTEM_CLOCK should have the same kind.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate8, max4)
+
+  !STRICT: Integer arguments to SYSTEM_CLOCK should have the same kind.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate4, max8)
+
+  !STRICT: Integer arguments to SYSTEM_CLOCK should have the same kind.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count4, rate_real4, max8)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count2)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count2, rate2)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count2, rate_real4)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count2, rate2, max2)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count2, rate_real4, max2)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count1)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count1, rate1)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count1, rate_real4)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count1, rate1, max1)
+
+  !STRICT: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 4.
+  !STRICT-8: Integer argument to SYSTEM_CLOCK should be an integer with kind >= 8.
+  call system_clock(count1, rate_real4, max1)
+end program

>From 17610a058e1e34132fbd1aa2b99cc9f0fbd9e127 Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Fri, 26 Jun 2026 16:39:58 -0500
Subject: [PATCH 4/6] [flang] Fix formatting

---
 flang/lib/Frontend/CompilerInvocation.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 491c4c5f4c2d5..917865adb781f 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1236,9 +1236,10 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     //    the last `std` flag, then the warnings are disabled.
     //  - Otherwise, the warnings are enabled.
     auto last = args.getLastArg(clang::options::OPT_fsystem_clock_strict,
-        clang::options::OPT_fno_system_clock_strict);
+                                clang::options::OPT_fno_system_clock_strict);
     if (last) {
-      if (last->getOption().matches(clang::options::OPT_fno_system_clock_strict)) {
+      if (last->getOption().matches(
+              clang::options::OPT_fno_system_clock_strict)) {
         // If the last of these args is `-fno-system-clock-strict`, disable the
         // warnings. Otherwise leave the warnings enabled.
         res.getFrontendOpts().features.EnableWarning(

>From 1c9335bcc18a8e3febf211fa67b87bdfd521ee26 Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Tue, 11 Aug 2026 16:40:53 -0500
Subject: [PATCH 5/6] [flang] Fix flags for F2023 SYSTEM_CLOCK restrictions
 checks

Change -fsystem-clock-strict and -fno-system-clock-strict to work in the
Flang driver instead of fc1.
---
 clang/include/clang/Options/FlangOptions.td |  7 +++--
 clang/lib/Driver/ToolChains/Flang.cpp       |  2 ++
 flang/lib/Frontend/CompilerInvocation.cpp   | 29 +++++++++++--------
 flang/test/Semantics/system_clock.f90       | 32 ++++++++++-----------
 4 files changed, 39 insertions(+), 31 deletions(-)

diff --git a/clang/include/clang/Options/FlangOptions.td b/clang/include/clang/Options/FlangOptions.td
index 5a7652fffd0ae..ff9a4111cf3a1 100644
--- a/clang/include/clang/Options/FlangOptions.td
+++ b/clang/include/clang/Options/FlangOptions.td
@@ -318,9 +318,10 @@ def fno_realloc_lhs : Flag<["-"], "fno-realloc-lhs">, Group<f_Group>,
 def frealloc_lhs : Flag<["-"], "frealloc-lhs">, Group<f_Group>,
   HelpText<"If an allocatable left-hand side of an intrinsic assignment is unallocated or its shape/type does not match the right-hand side, then it is automatically (re)allocated">;
 
-defm system_clock_strict : OptOutFC1FFlag<"system-clock-strict",
-  "Issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023 (default)",
-  "Do not issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023">;
+def fno_system_clock_strict : Flag<["-"], "fno-system-clock-strict">, Group<f_Group>,
+  HelpText<"Do not issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023">;
+def fsystem_clock_strict : Flag<["-"], "fsystem-clock-strict">, Group<f_Group>,
+  HelpText<"Issue warnings for violations of SYSTEM_CLOCK argument restrictions from Fortran 2023 (default)">;
 
 //===----------------------------------------------------------------------===//
 // Coarray Options
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index ea4df1db38ec8..2fed6039d97ef 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -62,6 +62,8 @@ void Flang::addFortranDialectOptions(const ArgList &Args,
                             options::OPT_fhermetic_module_files,
                             options::OPT_frealloc_lhs,
                             options::OPT_fno_realloc_lhs,
+                            options::OPT_fsystem_clock_strict,
+                            options::OPT_fno_system_clock_strict,
                             options::OPT_fsave_main_program,
                             options::OPT_fd_lines_as_code,
                             options::OPT_fd_lines_as_comments,
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 917865adb781f..361e9a84baf04 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1237,18 +1237,23 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     //  - Otherwise, the warnings are enabled.
     auto last = args.getLastArg(clang::options::OPT_fsystem_clock_strict,
                                 clang::options::OPT_fno_system_clock_strict);
-    if (last) {
-      if (last->getOption().matches(
-              clang::options::OPT_fno_system_clock_strict)) {
-        // If the last of these args is `-fno-system-clock-strict`, disable the
-        // warnings. Otherwise leave the warnings enabled.
-        res.getFrontendOpts().features.EnableWarning(
-            Fortran::common::LanguageFeature::SystemClockStrict, false);
-      }
-    } else if (res.getLangOpts().getFortranStandard() ==
-               Fortran::common::LangOptions::Fortran2018) {
-      // If the Fortran standard is set to `f2018`, disable the warnings.
-      // Otherwise, leave the warnings enabled.
+
+    // If the last of the system_clock_strict arguments is
+    // `-fno-system-clock-strict`, disable the warnings.
+    const bool last_is_no_strict =
+        last &&
+        last->getOption().matches(
+            clang::options::OPT_fno_system_clock_strict);
+
+    // If there are no system_clock_strict arguments present and the Fortran
+    // standard is set to `f2018`, disable the warnings.
+    const bool no_arg_and_f2018 =
+        !last &&
+	res.getLangOpts().getFortranStandard() ==
+            Fortran::common::LangOptions::Fortran2018;
+
+    // If either condition is met, disable the warnings.
+    if (last_is_no_strict || no_arg_and_f2018) {
       res.getFrontendOpts().features.EnableWarning(
           Fortran::common::LanguageFeature::SystemClockStrict, false);
     }
diff --git a/flang/test/Semantics/system_clock.f90 b/flang/test/Semantics/system_clock.f90
index 04b03c7ed1698..4c28203bd3e4f 100644
--- a/flang/test/Semantics/system_clock.f90
+++ b/flang/test/Semantics/system_clock.f90
@@ -1,24 +1,24 @@
-! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck --check-prefix=STRICT %s
-! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
-! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
 
-! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
-! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -fno-system-clock-strict -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -fsystem-clock-strict -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
 
-! RUN: %flang_fc1 -fsyntax-only -fdefault-integer-8 %s 2>&1 | FileCheck --check-prefix=STRICT-8 %s
-! RUN: %flang_fc1 -fsyntax-only -fdefault-integer-8 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -fdefault-integer-8 %s 2>&1 | FileCheck --check-prefix=STRICT-8 %s
+! RUN: %flang -fdefault-integer-8 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
 
-! RUN: %flang_fc1 -fsyntax-only -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
-! RUN: %flang_fc1 -fsyntax-only -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
-! RUN: %flang_fc1 -fsyntax-only -std=f202Y %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -std=f202Y %s 2>&1 | FileCheck --check-prefix=STRICT %s
 
-! RUN: %flang_fc1 -fsyntax-only -std=f2023 -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
-! RUN: %flang_fc1 -fsyntax-only -std=f2018 -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -std=f2023 -std=f2018 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -std=f2018 -std=f2023 %s 2>&1 | FileCheck --check-prefix=STRICT %s
 
-! RUN: %flang_fc1 -fsyntax-only -std=f2023 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
-! RUN: %flang_fc1 -fsyntax-only -fno-system-clock-strict -std=f2023 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
-! RUN: %flang_fc1 -fsyntax-only -std=f2018 -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
-! RUN: %flang_fc1 -fsyntax-only -fsystem-clock-strict -std=f2018 %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -std=f2023 -fno-system-clock-strict %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -fno-system-clock-strict -std=f2023 %s 2>&1 | FileCheck --allow-empty --implicit-check-not="SYSTEM_CLOCK" %s
+! RUN: %flang -std=f2018 -fsystem-clock-strict %s 2>&1 | FileCheck --check-prefix=STRICT %s
+! RUN: %flang -fsystem-clock-strict -std=f2018 %s 2>&1 | FileCheck --check-prefix=STRICT %s
 
 ! Tests for SYSTEM_CLOCK argument warnings
 

>From 42ff13497bb7ff5a1bc0b6fce71044d67b2d4142 Mon Sep 17 00:00:00 2001
From: Chris Earl <chris.earl at hpe.com>
Date: Wed, 12 Aug 2026 12:02:59 -0500
Subject: [PATCH 6/6] [flang] Simplify logic for F2023 SYSTEM_CLOCK restriction
 flags

Change logic for `-f{no-}system-clock-strict` to use `hasFlag()`.
---
 flang/lib/Frontend/CompilerInvocation.cpp | 29 ++++++-----------------
 1 file changed, 7 insertions(+), 22 deletions(-)

diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index 361e9a84baf04..f0b510d0d72b7 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -1235,28 +1235,13 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     //    been set as the Fortran standard to follow, that is `-std=f2018` is
     //    the last `std` flag, then the warnings are disabled.
     //  - Otherwise, the warnings are enabled.
-    auto last = args.getLastArg(clang::options::OPT_fsystem_clock_strict,
-                                clang::options::OPT_fno_system_clock_strict);
-
-    // If the last of the system_clock_strict arguments is
-    // `-fno-system-clock-strict`, disable the warnings.
-    const bool last_is_no_strict =
-        last &&
-        last->getOption().matches(
-            clang::options::OPT_fno_system_clock_strict);
-
-    // If there are no system_clock_strict arguments present and the Fortran
-    // standard is set to `f2018`, disable the warnings.
-    const bool no_arg_and_f2018 =
-        !last &&
-	res.getLangOpts().getFortranStandard() ==
-            Fortran::common::LangOptions::Fortran2018;
-
-    // If either condition is met, disable the warnings.
-    if (last_is_no_strict || no_arg_and_f2018) {
-      res.getFrontendOpts().features.EnableWarning(
-          Fortran::common::LanguageFeature::SystemClockStrict, false);
-    }
+    const bool enable_warning =
+        args.hasFlag(clang::options::OPT_fsystem_clock_strict,
+                     clang::options::OPT_fno_system_clock_strict,
+                     res.getLangOpts().getFortranStandard() !=
+                         Fortran::common::LangOptions::Fortran2018);
+    res.getFrontendOpts().features.EnableWarning(
+        Fortran::common::LanguageFeature::SystemClockStrict, enable_warning);
   }
 
   // -fcoarray



More information about the flang-commits mailing list