diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index 1d1a4a163084b..6604e42957f84 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -4893,8 +4893,11 @@ struct OpenMPSectionsConstruct { CharBlock source; // Each of the OpenMPConstructs in the list below contains an // OpenMPSectionConstruct. This is guaranteed by the parser. + // The end sections directive is optional here because it is difficult to + // generate helpful error messages for a missing end directive within the + // parser. Semantics will generate an error if this is absent. std::tuple, - OmpEndSectionsDirective> + std::optional> t; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index 1044b7ad31202..c3ee67f4b3461 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -3979,9 +3979,12 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, List clauses = makeClauses( std::get(beginSectionsDirective.t), semaCtx); const auto &endSectionsDirective = - std::get(sectionsConstruct.t); + std::get>( + sectionsConstruct.t); + assert(endSectionsDirective && + "Missing end section directive should have been handled in semantics"); clauses.append(makeClauses( - std::get(endSectionsDirective.t), semaCtx)); + std::get(endSectionsDirective->t), semaCtx)); mlir::Location currentLocation = converter.getCurrentLocation(); llvm::omp::Directive directive = diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index c5a80e0c87092..5c17ddff8d7d3 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -1921,7 +1921,7 @@ TYPE_PARSER(sourced(construct( construct(maybe(sectionDir), block))), many(construct( sourced(construct(sectionDir, block))))), - Parser{} / endOmpLine))) + maybe(Parser{} / endOmpLine)))) static bool IsExecutionPart(const OmpDirectiveName &name) { return name.IsExecutionPart(); diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 09dcfe60a46bc..87e699dbc4e8d 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2788,7 +2788,7 @@ class UnparseVisitor { Walk(std::get>(x.t), ""); BeginOpenMP(); Word("!$OMP END "); - Walk(std::get(x.t)); + Walk(std::get>(x.t)); Put("\n"); EndOpenMP(); } diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index 3a7d1ed3ce7f9..04f2ebcbcaee2 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1138,14 +1138,23 @@ void OmpStructureChecker::Leave(const parser::OmpBeginDirective &) { void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) { const auto &beginSectionsDir{ std::get(x.t)}; - const auto &endSectionsDir{std::get(x.t)}; + const auto &endSectionsDir{ + std::get>(x.t)}; const auto &beginDir{ std::get(beginSectionsDir.t)}; - const auto &endDir{std::get(endSectionsDir.t)}; + PushContextAndClauseSets(beginDir.source, beginDir.v); + + if (!endSectionsDir) { + context_.Say(beginSectionsDir.source, + "Expected OpenMP END SECTIONS directive"_err_en_US); + // Following code assumes the option is present. + return; + } + + const auto &endDir{std::get(endSectionsDir->t)}; CheckMatching(beginDir, endDir); - PushContextAndClauseSets(beginDir.source, beginDir.v); - AddEndDirectiveClauses(std::get(endSectionsDir.t)); + AddEndDirectiveClauses(std::get(endSectionsDir->t)); const auto §ionBlocks{std::get>(x.t)}; for (const parser::OpenMPConstruct &construct : sectionBlocks) { diff --git a/flang/test/Semantics/OpenMP/missing-end-directive.f90 b/flang/test/Semantics/OpenMP/missing-end-directive.f90 index 3b870d134155b..33481f9d650f4 100644 --- a/flang/test/Semantics/OpenMP/missing-end-directive.f90 +++ b/flang/test/Semantics/OpenMP/missing-end-directive.f90 @@ -6,8 +6,12 @@ !$omp parallel ! ERROR: Expected OpenMP end directive !$omp task +! ERROR: Expected OpenMP END SECTIONS directive +!$omp sections ! ERROR: Expected OpenMP end directive !$omp parallel ! ERROR: Expected OpenMP end directive !$omp task +! ERROR: Expected OpenMP END SECTIONS directive +!$omp sections end