Skip to content

Commit b0181be

Browse files
authored
[OpenACC] Implement Duffs-Device restriction for Compute Constructs (llvm#83460)
Like the last few patches, branching in/out of a compute construct is not valid. This patch implements checking to ensure that a 'case' or 'default' statement cannot jump into a Compute Construct (in the style of a duff's device!).
1 parent f15d799 commit b0181be

File tree

4 files changed

+89
-1
lines changed

4 files changed

+89
-1
lines changed

clang/include/clang/Sema/Scope.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,25 @@ class Scope {
534534
return false;
535535
}
536536

537+
/// Determine if this scope (or its parents) are a compute construct inside of
538+
/// the nearest 'switch' scope. This is needed to check whether we are inside
539+
/// of a 'duffs' device, which is an illegal branch into a compute construct.
540+
bool isInOpenACCComputeConstructBeforeSwitch() const {
541+
for (const Scope *S = this; S; S = S->getParent()) {
542+
if (S->getFlags() & Scope::OpenACCComputeConstructScope)
543+
return true;
544+
if (S->getFlags() & Scope::SwitchScope)
545+
return false;
546+
547+
if (S->getFlags() &
548+
(Scope::FnScope | Scope::ClassScope | Scope::BlockScope |
549+
Scope::TemplateParamScope | Scope::FunctionPrototypeScope |
550+
Scope::AtCatchScope | Scope::ObjCMethodScope))
551+
return false;
552+
}
553+
return false;
554+
}
555+
537556
/// Determine whether this scope is a while/do/for statement, which can have
538557
/// continue statements embedded into it.
539558
bool isContinueScope() const {

clang/lib/Sema/SemaStmt.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -527,6 +527,13 @@ Sema::ActOnCaseStmt(SourceLocation CaseLoc, ExprResult LHSVal,
527527
return StmtError();
528528
}
529529

530+
if (LangOpts.OpenACC &&
531+
getCurScope()->isInOpenACCComputeConstructBeforeSwitch()) {
532+
Diag(CaseLoc, diag::err_acc_branch_in_out_compute_construct)
533+
<< /*branch*/ 0 << /*into*/ 1;
534+
return StmtError();
535+
}
536+
530537
auto *CS = CaseStmt::Create(Context, LHSVal.get(), RHSVal.get(),
531538
CaseLoc, DotDotDotLoc, ColonLoc);
532539
getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(CS);
@@ -546,6 +553,13 @@ Sema::ActOnDefaultStmt(SourceLocation DefaultLoc, SourceLocation ColonLoc,
546553
return SubStmt;
547554
}
548555

556+
if (LangOpts.OpenACC &&
557+
getCurScope()->isInOpenACCComputeConstructBeforeSwitch()) {
558+
Diag(DefaultLoc, diag::err_acc_branch_in_out_compute_construct)
559+
<< /*branch*/ 0 << /*into*/ 1;
560+
return StmtError();
561+
}
562+
549563
DefaultStmt *DS = new (Context) DefaultStmt(DefaultLoc, ColonLoc, SubStmt);
550564
getCurFunction()->SwitchStack.back().getPointer()->addSwitchCase(DS);
551565
return DS;

clang/test/SemaOpenACC/no-branch-in-out.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,30 @@ LABEL4:{}
310310

311311
ptr=&&LABEL5;
312312
}
313+
314+
void DuffsDevice() {
315+
int j;
316+
switch (j) {
317+
#pragma acc parallel
318+
for(int i =0; i < 5; ++i) {
319+
case 0: // expected-error{{invalid branch into OpenACC Compute Construct}}
320+
{}
321+
}
322+
}
323+
324+
switch (j) {
325+
#pragma acc parallel
326+
for(int i =0; i < 5; ++i) {
327+
default: // expected-error{{invalid branch into OpenACC Compute Construct}}
328+
{}
329+
}
330+
}
331+
332+
switch (j) {
333+
#pragma acc parallel
334+
for(int i =0; i < 5; ++i) {
335+
case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}}
336+
{}
337+
}
338+
}
339+
}

clang/test/SemaOpenACC/no-branch-in-out.cpp

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ void ReturnTest() {
1818

1919
template<typename T>
2020
void BreakContinue() {
21-
2221
#pragma acc parallel
2322
for(int i =0; i < 5; ++i) {
2423
switch(i) {
@@ -109,6 +108,35 @@ void BreakContinue() {
109108
} while (j );
110109
}
111110

111+
template<typename T>
112+
void DuffsDevice() {
113+
int j;
114+
switch (j) {
115+
#pragma acc parallel
116+
for(int i =0; i < 5; ++i) {
117+
case 0: // expected-error{{invalid branch into OpenACC Compute Construct}}
118+
{}
119+
}
120+
}
121+
122+
switch (j) {
123+
#pragma acc parallel
124+
for(int i =0; i < 5; ++i) {
125+
default: // expected-error{{invalid branch into OpenACC Compute Construct}}
126+
{}
127+
}
128+
}
129+
130+
switch (j) {
131+
#pragma acc parallel
132+
for(int i =0; i < 5; ++i) {
133+
case 'a' ... 'z': // expected-error{{invalid branch into OpenACC Compute Construct}}
134+
{}
135+
}
136+
}
137+
}
138+
112139
void Instantiate() {
113140
BreakContinue<int>();
141+
DuffsDevice<int>();
114142
}

0 commit comments

Comments
 (0)