-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang][CLI] Have the CLI hint the flag to disable a warning #144767
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
d8d3dd0
to
0fbbbb9
Compare
This comment was marked as outdated.
This comment was marked as outdated.
@llvm/pr-subscribers-flang-parser @llvm/pr-subscribers-flang-driver Author: Andre Kuhlenschmidt (akuhlens) ChangesAdds a hint to the warning message to disable a warning and updates the tests to expect this. Also fixes a bug in the storage of canonical spelling of error flags so that they are not used after free. Patch is 247.40 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144767.diff 161 Files Affected:
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index e19b16c23b82b..7371a46ad36ce 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -292,7 +292,8 @@ class Message : public common::ReferenceCounted<Message> {
std::optional<ProvenanceRange> GetProvenanceRange(
const AllCookedSources &) const;
void Emit(llvm::raw_ostream &, const AllCookedSources &,
- bool echoSourceLine = true) const;
+ bool echoSourceLine = true,
+ const common::LanguageFeatureControl *hintFlags = nullptr) const;
// If this Message or any of its attachments locates itself via a CharBlock,
// replace its location with the corresponding ProvenanceRange.
@@ -352,7 +353,8 @@ class Messages {
void Copy(const Messages &);
void ResolveProvenances(const AllCookedSources &);
void Emit(llvm::raw_ostream &, const AllCookedSources &,
- bool echoSourceLines = true) const;
+ bool echoSourceLines = true,
+ const common::LanguageFeatureControl *hintFlags = nullptr) const;
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
bool AnyFatalError() const;
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 39356daa3606a..cb7e1d81206c8 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -161,9 +161,9 @@ class LanguageFeatureControl {
// These two arrays map the enum values to their cannonical Cli spellings.
// Since each of the CanonicalSpelling is a string in the domain of the map
// above we just use a view of the string instead of another copy.
- std::array<std::string_view, LanguageFeature_enumSize>
+ std::array<std::string, LanguageFeature_enumSize>
languageFeatureCliCanonicalSpelling_;
- std::array<std::string_view, UsageWarning_enumSize>
+ std::array<std::string, UsageWarning_enumSize>
usageWarningCliCanonicalSpelling_;
LanguageFeatures disable_;
LanguageFeatures warnLanguage_;
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index d178fd6a9395d..5d95d6de337b1 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -171,7 +171,10 @@ bool FrontendAction::runParse(bool emitMessages) {
if (emitMessages) {
// Report any non-fatal diagnostics from getParsing now rather than
// combining them with messages from semantics.
- ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+ bool echoSourceLine{true};
+ const auto &features{ci.getInvocation().getFortranOpts().features};
+ ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources(),
+ echoSourceLine, &features);
}
return true;
}
@@ -223,6 +226,8 @@ bool FrontendAction::generateRtTypeTables() {
template <unsigned N>
bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
+ bool echoSourceLine{true};
+ const auto &features{instance->getInvocation().getFortranOpts().features};
if (!instance->getParsing().messages().empty() &&
(instance->getInvocation().getWarnAsErr() ||
instance->getParsing().messages().AnyFatalError())) {
@@ -230,7 +235,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(llvm::errs(),
- instance->getAllCookedSources());
+ instance->getAllCookedSources(),
+ echoSourceLine, &features);
return true;
}
if (instance->getParsing().parseTree().has_value() &&
@@ -240,7 +246,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(llvm::errs(),
- instance->getAllCookedSources());
+ instance->getAllCookedSources(),
+ echoSourceLine, &features);
instance->getParsing().EmitMessage(
llvm::errs(), instance->getParsing().finalRestingPlace(),
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 799998c54b531..721c8ea339568 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -273,14 +273,37 @@ static llvm::raw_ostream::Colors PrefixColor(Severity severity) {
return llvm::raw_ostream::SAVEDCOLOR;
}
+static std::string HintLanguageControlFlag(
+ const common::LanguageFeatureControl *hintFlagPtr,
+ std::optional<common::LanguageFeature> feature,
+ std::optional<common::UsageWarning> warning) {
+ if (hintFlagPtr) {
+ std::string_view flag{""};
+ if (warning) {
+ flag = hintFlagPtr->getDefaultCliSpelling(*warning);
+ } else if (feature) {
+ flag = hintFlagPtr->getDefaultCliSpelling(*feature);
+ }
+ if (!flag.empty()) {
+ std::string s{" [-Wno-" + std::string(flag) + "]"};
+ return s;
+ }
+ }
+ return "";
+}
+
static constexpr int MAX_CONTEXTS_EMITTED{2};
static constexpr bool OMIT_SHARED_CONTEXTS{true};
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLine) const {
+ bool echoSourceLine,
+ const common::LanguageFeatureControl *hintFlagPtr) const {
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
const AllSources &sources{allCooked.allSources()};
- sources.EmitMessage(o, provenanceRange, ToString(), Prefix(severity()),
+ const std::string text{ToString()};
+ const std::string hint{
+ HintLanguageControlFlag(hintFlagPtr, languageFeature_, usageWarning_)};
+ sources.EmitMessage(o, provenanceRange, text + hint, Prefix(severity()),
PrefixColor(severity()), echoSourceLine);
// Refers to whether the attachment in the loop below is a context, but can't
// be declared inside the loop because the previous iteration's
@@ -430,7 +453,8 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) {
}
void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLines) const {
+ bool echoSourceLines,
+ const common::LanguageFeatureControl *hintFlagPtr) const {
std::vector<const Message *> sorted;
for (const auto &msg : messages_) {
sorted.push_back(&msg);
@@ -443,7 +467,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
// Don't emit two identical messages for the same location
continue;
}
- msg->Emit(o, allCooked, echoSourceLines);
+ msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
lastMsg = msg;
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index e07054f8ec564..813f6facee1ac 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -655,8 +655,11 @@ bool Semantics::Perform() {
void Semantics::EmitMessages(llvm::raw_ostream &os) {
// Resolve the CharBlock locations of the Messages to ProvenanceRanges
// so messages from parsing and semantics are intermixed in source order.
+ bool echoSourceLine{true};
+ const auto &features{context_.languageFeatures()};
context_.messages().ResolveProvenances(context_.allCookedSources());
- context_.messages().Emit(os, context_.allCookedSources());
+ context_.messages().Emit(
+ os, context_.allCookedSources(), echoSourceLine, &features);
}
void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 17b5f8368916d..07ca2a5f3cd91 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -57,17 +57,17 @@ LanguageFeatureControl::LanguageFeatureControl() {
ForEachLanguageFeature([&](auto feature) {
std::string_view name{Fortran::common::EnumToString(feature)};
std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};
- cliOptions_.insert({cliOption, {feature}});
+ cliOptions_.insert({std::string{cliOption}, {feature}});
languageFeatureCliCanonicalSpelling_[EnumToInt(feature)] =
- std::string_view{cliOption};
+ std::move(cliOption);
});
ForEachUsageWarning([&](auto warning) {
std::string_view name{Fortran::common::EnumToString(warning)};
std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};
- cliOptions_.insert({cliOption, {warning}});
+ cliOptions_.insert({std::string{cliOption}, {warning}});
usageWarningCliCanonicalSpelling_[EnumToInt(warning)] =
- std::string_view{cliOption};
+ std::move(cliOption);
});
// These features must be explicitly enabled by command line options.
@@ -172,20 +172,27 @@ bool LanguageFeatureControl::EnableWarning(std::string_view input) {
return false;
}
+template <typename T, size_t ENUM_SIZE>
+static void replaceCliCanonicalSpelling(
+ std::unordered_map<std::string, std::variant<LanguageFeature, UsageWarning>>
+ &cliOptions,
+ std::array<std::string, ENUM_SIZE> &canonicalSpelling, T t,
+ std::string &input) {
+ cliOptions.erase({canonicalSpelling[EnumToInt(t)]});
+ cliOptions.insert({std::string{input}, {t}});
+ canonicalSpelling[EnumToInt(t)] = std::move(input);
+}
+
void LanguageFeatureControl::ReplaceCliCanonicalSpelling(
LanguageFeature f, std::string input) {
- std::string_view &old{languageFeatureCliCanonicalSpelling_[EnumToInt(f)]};
- cliOptions_.erase(std::string{old});
- languageFeatureCliCanonicalSpelling_[EnumToInt(f)] = input;
- cliOptions_.insert({input, {f}});
+ replaceCliCanonicalSpelling(
+ cliOptions_, languageFeatureCliCanonicalSpelling_, f, input);
}
void LanguageFeatureControl::ReplaceCliCanonicalSpelling(
UsageWarning w, std::string input) {
- std::string_view &old{usageWarningCliCanonicalSpelling_[EnumToInt(w)]};
- cliOptions_.erase(std::string{old});
- usageWarningCliCanonicalSpelling_[EnumToInt(w)] = input;
- cliOptions_.insert({input, {w}});
+ replaceCliCanonicalSpelling(
+ cliOptions_, usageWarningCliCanonicalSpelling_, w, input);
}
std::vector<const char *> LanguageFeatureControl::GetNames(
diff --git a/flang/test/Evaluate/fold-dim.f90 b/flang/test/Evaluate/fold-dim.f90
index 40163c3f5a5ee..30dece869387a 100644
--- a/flang/test/Evaluate/fold-dim.f90
+++ b/flang/test/Evaluate/fold-dim.f90
@@ -11,7 +11,7 @@ module m
logical, parameter :: test_a3 = dim(2., 1.) == 1.
logical, parameter :: test_a4 = dim(2., -1.) == 3.
logical, parameter :: test_a5 = dim(-1., 2.) == 0.
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real, parameter :: nan = 0./0.
logical, parameter :: test_a6 = dim(nan, 1.) /= dim(nan, 1.)
end module
diff --git a/flang/test/Evaluate/fold-nearest.f90 b/flang/test/Evaluate/fold-nearest.f90
index 48b9ef37840e3..9502740a7dc0f 100644
--- a/flang/test/Evaluate/fold-nearest.f90
+++ b/flang/test/Evaluate/fold-nearest.f90
@@ -19,16 +19,16 @@ module m1
real, parameter :: negZero = sign(0., -1.)
logical, parameter :: test_12 = nearest(negZero, 1.) == minSubnormal
logical, parameter :: test_13 = nearest(negZero, -1.) == -minSubnormal
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
logical, parameter :: test_14 = nearest(0., negZero) == -minSubnormal
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
logical, parameter :: test_15 = nearest(negZero, 0.) == minSubnormal
logical, parameter :: test_16 = nearest(tiny(1.),-1.) == 1.1754942E-38
logical, parameter :: test_17 = nearest(tiny(1.),1.) == 1.1754945E-38
contains
subroutine subr(a)
real, intent(in) :: a
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
print *, nearest(a, 0.)
end
end module
@@ -42,7 +42,7 @@ module m2
logical, parameter :: test_2 = ieee_next_after(minSubnormal, -1.) == 0
logical, parameter :: test_3 = ieee_next_after(1., 2.) == 1.0000001
logical, parameter :: test_4 = ieee_next_after(1.0000001, -1.) == 1
- !WARN: warning: division by zero
+ !WARN: warning: division by zero [-Wno-folding-exception]
real, parameter :: inf = 1. / 0.
logical, parameter :: test_5 = ieee_next_after(inf, inf) == inf
logical, parameter :: test_6 = ieee_next_after(inf, -inf) == h
@@ -54,12 +54,12 @@ module m2
logical, parameter :: test_11 = ieee_next_after(1.9999999999999999999_10, 3.) == 2._10
#endif
logical, parameter :: test_12 = ieee_next_after(1., 1.) == 1.
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real, parameter :: nan = 0. / 0.
- !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered
+ !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered [-Wno-folding-value-checks]
real, parameter :: x13 = ieee_next_after(nan, nan)
logical, parameter :: test_13 = .not. (x13 == x13)
- !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered
+ !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered [-Wno-folding-value-checks]
real, parameter :: x14 = ieee_next_after(nan, 0.)
logical, parameter :: test_14 = .not. (x14 == x14)
end module
@@ -72,7 +72,7 @@ module m3
logical, parameter :: test_2 = ieee_next_down(0.d0) == -minSubnormal
logical, parameter :: test_3 = ieee_next_up(1.d0) == 1.0000000000000002d0
logical, parameter :: test_4 = ieee_next_down(1.0000000000000002d0) == 1.d0
- !WARN: warning: division by zero
+ !WARN: warning: division by zero [-Wno-folding-exception]
real(kind(0.d0)), parameter :: inf = 1.d0 / 0.d0
logical, parameter :: test_5 = ieee_next_up(huge(0.d0)) == inf
logical, parameter :: test_6 = ieee_next_down(-huge(0.d0)) == -inf
@@ -82,12 +82,12 @@ module m3
logical, parameter :: test_10 = ieee_next_down(-inf) == -inf
logical, parameter :: test_11 = ieee_next_up(1.9999999999999997d0) == 2.d0
logical, parameter :: test_12 = ieee_next_down(2.d0) == 1.9999999999999997d0
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real(kind(0.d0)), parameter :: nan = 0.d0 / 0.d0
- !WARN: warning: IEEE_NEXT_UP intrinsic folding: argument is NaN
+ !WARN: warning: IEEE_NEXT_UP intrinsic folding: argument is NaN [-Wno-folding-exception]
real(kind(0.d0)), parameter :: x13 = ieee_next_up(nan)
logical, parameter :: test_13 = .not. (x13 == x13)
- !WARN: warning: IEEE_NEXT_DOWN intrinsic folding: argument is NaN
+ !WARN: warning: IEEE_NEXT_DOWN intrinsic folding: argument is NaN [-Wno-folding-exception]
real(kind(0.d0)), parameter :: x14 = ieee_next_down(nan)
logical, parameter :: test_14 = .not. (x14 == x14)
end module
diff --git a/flang/test/Evaluate/fold-unsigned.f90 b/flang/test/Evaluate/fold-unsigned.f90
index 719bdcc1a40b9..27f2fe4404483 100644
--- a/flang/test/Evaluate/fold-unsigned.f90
+++ b/flang/test/Evaluate/fold-unsigned.f90
@@ -24,7 +24,7 @@ module m
logical, parameter :: test_cus0 = int(0u,1) == 0
logical, parameter :: test_cus0_k = kind(int(0u,1)) == 1
- !WARN: warning: conversion of 255_U1 to INTEGER(1) overflowed; result is -1
+ !WARN: warning: conversion of 255_U1 to INTEGER(1) overflowed; result is -1 [-Wno-folding-exception]
logical, parameter :: test_cus255 = int(255u_1,1) == -1
logical, parameter :: test_cur255 = real(255u) == 255.
diff --git a/flang/test/Evaluate/folding03.f90 b/flang/test/Evaluate/folding03.f90
index 827bde86757c8..6441cde946a4a 100644
--- a/flang/test/Evaluate/folding03.f90
+++ b/flang/test/Evaluate/folding03.f90
@@ -15,32 +15,32 @@ module integer_tests
! Integer division by zero are not tested here because they are handled as fatal
! errors in constants.
- !WARN: warning: INTEGER(4) negation overflowed
+ !WARN: warning: INTEGER(4) negation overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_unary_minus1 = (-i4_nmax).EQ.i4_nmax
logical, parameter :: test_no_overflow_unary_minus1 = (-i4_pmax).EQ.(i4_nmax+1_4)
logical, parameter :: test_no_overflow_unary_plus1 = (+i4_pmax).EQ.i4_pmax
logical, parameter :: test_no_overflow_unary_plus2 = (+i4_nmax).EQ.i4_nmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add1 = (i4_pmax+1_4).EQ.i4_nmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add2 = (i4_nmax + (-1_4)).EQ.i4_pmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add3 = (i4_pmax + i4_pmax).EQ.(-2_4)
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add4 = (i4_nmax + i4_nmax).EQ.(0_4)
logical, parameter :: test_no_overflow_add1 = (i4_pmax + 0_4).EQ.i4_pmax
logical, parameter :: test_no_overflow_add2 = (i4_nmax + (-0_4)).EQ.i4_nmax
logical, parameter :: test_no_overflow_add3 = (i4_pmax + i4_nmax).EQ.(-1_4)
logical, parameter :: test_no_overflow_add4 = (i4_nmax + i4_pmax).EQ.(-1_4)
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub1 = (i4_nmax - 1_4).EQ.i4_pmax
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub2 = (i4_pmax - (-1_4)).EQ.i4_nmax
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub3 = (i4_nmax - i4_pmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub4 = (i4_pmax - i4_nmax).EQ.(-1_4)
logical, parameter :: test_no_overflow_sub1 = (i4_nmax - 0_4).EQ.i4_nmax
logical, parameter :: test_no_overflow_sub2 = (i4_pmax - (-0_4)).EQ.i4_pmax
@@ -48,23 +48,23 @@ module integer_tests
logical, parameter :: test_no_overflow_sub4 = (i4_pmax - i4_pmax).EQ.0_4
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult1 = (i4_pmax*2_4).EQ.(-2_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult2 = (i4_nmax*2_4).EQ.(0_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult3 = (i4_nmax*i4_nmax).EQ.(0_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult4 = (i4_pmax*i4_pmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) division overflowed
+ !WARN: warning: INTEGER(4) division overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_div1 = (i4_nmax/(-1_4)).EQ.(i4_nmax)
logical, parameter :: test_no_overflow_div1 = (i4_nmax/(-2_4)).EQ.(1_4 + i4_pmax/2_4)
logical, parameter :: test_no_overflow_div2 = (i4_nmax/i4_nmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) power overflowed
+ !WARN: warning: INTEGER(4) power overflowed [...
[truncated]
|
@llvm/pr-subscribers-flang-openmp Author: Andre Kuhlenschmidt (akuhlens) ChangesAdds a hint to the warning message to disable a warning and updates the tests to expect this. Also fixes a bug in the storage of canonical spelling of error flags so that they are not used after free. Patch is 247.40 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/144767.diff 161 Files Affected:
diff --git a/flang/include/flang/Parser/message.h b/flang/include/flang/Parser/message.h
index e19b16c23b82b..7371a46ad36ce 100644
--- a/flang/include/flang/Parser/message.h
+++ b/flang/include/flang/Parser/message.h
@@ -292,7 +292,8 @@ class Message : public common::ReferenceCounted<Message> {
std::optional<ProvenanceRange> GetProvenanceRange(
const AllCookedSources &) const;
void Emit(llvm::raw_ostream &, const AllCookedSources &,
- bool echoSourceLine = true) const;
+ bool echoSourceLine = true,
+ const common::LanguageFeatureControl *hintFlags = nullptr) const;
// If this Message or any of its attachments locates itself via a CharBlock,
// replace its location with the corresponding ProvenanceRange.
@@ -352,7 +353,8 @@ class Messages {
void Copy(const Messages &);
void ResolveProvenances(const AllCookedSources &);
void Emit(llvm::raw_ostream &, const AllCookedSources &,
- bool echoSourceLines = true) const;
+ bool echoSourceLines = true,
+ const common::LanguageFeatureControl *hintFlags = nullptr) const;
void AttachTo(Message &, std::optional<Severity> = std::nullopt);
bool AnyFatalError() const;
diff --git a/flang/include/flang/Support/Fortran-features.h b/flang/include/flang/Support/Fortran-features.h
index 39356daa3606a..cb7e1d81206c8 100644
--- a/flang/include/flang/Support/Fortran-features.h
+++ b/flang/include/flang/Support/Fortran-features.h
@@ -161,9 +161,9 @@ class LanguageFeatureControl {
// These two arrays map the enum values to their cannonical Cli spellings.
// Since each of the CanonicalSpelling is a string in the domain of the map
// above we just use a view of the string instead of another copy.
- std::array<std::string_view, LanguageFeature_enumSize>
+ std::array<std::string, LanguageFeature_enumSize>
languageFeatureCliCanonicalSpelling_;
- std::array<std::string_view, UsageWarning_enumSize>
+ std::array<std::string, UsageWarning_enumSize>
usageWarningCliCanonicalSpelling_;
LanguageFeatures disable_;
LanguageFeatures warnLanguage_;
diff --git a/flang/lib/Frontend/FrontendAction.cpp b/flang/lib/Frontend/FrontendAction.cpp
index d178fd6a9395d..5d95d6de337b1 100644
--- a/flang/lib/Frontend/FrontendAction.cpp
+++ b/flang/lib/Frontend/FrontendAction.cpp
@@ -171,7 +171,10 @@ bool FrontendAction::runParse(bool emitMessages) {
if (emitMessages) {
// Report any non-fatal diagnostics from getParsing now rather than
// combining them with messages from semantics.
- ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources());
+ bool echoSourceLine{true};
+ const auto &features{ci.getInvocation().getFortranOpts().features};
+ ci.getParsing().messages().Emit(llvm::errs(), ci.getAllCookedSources(),
+ echoSourceLine, &features);
}
return true;
}
@@ -223,6 +226,8 @@ bool FrontendAction::generateRtTypeTables() {
template <unsigned N>
bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
+ bool echoSourceLine{true};
+ const auto &features{instance->getInvocation().getFortranOpts().features};
if (!instance->getParsing().messages().empty() &&
(instance->getInvocation().getWarnAsErr() ||
instance->getParsing().messages().AnyFatalError())) {
@@ -230,7 +235,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(llvm::errs(),
- instance->getAllCookedSources());
+ instance->getAllCookedSources(),
+ echoSourceLine, &features);
return true;
}
if (instance->getParsing().parseTree().has_value() &&
@@ -240,7 +246,8 @@ bool FrontendAction::reportFatalErrors(const char (&message)[N]) {
clang::DiagnosticsEngine::Error, message);
instance->getDiagnostics().Report(diagID) << getCurrentFileOrBufferName();
instance->getParsing().messages().Emit(llvm::errs(),
- instance->getAllCookedSources());
+ instance->getAllCookedSources(),
+ echoSourceLine, &features);
instance->getParsing().EmitMessage(
llvm::errs(), instance->getParsing().finalRestingPlace(),
"parser FAIL (final position)", "error: ", llvm::raw_ostream::RED);
diff --git a/flang/lib/Parser/message.cpp b/flang/lib/Parser/message.cpp
index 799998c54b531..721c8ea339568 100644
--- a/flang/lib/Parser/message.cpp
+++ b/flang/lib/Parser/message.cpp
@@ -273,14 +273,37 @@ static llvm::raw_ostream::Colors PrefixColor(Severity severity) {
return llvm::raw_ostream::SAVEDCOLOR;
}
+static std::string HintLanguageControlFlag(
+ const common::LanguageFeatureControl *hintFlagPtr,
+ std::optional<common::LanguageFeature> feature,
+ std::optional<common::UsageWarning> warning) {
+ if (hintFlagPtr) {
+ std::string_view flag{""};
+ if (warning) {
+ flag = hintFlagPtr->getDefaultCliSpelling(*warning);
+ } else if (feature) {
+ flag = hintFlagPtr->getDefaultCliSpelling(*feature);
+ }
+ if (!flag.empty()) {
+ std::string s{" [-Wno-" + std::string(flag) + "]"};
+ return s;
+ }
+ }
+ return "";
+}
+
static constexpr int MAX_CONTEXTS_EMITTED{2};
static constexpr bool OMIT_SHARED_CONTEXTS{true};
void Message::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLine) const {
+ bool echoSourceLine,
+ const common::LanguageFeatureControl *hintFlagPtr) const {
std::optional<ProvenanceRange> provenanceRange{GetProvenanceRange(allCooked)};
const AllSources &sources{allCooked.allSources()};
- sources.EmitMessage(o, provenanceRange, ToString(), Prefix(severity()),
+ const std::string text{ToString()};
+ const std::string hint{
+ HintLanguageControlFlag(hintFlagPtr, languageFeature_, usageWarning_)};
+ sources.EmitMessage(o, provenanceRange, text + hint, Prefix(severity()),
PrefixColor(severity()), echoSourceLine);
// Refers to whether the attachment in the loop below is a context, but can't
// be declared inside the loop because the previous iteration's
@@ -430,7 +453,8 @@ void Messages::ResolveProvenances(const AllCookedSources &allCooked) {
}
void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
- bool echoSourceLines) const {
+ bool echoSourceLines,
+ const common::LanguageFeatureControl *hintFlagPtr) const {
std::vector<const Message *> sorted;
for (const auto &msg : messages_) {
sorted.push_back(&msg);
@@ -443,7 +467,7 @@ void Messages::Emit(llvm::raw_ostream &o, const AllCookedSources &allCooked,
// Don't emit two identical messages for the same location
continue;
}
- msg->Emit(o, allCooked, echoSourceLines);
+ msg->Emit(o, allCooked, echoSourceLines, hintFlagPtr);
lastMsg = msg;
}
}
diff --git a/flang/lib/Semantics/semantics.cpp b/flang/lib/Semantics/semantics.cpp
index e07054f8ec564..813f6facee1ac 100644
--- a/flang/lib/Semantics/semantics.cpp
+++ b/flang/lib/Semantics/semantics.cpp
@@ -655,8 +655,11 @@ bool Semantics::Perform() {
void Semantics::EmitMessages(llvm::raw_ostream &os) {
// Resolve the CharBlock locations of the Messages to ProvenanceRanges
// so messages from parsing and semantics are intermixed in source order.
+ bool echoSourceLine{true};
+ const auto &features{context_.languageFeatures()};
context_.messages().ResolveProvenances(context_.allCookedSources());
- context_.messages().Emit(os, context_.allCookedSources());
+ context_.messages().Emit(
+ os, context_.allCookedSources(), echoSourceLine, &features);
}
void SemanticsContext::DumpSymbols(llvm::raw_ostream &os) {
diff --git a/flang/lib/Support/Fortran-features.cpp b/flang/lib/Support/Fortran-features.cpp
index 17b5f8368916d..07ca2a5f3cd91 100644
--- a/flang/lib/Support/Fortran-features.cpp
+++ b/flang/lib/Support/Fortran-features.cpp
@@ -57,17 +57,17 @@ LanguageFeatureControl::LanguageFeatureControl() {
ForEachLanguageFeature([&](auto feature) {
std::string_view name{Fortran::common::EnumToString(feature)};
std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};
- cliOptions_.insert({cliOption, {feature}});
+ cliOptions_.insert({std::string{cliOption}, {feature}});
languageFeatureCliCanonicalSpelling_[EnumToInt(feature)] =
- std::string_view{cliOption};
+ std::move(cliOption);
});
ForEachUsageWarning([&](auto warning) {
std::string_view name{Fortran::common::EnumToString(warning)};
std::string cliOption{details::CamelCaseToLowerCaseHyphenated(name)};
- cliOptions_.insert({cliOption, {warning}});
+ cliOptions_.insert({std::string{cliOption}, {warning}});
usageWarningCliCanonicalSpelling_[EnumToInt(warning)] =
- std::string_view{cliOption};
+ std::move(cliOption);
});
// These features must be explicitly enabled by command line options.
@@ -172,20 +172,27 @@ bool LanguageFeatureControl::EnableWarning(std::string_view input) {
return false;
}
+template <typename T, size_t ENUM_SIZE>
+static void replaceCliCanonicalSpelling(
+ std::unordered_map<std::string, std::variant<LanguageFeature, UsageWarning>>
+ &cliOptions,
+ std::array<std::string, ENUM_SIZE> &canonicalSpelling, T t,
+ std::string &input) {
+ cliOptions.erase({canonicalSpelling[EnumToInt(t)]});
+ cliOptions.insert({std::string{input}, {t}});
+ canonicalSpelling[EnumToInt(t)] = std::move(input);
+}
+
void LanguageFeatureControl::ReplaceCliCanonicalSpelling(
LanguageFeature f, std::string input) {
- std::string_view &old{languageFeatureCliCanonicalSpelling_[EnumToInt(f)]};
- cliOptions_.erase(std::string{old});
- languageFeatureCliCanonicalSpelling_[EnumToInt(f)] = input;
- cliOptions_.insert({input, {f}});
+ replaceCliCanonicalSpelling(
+ cliOptions_, languageFeatureCliCanonicalSpelling_, f, input);
}
void LanguageFeatureControl::ReplaceCliCanonicalSpelling(
UsageWarning w, std::string input) {
- std::string_view &old{usageWarningCliCanonicalSpelling_[EnumToInt(w)]};
- cliOptions_.erase(std::string{old});
- usageWarningCliCanonicalSpelling_[EnumToInt(w)] = input;
- cliOptions_.insert({input, {w}});
+ replaceCliCanonicalSpelling(
+ cliOptions_, usageWarningCliCanonicalSpelling_, w, input);
}
std::vector<const char *> LanguageFeatureControl::GetNames(
diff --git a/flang/test/Evaluate/fold-dim.f90 b/flang/test/Evaluate/fold-dim.f90
index 40163c3f5a5ee..30dece869387a 100644
--- a/flang/test/Evaluate/fold-dim.f90
+++ b/flang/test/Evaluate/fold-dim.f90
@@ -11,7 +11,7 @@ module m
logical, parameter :: test_a3 = dim(2., 1.) == 1.
logical, parameter :: test_a4 = dim(2., -1.) == 3.
logical, parameter :: test_a5 = dim(-1., 2.) == 0.
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real, parameter :: nan = 0./0.
logical, parameter :: test_a6 = dim(nan, 1.) /= dim(nan, 1.)
end module
diff --git a/flang/test/Evaluate/fold-nearest.f90 b/flang/test/Evaluate/fold-nearest.f90
index 48b9ef37840e3..9502740a7dc0f 100644
--- a/flang/test/Evaluate/fold-nearest.f90
+++ b/flang/test/Evaluate/fold-nearest.f90
@@ -19,16 +19,16 @@ module m1
real, parameter :: negZero = sign(0., -1.)
logical, parameter :: test_12 = nearest(negZero, 1.) == minSubnormal
logical, parameter :: test_13 = nearest(negZero, -1.) == -minSubnormal
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
logical, parameter :: test_14 = nearest(0., negZero) == -minSubnormal
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
logical, parameter :: test_15 = nearest(negZero, 0.) == minSubnormal
logical, parameter :: test_16 = nearest(tiny(1.),-1.) == 1.1754942E-38
logical, parameter :: test_17 = nearest(tiny(1.),1.) == 1.1754945E-38
contains
subroutine subr(a)
real, intent(in) :: a
- !WARN: warning: NEAREST: S argument is zero
+ !WARN: warning: NEAREST: S argument is zero [-Wno-folding-value-checks]
print *, nearest(a, 0.)
end
end module
@@ -42,7 +42,7 @@ module m2
logical, parameter :: test_2 = ieee_next_after(minSubnormal, -1.) == 0
logical, parameter :: test_3 = ieee_next_after(1., 2.) == 1.0000001
logical, parameter :: test_4 = ieee_next_after(1.0000001, -1.) == 1
- !WARN: warning: division by zero
+ !WARN: warning: division by zero [-Wno-folding-exception]
real, parameter :: inf = 1. / 0.
logical, parameter :: test_5 = ieee_next_after(inf, inf) == inf
logical, parameter :: test_6 = ieee_next_after(inf, -inf) == h
@@ -54,12 +54,12 @@ module m2
logical, parameter :: test_11 = ieee_next_after(1.9999999999999999999_10, 3.) == 2._10
#endif
logical, parameter :: test_12 = ieee_next_after(1., 1.) == 1.
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real, parameter :: nan = 0. / 0.
- !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered
+ !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered [-Wno-folding-value-checks]
real, parameter :: x13 = ieee_next_after(nan, nan)
logical, parameter :: test_13 = .not. (x13 == x13)
- !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered
+ !WARN: warning: IEEE_NEXT_AFTER intrinsic folding: arguments are unordered [-Wno-folding-value-checks]
real, parameter :: x14 = ieee_next_after(nan, 0.)
logical, parameter :: test_14 = .not. (x14 == x14)
end module
@@ -72,7 +72,7 @@ module m3
logical, parameter :: test_2 = ieee_next_down(0.d0) == -minSubnormal
logical, parameter :: test_3 = ieee_next_up(1.d0) == 1.0000000000000002d0
logical, parameter :: test_4 = ieee_next_down(1.0000000000000002d0) == 1.d0
- !WARN: warning: division by zero
+ !WARN: warning: division by zero [-Wno-folding-exception]
real(kind(0.d0)), parameter :: inf = 1.d0 / 0.d0
logical, parameter :: test_5 = ieee_next_up(huge(0.d0)) == inf
logical, parameter :: test_6 = ieee_next_down(-huge(0.d0)) == -inf
@@ -82,12 +82,12 @@ module m3
logical, parameter :: test_10 = ieee_next_down(-inf) == -inf
logical, parameter :: test_11 = ieee_next_up(1.9999999999999997d0) == 2.d0
logical, parameter :: test_12 = ieee_next_down(2.d0) == 1.9999999999999997d0
- !WARN: warning: invalid argument on division
+ !WARN: warning: invalid argument on division [-Wno-folding-exception]
real(kind(0.d0)), parameter :: nan = 0.d0 / 0.d0
- !WARN: warning: IEEE_NEXT_UP intrinsic folding: argument is NaN
+ !WARN: warning: IEEE_NEXT_UP intrinsic folding: argument is NaN [-Wno-folding-exception]
real(kind(0.d0)), parameter :: x13 = ieee_next_up(nan)
logical, parameter :: test_13 = .not. (x13 == x13)
- !WARN: warning: IEEE_NEXT_DOWN intrinsic folding: argument is NaN
+ !WARN: warning: IEEE_NEXT_DOWN intrinsic folding: argument is NaN [-Wno-folding-exception]
real(kind(0.d0)), parameter :: x14 = ieee_next_down(nan)
logical, parameter :: test_14 = .not. (x14 == x14)
end module
diff --git a/flang/test/Evaluate/fold-unsigned.f90 b/flang/test/Evaluate/fold-unsigned.f90
index 719bdcc1a40b9..27f2fe4404483 100644
--- a/flang/test/Evaluate/fold-unsigned.f90
+++ b/flang/test/Evaluate/fold-unsigned.f90
@@ -24,7 +24,7 @@ module m
logical, parameter :: test_cus0 = int(0u,1) == 0
logical, parameter :: test_cus0_k = kind(int(0u,1)) == 1
- !WARN: warning: conversion of 255_U1 to INTEGER(1) overflowed; result is -1
+ !WARN: warning: conversion of 255_U1 to INTEGER(1) overflowed; result is -1 [-Wno-folding-exception]
logical, parameter :: test_cus255 = int(255u_1,1) == -1
logical, parameter :: test_cur255 = real(255u) == 255.
diff --git a/flang/test/Evaluate/folding03.f90 b/flang/test/Evaluate/folding03.f90
index 827bde86757c8..6441cde946a4a 100644
--- a/flang/test/Evaluate/folding03.f90
+++ b/flang/test/Evaluate/folding03.f90
@@ -15,32 +15,32 @@ module integer_tests
! Integer division by zero are not tested here because they are handled as fatal
! errors in constants.
- !WARN: warning: INTEGER(4) negation overflowed
+ !WARN: warning: INTEGER(4) negation overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_unary_minus1 = (-i4_nmax).EQ.i4_nmax
logical, parameter :: test_no_overflow_unary_minus1 = (-i4_pmax).EQ.(i4_nmax+1_4)
logical, parameter :: test_no_overflow_unary_plus1 = (+i4_pmax).EQ.i4_pmax
logical, parameter :: test_no_overflow_unary_plus2 = (+i4_nmax).EQ.i4_nmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add1 = (i4_pmax+1_4).EQ.i4_nmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add2 = (i4_nmax + (-1_4)).EQ.i4_pmax
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add3 = (i4_pmax + i4_pmax).EQ.(-2_4)
- !WARN: warning: INTEGER(4) addition overflowed
+ !WARN: warning: INTEGER(4) addition overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_add4 = (i4_nmax + i4_nmax).EQ.(0_4)
logical, parameter :: test_no_overflow_add1 = (i4_pmax + 0_4).EQ.i4_pmax
logical, parameter :: test_no_overflow_add2 = (i4_nmax + (-0_4)).EQ.i4_nmax
logical, parameter :: test_no_overflow_add3 = (i4_pmax + i4_nmax).EQ.(-1_4)
logical, parameter :: test_no_overflow_add4 = (i4_nmax + i4_pmax).EQ.(-1_4)
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub1 = (i4_nmax - 1_4).EQ.i4_pmax
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub2 = (i4_pmax - (-1_4)).EQ.i4_nmax
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub3 = (i4_nmax - i4_pmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) subtraction overflowed
+ !WARN: warning: INTEGER(4) subtraction overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_sub4 = (i4_pmax - i4_nmax).EQ.(-1_4)
logical, parameter :: test_no_overflow_sub1 = (i4_nmax - 0_4).EQ.i4_nmax
logical, parameter :: test_no_overflow_sub2 = (i4_pmax - (-0_4)).EQ.i4_pmax
@@ -48,23 +48,23 @@ module integer_tests
logical, parameter :: test_no_overflow_sub4 = (i4_pmax - i4_pmax).EQ.0_4
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult1 = (i4_pmax*2_4).EQ.(-2_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult2 = (i4_nmax*2_4).EQ.(0_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult3 = (i4_nmax*i4_nmax).EQ.(0_4)
- !WARN: warning: INTEGER(4) multiplication overflowed
+ !WARN: warning: INTEGER(4) multiplication overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_mult4 = (i4_pmax*i4_pmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) division overflowed
+ !WARN: warning: INTEGER(4) division overflowed [-Wno-folding-exception]
logical, parameter :: test_overflow_div1 = (i4_nmax/(-1_4)).EQ.(i4_nmax)
logical, parameter :: test_no_overflow_div1 = (i4_nmax/(-2_4)).EQ.(1_4 + i4_pmax/2_4)
logical, parameter :: test_no_overflow_div2 = (i4_nmax/i4_nmax).EQ.(1_4)
- !WARN: warning: INTEGER(4) power overflowed
+ !WARN: warning: INTEGER(4) power overflowed [...
[truncated]
|
Note, I updated the hints from "[-Wno-<warning-name>]" to "[-W<warning-name>]" to match more precisely what clang hints. |
While this PR LGTM, I'm not the deciding vote on flang driver changes. I think there should be at least one other approval. |
Adds a hint to the warning message to disable a warning and updates the tests to expect this.
Also fixes a bug in the storage of canonical spelling of error flags so that they are not used after free.