Skip to content

Commit 1d23005

Browse files
authored
[flang][OpenMP] Insert CRITICAL construct names into global scope (#152004)
They were inserted in the current scope. OpenMP spec (all versions): The names of critical constructs are global entities of the program. If a name conflicts with any other entity, the behavior of the program is unspecified.
1 parent a9dacb1 commit 1d23005

File tree

4 files changed

+57
-10
lines changed

4 files changed

+57
-10
lines changed

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2140,17 +2140,8 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionConstruct &x) {
21402140

21412141
bool OmpAttributeVisitor::Pre(const parser::OpenMPCriticalConstruct &x) {
21422142
const auto &beginCriticalDir{std::get<parser::OmpCriticalDirective>(x.t)};
2143-
const auto &endCriticalDir{std::get<parser::OmpEndCriticalDirective>(x.t)};
21442143
PushContext(beginCriticalDir.source, llvm::omp::Directive::OMPD_critical);
21452144
GetContext().withinConstruct = true;
2146-
if (const auto &criticalName{
2147-
std::get<std::optional<parser::Name>>(beginCriticalDir.t)}) {
2148-
ResolveOmpName(*criticalName, Symbol::Flag::OmpCriticalLock);
2149-
}
2150-
if (const auto &endCriticalName{
2151-
std::get<std::optional<parser::Name>>(endCriticalDir.t)}) {
2152-
ResolveOmpName(*endCriticalName, Symbol::Flag::OmpCriticalLock);
2153-
}
21542145
return true;
21552146
}
21562147

flang/lib/Semantics/resolve-names.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1593,13 +1593,25 @@ class OmpVisitor : public virtual DeclarationVisitor {
15931593
}
15941594
bool Pre(const parser::OmpCriticalDirective &x) {
15951595
AddOmpSourceRange(x.source);
1596+
// Manually resolve names in CRITICAL directives. This is because these
1597+
// names do not denote Fortran objects, and the CRITICAL directive causes
1598+
// them to be "auto-declared", i.e. inserted into the global scope.
1599+
// More specifically, they are not expected to have explicit declarations,
1600+
// and if they do the behavior is unspeficied.
1601+
if (auto &maybeName{std::get<std::optional<parser::Name>>(x.t)}) {
1602+
ResolveCriticalName(*maybeName);
1603+
}
15961604
return true;
15971605
}
15981606
void Post(const parser::OmpCriticalDirective &) {
15991607
messageHandler().set_currStmtSource(std::nullopt);
16001608
}
16011609
bool Pre(const parser::OmpEndCriticalDirective &x) {
16021610
AddOmpSourceRange(x.source);
1611+
// Manually resolve names in CRITICAL directives.
1612+
if (auto &maybeName{std::get<std::optional<parser::Name>>(x.t)}) {
1613+
ResolveCriticalName(*maybeName);
1614+
}
16031615
return true;
16041616
}
16051617
void Post(const parser::OmpEndCriticalDirective &) {
@@ -1720,6 +1732,8 @@ class OmpVisitor : public virtual DeclarationVisitor {
17201732
const std::optional<parser::OmpClauseList> &clauses,
17211733
const T &wholeConstruct);
17221734

1735+
void ResolveCriticalName(const parser::Name &name);
1736+
17231737
int metaLevel_{0};
17241738
const parser::OmpMetadirectiveDirective *metaDirective_{nullptr};
17251739
};
@@ -1947,6 +1961,28 @@ void OmpVisitor::ProcessReductionSpecifier(
19471961
}
19481962
}
19491963

1964+
void OmpVisitor::ResolveCriticalName(const parser::Name &name) {
1965+
auto &globalScope{[&]() -> Scope & {
1966+
for (Scope *s{&currScope()};; s = &s->parent()) {
1967+
if (s->IsTopLevel()) {
1968+
return *s;
1969+
}
1970+
}
1971+
llvm_unreachable("Cannot find global scope");
1972+
}()};
1973+
1974+
if (auto *symbol{FindInScope(globalScope, name)}) {
1975+
if (!symbol->test(Symbol::Flag::OmpCriticalLock)) {
1976+
SayWithDecl(name, *symbol,
1977+
"CRITICAL construct name '%s' conflicts with a previous declaration"_warn_en_US,
1978+
name.ToString());
1979+
}
1980+
} else {
1981+
name.symbol = &MakeSymbol(globalScope, name.source, Attrs{});
1982+
name.symbol->set(Symbol::Flag::OmpCriticalLock);
1983+
}
1984+
}
1985+
19501986
bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
19511987
AddOmpSourceRange(x.source);
19521988
if (metaLevel_ == 0) {
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
! RUN: %python %S/../test_errors.py %s %flang_fc1 -fopenmp -Werror
2+
3+
subroutine g
4+
end
5+
6+
subroutine f(x)
7+
implicit none
8+
integer :: x
9+
10+
!ERROR: CRITICAL construct name 'g' conflicts with a previous declaration
11+
!$omp critical(g)
12+
x = 0
13+
!ERROR: CRITICAL construct name 'g' conflicts with a previous declaration
14+
!$omp end critical(g)
15+
end

flang/test/Semantics/OpenMP/critical_within_default.f90

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
! RUN: %flang_fc1 -fopenmp -fdebug-dump-symbols %s | FileCheck %s
22
! Test that we do not make a private copy of the critical name
33

4+
!CHECK: Global scope:
5+
!CHECK-NEXT: MN: MainProgram
6+
!CHECK-NEXT: k2 (OmpCriticalLock): Unknown
7+
48
!CHECK: MainProgram scope: MN
59
!CHECK-NEXT: j size=4 offset=0: ObjectEntity type: INTEGER(4)
610
!CHECK-NEXT: OtherConstruct scope:
711
!CHECK-NEXT: j (OmpPrivate): HostAssoc
8-
!CHECK-NEXT: k2 (OmpCriticalLock): Unknown
12+
!CHECK-NOT: k2
13+
914
program mn
1015
integer :: j
1116
j=2

0 commit comments

Comments
 (0)