Skip to content

Commit bf60aa1

Browse files
authored
[flang][cli] Add diagnostic flags to the CLI (#142022)
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.
1 parent c34351c commit bf60aa1

File tree

11 files changed

+816
-101
lines changed

11 files changed

+816
-101
lines changed

flang/include/flang/Common/enum-class.h

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
#define FORTRAN_COMMON_ENUM_CLASS_H_
1919

2020
#include <array>
21-
#include <string>
22-
21+
#include <functional>
22+
#include <string_view>
2323
namespace Fortran::common {
2424

2525
constexpr std::size_t CountEnumNames(const char *p) {
@@ -62,11 +62,19 @@ constexpr std::array<std::string_view, ITEMS> EnumNames(const char *p) {
6262
enum class NAME { __VA_ARGS__ }; \
6363
[[maybe_unused]] static constexpr std::size_t NAME##_enumSize{ \
6464
::Fortran::common::CountEnumNames(#__VA_ARGS__)}; \
65+
[[maybe_unused]] static constexpr std::array<std::string_view, \
66+
NAME##_enumSize> NAME##_names{ \
67+
::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
68+
[[maybe_unused]] static inline std::size_t EnumToInt(NAME e) { \
69+
return static_cast<std::size_t>(e); \
70+
} \
6571
[[maybe_unused]] static inline std::string_view EnumToString(NAME e) { \
66-
static const constexpr auto names{ \
67-
::Fortran::common::EnumNames<NAME##_enumSize>(#__VA_ARGS__)}; \
68-
return names[static_cast<std::size_t>(e)]; \
72+
return NAME##_names[static_cast<std::size_t>(e)]; \
73+
} \
74+
[[maybe_unused]] inline void ForEach##NAME(std::function<void(NAME)> f) { \
75+
for (std::size_t i{0}; i < NAME##_enumSize; ++i) { \
76+
f(static_cast<NAME>(i)); \
77+
} \
6978
}
70-
7179
} // namespace Fortran::common
7280
#endif // FORTRAN_COMMON_ENUM_CLASS_H_

flang/include/flang/Common/optional.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828

2929
#include "api-attrs.h"
3030
#include <optional>
31-
#include <type_traits>
3231

3332
#if !defined(STD_OPTIONAL_UNSUPPORTED) && \
3433
(defined(__CUDACC__) || defined(__CUDA__)) && defined(__CUDA_ARCH__)

flang/include/flang/Support/Fortran-features.h

Lines changed: 45 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@
1111

1212
#include "Fortran.h"
1313
#include "flang/Common/enum-set.h"
14-
#include "flang/Common/idioms.h"
15-
#include <optional>
14+
#include <string_view>
1615
#include <vector>
1716

1817
namespace Fortran::common {
@@ -83,9 +82,6 @@ ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
8382
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;
8483
using UsageWarnings = EnumSet<UsageWarning, UsageWarning_enumSize>;
8584

86-
std::optional<LanguageFeature> FindLanguageFeature(const char *);
87-
std::optional<UsageWarning> FindUsageWarning(const char *);
88-
8985
class LanguageFeatureControl {
9086
public:
9187
LanguageFeatureControl();
@@ -98,8 +94,10 @@ class LanguageFeatureControl {
9894
void EnableWarning(UsageWarning w, bool yes = true) {
9995
warnUsage_.set(w, yes);
10096
}
101-
void WarnOnAllNonstandard(bool yes = true) { warnAllLanguage_ = yes; }
102-
void WarnOnAllUsage(bool yes = true) { warnAllUsage_ = yes; }
97+
void WarnOnAllNonstandard(bool yes = true);
98+
bool IsWarnOnAllNonstandard() const { return warnAllLanguage_; }
99+
void WarnOnAllUsage(bool yes = true);
100+
bool IsWarnOnAllUsage() const { return warnAllUsage_; }
103101
void DisableAllNonstandardWarnings() {
104102
warnAllLanguage_ = false;
105103
warnLanguage_.clear();
@@ -108,26 +106,59 @@ class LanguageFeatureControl {
108106
warnAllUsage_ = false;
109107
warnUsage_.clear();
110108
}
111-
109+
void DisableAllWarnings() {
110+
disableAllWarnings_ = true;
111+
DisableAllNonstandardWarnings();
112+
DisableAllUsageWarnings();
113+
}
114+
bool AreWarningsDisabled() const { return disableAllWarnings_; }
112115
bool IsEnabled(LanguageFeature f) const { return !disable_.test(f); }
113-
bool ShouldWarn(LanguageFeature f) const {
114-
return (warnAllLanguage_ && f != LanguageFeature::OpenMP &&
115-
f != LanguageFeature::OpenACC && f != LanguageFeature::CUDA) ||
116-
warnLanguage_.test(f);
116+
bool ShouldWarn(LanguageFeature f) const { return warnLanguage_.test(f); }
117+
bool ShouldWarn(UsageWarning w) const { return warnUsage_.test(w); }
118+
// Cli options
119+
// Take a string from the Cli and apply it to the LanguageFeatureControl.
120+
// Return true if the option was recognized (and hence applied).
121+
bool ApplyCliOption(std::string input);
122+
// The add and replace functions are not currently used but are provided
123+
// to allow a flexible many-to-one mapping from Cli spellings to enum values.
124+
// Taking a string by value because the functions own this string after the
125+
// call.
126+
void AddAlternativeCliSpelling(LanguageFeature f, std::string input) {
127+
cliOptions_.insert({input, {f}});
117128
}
118-
bool ShouldWarn(UsageWarning w) const {
119-
return warnAllUsage_ || warnUsage_.test(w);
129+
void AddAlternativeCliSpelling(UsageWarning w, std::string input) {
130+
cliOptions_.insert({input, {w}});
120131
}
132+
void ReplaceCliCanonicalSpelling(LanguageFeature f, std::string input);
133+
void ReplaceCliCanonicalSpelling(UsageWarning w, std::string input);
134+
std::string_view getDefaultCliSpelling(LanguageFeature f) const {
135+
return languageFeatureCliCanonicalSpelling_[EnumToInt(f)];
136+
};
137+
std::string_view getDefaultCliSpelling(UsageWarning w) const {
138+
return usageWarningCliCanonicalSpelling_[EnumToInt(w)];
139+
};
121140
// Return all spellings of operators names, depending on features enabled
122141
std::vector<const char *> GetNames(LogicalOperator) const;
123142
std::vector<const char *> GetNames(RelationalOperator) const;
124143

125144
private:
145+
// Map from Cli syntax of language features and usage warnings to their enum
146+
// values.
147+
std::unordered_map<std::string, std::variant<LanguageFeature, UsageWarning>>
148+
cliOptions_;
149+
// These two arrays map the enum values to their cannonical Cli spellings.
150+
// Since each of the CanonicalSpelling is a string in the domain of the map
151+
// above we just use a view of the string instead of another copy.
152+
std::array<std::string_view, LanguageFeature_enumSize>
153+
languageFeatureCliCanonicalSpelling_;
154+
std::array<std::string_view, UsageWarning_enumSize>
155+
usageWarningCliCanonicalSpelling_;
126156
LanguageFeatures disable_;
127157
LanguageFeatures warnLanguage_;
128158
bool warnAllLanguage_{false};
129159
UsageWarnings warnUsage_;
130160
bool warnAllUsage_{false};
161+
bool disableAllWarnings_{false};
131162
};
132163
} // namespace Fortran::common
133164
#endif // FORTRAN_SUPPORT_FORTRAN_FEATURES_H_

flang/lib/Frontend/CompilerInvocation.cpp

Lines changed: 30 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,10 @@
2020
#include "flang/Support/Version.h"
2121
#include "flang/Tools/TargetSetup.h"
2222
#include "flang/Version.inc"
23-
#include "clang/Basic/AllDiagnostics.h"
2423
#include "clang/Basic/DiagnosticDriver.h"
2524
#include "clang/Basic/DiagnosticOptions.h"
2625
#include "clang/Driver/CommonArgs.h"
2726
#include "clang/Driver/Driver.h"
28-
#include "clang/Driver/DriverDiagnostic.h"
2927
#include "clang/Driver/OptionUtils.h"
3028
#include "clang/Driver/Options.h"
3129
#include "llvm/ADT/StringRef.h"
@@ -36,7 +34,6 @@
3634
#include "llvm/Option/OptTable.h"
3735
#include "llvm/Support/CodeGen.h"
3836
#include "llvm/Support/FileSystem.h"
39-
#include "llvm/Support/FileUtilities.h"
4037
#include "llvm/Support/Path.h"
4138
#include "llvm/Support/Process.h"
4239
#include "llvm/Support/raw_ostream.h"
@@ -975,10 +972,23 @@ static bool parseSemaArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
975972

976973
/// Parses all diagnostics related arguments and populates the variables
977974
/// options accordingly. Returns false if new errors are generated.
975+
/// FC1 driver entry point for parsing diagnostic arguments.
978976
static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
979977
clang::DiagnosticsEngine &diags) {
980978
unsigned numErrorsBefore = diags.getNumErrors();
981979

980+
auto &features{res.getFrontendOpts().features};
981+
// The order of these flags (-pedantic -W<feature> -w) is important and is
982+
// chosen to match clang's behavior.
983+
984+
// -pedantic
985+
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
986+
features.WarnOnAllNonstandard();
987+
features.WarnOnAllUsage();
988+
res.setEnableConformanceChecks();
989+
res.setEnableUsageChecks();
990+
}
991+
982992
// -Werror option
983993
// TODO: Currently throws a Diagnostic for anything other than -W<error>,
984994
// this has to change when other -W<opt>'s are supported.
@@ -988,22 +998,26 @@ static bool parseDiagArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
988998
for (const auto &wArg : wArgs) {
989999
if (wArg == "error") {
9901000
res.setWarnAsErr(true);
991-
} else {
992-
const unsigned diagID =
993-
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
994-
"Only `-Werror` is supported currently.");
995-
diags.Report(diagID);
1001+
// -W(no-)<feature>
1002+
} else if (!features.ApplyCliOption(wArg)) {
1003+
const unsigned diagID = diags.getCustomDiagID(
1004+
clang::DiagnosticsEngine::Error, "Unknown diagnostic option: -W%0");
1005+
diags.Report(diagID) << wArg;
9961006
}
9971007
}
9981008
}
9991009

1000-
// Default to off for `flang -fc1`.
1001-
res.getFrontendOpts().showColors =
1002-
parseShowColorsArgs(args, /*defaultDiagColor=*/false);
1003-
1004-
// Honor color diagnostics.
1005-
res.getDiagnosticOpts().ShowColors = res.getFrontendOpts().showColors;
1010+
// -w
1011+
if (args.hasArg(clang::driver::options::OPT_w)) {
1012+
features.DisableAllWarnings();
1013+
res.setDisableWarnings();
1014+
}
10061015

1016+
// Default to off for `flang -fc1`.
1017+
bool showColors{parseShowColorsArgs(args, false)};
1018+
diags.getDiagnosticOptions().ShowColors = showColors;
1019+
res.getDiagnosticOpts().ShowColors = showColors;
1020+
res.getFrontendOpts().showColors = showColors;
10071021
return diags.getNumErrors() == numErrorsBefore;
10081022
}
10091023

@@ -1078,16 +1092,6 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
10781092
Fortran::common::LanguageFeature::OpenACC);
10791093
}
10801094

1081-
// -pedantic
1082-
if (args.hasArg(clang::driver::options::OPT_pedantic)) {
1083-
res.setEnableConformanceChecks();
1084-
res.setEnableUsageChecks();
1085-
}
1086-
1087-
// -w
1088-
if (args.hasArg(clang::driver::options::OPT_w))
1089-
res.setDisableWarnings();
1090-
10911095
// -std=f2018
10921096
// TODO: Set proper options when more fortran standards
10931097
// are supported.
@@ -1096,6 +1100,7 @@ static bool parseDialectArgs(CompilerInvocation &res, llvm::opt::ArgList &args,
10961100
// We only allow f2018 as the given standard
10971101
if (standard == "f2018") {
10981102
res.setEnableConformanceChecks();
1103+
res.getFrontendOpts().features.WarnOnAllNonstandard();
10991104
} else {
11001105
const unsigned diagID =
11011106
diags.getCustomDiagID(clang::DiagnosticsEngine::Error,
@@ -1702,16 +1707,7 @@ void CompilerInvocation::setFortranOpts() {
17021707
if (frontendOptions.needProvenanceRangeToCharBlockMappings)
17031708
fortranOptions.needProvenanceRangeToCharBlockMappings = true;
17041709

1705-
if (getEnableConformanceChecks())
1706-
fortranOptions.features.WarnOnAllNonstandard();
1707-
1708-
if (getEnableUsageChecks())
1709-
fortranOptions.features.WarnOnAllUsage();
1710-
1711-
if (getDisableWarnings()) {
1712-
fortranOptions.features.DisableAllNonstandardWarnings();
1713-
fortranOptions.features.DisableAllUsageWarnings();
1714-
}
1710+
fortranOptions.features = frontendOptions.features;
17151711
}
17161712

17171713
std::unique_ptr<Fortran::semantics::SemanticsContext>

0 commit comments

Comments
 (0)