-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[OpenMP] Missing implicit otherwise clause in metadirective. #127113
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@llvm/pr-subscribers-flang-openmp @llvm/pr-subscribers-clang Author: Zahira Ammarguellat (zahiraam) ChangesCompiling this: is generating an error: Full diff: https://github.com/llvm/llvm-project/pull/127113.diff 4 Files Affected:
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index a455659ca8f2c..0f68d4002ad8e 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2882,6 +2882,12 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
/*ReadDirectiveWithinMetadirective=*/true);
break;
}
+ // If no match is found and no otherwise clause is present, skip
+ // OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as
+ // if one was specified without an associated directive variant.
+ if (BestIdx == -1 && Idx == 1) {
+ SkipUntil(tok::annot_pragma_openmp_end);
+ }
break;
}
case OMPD_threadprivate: {
diff --git a/clang/test/OpenMP/metadirective_ast_print.c b/clang/test/OpenMP/metadirective_ast_print.c
index d9ff7e7645216..06991c6f06a02 100644
--- a/clang/test/OpenMP/metadirective_ast_print.c
+++ b/clang/test/OpenMP/metadirective_ast_print.c
@@ -77,6 +77,24 @@ void foo(void) {
: parallel) default(nothing)
for (int i = 0; i < 16; i++)
;
+
+#pragma omp metadirective when(user = {condition(0)} \
+ : parallel for) otherwise()
+ for (int i=0; i<10; i++)
+ ;
+#pragma omp metadirective when(user = {condition(0)} \
+ : parallel for)
+ for (int i=0; i<10; i++)
+ ;
+
+#pragma omp metadirective when(user = {condition(1)} \
+ : parallel for) otherwise()
+ for (int i=0; i<10; i++)
+ ;
+#pragma omp metadirective when(user = {condition(1)} \
+ : parallel for)
+ for (int i=0; i<10; i++)
+ ;
}
// CHECK: void bar(void);
diff --git a/clang/test/OpenMP/metadirective_otherwise.cpp b/clang/test/OpenMP/metadirective_otherwise.cpp
new file mode 100644
index 0000000000000..50c9fe8a2b0e7
--- /dev/null
+++ b/clang/test/OpenMP/metadirective_otherwise.cpp
@@ -0,0 +1,72 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux -emit-llvm %s -o - | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+void func1() {
+#pragma omp metadirective when(user = {condition(0)} \
+ : parallel for) otherwise()
+ for (int i = 0; i < 100; i++)
+ ;
+
+#pragma omp metadirective when(user = {condition(0)} \
+ : parallel for)
+ for (int i = 0; i < 100; i++)
+ ;
+}
+
+// CHECK-LABEL: define dso_local void @_Z5func1v()
+// CHECK: entry
+// CHECK-NEXT: [[I:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[I1:%.*]] = alloca i32, align 4
+// CHECK-NEXT: store i32 0, ptr [[I]], align 4
+// CHECK-NEXT: br label %[[FOR_COND:.*]]
+// CHECK: [[FOR_COND]]:
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[I]], align 4
+// CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP0]], 100
+// CHECK-NEXT: br i1 [[CMP]], label %[[FOR_BODY:.*]], label %[[FOR_END:.*]]
+// CHECK: [[FOR_BODY]]:
+// CHECK-NEXT: br label %[[FOR_INC:.*]]
+// CHECK: [[FOR_INC]]:
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[I]], align 4
+// CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1
+// CHECK-NEXT: store i32 [[INC]], ptr [[I]], align 4
+// CHECK-NEXT: br label %[[FOR_COND]], !llvm.loop [[LOOP3:![0-9]+]]
+// CHECK: [[FOR_END]]:
+// CHECK-NEXT: store i32 0, ptr [[I1]], align 4
+// CHECK-NEXT: br label %[[FOR_COND2:.*]]
+// CHECK: [[FOR_COND2]]:
+// CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[I1]], align 4
+// CHECK-NEXT: [[CMP3:%.*]] = icmp slt i32 [[TMP2]], 100
+// CHECK-NEXT: br i1 [[CMP3]], label %[[FOR_BODY4:.*]], label %[[FOR_END7:.*]]
+// CHECK: [[FOR_BODY4]]:
+// CHECK-NEXT: br label %[[FOR_INC5:.*]]
+// CHECK: [[FOR_INC5]]:
+// CHECK-NEXT: [[TMP3:%.*]] = load i32, ptr [[I1]], align 4
+// CHECK-NEXT: [[INC6:%.*]] = add nsw i32 [[TMP3]], 1
+// CHECK-NEXT: store i32 [[INC6]], ptr [[I1]], align 4
+// CHECK-NEXT: br label %[[FOR_COND2]], !llvm.loop [[LOOP5:![0-9]+]]
+// CHECK: [[FOR_END7]]:
+// CHECK-NEXT: ret void
+
+void func2() {
+#pragma omp metadirective when(user = {condition(1)} \
+ : parallel for) otherwise()
+ for (int i = 0; i < 100; i++)
+ ;
+
+#pragma omp metadirective when(user = {condition(1)} \
+ : parallel for)
+ for (int i = 0; i < 100; i++)
+ ;
+}
+
+// CHECK-LABEL: define dso_local void @_Z5func2v()
+// CHECK: entry
+// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2:[0-9]+]], i32 0, ptr @_Z5func2v.omp_outlined)
+// CHECK-NEXT: call void (ptr, i32, ptr, ...) @__kmpc_fork_call(ptr @[[GLOB2]], i32 0, ptr @_Z5func2v.omp_outlined.1)
+// CHECK-NEXT: ret void
+
+
+#endif
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
index a501eaf2356ff..26163fdb4b63d 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
+++ b/llvm/include/llvm/Frontend/OpenMP/OMPContext.h
@@ -188,7 +188,7 @@ bool isVariantApplicableInContext(const VariantMatchInfo &VMI,
bool DeviceSetOnly = false);
/// Return the index (into \p VMIs) of the variant with the highest score
-/// from the ones applicble in \p Ctx. See llvm::isVariantApplicableInContext.
+/// from the ones applicable in \p Ctx. See llvm::isVariantApplicableInContext.
int getBestVariantMatchForContext(const SmallVectorImpl<VariantMatchInfo> &VMIs,
const OMPContext &Ctx);
|
clang/lib/Parse/ParseOpenMP.cpp
Outdated
if (BestIdx == -1 && Idx == 1) { | ||
SkipUntil(tok::annot_pragma_openmp_end); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure skipUntil is good here, since you may miss some junk at the end of the directive
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this enough to not miss the potential upcoming tokens?
✅ With the latest revision this PR passed the C/C++ code formatter. |
clang/lib/Parse/ParseOpenMP.cpp
Outdated
// OMP5.2 Chapter 7.4: If no otherwise clause is specified the effect is as | ||
// if one was specified without an associated directive variant. | ||
if (BestIdx == -1 && Idx == 1) { | ||
SkipUntil(tok::annot_pragma_openmp_end,tok::identifier); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You still losing some data, SkipUntil does not work here
clang/lib/Parse/ParseOpenMP.cpp
Outdated
if (BestIdx == -1 && Idx == 1) { | ||
ConsumeAnnotationToken(); | ||
return StmtEmpty(); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you have a test for the situation where you have extra tokens at this point? Or only tok::annot_pragma_openmp_end is expected here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Line #89 of OpenMP/metadirective_ast_print.c
show this situation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add an assertion here, that the next expected token is tok::annot_pragma_openmp_end?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next expected token should be kw_for
no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, before ConsumeAnnotationToken();
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all cases I am seeing, at this point Tok=annot_pragma_openmp_end
and NextToken = kw_for
. Asserting here would not work! But doesn't it make sense to have the kw_for
right at the end of the pragma?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, check that Tok=annot_pragma_openmp_end
, this is what I meant
@alexey-bataev Thanks for the reviews. |
…7113) Compiling this: `int main() {` ` #pragma omp metadirective when(use r= {condition(0)}` `: parallel for)` `for (int i=0; i<10; i++)` ; }` is generating an error: `error: expected expression` The compiler is interpreting this as if it's compiling a `#pragma omp metadirective` with no `otherwise` clause. In the OMP5.2 specs chapter 7.4 it's mentioned that: `If no otherwise clause is specified the effect is as if one was specified without an associated directive variant.` This patch fixes the issue.
Compiling this:
int main() {
#pragma omp metadirective when(use r= {condition(0)}
: parallel for)
for (int i=0; i<10; i++)
;
}`
is generating an error:
error: expected expression
The compiler is interpreting this as if it's compiling a
#pragma omp metadirective
with nootherwise
clause.In the OMP5.2 specs chapter 7.4 it's mentioned that:
If no otherwise clause is specified the effect is as if one was specified without an associated directive variant.
This patch fixes the issue.