[flang-commits] [flang] [flang][cli] Add diagnostic flags to the CLI (PR #142022)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Sat May 31 13:17:38 PDT 2025


================
@@ -107,44 +114,138 @@ static std::optional<char> GetWarningChar(char ch) {
   }
 }
 
-static bool WarningNameMatch(const char *a, const char *b) {
+// Check for case and punctuation insensitive string equality.
+// NB, b is probably not null terminated, so don't treat is like a C string.
+static bool InsensitiveWarningNameMatch(
+    std::string_view a, std::string_view b) {
+  size_t j{0}, aSize{a.size()}, k{0}, bSize{b.size()};
   while (true) {
-    auto ach{GetWarningChar(*a)};
-    while (!ach && *a) {
-      ach = GetWarningChar(*++a);
+    optional<char> ach{nullopt};
+    while (!ach && j < aSize) {
+      ach = GetWarningChar(a[j++]);
     }
-    auto bch{GetWarningChar(*b)};
-    while (!bch && *b) {
-      bch = GetWarningChar(*++b);
+    optional<char> bch{};
+    while (!bch && k < bSize) {
+      bch = GetWarningChar(b[k++]);
     }
     if (!ach && !bch) {
       return true;
     } else if (!ach || !bch || *ach != *bch) {
       return false;
     }
-    ++a, ++b;
+    ach = bch = nullopt;
   }
 }
 
-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;
+// Check if lower case hyphenated words are equal to camel case words.
+// Because of out use case we know that 'r' the camel case string is
+// well formed in the sense that it is a sequence [a-zA-Z]+[a-zA-Z0-9]*.
+// This is checked in the enum-class.h file.
+static bool SensitiveWarningNameMatch(llvm::StringRef l, llvm::StringRef r) {
+  size_t ls{l.size()}, rs{r.size()};
+  if (ls < rs) {
+    return false;
+  }
+  bool atStartOfWord{true};
+  size_t wordCount{0}, j{0}; // j is the number of word characters checked in r.
+  for (; j < rs; j++) {
+    if (wordCount + j >= ls) {
+      // `l` was shorter once the hiphens were removed.
+      // If r is null terminated, then we are good.
+      return r[j] == '\0';
+    }
+    if (atStartOfWord) {
+      if (llvm::isUpper(r[j])) {
+        // Upper Case Run
+        if (l[wordCount + j] != llvm::toLower(r[j])) {
+          return false;
+        }
+      } else {
+        atStartOfWord = false;
+        if (l[wordCount + j] != r[j]) {
+          return false;
+        }
       }
+    } else {
+      if (llvm::isUpper(r[j])) {
+        atStartOfWord = true;
+        if (l[wordCount + j] != '-') {
+          return false;
+        }
+        ++wordCount;
+        if (l[wordCount + j] != llvm::toLower(r[j])) {
+          return false;
+        }
+      } else if (l[wordCount + j] != r[j]) {
+        return false;
+      }
+    }
+  }
+  // If there are more characters in l after processing all the characters in r.
+  // then fail unless the string is null terminated.
+  if (ls > wordCount + j) {
+    return l[wordCount + j] == '\0';
+  }
+  return true;
+}
+
+// Parse a CLI enum option return the enum index and whether it should be
+// enabled (true) or disabled (false).
+template <typename T>
+optional<std::pair<bool, T>> ParseCLIEnum(llvm::StringRef input,
+    EnumClass::FindIndexType findIndex, bool insensitive) {
+  bool negated{false};
+  EnumClass::Predicate predicate;
+  if (insensitive) {
+    if (input.starts_with_insensitive("no")) {
+      negated = true;
+      input = input.drop_front(2);
+    }
+    predicate = [input](std::string_view r) {
+      return InsensitiveWarningNameMatch(input, r);
+    };
+  } else {
+    if (input.starts_with("no-")) {
+      negated = true;
+      input = input.drop_front(3);
     }
+    predicate = [input](std::string_view r) {
+      return SensitiveWarningNameMatch(input, r);
+    };
   }
-  return std::nullopt;
+  optional<T> x = EnumClass::Find<T>(predicate, findIndex);
+  return MapOption<T, std::pair<bool, T>>(
+      x, [negated](T x) { return std::pair{!negated, x}; });
 }
 
-std::optional<LanguageFeature> FindLanguageFeature(const char *name) {
-  return ScanEnum<LanguageFeature, LanguageFeature_enumSize>(name);
+optional<std::pair<bool, UsageWarning>> parseCLIUsageWarning(
+    llvm::StringRef input, bool insensitive) {
+  return ParseCLIEnum<UsageWarning>(input, FindUsageWarningIndex, insensitive);
 }
 
-std::optional<UsageWarning> FindUsageWarning(const char *name) {
-  return ScanEnum<UsageWarning, UsageWarning_enumSize>(name);
+optional<std::pair<bool, LanguageFeature>> parseCLILanguageFeature(
+    llvm::StringRef input, bool insensitive) {
+  return ParseCLIEnum<LanguageFeature>(
+      input, FindLanguageFeatureIndex, insensitive);
+}
+
+} // namespace FortranFeaturesHelpers
+
+// Take a string from the CLI and apply it to the LanguageFeatureControl.
+// Return true if the option was applied recognized.
----------------
klausler wrote:

"if the option was recognized"

https://github.com/llvm/llvm-project/pull/142022


More information about the flang-commits mailing list