Skip to content

[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

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

Conversation

akuhlens
Copy link
Contributor

@akuhlens akuhlens commented Jun 18, 2025

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.

@akuhlens akuhlens force-pushed the andre/language-control-flag-hints branch from d8d3dd0 to 0fbbbb9 Compare June 18, 2025 18:13

This comment was marked as outdated.

@akuhlens akuhlens requested a review from klausler June 18, 2025 18:37
@akuhlens akuhlens marked this pull request as ready for review June 18, 2025 18:47
@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-flang-parser

@llvm/pr-subscribers-flang-driver

Author: Andre Kuhlenschmidt (akuhlens)

Changes

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.


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:

  • (modified) flang/include/flang/Parser/message.h (+4-2)
  • (modified) flang/include/flang/Support/Fortran-features.h (+2-2)
  • (modified) flang/lib/Frontend/FrontendAction.cpp (+10-3)
  • (modified) flang/lib/Parser/message.cpp (+28-4)
  • (modified) flang/lib/Semantics/semantics.cpp (+4-1)
  • (modified) flang/lib/Support/Fortran-features.cpp (+19-12)
  • (modified) flang/test/Evaluate/fold-dim.f90 (+1-1)
  • (modified) flang/test/Evaluate/fold-nearest.f90 (+11-11)
  • (modified) flang/test/Evaluate/fold-unsigned.f90 (+1-1)
  • (modified) flang/test/Evaluate/folding03.f90 (+38-38)
  • (modified) flang/test/Evaluate/folding04.f90 (+11-11)
  • (modified) flang/test/Evaluate/folding05.f90 ()
  • (modified) flang/test/Evaluate/folding06.f90 (+2-2)
  • (modified) flang/test/Evaluate/folding14.f90 (+2-2)
  • (modified) flang/test/Evaluate/folding28.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-branch.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-data.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-declare-validity.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-serial.f90 (+3-3)
  • (modified) flang/test/Semantics/OpenMP/allocate-align01.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/allocate01.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/clause-validity01.f90 (+2-2)
  • (modified) flang/test/Semantics/OpenMP/copying.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/declarative-directive01.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/declare-target01.f90 (+13-13)
  • (modified) flang/test/Semantics/OpenMP/declare-target02.f90 (+15-15)
  • (modified) flang/test/Semantics/OpenMP/declare-target03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/declare-target06.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/deprecation.f90 (+6-6)
  • (modified) flang/test/Semantics/OpenMP/nested-target.f90 (+7-7)
  • (modified) flang/test/Semantics/OpenMP/requires04.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/requires05.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/single03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/single04.f90 (+6-6)
  • (modified) flang/test/Semantics/OpenMP/target01.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/threadprivate03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/use_device_ptr1.f90 (+1-1)
  • (modified) flang/test/Semantics/allocate09.f90 (+2-2)
  • (modified) flang/test/Semantics/argshape01.f90 (+2-2)
  • (modified) flang/test/Semantics/assign02.f90 (+7-7)
  • (modified) flang/test/Semantics/assign09.f90 (+2-2)
  • (modified) flang/test/Semantics/associate01.f90 (+1-1)
  • (modified) flang/test/Semantics/associated.f90 (+7-7)
  • (modified) flang/test/Semantics/bind-c02.f90 (+2-2)
  • (modified) flang/test/Semantics/bind-c04.f90 (+1-1)
  • (modified) flang/test/Semantics/bind-c06.f90 (+3-3)
  • (modified) flang/test/Semantics/bind-c11.f90 (+1-1)
  • (modified) flang/test/Semantics/bind-c13.f90 (+2-2)
  • (modified) flang/test/Semantics/bind-c17.f90 (+1-1)
  • (modified) flang/test/Semantics/bindings01.f90 (+3-3)
  • (modified) flang/test/Semantics/bindings03.f90 (+2-2)
  • (modified) flang/test/Semantics/block-data01.f90 (+1-1)
  • (modified) flang/test/Semantics/boz-literal-constants.f90 (+1-1)
  • (modified) flang/test/Semantics/c7108.f90 (+2-2)
  • (modified) flang/test/Semantics/c_f_pointer.f90 (+4-4)
  • (modified) flang/test/Semantics/c_loc01.f90 (+3-3)
  • (modified) flang/test/Semantics/call01.f90 (+3-3)
  • (modified) flang/test/Semantics/call02.f90 (+3-3)
  • (modified) flang/test/Semantics/call03.f90 (+6-6)
  • (modified) flang/test/Semantics/call05.f90 (+2-2)
  • (modified) flang/test/Semantics/call07.f90 (+3-3)
  • (modified) flang/test/Semantics/call09.f90 (+1-1)
  • (modified) flang/test/Semantics/call10.f90 (+1-1)
  • (modified) flang/test/Semantics/call14.f90 (+2-2)
  • (modified) flang/test/Semantics/call24.f90 (+1-1)
  • (modified) flang/test/Semantics/call27.f90 (+2-2)
  • (modified) flang/test/Semantics/call30.f90 (+15-15)
  • (modified) flang/test/Semantics/call31.f90 (+2-2)
  • (modified) flang/test/Semantics/call33.f90 (+1-1)
  • (modified) flang/test/Semantics/call34.f90 (+3-3)
  • (modified) flang/test/Semantics/call35.f90 (+2-2)
  • (modified) flang/test/Semantics/call36.f90 (+1-1)
  • (modified) flang/test/Semantics/call37.f90 (+7-7)
  • (modified) flang/test/Semantics/call38.f90 (+2-2)
  • (modified) flang/test/Semantics/call41.f90 (+1-1)
  • (modified) flang/test/Semantics/call42.f90 (+6-6)
  • (modified) flang/test/Semantics/call43.f90 (+3-3)
  • (modified) flang/test/Semantics/call44.f90 (+2-2)
  • (modified) flang/test/Semantics/case01.f90 (+6-6)
  • (modified) flang/test/Semantics/common-blocks.f90 (+2-2)
  • (modified) flang/test/Semantics/contiguous01.f90 (+8-8)
  • (modified) flang/test/Semantics/cuf01.cuf (+4-4)
  • (modified) flang/test/Semantics/cuf03.cuf (+5-5)
  • (modified) flang/test/Semantics/cuf04.cuf (+2-2)
  • (modified) flang/test/Semantics/cuf09.cuf (+1-1)
  • (modified) flang/test/Semantics/data06.f90 (+2-2)
  • (modified) flang/test/Semantics/data17.f90 (+2-2)
  • (modified) flang/test/Semantics/declarations04.f90 (+1-1)
  • (modified) flang/test/Semantics/declarations05.f90 (+1-1)
  • (modified) flang/test/Semantics/declarations07.f90 (+2-2)
  • (modified) flang/test/Semantics/deferred01.f90 (+1-1)
  • (modified) flang/test/Semantics/definable02.f90 (+2-2)
  • (modified) flang/test/Semantics/dim01.f90 (+8-8)
  • (modified) flang/test/Semantics/dosemantics02.f90 (+2-2)
  • (modified) flang/test/Semantics/dosemantics03.f90 (+18-18)
  • (modified) flang/test/Semantics/dosemantics12.f90 (+3-3)
  • (modified) flang/test/Semantics/expr-errors05.f90 (+7-7)
  • (modified) flang/test/Semantics/expr-errors06.f90 (+1-1)
  • (modified) flang/test/Semantics/final03.f90 (+1-1)
  • (modified) flang/test/Semantics/forall01.f90 (+11-11)
  • (modified) flang/test/Semantics/forall02.f90 (+3-3)
  • (modified) flang/test/Semantics/generic03.f90 (+1-1)
  • (modified) flang/test/Semantics/generic06.f90 (+2-2)
  • (modified) flang/test/Semantics/global01.f90 (+2-2)
  • (modified) flang/test/Semantics/ichar01.f90 (+2-2)
  • (modified) flang/test/Semantics/ignore_tkr01.f90 (+5-5)
  • (modified) flang/test/Semantics/int-literals.f90 (+2-2)
  • (modified) flang/test/Semantics/intrinsics02.f90 (+1-1)
  • (modified) flang/test/Semantics/kinds05b.f90 (+2-2)
  • (modified) flang/test/Semantics/label18.f90 (+2-2)
  • (modified) flang/test/Semantics/local-vs-global.f90 (+16-16)
  • (modified) flang/test/Semantics/long-name.f90 (+3-3)
  • (modified) flang/test/Semantics/modfile43.f90 (+1-1)
  • (modified) flang/test/Semantics/null-init.f90 (+1-1)
  • (modified) flang/test/Semantics/null01.f90 (+3-3)
  • (modified) flang/test/Semantics/pointer01.f90 (+1-1)
  • (modified) flang/test/Semantics/procinterface02.f90 (+1-1)
  • (modified) flang/test/Semantics/procinterface04.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve05.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve108.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve11.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve114.f90 (+10-10)
  • (modified) flang/test/Semantics/resolve118.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve17.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve18.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve20.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve24.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve30.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve31.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve35.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve37.f90 (+7-7)
  • (modified) flang/test/Semantics/resolve45.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve46.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve58.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve59.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve60.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve61.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve65.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve67.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve69.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve77.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve78.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve79.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve80.f90 (+6-6)
  • (modified) flang/test/Semantics/resolve81.f90 (+19-19)
  • (modified) flang/test/Semantics/resolve82.f90 (+10-10)
  • (modified) flang/test/Semantics/resolve83.f90 (+6-6)
  • (modified) flang/test/Semantics/resolve85.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve90.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve99.f90 (+2-2)
  • (modified) flang/test/Semantics/separate-mp02.f90 (+1-1)
  • (modified) flang/test/Semantics/spec-expr.f90 (+1-1)
  • (modified) flang/test/Semantics/stmt-func01.f90 (+8-8)
  • (modified) flang/test/Semantics/stmt-func02.f90 (+3-3)
  • (modified) flang/test/Semantics/structconst03.f90 (+1-1)
  • (modified) flang/test/Semantics/structconst04.f90 (+1-1)
  • (modified) flang/test/Semantics/structconst08.f90 (+5-5)
  • (modified) flang/test/Semantics/structconst10.f90 (+4-4)
  • (modified) flang/test/Semantics/transfer01.f90 (+5-5)
  • (modified) flang/test/Semantics/undef-result01.f90 (+4-4)
  • (modified) flang/unittests/Common/FortranFeaturesTest.cpp (+8)
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]

@llvmbot
Copy link
Member

llvmbot commented Jun 18, 2025

@llvm/pr-subscribers-flang-openmp

Author: Andre Kuhlenschmidt (akuhlens)

Changes

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.


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:

  • (modified) flang/include/flang/Parser/message.h (+4-2)
  • (modified) flang/include/flang/Support/Fortran-features.h (+2-2)
  • (modified) flang/lib/Frontend/FrontendAction.cpp (+10-3)
  • (modified) flang/lib/Parser/message.cpp (+28-4)
  • (modified) flang/lib/Semantics/semantics.cpp (+4-1)
  • (modified) flang/lib/Support/Fortran-features.cpp (+19-12)
  • (modified) flang/test/Evaluate/fold-dim.f90 (+1-1)
  • (modified) flang/test/Evaluate/fold-nearest.f90 (+11-11)
  • (modified) flang/test/Evaluate/fold-unsigned.f90 (+1-1)
  • (modified) flang/test/Evaluate/folding03.f90 (+38-38)
  • (modified) flang/test/Evaluate/folding04.f90 (+11-11)
  • (modified) flang/test/Evaluate/folding05.f90 ()
  • (modified) flang/test/Evaluate/folding06.f90 (+2-2)
  • (modified) flang/test/Evaluate/folding14.f90 (+2-2)
  • (modified) flang/test/Evaluate/folding28.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-branch.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-data.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-declare-validity.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenACC/acc-serial.f90 (+3-3)
  • (modified) flang/test/Semantics/OpenMP/allocate-align01.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/allocate01.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/clause-validity01.f90 (+2-2)
  • (modified) flang/test/Semantics/OpenMP/copying.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/declarative-directive01.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/declare-target01.f90 (+13-13)
  • (modified) flang/test/Semantics/OpenMP/declare-target02.f90 (+15-15)
  • (modified) flang/test/Semantics/OpenMP/declare-target03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/declare-target06.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/deprecation.f90 (+6-6)
  • (modified) flang/test/Semantics/OpenMP/nested-target.f90 (+7-7)
  • (modified) flang/test/Semantics/OpenMP/requires04.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/requires05.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/single03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/single04.f90 (+6-6)
  • (modified) flang/test/Semantics/OpenMP/target01.f90 (+4-4)
  • (modified) flang/test/Semantics/OpenMP/threadprivate03.f90 (+1-1)
  • (modified) flang/test/Semantics/OpenMP/use_device_ptr1.f90 (+1-1)
  • (modified) flang/test/Semantics/allocate09.f90 (+2-2)
  • (modified) flang/test/Semantics/argshape01.f90 (+2-2)
  • (modified) flang/test/Semantics/assign02.f90 (+7-7)
  • (modified) flang/test/Semantics/assign09.f90 (+2-2)
  • (modified) flang/test/Semantics/associate01.f90 (+1-1)
  • (modified) flang/test/Semantics/associated.f90 (+7-7)
  • (modified) flang/test/Semantics/bind-c02.f90 (+2-2)
  • (modified) flang/test/Semantics/bind-c04.f90 (+1-1)
  • (modified) flang/test/Semantics/bind-c06.f90 (+3-3)
  • (modified) flang/test/Semantics/bind-c11.f90 (+1-1)
  • (modified) flang/test/Semantics/bind-c13.f90 (+2-2)
  • (modified) flang/test/Semantics/bind-c17.f90 (+1-1)
  • (modified) flang/test/Semantics/bindings01.f90 (+3-3)
  • (modified) flang/test/Semantics/bindings03.f90 (+2-2)
  • (modified) flang/test/Semantics/block-data01.f90 (+1-1)
  • (modified) flang/test/Semantics/boz-literal-constants.f90 (+1-1)
  • (modified) flang/test/Semantics/c7108.f90 (+2-2)
  • (modified) flang/test/Semantics/c_f_pointer.f90 (+4-4)
  • (modified) flang/test/Semantics/c_loc01.f90 (+3-3)
  • (modified) flang/test/Semantics/call01.f90 (+3-3)
  • (modified) flang/test/Semantics/call02.f90 (+3-3)
  • (modified) flang/test/Semantics/call03.f90 (+6-6)
  • (modified) flang/test/Semantics/call05.f90 (+2-2)
  • (modified) flang/test/Semantics/call07.f90 (+3-3)
  • (modified) flang/test/Semantics/call09.f90 (+1-1)
  • (modified) flang/test/Semantics/call10.f90 (+1-1)
  • (modified) flang/test/Semantics/call14.f90 (+2-2)
  • (modified) flang/test/Semantics/call24.f90 (+1-1)
  • (modified) flang/test/Semantics/call27.f90 (+2-2)
  • (modified) flang/test/Semantics/call30.f90 (+15-15)
  • (modified) flang/test/Semantics/call31.f90 (+2-2)
  • (modified) flang/test/Semantics/call33.f90 (+1-1)
  • (modified) flang/test/Semantics/call34.f90 (+3-3)
  • (modified) flang/test/Semantics/call35.f90 (+2-2)
  • (modified) flang/test/Semantics/call36.f90 (+1-1)
  • (modified) flang/test/Semantics/call37.f90 (+7-7)
  • (modified) flang/test/Semantics/call38.f90 (+2-2)
  • (modified) flang/test/Semantics/call41.f90 (+1-1)
  • (modified) flang/test/Semantics/call42.f90 (+6-6)
  • (modified) flang/test/Semantics/call43.f90 (+3-3)
  • (modified) flang/test/Semantics/call44.f90 (+2-2)
  • (modified) flang/test/Semantics/case01.f90 (+6-6)
  • (modified) flang/test/Semantics/common-blocks.f90 (+2-2)
  • (modified) flang/test/Semantics/contiguous01.f90 (+8-8)
  • (modified) flang/test/Semantics/cuf01.cuf (+4-4)
  • (modified) flang/test/Semantics/cuf03.cuf (+5-5)
  • (modified) flang/test/Semantics/cuf04.cuf (+2-2)
  • (modified) flang/test/Semantics/cuf09.cuf (+1-1)
  • (modified) flang/test/Semantics/data06.f90 (+2-2)
  • (modified) flang/test/Semantics/data17.f90 (+2-2)
  • (modified) flang/test/Semantics/declarations04.f90 (+1-1)
  • (modified) flang/test/Semantics/declarations05.f90 (+1-1)
  • (modified) flang/test/Semantics/declarations07.f90 (+2-2)
  • (modified) flang/test/Semantics/deferred01.f90 (+1-1)
  • (modified) flang/test/Semantics/definable02.f90 (+2-2)
  • (modified) flang/test/Semantics/dim01.f90 (+8-8)
  • (modified) flang/test/Semantics/dosemantics02.f90 (+2-2)
  • (modified) flang/test/Semantics/dosemantics03.f90 (+18-18)
  • (modified) flang/test/Semantics/dosemantics12.f90 (+3-3)
  • (modified) flang/test/Semantics/expr-errors05.f90 (+7-7)
  • (modified) flang/test/Semantics/expr-errors06.f90 (+1-1)
  • (modified) flang/test/Semantics/final03.f90 (+1-1)
  • (modified) flang/test/Semantics/forall01.f90 (+11-11)
  • (modified) flang/test/Semantics/forall02.f90 (+3-3)
  • (modified) flang/test/Semantics/generic03.f90 (+1-1)
  • (modified) flang/test/Semantics/generic06.f90 (+2-2)
  • (modified) flang/test/Semantics/global01.f90 (+2-2)
  • (modified) flang/test/Semantics/ichar01.f90 (+2-2)
  • (modified) flang/test/Semantics/ignore_tkr01.f90 (+5-5)
  • (modified) flang/test/Semantics/int-literals.f90 (+2-2)
  • (modified) flang/test/Semantics/intrinsics02.f90 (+1-1)
  • (modified) flang/test/Semantics/kinds05b.f90 (+2-2)
  • (modified) flang/test/Semantics/label18.f90 (+2-2)
  • (modified) flang/test/Semantics/local-vs-global.f90 (+16-16)
  • (modified) flang/test/Semantics/long-name.f90 (+3-3)
  • (modified) flang/test/Semantics/modfile43.f90 (+1-1)
  • (modified) flang/test/Semantics/null-init.f90 (+1-1)
  • (modified) flang/test/Semantics/null01.f90 (+3-3)
  • (modified) flang/test/Semantics/pointer01.f90 (+1-1)
  • (modified) flang/test/Semantics/procinterface02.f90 (+1-1)
  • (modified) flang/test/Semantics/procinterface04.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve05.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve108.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve11.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve114.f90 (+10-10)
  • (modified) flang/test/Semantics/resolve118.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve17.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve18.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve20.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve24.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve30.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve31.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve35.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve37.f90 (+7-7)
  • (modified) flang/test/Semantics/resolve45.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve46.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve58.f90 (+4-4)
  • (modified) flang/test/Semantics/resolve59.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve60.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve61.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve65.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve67.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve69.f90 (+3-3)
  • (modified) flang/test/Semantics/resolve77.f90 (+2-2)
  • (modified) flang/test/Semantics/resolve78.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve79.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve80.f90 (+6-6)
  • (modified) flang/test/Semantics/resolve81.f90 (+19-19)
  • (modified) flang/test/Semantics/resolve82.f90 (+10-10)
  • (modified) flang/test/Semantics/resolve83.f90 (+6-6)
  • (modified) flang/test/Semantics/resolve85.f90 (+5-5)
  • (modified) flang/test/Semantics/resolve90.f90 (+1-1)
  • (modified) flang/test/Semantics/resolve99.f90 (+2-2)
  • (modified) flang/test/Semantics/separate-mp02.f90 (+1-1)
  • (modified) flang/test/Semantics/spec-expr.f90 (+1-1)
  • (modified) flang/test/Semantics/stmt-func01.f90 (+8-8)
  • (modified) flang/test/Semantics/stmt-func02.f90 (+3-3)
  • (modified) flang/test/Semantics/structconst03.f90 (+1-1)
  • (modified) flang/test/Semantics/structconst04.f90 (+1-1)
  • (modified) flang/test/Semantics/structconst08.f90 (+5-5)
  • (modified) flang/test/Semantics/structconst10.f90 (+4-4)
  • (modified) flang/test/Semantics/transfer01.f90 (+5-5)
  • (modified) flang/test/Semantics/undef-result01.f90 (+4-4)
  • (modified) flang/unittests/Common/FortranFeaturesTest.cpp (+8)
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]

@akuhlens akuhlens requested a review from klausler June 25, 2025 19:47
@akuhlens
Copy link
Contributor Author

akuhlens commented Jun 25, 2025

Note, I updated the hints from "[-Wno-<warning-name>]" to "[-W<warning-name>]" to match more precisely what clang hints.

@akuhlens akuhlens requested a review from eugeneepshteyn June 26, 2025 23:23
@eugeneepshteyn
Copy link
Contributor

While this PR LGTM, I'm not the deciding vote on flang driver changes. I think there should be at least one other approval.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants