diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index b5f8667fe36f2..282660684e78a 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -384,6 +384,9 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor { bool Pre(const parser::OpenMPSectionsConstruct &); void Post(const parser::OpenMPSectionsConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPSectionConstruct &); + void Post(const parser::OpenMPSectionConstruct &) { PopContext(); } + bool Pre(const parser::OpenMPCriticalConstruct &critical); void Post(const parser::OpenMPCriticalConstruct &) { PopContext(); } @@ -2003,6 +2006,12 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) { return true; } +bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionConstruct &x) { + PushContext(x.source, llvm::omp::Directive::OMPD_section); + GetContext().withinConstruct = true; + return true; +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) { const auto &beginCriticalDir{std::get(x.t)}; const auto &endCriticalDir{std::get(x.t)}; @@ -3024,8 +3033,13 @@ void OmpAttributeVisitor::CheckLabelContext(const parser::CharBlock source, const parser::CharBlock target, std::optional sourceContext, std::optional targetContext) { auto dirContextsSame = [](DirContext &lhs, DirContext &rhs) -> bool { - // Sometimes nested constructs share a scope but are different contexts - return (lhs.scope == rhs.scope) && (lhs.directive == rhs.directive); + // Sometimes nested constructs share a scope but are different contexts. + // The directiveSource comparison is for OmpSection. Sections do not have + // their own scopes and two different sections both have the same directive. + // Their source however is different. This string comparison is unfortunate + // but should only happen for GOTOs inside of SECTION. + return (lhs.scope == rhs.scope) && (lhs.directive == rhs.directive) && + (lhs.directiveSource == rhs.directiveSource); }; unsigned version{context_.langOptions().OpenMPVersion}; if (targetContext && diff --git a/flang/test/Semantics/OpenMP/parallel-sections01.f90 b/flang/test/Semantics/OpenMP/parallel-sections01.f90 index 6c5a053bf49c9..19448258af766 100644 --- a/flang/test/Semantics/OpenMP/parallel-sections01.f90 +++ b/flang/test/Semantics/OpenMP/parallel-sections01.f90 @@ -35,6 +35,8 @@ program OmpConstructSections01 !$omp section print *, "This is a single statement structured block" !$omp section + !ERROR: invalid branch into an OpenMP structured block + !ERROR: invalid branch leaving an OpenMP structured block open (10, file="random-file-name.txt", err=30) !ERROR: invalid branch into an OpenMP structured block !ERROR: invalid branch leaving an OpenMP structured block diff --git a/flang/test/Semantics/OpenMP/sections-goto.f90 b/flang/test/Semantics/OpenMP/sections-goto.f90 new file mode 100644 index 0000000000000..9fa9df9f50b9c --- /dev/null +++ b/flang/test/Semantics/OpenMP/sections-goto.f90 @@ -0,0 +1,11 @@ +! RUN: %python %S/../test_errors.py %s %flang -fopenmp +! Regression test for #143231 + +!$omp sections +! ERROR: invalid branch into an OpenMP structured block +! ERROR: invalid branch leaving an OpenMP structured block +goto 10 +!$omp section +10 print *, "Invalid jump" +!$omp end sections +end diff --git a/flang/test/Semantics/OpenMP/sections02.f90 b/flang/test/Semantics/OpenMP/sections02.f90 index ee29922a72c08..8144b491071d8 100644 --- a/flang/test/Semantics/OpenMP/sections02.f90 +++ b/flang/test/Semantics/OpenMP/sections02.f90 @@ -19,6 +19,8 @@ program OmpConstructSections01 !$omp section print *, "This is a single statement structured block" !$omp section + !ERROR: invalid branch into an OpenMP structured block + !ERROR: invalid branch leaving an OpenMP structured block open (10, file="random-file-name.txt", err=30) !ERROR: invalid branch into an OpenMP structured block !ERROR: invalid branch leaving an OpenMP structured block