diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index e7d74dda71a20..494e54faa64c8 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -568,6 +568,7 @@ class ParseTreeDumper { NODE(parser, OpenACCCombinedConstruct) NODE(parser, OpenACCConstruct) NODE(parser, OpenACCDeclarativeConstruct) + NODE(parser, OpenACCEndConstruct) NODE(parser, OpenACCLoopConstruct) NODE(parser, OpenACCRoutineConstruct) NODE(parser, OpenACCStandaloneDeclarativeConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 408a474cfa8a5..a51921f2562b8 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4257,6 +4257,11 @@ struct OpenACCLoopConstruct { t; }; +struct OpenACCEndConstruct { + WRAPPER_CLASS_BOILERPLATE(OpenACCEndConstruct, llvm::acc::Directive); + CharBlock source; +}; + struct OpenACCStandaloneConstruct { TUPLE_CLASS_BOILERPLATE(OpenACCStandaloneConstruct); CharBlock source; @@ -4267,7 +4272,7 @@ struct OpenACCConstruct { UNION_CLASS_BOILERPLATE(OpenACCConstruct); std::variant + OpenACCWaitConstruct, OpenACCAtomicConstruct, OpenACCEndConstruct> u; }; diff --git a/flang/lib/Lower/OpenACC.cpp b/flang/lib/Lower/OpenACC.cpp index c8dcc91064415..4fafcebc30d11 100644 --- a/flang/lib/Lower/OpenACC.cpp +++ b/flang/lib/Lower/OpenACC.cpp @@ -3358,6 +3358,9 @@ void Fortran::lower::genOpenACCConstruct( [&](const Fortran::parser::OpenACCAtomicConstruct &atomicConstruct) { genACC(converter, eval, atomicConstruct); }, + [&](const Fortran::parser::OpenACCEndConstruct &) { + // No op + }, }, accConstruct.u); } diff --git a/flang/lib/Parser/openacc-parsers.cpp b/flang/lib/Parser/openacc-parsers.cpp index 75aeffd29f92f..bd5dcd8405e8f 100644 --- a/flang/lib/Parser/openacc-parsers.cpp +++ b/flang/lib/Parser/openacc-parsers.cpp @@ -235,6 +235,9 @@ TYPE_PARSER(startAccLine >> sourced(construct( Parser{}))))) +TYPE_PARSER(sourced(construct( + "END"_tok >> "LOOP"_tok >> pure(llvm::acc::Directive::ACCD_loop)))) + // OpenACC constructs TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, startAccLine >> @@ -246,7 +249,8 @@ TYPE_CONTEXT_PARSER("OpenACC construct"_en_US, Parser{}), construct(Parser{}), construct(Parser{}), - construct(Parser{})))) + construct(Parser{}), + construct(Parser{})))) TYPE_PARSER(startAccLine >> sourced(construct(sourced("END"_tok >> diff --git a/flang/lib/Semantics/check-acc-structure.cpp b/flang/lib/Semantics/check-acc-structure.cpp index ce3525e3c335b..ef253586cfa0e 100644 --- a/flang/lib/Semantics/check-acc-structure.cpp +++ b/flang/lib/Semantics/check-acc-structure.cpp @@ -673,6 +673,10 @@ void AccStructureChecker::Enter(const parser::AccClause::If &x) { GetContext().clauseSource, "Must have LOGICAL or INTEGER type"_err_en_US); } +void AccStructureChecker::Enter(const parser::OpenACCEndConstruct &x) { + context_.Say(x.source, "Misplaced OpenACC end directive"_warn_en_US); +} + void AccStructureChecker::Enter(const parser::Module &) { declareSymbols.clear(); } diff --git a/flang/lib/Semantics/check-acc-structure.h b/flang/lib/Semantics/check-acc-structure.h index 8b87b8ddc502f..2a09b7a39395d 100644 --- a/flang/lib/Semantics/check-acc-structure.h +++ b/flang/lib/Semantics/check-acc-structure.h @@ -63,6 +63,7 @@ class AccStructureChecker void Enter(const parser::OpenACCCacheConstruct &); void Leave(const parser::OpenACCCacheConstruct &); void Enter(const parser::AccAtomicUpdate &); + void Enter(const parser::OpenACCEndConstruct &); // Clauses void Leave(const parser::AccClauseList &); diff --git a/flang/test/Semantics/OpenACC/acc-error.f90 b/flang/test/Semantics/OpenACC/acc-error.f90 index b1c3b77847429..69ee59f97ec6b 100644 --- a/flang/test/Semantics/OpenACC/acc-error.f90 +++ b/flang/test/Semantics/OpenACC/acc-error.f90 @@ -13,3 +13,17 @@ subroutine test(a, n) !ERROR: expected OpenACC directive !$acc p end subroutine + +subroutine test2(a, n) + integer :: a(n) + integer :: i + + !$acc parallel + !$acc loop + DO i = 1, n + END DO + !$acc end parallel + !WARN: Misplaced OpenACC end directive + !$acc end loop + +end subroutine