-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-driver Author: Andre Kuhlenschmidt (akuhlens) ChangesThis change allows the flang CLI to accept 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:
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]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
} | ||
bool applyCLIOption(llvm::StringRef input); |
There was a problem hiding this comment.
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
.
There was a problem hiding this comment.
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?
// functions. | ||
namespace featuresHelpers { | ||
|
||
static std::vector<std::string_view> SplitCamelCase(std::string_view x) { |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
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.