Skip to content

Commit 063c5bc

Browse files
NimishMishranimishra
authored andcommitted
[flang][OpenMP] Added OpenMP 5.0 specification based semantic checks for sections construct and test case for simd construct
According to OpenMP 5.0 spec document, the following semantic restrictions have been dealt with in this patch. 1. [sections construct] Orphaned section directives are prohibited. That is, the section directives must appear within the sections construct and must not be encountered elsewhere in the sections region. Semantic checks for the following are not necessary, since use of orphaned section construct (i.e. without an enclosing sections directive) throws parser errors and control flow never reaches the semantic checking phase. Added a test case for the same. 2. [sections construct] Must be a structured block Added test case and made changes to branching logic 3. [simd construct] Must be a structured block / A program that branches in or out of a function with declare simd is non conforming 4. Fixed !$omp do's handling of unlabeled CYCLEs Reviewed By: kiranchandramohan Differential Revision: https://reviews.llvm.org/D108904
1 parent 237e905 commit 063c5bc

File tree

4 files changed

+241
-19
lines changed

4 files changed

+241
-19
lines changed

flang/lib/Semantics/check-directive-structure.h

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ template <typename D> class NoBranchingEnforce {
3535
parser::CharBlock sourcePosition, D directive,
3636
std::string &&upperCaseDirName)
3737
: context_{context}, sourcePosition_{sourcePosition},
38-
upperCaseDirName_{std::move(upperCaseDirName)}, currentDirective_{
39-
directive} {}
38+
upperCaseDirName_{std::move(upperCaseDirName)},
39+
currentDirective_{directive}, numDoConstruct_{0} {}
4040
template <typename T> bool Pre(const T &) { return true; }
4141
template <typename T> void Post(const T &) {}
4242

@@ -45,16 +45,34 @@ template <typename D> class NoBranchingEnforce {
4545
return true;
4646
}
4747

48+
bool Pre(const parser::DoConstruct &) {
49+
numDoConstruct_++;
50+
return true;
51+
}
52+
void Post(const parser::DoConstruct &) { numDoConstruct_--; }
4853
void Post(const parser::ReturnStmt &) { EmitBranchOutError("RETURN"); }
4954
void Post(const parser::ExitStmt &exitStmt) {
5055
if (const auto &exitName{exitStmt.v}) {
5156
CheckConstructNameBranching("EXIT", exitName.value());
57+
} else {
58+
CheckConstructNameBranching("EXIT");
5259
}
5360
}
5461
void Post(const parser::StopStmt &) { EmitBranchOutError("STOP"); }
5562
void Post(const parser::CycleStmt &cycleStmt) {
5663
if (const auto &cycleName{cycleStmt.v}) {
5764
CheckConstructNameBranching("CYCLE", cycleName.value());
65+
} else {
66+
switch ((llvm::omp::Directive)currentDirective_) {
67+
// exclude directives which do not need a check for unlabelled CYCLES
68+
case llvm::omp::Directive::OMPD_do:
69+
return;
70+
case llvm::omp::Directive::OMPD_simd:
71+
return;
72+
default:
73+
break;
74+
}
75+
CheckConstructNameBranching("CYCLE");
5876
}
5977
}
6078

@@ -71,6 +89,14 @@ template <typename D> class NoBranchingEnforce {
7189
.Attach(sourcePosition_, GetEnclosingMsg());
7290
}
7391

92+
inline void EmitUnlabelledBranchOutError(const char *stmt) {
93+
context_
94+
.Say(currentStatementSourcePosition_,
95+
"%s to construct outside of %s construct is not allowed"_err_en_US,
96+
stmt, upperCaseDirName_)
97+
.Attach(sourcePosition_, GetEnclosingMsg());
98+
}
99+
74100
void EmitBranchOutErrorWithName(
75101
const char *stmt, const parser::Name &toName) const {
76102
const std::string branchingToName{toName.ToString()};
@@ -102,11 +128,25 @@ template <typename D> class NoBranchingEnforce {
102128
}
103129
}
104130

131+
// Check branching for unlabelled CYCLES and EXITs
132+
void CheckConstructNameBranching(const char *stmt) {
133+
// found an enclosing looping construct for the unlabelled EXIT/CYCLE
134+
if (numDoConstruct_ > 0) {
135+
return;
136+
}
137+
// did not found an enclosing looping construct within the OpenMP/OpenACC
138+
// directive
139+
EmitUnlabelledBranchOutError(stmt);
140+
return;
141+
}
142+
105143
SemanticsContext &context_;
106144
parser::CharBlock currentStatementSourcePosition_;
107145
parser::CharBlock sourcePosition_;
108146
std::string upperCaseDirName_;
109147
D currentDirective_;
148+
int numDoConstruct_; // tracks number of DoConstruct found AFTER encountering
149+
// an OpenMP/OpenACC directive
110150
};
111151

112152
// Generic structure checker for directives/clauses language such as OpenMP
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
! RUN: %python %S/test_errors.py %s %flang -fopenmp
2+
! OpenMP version 5.0.0
3+
! 2.8.1 sections construct
4+
! The code enclosed in a sections construct must be a structured block.
5+
program OmpConstructSections01
6+
use omp_lib
7+
integer :: section_count = 0
8+
integer, parameter :: NT = 4
9+
print *, 'section_count', section_count
10+
!ERROR: invalid branch into an OpenMP structured block
11+
!ERROR: invalid branch into an OpenMP structured block
12+
!ERROR: invalid branch into an OpenMP structured block
13+
if (NT) 20, 30, 40
14+
!ERROR: invalid branch into an OpenMP structured block
15+
goto 20
16+
!$omp sections
17+
!$omp section
18+
print *, "This is a single statement structured block"
19+
!$omp section
20+
open (10, file="random-file-name.txt", err=30)
21+
!ERROR: invalid branch into an OpenMP structured block
22+
!ERROR: invalid branch leaving an OpenMP structured block
23+
open (10, file="random-file-name.txt", err=40)
24+
!$omp section
25+
section_count = section_count + 1
26+
20 print *, 'Entering into section'
27+
call calledFromWithinSection()
28+
print *, 'section_count', section_count
29+
!$omp section
30+
section_count = section_count + 1
31+
print *, 'section_count', section_count
32+
!ERROR: invalid branch leaving an OpenMP structured block
33+
goto 10
34+
!$omp section
35+
30 print *, "Error in opening file"
36+
!$omp end sections
37+
10 print *, 'Jump from section'
38+
39+
!$omp sections
40+
!$omp section
41+
40 print *, 'Error in opening file'
42+
!$omp end sections
43+
end program OmpConstructSections01
44+
45+
function returnFromSections()
46+
!$omp sections
47+
!$omp section
48+
!ERROR: RETURN statement is not allowed in a SECTIONS construct
49+
RETURN
50+
!$omp end sections
51+
end function
52+
53+
subroutine calledFromWithinSection()
54+
print *, "I am called from within a 'section' structured block"
55+
return
56+
end subroutine calledFromWithinSection
57+
58+
subroutine continueWithinSections()
59+
integer i
60+
do i = 1, 10
61+
print *, "Statement within loop but outside section construct"
62+
!$omp sections
63+
!$omp section
64+
IF (i .EQ. 5) THEN
65+
!ERROR: CYCLE to construct outside of SECTIONS construct is not allowed
66+
CYCLE
67+
END IF
68+
!$omp end sections
69+
print *, "Statement within loop but outside section contruct"
70+
end do
71+
72+
!$omp sections
73+
!$omp section
74+
do i = 1, 10
75+
CYCLE
76+
end do
77+
!$omp end sections
78+
79+
!$omp sections
80+
!$omp section
81+
loop_1: do i = 1, 10
82+
IF (i .EQ. 5) THEN
83+
CYCLE loop_1
84+
END IF
85+
end do loop_1
86+
!$omp end sections
87+
88+
loop_2: do i = 1, 10
89+
!$omp sections
90+
!$omp section
91+
IF (i .EQ. 5) THEN
92+
!ERROR: CYCLE to construct 'loop_2' outside of SECTIONS construct is not allowed
93+
CYCLE loop_2
94+
END IF
95+
!$omp end sections
96+
end do loop_2
97+
end subroutine continueWithinSections
98+
99+
subroutine breakWithinSections()
100+
loop_3: do i = 1, 10
101+
!$omp sections
102+
!$omp section
103+
IF (i .EQ. 5) THEN
104+
!ERROR: EXIT to construct 'loop_3' outside of SECTIONS construct is not allowed
105+
EXIT loop_3
106+
END IF
107+
!$omp end sections
108+
end do loop_3
109+
110+
loop_4: do i = 1, 10
111+
!$omp sections
112+
!$omp section
113+
IF (i .EQ. 5) THEN
114+
!ERROR: EXIT to construct outside of SECTIONS construct is not allowed
115+
EXIT
116+
END IF
117+
!$omp end sections
118+
end do loop_4
119+
120+
!$omp sections
121+
!$omp section
122+
do i = 1, 10
123+
IF (i .EQ. 5) THEN
124+
EXIT
125+
END IF
126+
end do
127+
!$omp end sections
128+
129+
!$omp sections
130+
!$omp section
131+
loop_5: do i = 1, 10
132+
IF (i .EQ. 5) THEN
133+
EXIT loop_5
134+
END IF
135+
end do loop_5
136+
!$omp end sections
137+
end subroutine breakWithinSections
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
! RUN: %python %S/test_errors.py %s %flang -fopenmp
2+
!XFAIL: *
3+
! OpenMP version 5.0.0
4+
! 2.8.1 sections construct
5+
! Orphaned section directives are prohibited. That is, the section directives must appear within the sections construct and must not be encountered elsewhere in the sections region
6+
!TODO: Error in parsing. Make parser errors more informative. Until then, the test is XFAIL
7+
8+
program OmpOrphanedSections
9+
use omp_lib
10+
integer counter
11+
counter = 0
12+
!CHECK: expected 'END'
13+
!CHECK: END PROGRAM statement
14+
!CHECK: in the context: main program
15+
!CHECK: expected 'END PROGRAM'
16+
!CHECK: in the context: END PROGRAM statement
17+
!CHECK: in the context: main program
18+
!$omp section
19+
print *, "An orphaned section containing a single statement"
20+
!$omp section
21+
counter = counter + 1
22+
print *, "An orphaned section containing multiple statements"
23+
!$omp sections
24+
!$omp section
25+
print *, "Not an orphan structured block"
26+
!$omp end sections
27+
end program OmpOrphanedSections

flang/test/Semantics/omp-simd01.f90

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,40 @@
1-
! RUN: not %flang -fsyntax-only -fopenmp %s 2>&1 | FileCheck %s
2-
! OpenMP Version 4.5
3-
! 2.8.1 simd Construct
4-
! A program that branches into or out of a simd region is non-conforming.
1+
! RUN: %python %S/test_errors.py %s %flang -fopenmp
2+
! OpenMP Version 5.0
3+
! 2.9.3.1 simd Construct
4+
! - A program that branches into or out of a simd region is non-conforming.
5+
! - The associated loops must be structured blocks
56

67
program omp_simd
7-
integer i, j
8+
integer i, j
89

9-
!$omp simd
10-
do i = 1, 10
11-
do j = 1, 10
12-
print *, "omp simd"
13-
!CHECK: invalid branch leaving an OpenMP structured block
14-
goto 10
15-
end do
16-
end do
17-
!$omp end simd
18-
19-
!CHECK: Outside the enclosing SIMD directive
20-
10 stop
10+
!$omp simd
11+
do i = 1, 10
12+
do j = 1, 10
13+
print *, "omp simd"
14+
!ERROR: invalid branch leaving an OpenMP structured block
15+
goto 10
16+
end do
17+
if (i .EQ. 5) THEN
18+
call function1()
19+
else if (i .EQ. 7) THEN
20+
open (10, file="random-file-name.txt", err=20)
21+
20 print *, "Error message doesn't branch out of the loop's structured block"
22+
else
23+
!ERROR: invalid branch leaving an OpenMP structured block
24+
open (10, file="random-file-name.txt", err=10)
25+
end if
26+
end do
27+
!$omp end simd
28+
10 stop
2129

2230
end program omp_simd
31+
32+
subroutine function1()
33+
integer i, option
34+
option = 1
35+
!$omp simd
36+
do i = 1, 10
37+
print *, "CORRECT SIMD LOOP"
38+
end do
39+
!$omp end simd
40+
end subroutine function1

0 commit comments

Comments
 (0)