Skip to content

[flang][cli] Add diagnostic flags to the CLI #142022

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 21 commits into
base: main
Choose a base branch
from

Conversation

akuhlens
Copy link
Contributor

This change allows the flang CLI to accept -W[no-]<feature> flags matching the clang syntax and enable and disable usage and language feature warnings.

@llvmbot llvmbot added flang:driver flang Flang issues not falling into any other category labels May 29, 2025
@akuhlens akuhlens requested a review from klausler May 29, 2025 19:39
@llvmbot
Copy link
Member

llvmbot commented May 29, 2025

@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-driver

Author: Andre Kuhlenschmidt (akuhlens)

Changes

This change allows the flang CLI to accept -W[no-]&lt;feature&gt; flags matching the clang syntax and enable and disable usage and language feature warnings.


Patch is 29.87 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/142022.diff

12 Files Affected:

  • (modified) flang/include/flang/Common/enum-class.h (+42-5)
  • (modified) flang/include/flang/Support/Fortran-features.h (+37-14)
  • (modified) flang/lib/Frontend/CompilerInvocation.cpp (+33-29)
  • (modified) flang/lib/Support/CMakeLists.txt (+1)
  • (modified) flang/lib/Support/Fortran-features.cpp (+132-36)
  • (added) flang/lib/Support/enum-class.cpp (+24)
  • (added) flang/test/Driver/disable-diagnostic.f90 (+19)
  • (modified) flang/test/Driver/werror-wrong.f90 (+4-3)
  • (modified) flang/test/Driver/wextra-ok.f90 (+1-1)
  • (modified) flang/unittests/Common/CMakeLists.txt (+3)
  • (added) flang/unittests/Common/EnumClassTests.cpp (+45)
  • (added) flang/unittests/Common/FortranFeaturesTest.cpp (+142)
diff --git a/flang/include/flang/Common/enum-class.h b/flang/include/flang/Common/enum-class.h
index 41575d45091a8..baf9fe418141d 100644
--- a/flang/include/flang/Common/enum-class.h
+++ b/flang/include/flang/Common/enum-class.h
@@ -18,8 +18,9 @@
 #define FORTRAN_COMMON_ENUM_CLASS_H_
 
 #include <array>
-#include <string>
-
+#include <functional>
+#include <optional>
+#include <string_view>
 namespace Fortran::common {
 
 constexpr std::size_t CountEnumNames(const char *p) {
@@ -58,15 +59,51 @@ constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
   return result;
 }
 
+template <typename F, typename T>
+std::optional<T> inline fmap(std::optional<F> x, std::function<T(const F)> f) {
+  return x ? std::optional<T>{f(*x)} : std::nullopt;
+}
+
+using Predicate = std::function<bool(const std::string_view)>;
+// Finds the first index for which the predicate returns true.
+std::optional<int> FindEnumIndex(
+    Predicate pred, int size, const std::string_view *names);
+
+using FindEnumIndexType = std::optional<int>(
+    Predicate, int, const std::string_view *);
+
+template <typename NAME>
+std::optional<NAME> inline FindEnum(
+    Predicate pred, std::function<std::optional<int>(Predicate)> find) {
+  std::function<NAME(int)> f = [](int x) { return static_cast<NAME>(x); };
+  return fmap(find(pred), f);
+}
+
 #define ENUM_CLASS(NAME, ...) \
   enum class NAME { __VA_ARGS__ }; \
   [[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \
       ::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \
+  [[maybe_unused]] static constexpr std::array<std::string_view, \
+      NAME##_enumSize> NAME##_names{ \
+      ::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
   [[maybe_unused]] static inline std::string_view EnumToString(NAME e) { \
-    static const constexpr auto names{ \
-        ::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
-    return names[static_cast<std::size_t>(e)]; \
+    return NAME##_names[static_cast<std::size_t>(e)]; \
   }
 
+#define ENUM_CLASS_EXTRA(NAME) \
+  [[maybe_unused]] inline std::optional<int> Find##NAME##Index( \
+      ::Fortran::common::Predicate p) { \
+    return ::Fortran::common::FindEnumIndex( \
+        p, NAME##_enumSize, NAME##_names.data()); \
+  } \
+  [[maybe_unused]] inline std::optional<NAME> Find##NAME( \
+      ::Fortran::common::Predicate p) { \
+    return ::Fortran::common::FindEnum<NAME>(p, Find##NAME##Index); \
+  } \
+  [[maybe_unused]] inline std::optional<NAME> StringTo##NAME( \
+      const std::string_view name) { \
+    return Find##NAME( \
+        [name](const std::string_view s) -> bool { return name == s; }); \
+  }
 } // namespace Fortran::common
 #endif // FORTRAN_COMMON_ENUM_CLASS_H_
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index e696da9042480..d5aa7357ffea0 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -12,6 +12,8 @@
 #include "Fortran.h"
 #include "flang/Common/enum-set.h"
 #include "flang/Common/idioms.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/raw_ostream.h"
 #include <optional>
 #include <vector>
 
@@ -79,12 +81,13 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
     NullActualForDefaultIntentAllocatable, UseAssociationIntoSameNameSubprogram,
     HostAssociatedIntentOutInSpecExpr, NonVolatilePointerToVolatile)
 
+// Generate default String -> Enum mapping.
+ENUM_CLASS_EXTRA(LanguageFeature)
+ENUM_CLASS_EXTRA(UsageWarning)
+
 using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
 using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
 
-std::optional<LanguageFeature> FindLanguageFeature(const char *);
-std::optional<UsageWarning> FindUsageWarning(const char *);
-
 class LanguageFeatureControl {
 public:
   LanguageFeatureControl();
@@ -97,8 +100,10 @@ class LanguageFeatureControl {
   void EnableWarning(UsageWarning w, bool yes = true) {
     warnUsage_.set(w, yes);
   }
-  void WarnOnAllNonstandard(bool yes = true) { warnAllLanguage_ = yes; }
-  void WarnOnAllUsage(bool yes = true) { warnAllUsage_ = yes; }
+  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();
@@ -107,16 +112,16 @@ class LanguageFeatureControl {
     warnAllUsage_ = false;
     warnUsage_.clear();
   }
-
-  bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
-  bool ShouldWarn(LanguageFeature f) const {
-    return (warnAllLanguage_ && f != LanguageFeature::OpenMP &&
-               f != LanguageFeature::OpenACC && f != LanguageFeature::CUDA) ||
-        warnLanguage_.test(f);
-  }
-  bool ShouldWarn(UsageWarning w) const {
-    return warnAllUsage_ || warnUsage_.test(w);
+  void DisableAllWarnings() {
+    disableAllWarnings_ = true;
+    DisableAllNonstandardWarnings();
+    DisableAllUsageWarnings();
   }
+  bool applyCLIOption(llvm::StringRef input);
+  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); }
   // Return all spellings of operators names, depending on features enabled
   std::vector<const char *> GetNames(LogicalOperator) const;
   std::vector<const char *> GetNames(RelationalOperator) const;
@@ -127,6 +132,24 @@ class LanguageFeatureControl {
   bool warnAllLanguage_{false};
   UsageWarnings warnUsage_;
   bool warnAllUsage_{false};
+  bool disableAllWarnings_{false};
 };
+
+// Parse a CLI enum option return the enum index and whether it should be
+// enabled (true) or disabled (false). Just exposed for the template below.
+std::optional<std::pair<bool, int>> parseCLIEnumIndex(
+    llvm::StringRef input, std::function<std::optional<int>(Predicate)> find);
+
+template <typename ENUM>
+std::optional<std::pair<bool, ENUM>> parseCLIEnum(
+    llvm::StringRef input, std::function<std::optional<int>(Predicate)> find) {
+  using To = std::pair<bool, ENUM>;
+  using From = std::pair<bool, int>;
+  static std::function<To(From)> cast = [](From x) {
+    return std::pair{x.first, static_cast<ENUM>(x.second)};
+  };
+  return fmap(parseCLIEnumIndex(input, find), cast);
+}
+
 } // namespace Fortran::common
 #endif // FORTRAN_SUPPORT_FORTRAN_FEATURES_H_
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp b/flang/lib/Frontend/CompilerInvocation.cpp
index ba2531819ee5e..9ea568549bd6c 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -34,6 +34,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Option/OptTable.h"
 #include "llvm/Support/CodeGen.h"
+#include "llvm/Support/Error.h"
 #include "llvm/Support/FileSystem.h"
 #include "llvm/Support/FileUtilities.h"
 #include "llvm/Support/Path.h"
@@ -45,6 +46,7 @@
 #include <cstdlib>
 #include <memory>
 #include <optional>
+#include <string>
 
 using namespace Fortran::frontend;
 
@@ -971,10 +973,23 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
 
 /// Parses all diagnostics related arguments and populates the variables
 /// options accordingly. Returns false if new errors are generated.
+/// FC1 driver entry point for parsing diagnostic arguments.
 static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
                           clang::DiagnosticsEngine &diags) {
   unsigned numErrorsBefore = diags.getNumErrors();
 
+  auto &features = res.getFrontendOpts().features;
+  // The order of these flags (-pedantic -W<feature> -w) is important and is
+  // chosen to match clang's behavior.
+
+  // -pedantic
+  if (args.hasArg(clang::driver::options::OPT_pedantic)) {
+    features.WarnOnAllNonstandard();
+    features.WarnOnAllUsage();
+    res.setEnableConformanceChecks();
+    res.setEnableUsageChecks();
+  }
+
   // -Werror option
   // TODO: Currently throws a Diagnostic for anything other than -W<error>,
   // this has to change when other -W<opt>'s are supported.
@@ -984,21 +999,27 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     for (const auto &wArg : wArgs) {
       if (wArg == "error") {
         res.setWarnAsErr(true);
-      } else {
-        const unsigned diagID =
-            diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
-                                  "Only `-Werror` is supported currently.");
-        diags.Report(diagID);
+        // -W(no-)<feature>
+      } else if (!features.applyCLIOption(wArg)) {
+        const unsigned diagID = diags.getCustomDiagID(
+            clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
+        diags.Report(diagID) << wArg;
       }
     }
   }
 
+  // -w
+  if (args.hasArg(clang::driver::options::OPT_w)) {
+    features.DisableAllWarnings();
+    res.setDisableWarnings();
+  }
+
   // Default to off for `flang -fc1`.
-  res.getFrontendOpts().showColors =
-      parseShowColorsArgs(args, /*defaultDiagColor=*/false);
+  bool showColors = parseShowColorsArgs(args, false);
 
-  // Honor color diagnostics.
-  res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
+  diags.getDiagnosticOptions().ShowColors = showColors;
+  res.getDiagnosticOpts().ShowColors = showColors;
+  res.getFrontendOpts().showColors = showColors;
 
   return diags.getNumErrors() == numErrorsBefore;
 }
@@ -1074,16 +1095,6 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
         Fortran::common::LanguageFeature::OpenACC);
   }
 
-  // -pedantic
-  if (args.hasArg(clang::driver::options::OPT_pedantic)) {
-    res.setEnableConformanceChecks();
-    res.setEnableUsageChecks();
-  }
-
-  // -w
-  if (args.hasArg(clang::driver::options::OPT_w))
-    res.setDisableWarnings();
-
   // -std=f2018
   // TODO: Set proper options when more fortran standards
   // are supported.
@@ -1092,6 +1103,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
     // We only allow f2018 as the given standard
     if (standard == "f2018") {
       res.setEnableConformanceChecks();
+      res.getFrontendOpts().features.WarnOnAllNonstandard();
     } else {
       const unsigned diagID =
           diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
@@ -1099,6 +1111,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
       diags.Report(diagID);
     }
   }
+
   return diags.getNumErrors() == numErrorsBefore;
 }
 
@@ -1694,16 +1707,7 @@ void CompilerInvocation::setFortranOpts() {
   if (frontendOptions.needProvenanceRangeToCharBlockMappings)
     fortranOptions.needProvenanceRangeToCharBlockMappings = true;
 
-  if (getEnableConformanceChecks())
-    fortranOptions.features.WarnOnAllNonstandard();
-
-  if (getEnableUsageChecks())
-    fortranOptions.features.WarnOnAllUsage();
-
-  if (getDisableWarnings()) {
-    fortranOptions.features.DisableAllNonstandardWarnings();
-    fortranOptions.features.DisableAllUsageWarnings();
-  }
+  fortranOptions.features = frontendOptions.features;
 }
 
 std::unique_ptr<Fortran::semantics::SemanticsContext>
diff --git a/flang/lib/Support/CMakeLists.txt b/flang/lib/Support/CMakeLists.txt
index 363f57ce97dae..9ef31a2a6dcc7 100644
--- a/flang/lib/Support/CMakeLists.txt
+++ b/flang/lib/Support/CMakeLists.txt
@@ -44,6 +44,7 @@ endif()
 
 add_flang_library(FortranSupport
   default-kinds.cpp
+  enum-class.cpp
   Flags.cpp
   Fortran.cpp
   Fortran-features.cpp
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index bee8984102b82..55abf0385d185 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -9,6 +9,8 @@
 #include "flang/Support/Fortran-features.h"
 #include "flang/Common/idioms.h"
 #include "flang/Support/Fortran.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
 
 namespace Fortran::common {
 
@@ -94,57 +96,123 @@ LanguageFeatureControl::LanguageFeatureControl() {
   warnLanguage_.set(LanguageFeature::NullActualForAllocatable);
 }
 
-// Ignore case and any inserted punctuation (like '-'/'_')
-static std::optional<char> GetWarningChar(char ch) {
-  if (ch >= 'a' && ch <= 'z') {
-    return ch;
-  } else if (ch >= 'A' && ch <= 'Z') {
-    return ch - 'A' + 'a';
-  } else if (ch >= '0' && ch <= '9') {
-    return ch;
-  } else {
-    return std::nullopt;
+// Split a string with camel case into the individual words.
+// Note, the small vector is just an array of a few pointers and lengths
+// into the original input string. So all this allocation should be pretty
+// cheap.
+llvm::SmallVector<llvm::StringRef> splitCamelCase(llvm::StringRef input) {
+  using namespace llvm;
+  if (input.empty()) {
+    return {};
   }
+  SmallVector<StringRef> parts{};
+  parts.reserve(input.size());
+  auto check = [&input](size_t j, function_ref<bool(char)> predicate) {
+    return j < input.size() && predicate(input[j]);
+  };
+  size_t i{0};
+  size_t startWord = i;
+  for (; i < input.size(); i++) {
+    if ((check(i, isUpper) && check(i + 1, isUpper) && check(i + 2, isLower)) ||
+        ((check(i, isLower) || check(i, isDigit)) && check(i + 1, isUpper))) {
+      parts.push_back(StringRef(input.data() + startWord, i - startWord + 1));
+      startWord = i + 1;
+    }
+  }
+  parts.push_back(llvm::StringRef(input.data() + startWord, i - startWord));
+  return parts;
 }
 
-static bool WarningNameMatch(const char *a, const char *b) {
-  while (true) {
-    auto ach{GetWarningChar(*a)};
-    while (!ach && *a) {
-      ach = GetWarningChar(*++a);
-    }
-    auto bch{GetWarningChar(*b)};
-    while (!bch && *b) {
-      bch = GetWarningChar(*++b);
+// Split a string whith hyphens into the individual words.
+llvm::SmallVector<llvm::StringRef> splitHyphenated(llvm::StringRef input) {
+  auto parts = llvm::SmallVector<llvm::StringRef>{};
+  llvm::SplitString(input, parts, "-");
+  return parts;
+}
+
+// Check if two strings are equal while normalizing case for the
+// right word which is assumed to be a single word in camel case.
+bool equalLowerCaseWithCamelCaseWord(llvm::StringRef l, llvm::StringRef r) {
+  size_t ls = l.size();
+  if (ls != r.size())
+    return false;
+  size_t j{0};
+  // Process the upper case characters.
+  for (; j < ls; j++) {
+    char rc = r[j];
+    char rc2l = llvm::toLower(rc);
+    if (rc == rc2l) {
+      // Past run of Uppers Case;
+      break;
     }
-    if (!ach && !bch) {
-      return true;
-    } else if (!ach || !bch || *ach != *bch) {
+    if (l[j] != rc2l)
+      return false;
+  }
+  // Process the lower case characters.
+  for (; j < ls; j++) {
+    if (l[j] != r[j]) {
       return false;
     }
-    ++a, ++b;
   }
+  return true;
 }
 
-template <typename ENUM, std::size_t N>
-std::optional<ENUM> ScanEnum(const char *name) {
-  if (name) {
-    for (std::size_t j{0}; j < N; ++j) {
-      auto feature{static_cast<ENUM>(j)};
-      if (WarningNameMatch(name, EnumToString(feature).data())) {
-        return feature;
+// Parse a CLI enum option return the enum index and whether it should be
+// enabled (true) or disabled (false).
+std::optional<std::pair<bool, int>> parseCLIEnumIndex(
+    llvm::StringRef input, std::function<std::optional<int>(Predicate)> find) {
+  auto parts = splitHyphenated(input);
+  bool negated = false;
+  if (parts.size() >= 1 && !parts[0].compare(llvm::StringRef("no", 2))) {
+    negated = true;
+    // Remove the "no" part
+    parts = llvm::SmallVector<llvm::StringRef>(parts.begin() + 1, parts.end());
+  }
+  size_t chars = 0;
+  for (auto p : parts) {
+    chars += p.size();
+  }
+  auto pred = [&](auto s) {
+    if (chars != s.size()) {
+      return false;
+    }
+    auto ccParts = splitCamelCase(s);
+    auto num_ccParts = ccParts.size();
+    if (parts.size() != num_ccParts) {
+      return false;
+    }
+    for (size_t i{0}; i < num_ccParts; i++) {
+      if (!equalLowerCaseWithCamelCaseWord(parts[i], ccParts[i])) {
+        return false;
       }
     }
-  }
-  return std::nullopt;
+    return true;
+  };
+  auto cast = [negated](int x) { return std::pair{!negated, x}; };
+  return fmap<int, std::pair<bool, int>>(find(pred), cast);
 }
 
-std::optional<LanguageFeature> FindLanguageFeature(const char *name) {
-  return ScanEnum<LanguageFeature, LanguageFeature_enumSize>(name);
+std::optional<std::pair<bool, LanguageFeature>> parseCLILanguageFeature(
+    llvm::StringRef input) {
+  return parseCLIEnum<LanguageFeature>(input, FindLanguageFeatureIndex);
 }
 
-std::optional<UsageWarning> FindUsageWarning(const char *name) {
-  return ScanEnum<UsageWarning, UsageWarning_enumSize>(name);
+std::optional<std::pair<bool, UsageWarning>> parseCLIUsageWarning(
+    llvm::StringRef input) {
+  return parseCLIEnum<UsageWarning>(input, FindUsageWarningIndex);
+}
+
+// Take a string from the CLI and apply it to the LanguageFeatureControl.
+// Return true if the option was applied recognized.
+bool LanguageFeatureControl::applyCLIOption(llvm::StringRef input) {
+  if (auto result = parseCLILanguageFeature(input)) {
+    EnableWarning(result->second, result->first);
+    return true;
+  } else if (auto result = parseCLIUsageWarning(input)) {
+    EnableWarning(result->second, result->first);
+    return true;
+  }
+  return false;
 }
 
 std::vector<const char *> LanguageFeatureControl::GetNames(
@@ -201,4 +269,32 @@ std::vector<const char *> LanguageFeatureControl::GetNames(
   }
 }
 
+template <typename ENUM, std::size_t N>
+void ForEachEnum(std::function<void(ENUM)> f) {
+  for (size_t j{0}; j < N; ++j) {
+    f(static_cast<ENUM>(j));
+  }
+}
+
+void LanguageFeatureControl::WarnOnAllNonstandard(bool yes) {
+  warnAllLanguage_ = yes;
+  disableAllWarnings_ = yes ? false : disableAllWarnings_;
+  // should be equivalent to: reset().flip() set ...
+  ForEachEnum<LanguageFeature, LanguageFeature_enumSize>(
+      [&](LanguageFeature f) { warnLanguage_.set(f, yes); });
+  if (yes) {
+    // These three features do not need to be warned about,
+    // but we do want their feature flags.
+    warnLanguage_.set(LanguageFeature::OpenMP, false);
+    warnLanguage_.set(LanguageFeature::OpenACC, false);
+    warnLanguage_.set(LanguageFeature::CUDA, false);
+  }
+}
+
+void LanguageFeatureControl::WarnOnAllUsage(bool yes) {
+  warnAllUsage_ = yes;
+  disableAllWarnings_ = yes ? false : disableAllWarnings_;
+  ForEachEnum<UsageWarning, UsageWarning_enumSize>(
+      [&](UsageWarning w) { warnUsage_.set(w, yes); });
+}
 } // namespace Fortran::common
diff --git a/flang/lib/Support/enum-class.cpp b/flang/lib/Support/enum-class.cpp
new file mode 100644
index 0000000000000..ed11318382b35
--- /dev/null
+++ b/flang/lib/Support/enum-class.cpp
@@ -0,0 +1,24 @@
+//===-- lib/Support/enum-class.cpp -------------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "flang/Common/enum-class.h"
+#include <optional>
+#include <functional>
+namespace Fortran::common {
+
+std::optional<int> FindEnumIndex(std::function<bool(const std::string_view)> pred, int size, const std::string_view *names) {
+    for (int i = 0; i < size; ++i) {
+        if (pred(names[i])) {
+            return i;
+        }
+    }
+    return std::nullopt;
+}
+
+
+} // namespace Fortran::common
\ No newline at end of file
diff --git a/flang/test/Driver/disable-diagnostic.f90 b/flang/test/Driver/disable-diagnostic.f90
new file mode 100644
index 0000000000000..8a58e63cfa3ac
--- /dev/null
+++ b/flang/test/Driver/disable-diagnostic.f90
@@ -0,0 +1,19 @@
+! RUN: %flang -Wknown-bad-implicit-interface %s -c 2>&1 | FileCheck %s --check-prefix=WARN
+! RUN: %flang -pedantic -Wno-known-bad-implicit-interface %s -c 2>&1 | FileCheck %s --allow-empty
+! RUN: not %flang -WKnownBadImplicitInterface %s -c 2>&1 | FileCheck %s --check-prefix=ERROR1
+! RUN: not %flang -WKnow...
[truncated]

@akuhlens akuhlens requested a review from eugeneepshteyn May 29, 2025 19:39
Copy link

github-actions bot commented May 29, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

}
bool applyCLIOption(llvm::StringRef input);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I thought this part of the code intentionally avoided explicit LLVM dependencies? Perhaps use std::string_view instead? FWIW, llvm::StringRef has functionality to convert to/from std::string_view.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't know that. Do you know the reason behind avoiding having dependencies on llvm?

@akuhlens akuhlens requested a review from klausler May 31, 2025 04:34
@akuhlens akuhlens requested a review from klausler June 4, 2025 22:02
// functions.
namespace featuresHelpers {

static std::vector<std::string_view> SplitCamelCase(std::string_view x) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is static, so it doesn't need to be in a namespace. The following function can probably also be static, and then you don't need the namespace.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following function is not static because there are a bunch of unit tests testing it.

@akuhlens akuhlens requested a review from klausler June 4, 2025 23:02
@akuhlens akuhlens requested a review from banach-space June 5, 2025 18:43
@akuhlens akuhlens requested a review from klausler June 5, 2025 21:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:driver flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants