Skip to content

[flang] Support for warning and error compiler directives. #151510

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 1 commit into
base: main
Choose a base branch
from

Conversation

shivaramaarao
Copy link
Contributor

@shivaramaarao shivaramaarao commented Jul 31, 2025

The warning directive !$dir warning "warning message" can be used to issue warning in the codepath. Similarly, the directive !$dir error "error message" can be used to issue error in the codepath.

These directives can be used to inform the user about deprecated features.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics flang:parser labels Jul 31, 2025
@llvmbot
Copy link
Member

llvmbot commented Jul 31, 2025

@llvm/pr-subscribers-flang-parser

Author: None (shivaramaarao)

Changes

The warning directive !$dir warning("warning message") can be used to issue warning in the codepath. Similarly, the directive !$dir error("error message") can be used to issue error in the codepath.

These directives can be used to inform the user about deprecated features.


Full diff: https://github.com/llvm/llvm-project/pull/151510.diff

7 Files Affected:

  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+2)
  • (modified) flang/include/flang/Parser/parse-tree.h (+8-2)
  • (modified) flang/lib/Parser/Fortran-parsers.cpp (+8)
  • (modified) flang/lib/Parser/unparse.cpp (+2)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+6-1)
  • (added) flang/test/Parser/compiler-directive-error.f90 (+8)
  • (added) flang/test/Parser/compiler-directive-warning.f90 (+8)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 11725991e9c9a..a8947fddaf216 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -208,6 +208,8 @@ class ParseTreeDumper {
   NODE(CompilerDirective, NameValue)
   NODE(CompilerDirective, Unrecognized)
   NODE(CompilerDirective, VectorAlways)
+  NODE(CompilerDirective, Error)
+  NODE(CompilerDirective, Warning)
   NODE(parser, ComplexLiteralConstant)
   NODE(parser, ComplexPart)
   NODE(parser, ComponentArraySpec)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 00d85aa05fb3a..700cad310960e 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3363,6 +3363,12 @@ struct CompilerDirective {
     TUPLE_CLASS_BOILERPLATE(AssumeAligned);
     std::tuple<common::Indirection<Designator>, uint64_t> t;
   };
+  struct Error {
+    WRAPPER_CLASS_BOILERPLATE(Error, std::string);
+  };
+  struct Warning {
+    WRAPPER_CLASS_BOILERPLATE(Warning, std::string);
+  };
   EMPTY_CLASS(VectorAlways);
   struct NameValue {
     TUPLE_CLASS_BOILERPLATE(NameValue);
@@ -3370,8 +3376,8 @@ struct CompilerDirective {
   };
   EMPTY_CLASS(Unrecognized);
   CharBlock source;
-  std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
-      VectorAlways, std::list<NameValue>, Unrecognized>
+  std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>, Error,
+      Warning, VectorAlways, std::list<NameValue>, Unrecognized>
       u;
 };
 
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index 7cb35c1f173bb..2b9f8ef6ca695 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -1294,6 +1294,8 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) ||
 // !DIR$ LOOP COUNT (n1[, n2]...)
 // !DIR$ name[=value] [, name[=value]]...
 // !DIR$ <anything else>
+// !DIR$ ERROR  error-string
+// !DIR$ WARNING warning-string
 constexpr auto ignore_tkr{
     "IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>(
                         maybe(parenthesized(many(letter))), name))};
@@ -1305,11 +1307,17 @@ constexpr auto assumeAligned{"ASSUME_ALIGNED" >>
         indirect(designator), ":"_tok >> digitString64))};
 constexpr auto vectorAlways{
     "VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()};
+constexpr auto error{"ERROR" >>
+    construct<CompilerDirective::Error>(charLiteralConstantWithoutKind)};
+constexpr auto warning{"WARNING" >>
+    construct<CompilerDirective::Warning>(charLiteralConstantWithoutKind)};
 TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
     sourced((construct<CompilerDirective>(ignore_tkr) ||
                 construct<CompilerDirective>(loopCount) ||
                 construct<CompilerDirective>(assumeAligned) ||
                 construct<CompilerDirective>(vectorAlways) ||
+                construct<CompilerDirective>(error) ||
+                construct<CompilerDirective>(warning) ||
                 construct<CompilerDirective>(
                     many(construct<CompilerDirective::NameValue>(
                         name, maybe(("="_tok || ":"_tok) >> digitString64))))) /
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 7bf404bba2c3e..5c92a59d334db 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1847,6 +1847,8 @@ class UnparseVisitor {
             [&](const std::list<CompilerDirective::NameValue> &names) {
               Walk("!DIR$ ", names, " ");
             },
+            [&](const CompilerDirective::Error &) { Word("!DIR$ ERROR"); },
+            [&](const CompilerDirective::Warning &) { Word("!DIR$ WARNING"); },
             [&](const CompilerDirective::Unrecognized &) {
               Word("!DIR$ ");
               Word(x.source.ToString());
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index f3c2a5bf094d0..1e00eb29aabd3 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -9248,7 +9248,12 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
   if (std::holds_alternative<parser::CompilerDirective::VectorAlways>(x.u)) {
     return;
   }
-  if (const auto *tkr{
+  if (const auto *err{std::get_if<parser::CompilerDirective::Error>(&x.u)}) {
+    Say(err->v, "%s"_err_en_US);
+  }
+  else if (const auto *warn{std::get_if<parser::CompilerDirective::Warning>(&x.u)}) {
+    Say(warn->v, "%s"_warn_en_US);
+  } else if (const auto *tkr{
           std::get_if<std::list<parser::CompilerDirective::IgnoreTKR>>(&x.u)}) {
     if (currScope().IsTopLevel() ||
         GetProgramUnitContaining(currScope()).kind() !=
diff --git a/flang/test/Parser/compiler-directive-error.f90 b/flang/test/Parser/compiler-directive-error.f90
new file mode 100644
index 0000000000000..fa4d3cbc0cba8
--- /dev/null
+++ b/flang/test/Parser/compiler-directive-error.f90
@@ -0,0 +1,8 @@
+! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+! Test that error compiler directive issues error
+program warn
+!dir$ error "Error!"
+!CHECK: error: Error!
+end program
+
diff --git a/flang/test/Parser/compiler-directive-warning.f90 b/flang/test/Parser/compiler-directive-warning.f90
new file mode 100644
index 0000000000000..3fa5ede7105fc
--- /dev/null
+++ b/flang/test/Parser/compiler-directive-warning.f90
@@ -0,0 +1,8 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+! Test that warning compiler directive issues warning
+program warn
+!dir$ warning "Warning!"
+!CHECK: warning: Warning!
+end program
+

@llvmbot
Copy link
Member

llvmbot commented Jul 31, 2025

@llvm/pr-subscribers-flang-semantics

Author: None (shivaramaarao)

Changes

The warning directive !$dir warning("warning message") can be used to issue warning in the codepath. Similarly, the directive !$dir error("error message") can be used to issue error in the codepath.

These directives can be used to inform the user about deprecated features.


Full diff: https://github.com/llvm/llvm-project/pull/151510.diff

7 Files Affected:

  • (modified) flang/include/flang/Parser/dump-parse-tree.h (+2)
  • (modified) flang/include/flang/Parser/parse-tree.h (+8-2)
  • (modified) flang/lib/Parser/Fortran-parsers.cpp (+8)
  • (modified) flang/lib/Parser/unparse.cpp (+2)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+6-1)
  • (added) flang/test/Parser/compiler-directive-error.f90 (+8)
  • (added) flang/test/Parser/compiler-directive-warning.f90 (+8)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 11725991e9c9a..a8947fddaf216 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -208,6 +208,8 @@ class ParseTreeDumper {
   NODE(CompilerDirective, NameValue)
   NODE(CompilerDirective, Unrecognized)
   NODE(CompilerDirective, VectorAlways)
+  NODE(CompilerDirective, Error)
+  NODE(CompilerDirective, Warning)
   NODE(parser, ComplexLiteralConstant)
   NODE(parser, ComplexPart)
   NODE(parser, ComponentArraySpec)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 00d85aa05fb3a..700cad310960e 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -3363,6 +3363,12 @@ struct CompilerDirective {
     TUPLE_CLASS_BOILERPLATE(AssumeAligned);
     std::tuple<common::Indirection<Designator>, uint64_t> t;
   };
+  struct Error {
+    WRAPPER_CLASS_BOILERPLATE(Error, std::string);
+  };
+  struct Warning {
+    WRAPPER_CLASS_BOILERPLATE(Warning, std::string);
+  };
   EMPTY_CLASS(VectorAlways);
   struct NameValue {
     TUPLE_CLASS_BOILERPLATE(NameValue);
@@ -3370,8 +3376,8 @@ struct CompilerDirective {
   };
   EMPTY_CLASS(Unrecognized);
   CharBlock source;
-  std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>,
-      VectorAlways, std::list<NameValue>, Unrecognized>
+  std::variant<std::list<IgnoreTKR>, LoopCount, std::list<AssumeAligned>, Error,
+      Warning, VectorAlways, std::list<NameValue>, Unrecognized>
       u;
 };
 
diff --git a/flang/lib/Parser/Fortran-parsers.cpp b/flang/lib/Parser/Fortran-parsers.cpp
index 7cb35c1f173bb..2b9f8ef6ca695 100644
--- a/flang/lib/Parser/Fortran-parsers.cpp
+++ b/flang/lib/Parser/Fortran-parsers.cpp
@@ -1294,6 +1294,8 @@ TYPE_PARSER(construct<StatOrErrmsg>("STAT =" >> statVariable) ||
 // !DIR$ LOOP COUNT (n1[, n2]...)
 // !DIR$ name[=value] [, name[=value]]...
 // !DIR$ <anything else>
+// !DIR$ ERROR  error-string
+// !DIR$ WARNING warning-string
 constexpr auto ignore_tkr{
     "IGNORE_TKR" >> optionalList(construct<CompilerDirective::IgnoreTKR>(
                         maybe(parenthesized(many(letter))), name))};
@@ -1305,11 +1307,17 @@ constexpr auto assumeAligned{"ASSUME_ALIGNED" >>
         indirect(designator), ":"_tok >> digitString64))};
 constexpr auto vectorAlways{
     "VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()};
+constexpr auto error{"ERROR" >>
+    construct<CompilerDirective::Error>(charLiteralConstantWithoutKind)};
+constexpr auto warning{"WARNING" >>
+    construct<CompilerDirective::Warning>(charLiteralConstantWithoutKind)};
 TYPE_PARSER(beginDirective >> "DIR$ "_tok >>
     sourced((construct<CompilerDirective>(ignore_tkr) ||
                 construct<CompilerDirective>(loopCount) ||
                 construct<CompilerDirective>(assumeAligned) ||
                 construct<CompilerDirective>(vectorAlways) ||
+                construct<CompilerDirective>(error) ||
+                construct<CompilerDirective>(warning) ||
                 construct<CompilerDirective>(
                     many(construct<CompilerDirective::NameValue>(
                         name, maybe(("="_tok || ":"_tok) >> digitString64))))) /
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 7bf404bba2c3e..5c92a59d334db 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -1847,6 +1847,8 @@ class UnparseVisitor {
             [&](const std::list<CompilerDirective::NameValue> &names) {
               Walk("!DIR$ ", names, " ");
             },
+            [&](const CompilerDirective::Error &) { Word("!DIR$ ERROR"); },
+            [&](const CompilerDirective::Warning &) { Word("!DIR$ WARNING"); },
             [&](const CompilerDirective::Unrecognized &) {
               Word("!DIR$ ");
               Word(x.source.ToString());
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index f3c2a5bf094d0..1e00eb29aabd3 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -9248,7 +9248,12 @@ void ResolveNamesVisitor::Post(const parser::CompilerDirective &x) {
   if (std::holds_alternative<parser::CompilerDirective::VectorAlways>(x.u)) {
     return;
   }
-  if (const auto *tkr{
+  if (const auto *err{std::get_if<parser::CompilerDirective::Error>(&x.u)}) {
+    Say(err->v, "%s"_err_en_US);
+  }
+  else if (const auto *warn{std::get_if<parser::CompilerDirective::Warning>(&x.u)}) {
+    Say(warn->v, "%s"_warn_en_US);
+  } else if (const auto *tkr{
           std::get_if<std::list<parser::CompilerDirective::IgnoreTKR>>(&x.u)}) {
     if (currScope().IsTopLevel() ||
         GetProgramUnitContaining(currScope()).kind() !=
diff --git a/flang/test/Parser/compiler-directive-error.f90 b/flang/test/Parser/compiler-directive-error.f90
new file mode 100644
index 0000000000000..fa4d3cbc0cba8
--- /dev/null
+++ b/flang/test/Parser/compiler-directive-error.f90
@@ -0,0 +1,8 @@
+! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+! Test that error compiler directive issues error
+program warn
+!dir$ error "Error!"
+!CHECK: error: Error!
+end program
+
diff --git a/flang/test/Parser/compiler-directive-warning.f90 b/flang/test/Parser/compiler-directive-warning.f90
new file mode 100644
index 0000000000000..3fa5ede7105fc
--- /dev/null
+++ b/flang/test/Parser/compiler-directive-warning.f90
@@ -0,0 +1,8 @@
+! RUN: %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
+
+! Test that warning compiler directive issues warning
+program warn
+!dir$ warning "Warning!"
+!CHECK: warning: Warning!
+end program
+

@shivaramaarao shivaramaarao changed the title This commit adds the support for warning and error compiler directives. Support for warning and error compiler directives. Jul 31, 2025
@shivaramaarao shivaramaarao changed the title Support for warning and error compiler directives. [flang] Support for warning and error compiler directives. Aug 1, 2025
Copy link
Contributor

@eugeneepshteyn eugeneepshteyn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be mentioned in the documentation somewhere

@klausler
Copy link
Contributor

klausler commented Aug 4, 2025

The compiler already has #error, #warning, and other preprocessor directives. What purpose are these new ones for?

@@ -1305,11 +1307,17 @@ constexpr auto assumeAligned{"ASSUME_ALIGNED" >>
indirect(designator), ":"_tok >> digitString64))};
constexpr auto vectorAlways{
"VECTOR ALWAYS" >> construct<CompilerDirective::VectorAlways>()};
constexpr auto error{"ERROR" >>
construct<CompilerDirective::Error>(charLiteralConstantWithoutKind)};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the PR comment, these character literals are parenthesized.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks. updated the PR comment.

@@ -1847,6 +1847,8 @@ class UnparseVisitor {
[&](const std::list<CompilerDirective::NameValue> &names) {
Walk("!DIR$ ", names, " ");
},
[&](const CompilerDirective::Error &) { Word("!DIR$ ERROR"); },
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How will you test this? The directive will emit a fatal error in semantics, and then unpausing won't be run.

if (const auto *tkr{
if (const auto *err{std::get_if<parser::CompilerDirective::Error>(&x.u)}) {
Say(err->v, "%s"_err_en_US);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

put the else on this line too

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. thank you.

The warning directive !$dir warning "warning message" can be used to issue
warning in the codepath. Similarly, the directive !$dir error "error message"
can be used to issue error in the codepath.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:parser flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants