[flang-commits] [flang] [flang][OpenMP] Fix parsing of ASSUME directive (PR #155257)
Krzysztof Parzyszek via flang-commits
flang-commits at lists.llvm.org
Mon Aug 25 08:21:52 PDT 2025
https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/155257
The ASSUME directive is block-associated and whether the end-directive is optional or not depends on the form of the block. This is all taken care of automatically since the AST node for ASSUME inherits from OmpBlockConstruct.
>From 86cc364eab0114a0c44f1673de24e94bcad6acf3 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 25 Aug 2025 10:18:40 -0500
Subject: [PATCH] [flang][OpenMP] Fix parsing of ASSUME directive
The ASSUME directive is block-associated and whether the end-directive
is optional or not depends on the form of the block. This is all taken
care of automatically since the AST node for ASSUME inherits from
OmpBlockConstruct.
---
flang/include/flang/Parser/dump-parse-tree.h | 2 -
flang/include/flang/Parser/openmp-utils.h | 4 +-
flang/include/flang/Parser/parse-tree.h | 26 +--
flang/lib/Parser/openmp-parsers.cpp | 12 +-
flang/lib/Parser/unparse.cpp | 15 +-
flang/lib/Semantics/check-omp-structure.cpp | 8 -
flang/lib/Semantics/resolve-directives.cpp | 8 +
flang/test/Parser/OpenMP/assumption.f90 | 160 ++++++++++++++-----
8 files changed, 141 insertions(+), 94 deletions(-)
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 7170dfb591fae..29ae376711f51 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -517,7 +517,6 @@ class ParseTreeDumper {
NODE(OmpAppendArgsClause, OmpAppendOp)
NODE(parser, OmpArgument)
NODE(parser, OmpArgumentList)
- NODE(parser, OmpAssumeDirective)
NODE(parser, OmpAtClause)
NODE_ENUM(OmpAtClause, ActionTime)
NODE(parser, OmpAtomicDefaultMemOrderClause)
@@ -571,7 +570,6 @@ class ParseTreeDumper {
NODE(parser, OmpDoacrossClause)
NODE(parser, OmpDynGroupprivateClause)
NODE(OmpDynGroupprivateClause, Modifier)
- NODE(parser, OmpEndAssumeDirective)
NODE(parser, OmpEndCriticalDirective)
NODE(parser, OmpEndDirective)
NODE(parser, OmpEndLoopDirective)
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 6bd578b50dc3e..cbcf7f4328fd4 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -38,7 +38,6 @@ struct ConstructId {
static constexpr llvm::omp::Directive id{Id}; \
}
-MAKE_CONSTR_ID(OmpAssumeDirective, D::OMPD_assume);
MAKE_CONSTR_ID(OmpCriticalDirective, D::OMPD_critical);
MAKE_CONSTR_ID(OmpDeclareVariantDirective, D::OMPD_declare_variant);
MAKE_CONSTR_ID(OmpErrorDirective, D::OMPD_error);
@@ -104,8 +103,7 @@ struct DirectiveNameScope {
} else if constexpr (TupleTrait<T>) {
if constexpr (std::is_base_of_v<OmpBlockConstruct, T>) {
return std::get<OmpBeginDirective>(x.t).DirName();
- } else if constexpr (std::is_same_v<T, OmpAssumeDirective> ||
- std::is_same_v<T, OmpCriticalDirective> ||
+ } else if constexpr (std::is_same_v<T, OmpCriticalDirective> ||
std::is_same_v<T, OmpDeclareVariantDirective> ||
std::is_same_v<T, OmpErrorDirective> ||
std::is_same_v<T, OmpMetadirectiveDirective> ||
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 1d1a4a163084b..e5f4c57c976f1 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4835,28 +4835,14 @@ struct OpenMPDeclarativeAssumes {
CharBlock source;
};
-struct OmpAssumeDirective {
- TUPLE_CLASS_BOILERPLATE(OmpAssumeDirective);
- std::tuple<Verbatim, OmpClauseList> t;
- CharBlock source;
-};
-
-struct OmpEndAssumeDirective {
- WRAPPER_CLASS_BOILERPLATE(OmpEndAssumeDirective, Verbatim);
- CharBlock source;
-};
-
-// Ref: [5.2: 213-216]
+// Ref: [5.1:86-89], [5.2:215], [6.0:369]
//
-// assume-construct ->
-// ASSUME absent-clause | contains-clause | holds_clause | no-openmp-clause
-// no-openmp-routines-clause | no-parallelism-clause
-// block
+// assume-directive -> // since 5.1
+// ASSUME assumption-clause...
+// block
// [END ASSUME]
-struct OpenMPAssumeConstruct {
- TUPLE_CLASS_BOILERPLATE(OpenMPAssumeConstruct);
- std::tuple<OmpAssumeDirective, Block, std::optional<OmpEndAssumeDirective>> t;
- CharBlock source;
+struct OpenMPAssumeConstruct : public OmpBlockConstruct {
+ INHERITED_TUPLE_CLASS_BOILERPLATE(OpenMPAssumeConstruct, OmpBlockConstruct);
};
// 2.7.2 SECTIONS
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 51b49a591b02f..ac7cc2e6877e6 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1843,16 +1843,8 @@ TYPE_PARSER(
Parser<OmpMetadirectiveDirective>{})) /
endOmpLine))
-// Assume Construct
-TYPE_PARSER(sourced(construct<OmpAssumeDirective>(
- verbatim("ASSUME"_tok), Parser<OmpClauseList>{})))
-
-TYPE_PARSER(sourced(construct<OmpEndAssumeDirective>(
- startOmpLine >> verbatim("END ASSUME"_tok))))
-
-TYPE_PARSER(sourced(
- construct<OpenMPAssumeConstruct>(Parser<OmpAssumeDirective>{} / endOmpLine,
- block, maybe(Parser<OmpEndAssumeDirective>{} / endOmpLine))))
+TYPE_PARSER(construct<OpenMPAssumeConstruct>(
+ sourced(OmpBlockConstructParser{llvm::omp::Directive::OMPD_assume})))
// Block Construct
#define MakeBlockConstruct(dir) \
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 09dcfe60a46bc..bae9207eab97d 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2580,20 +2580,11 @@ class UnparseVisitor {
Put("\n");
EndOpenMP();
}
- void Unparse(const OpenMPAllocatorsConstruct &x) { //
+ void Unparse(const OpenMPAllocatorsConstruct &x) {
Unparse(static_cast<const OmpBlockConstruct &>(x));
}
- void Unparse(const OmpAssumeDirective &x) {
- BeginOpenMP();
- Word("!$OMP ASSUME");
- Walk(" ", std::get<OmpClauseList>(x.t).v);
- Put("\n");
- EndOpenMP();
- }
- void Unparse(const OmpEndAssumeDirective &x) {
- BeginOpenMP();
- Word("!$OMP END ASSUME\n");
- EndOpenMP();
+ void Unparse(const OpenMPAssumeConstruct &x) {
+ Unparse(static_cast<const OmpBlockConstruct &>(x));
}
void Unparse(const OmpCriticalDirective &x) {
BeginOpenMP();
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 6dad9a3d0711d..bd9b4c207e22d 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -589,14 +589,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
checker_(GetDirName(x.t).source, Directive::OMPD_allocators);
return false;
}
- bool Pre(const parser::OmpAssumeDirective &x) {
- checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assume);
- return false;
- }
- bool Pre(const parser::OmpEndAssumeDirective &x) {
- checker_(x.v.source, Directive::OMPD_assume);
- return false;
- }
bool Pre(const parser::OmpMetadirectiveDirective &x) {
checker_(
std::get<parser::Verbatim>(x.t).source, Directive::OMPD_metadirective);
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index dbd4f512a0465..9c4d3a8738ee5 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -531,6 +531,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
bool Pre(const parser::OpenMPDeclarativeAllocate &);
void Post(const parser::OpenMPDeclarativeAllocate &) { PopContext(); }
+ bool Pre(const parser::OpenMPAssumeConstruct &);
+ void Post(const parser::OpenMPAssumeConstruct &) { PopContext(); }
+
bool Pre(const parser::OpenMPAtomicConstruct &);
void Post(const parser::OpenMPAtomicConstruct &) { PopContext(); }
@@ -2220,6 +2223,11 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPDeclarativeAllocate &x) {
return false;
}
+bool OmpAttributeVisitor::Pre(const parser::OpenMPAssumeConstruct &x) {
+ PushContext(x.source, llvm::omp::Directive::OMPD_assume);
+ return true;
+}
+
bool OmpAttributeVisitor::Pre(const parser::OpenMPAtomicConstruct &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_atomic);
return true;
diff --git a/flang/test/Parser/OpenMP/assumption.f90 b/flang/test/Parser/OpenMP/assumption.f90
index f1cb0c87e1262..ffd071fd69659 100644
--- a/flang/test/Parser/OpenMP/assumption.f90
+++ b/flang/test/Parser/OpenMP/assumption.f90
@@ -1,59 +1,141 @@
-! RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s
-! RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s --check-prefix="PARSE-TREE"
+!RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-unparse-no-sema %s | FileCheck --check-prefix="UNPARSE" %s
+!RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-dump-parse-tree-no-sema %s | FileCheck --check-prefix="PARSE-TREE" %s
+
subroutine sub1
integer :: r
-!CHECK: !$OMP ASSUME NO_OPENMP
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp
!$omp assume no_openmp
-!CHECK: !$OMP ASSUME NO_PARALLELISM
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> NoParallelism
+ !$omp end assume
+
!$omp assume no_parallelism
-!CHECK: !$OMP ASSUME NO_OPENMP_ROUTINES
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmpRoutines
+ !$omp end assume
+
!$omp assume no_openmp_routines
-!CHECK: !$OMP ASSUME ABSENT(ALLOCATE), CONTAINS(WORKSHARE,TASK)
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> Absent -> OmpAbsentClause -> llvm::omp::Directive = allocate
-!PARSE-TREE: OmpClause -> Contains -> OmpContainsClause -> llvm::omp::Directive = workshare
-!PARSE-TREE: llvm::omp::Directive = task
- !$omp assume absent(allocate), contains(workshare, task)
-!CHECK: !$OMP ASSUME HOLDS(1==1)
+ !$omp end assume
+
+ !$omp assume absent(allocate), contains(workshare, task)
+ !$omp end assume
+
!$omp assume holds(1.eq.1)
+ !$omp end assume
print *, r
end subroutine sub1
+!UNPARSE: SUBROUTINE sub1
+!UNPARSE: INTEGER r
+!UNPARSE: !$OMP ASSUME NO_OPENMP
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: !$OMP ASSUME NO_PARALLELISM
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: !$OMP ASSUME NO_OPENMP_ROUTINES
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: !$OMP ASSUME ABSENT(ALLOCATE) CONTAINS(WORKSHARE,TASK)
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: !$OMP ASSUME HOLDS(1==1)
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: PRINT *, r
+!UNPARSE: END SUBROUTINE sub1
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmp
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> NoParallelism
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmpRoutines
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Absent -> OmpAbsentClause -> llvm::omp::Directive = allocate
+!PARSE-TREE: | | OmpClause -> Contains -> OmpContainsClause -> llvm::omp::Directive = workshare
+!PARSE-TREE: | | llvm::omp::Directive = task
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Holds -> OmpHoldsClause -> Expr -> EQ
+!PARSE-TREE: | | | Expr -> LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | | Expr -> LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+
+
subroutine sub2
integer :: r
integer :: v
-!CHECK !$OMP ASSUME NO_OPENMP
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
-!PARSE-TREE: OmpAssumeDirective
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp
-!PARSE-TREE: Block
-!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt
-!PARSE-TREE: Expr -> Add
-!PARSE-TREE: OmpEndAssumeDirective
v = 87
!$omp assume no_openmp
r = r + 1
-!CHECK !$OMP END ASSUME
!$omp end assume
end subroutine sub2
-
+
+!UNPARSE: SUBROUTINE sub2
+!UNPARSE: INTEGER r
+!UNPARSE: INTEGER v
+!UNPARSE: v = 87
+!UNPARSE: !$OMP ASSUME NO_OPENMP
+!UNPARSE: r = r+1
+!UNPARSE: !$OMP END ASSUME
+!UNPARSE: END SUBROUTINE sub2
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt
+!PARSE-TREE: | Variable -> Designator -> DataRef -> Name = 'v'
+!PARSE-TREE: | Expr -> LiteralConstant -> IntLiteralConstant = '87'
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct
+!PARSE-TREE: | OmpBeginDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> NoOpenmp
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | Block
+!PARSE-TREE: | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt
+!PARSE-TREE: | | | Variable -> Designator -> DataRef -> Name = 'r'
+!PARSE-TREE: | | | Expr -> Add
+!PARSE-TREE: | | | | Expr -> Designator -> DataRef -> Name = 'r'
+!PARSE-TREE: | | | | Expr -> LiteralConstant -> IntLiteralConstant = '1'
+!PARSE-TREE: | OmpEndDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = assume
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | | Flags = None
+
program p
-!CHECK !$OMP ASSUMES NO_OPENMP
-!PARSE-TREE: SpecificationPart
-!PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclarativeAssumes
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp
!$omp assumes no_openmp
end program p
-
+
+!UNPARSE: PROGRAM p
+!UNPARSE: !$OMP ASSUMES NO_OPENMP
+!UNPARSE: END PROGRAM p
+
+!PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclarativeAssumes
+!PARSE-TREE: | Verbatim
+!PARSE-TREE: | OmpClauseList -> OmpClause -> NoOpenmp
More information about the flang-commits
mailing list