[clang] dd4c838 - [OpenMP] Allow data members in interop init/use/destroy clauses
Mike Rice via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 11 09:39:45 PDT 2022
Author: Mike Rice
Date: 2022-08-11T09:39:12-07:00
New Revision: dd4c838da30ad4b6d5dc0f700df0a6629469f719
URL: https://github.com/llvm/llvm-project/commit/dd4c838da30ad4b6d5dc0f700df0a6629469f719
DIFF: https://github.com/llvm/llvm-project/commit/dd4c838da30ad4b6d5dc0f700df0a6629469f719.diff
LOG: [OpenMP] Allow data members in interop init/use/destroy clauses
Previously a diagnostic was given if the expression was not strictly a
DeclRef. Now also allow use of data members inside member functions.
Differential Revision: https://reviews.llvm.org/D131222
Added:
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaOpenMP.cpp
clang/test/OpenMP/interop_ast_print.cpp
clang/test/OpenMP/interop_irbuilder.cpp
clang/test/OpenMP/interop_messages.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 92217aed89747..e4e7d7b7338a4 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -10387,6 +10387,9 @@ def err_omp_unexpected_clause_value : Error<
"expected %0 in OpenMP clause '%1'">;
def err_omp_expected_var_name_member_expr : Error<
"expected variable name%select{| or data member of current class}0">;
+def err_omp_expected_var_name_member_expr_with_type : Error<
+ "expected variable%select{| or static data member|, static data member, "
+ "or non-static data member of current class}0 of type '%1'">;
def err_omp_expected_var_name_member_expr_or_array_item : Error<
"expected variable name%select{|, data member of current class}0, array element or array section">;
def err_omp_expected_addressable_lvalue_or_array_item : Error<
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 3b1aab6ca0e5f..1d9ec1162bafb 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -2718,7 +2718,8 @@ void Sema::EndOpenMPClause() {
static std::pair<ValueDecl *, bool>
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
- SourceRange &ERange, bool AllowArraySection = false);
+ SourceRange &ERange, bool AllowArraySection = false,
+ StringRef DiagType = "");
/// Check consistency of the reduction clauses.
static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
@@ -5279,7 +5280,8 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind Kind,
static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
SourceLocation &ELoc,
SourceRange &ERange,
- bool AllowArraySection) {
+ bool AllowArraySection,
+ StringRef DiagType) {
if (RefExpr->isTypeDependent() || RefExpr->isValueDependent() ||
RefExpr->containsUnexpandedParameterPack())
return std::make_pair(nullptr, true);
@@ -5324,6 +5326,12 @@ static std::pair<ValueDecl *, bool> getPrivateItem(Sema &S, Expr *&RefExpr,
if (IsArrayExpr != NoArrayExpr) {
S.Diag(ELoc, diag::err_omp_expected_base_var_name)
<< IsArrayExpr << ERange;
+ } else if (!DiagType.empty()) {
+ unsigned DiagSelect = S.getLangOpts().CPlusPlus
+ ? (S.getCurrentThisType().isNull() ? 1 : 2)
+ : 0;
+ S.Diag(ELoc, diag::err_omp_expected_var_name_member_expr_with_type)
+ << DiagSelect << DiagType << ERange;
} else {
S.Diag(ELoc,
AllowArraySection
@@ -17249,32 +17257,28 @@ StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
// OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
// Each interop-var may be specified for at most one action-clause of each
// interop construct.
- llvm::SmallPtrSet<const VarDecl *, 4> InteropVars;
- for (const OMPClause *C : Clauses) {
+ llvm::SmallPtrSet<const ValueDecl *, 4> InteropVars;
+ for (OMPClause *C : Clauses) {
OpenMPClauseKind ClauseKind = C->getClauseKind();
- const DeclRefExpr *DRE = nullptr;
- SourceLocation VarLoc;
+ std::pair<ValueDecl *, bool> DeclResult;
+ SourceLocation ELoc;
+ SourceRange ERange;
if (ClauseKind == OMPC_init) {
- const auto *IC = cast<OMPInitClause>(C);
- VarLoc = IC->getVarLoc();
- DRE = dyn_cast_or_null<DeclRefExpr>(IC->getInteropVar());
+ auto *E = cast<OMPInitClause>(C)->getInteropVar();
+ DeclResult = getPrivateItem(*this, E, ELoc, ERange);
} else if (ClauseKind == OMPC_use) {
- const auto *UC = cast<OMPUseClause>(C);
- VarLoc = UC->getVarLoc();
- DRE = dyn_cast_or_null<DeclRefExpr>(UC->getInteropVar());
+ auto *E = cast<OMPUseClause>(C)->getInteropVar();
+ DeclResult = getPrivateItem(*this, E, ELoc, ERange);
} else if (ClauseKind == OMPC_destroy) {
- const auto *DC = cast<OMPDestroyClause>(C);
- VarLoc = DC->getVarLoc();
- DRE = dyn_cast_or_null<DeclRefExpr>(DC->getInteropVar());
+ auto *E = cast<OMPDestroyClause>(C)->getInteropVar();
+ DeclResult = getPrivateItem(*this, E, ELoc, ERange);
}
- if (!DRE)
- continue;
-
- if (const auto *VD = dyn_cast<VarDecl>(DRE->getDecl())) {
- if (!InteropVars.insert(VD->getCanonicalDecl()).second) {
- Diag(VarLoc, diag::err_omp_interop_var_multiple_actions) << VD;
+ if (DeclResult.first) {
+ if (!InteropVars.insert(DeclResult.first).second) {
+ Diag(ELoc, diag::err_omp_interop_var_multiple_actions)
+ << DeclResult.first;
return StmtError();
}
}
@@ -17286,16 +17290,20 @@ StmtResult Sema::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
static bool isValidInteropVariable(Sema &SemaRef, Expr *InteropVarExpr,
SourceLocation VarLoc,
OpenMPClauseKind Kind) {
- if (InteropVarExpr->isValueDependent() || InteropVarExpr->isTypeDependent() ||
- InteropVarExpr->isInstantiationDependent() ||
- InteropVarExpr->containsUnexpandedParameterPack())
+ SourceLocation ELoc;
+ SourceRange ERange;
+ Expr *RefExpr = InteropVarExpr;
+ auto Res =
+ getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
+ /*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
+
+ if (Res.second) {
+ // It will be analyzed later.
return true;
+ }
- const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr);
- if (!DRE || !isa<VarDecl>(DRE->getDecl())) {
- SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0;
+ if (!Res.first)
return false;
- }
// Interop variable should be of type omp_interop_t.
bool HasError = false;
diff --git a/clang/test/OpenMP/interop_ast_print.cpp b/clang/test/OpenMP/interop_ast_print.cpp
index 8f8ddc839c722..1a492fb0a8319 100644
--- a/clang/test/OpenMP/interop_ast_print.cpp
+++ b/clang/test/OpenMP/interop_ast_print.cpp
@@ -23,6 +23,57 @@
typedef void *omp_interop_t;
+struct S {
+ omp_interop_t o1;
+ omp_interop_t o2;
+ omp_interop_t o3;
+ static omp_interop_t so;
+ void foo();
+ S();
+ ~S();
+};
+omp_interop_t S::so;
+
+struct T {
+ static void static_member_func();
+ static omp_interop_t to;
+};
+omp_interop_t T::to;
+
+void T::static_member_func() {
+ omp_interop_t o1;
+ //PRINT: #pragma omp interop init(target : o1)
+ #pragma omp interop init(target:o1)
+
+ //PRINT: #pragma omp interop init(target : to)
+ #pragma omp interop init(target: to)
+
+ //PRINT: #pragma omp interop init(target : T::to)
+ #pragma omp interop init(target: T::to)
+
+ //PRINT: #pragma omp interop init(target : S::so)
+ #pragma omp interop init(target: S::so)
+}
+
+
+S::S() {
+ //PRINT: #pragma omp interop init(target : this->o1)
+ #pragma omp interop init(target:o1)
+ //PRINT: #pragma omp interop use(this->o1) init(target : this->o2)
+ #pragma omp interop use(o1) init(target:o2)
+ //PRINT: #pragma omp interop use(this->o2) init(target : this->o3)
+ #pragma omp interop use(o2) init(target:o3)
+}
+S::~S() {
+ //PRINT: #pragma omp interop destroy(this->o1) destroy(this->o2) destroy(this->o3)
+ #pragma omp interop destroy(o1) destroy(o2) destroy(o3)
+}
+
+void S::foo() {
+ //PRINT: #pragma omp interop init(target : so)
+ #pragma omp interop init(target:so)
+}
+
//PRINT-LABEL: void foo1(
//DUMP-LABEL: FunctionDecl {{.*}} foo1
void foo1(int *ap, int dev) {
@@ -196,6 +247,9 @@ void foo1(int *ap, int dev) {
//DUMP: OMPUseClause
//DUMP: DeclRefExpr{{.*}}'omp_interop_t'{{.*}}Var{{.*}}'J'
#pragma omp interop destroy(I) use(J)
+
+ //PRINT: #pragma omp interop init(target : S::so)
+ #pragma omp interop init(target: S::so)
}
//DUMP: FunctionTemplateDecl{{.*}}fooTemp
@@ -274,6 +328,7 @@ void bar()
fooTemp<3>();
omp_interop_t Ivar;
barTemp(Ivar);
+ S s;
}
#endif // HEADER
diff --git a/clang/test/OpenMP/interop_irbuilder.cpp b/clang/test/OpenMP/interop_irbuilder.cpp
index bd18caa21423c..2cf2d56f16371 100644
--- a/clang/test/OpenMP/interop_irbuilder.cpp
+++ b/clang/test/OpenMP/interop_irbuilder.cpp
@@ -29,6 +29,34 @@ void test1() {
: D0, D1)
}
+struct S {
+ omp_interop_t interop;
+ void member_test();
+};
+
+void S::member_test() {
+
+ int device_id = 4;
+ int D0, D1;
+
+#pragma omp interop init(target \
+ : interop)
+
+#pragma omp interop init(targetsync \
+ : interop)
+
+#pragma omp interop init(target \
+ : interop) device(device_id)
+
+#pragma omp interop init(targetsync \
+ : interop) device(device_id)
+
+#pragma omp interop use(interop) depend(in \
+ : D0, D1) nowait
+
+#pragma omp interop destroy(interop) depend(in \
+ : D0, D1)
+}
// CHECK-LABEL: @_Z5test1v(
// CHECK-NEXT: entry:
// CHECK-NEXT: [[DEVICE_ID:%.*]] = alloca i32, align 4
@@ -94,3 +122,77 @@ void test1() {
// CHECK-NEXT: call void @__tgt_interop_destroy(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM7]], i8** [[INTEROP]], i32 -1, i32 2, i8* [[TMP25]], i32 0)
// CHECK-NEXT: ret void
//
+//
+// CHECK-LABEL: @_ZN1S11member_testEv(
+// CHECK-NEXT: entry:
+// CHECK-NEXT: [[THIS_ADDR:%.*]] = alloca %struct.S*, align 8
+// CHECK-NEXT: [[DEVICE_ID:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[D0:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[D1:%.*]] = alloca i32, align 4
+// CHECK-NEXT: [[DOTDEP_ARR_ADDR:%.*]] = alloca [2 x %struct.kmp_depend_info], align 8
+// CHECK-NEXT: [[DEP_COUNTER_ADDR:%.*]] = alloca i64, align 8
+// CHECK-NEXT: [[DOTDEP_ARR_ADDR10:%.*]] = alloca [2 x %struct.kmp_depend_info], align 8
+// CHECK-NEXT: [[DEP_COUNTER_ADDR11:%.*]] = alloca i64, align 8
+// CHECK-NEXT: store %struct.S* [[THIS:%.*]], %struct.S** [[THIS_ADDR]], align 8
+// CHECK-NEXT: [[THIS1:%.*]] = load %struct.S*, %struct.S** [[THIS_ADDR]], align 8
+// CHECK-NEXT: store i32 4, i32* [[DEVICE_ID]], align 4
+// CHECK-NEXT: [[INTEROP:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_init(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM]], i8** [[INTEROP]], i64 1, i32 -1, i32 0, i8* null, i32 0)
+// CHECK-NEXT: [[INTEROP2:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM3:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_init(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM3]], i8** [[INTEROP2]], i64 2, i32 -1, i32 0, i8* null, i32 0)
+// CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[DEVICE_ID]], align 4
+// CHECK-NEXT: [[INTEROP4:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM5:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_init(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM5]], i8** [[INTEROP4]], i64 1, i32 [[TMP0]], i32 0, i8* null, i32 0)
+// CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[DEVICE_ID]], align 4
+// CHECK-NEXT: [[INTEROP6:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM7:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_init(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM7]], i8** [[INTEROP6]], i64 2, i32 [[TMP1]], i32 0, i8* null, i32 0)
+// CHECK-NEXT: [[TMP2:%.*]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DOTDEP_ARR_ADDR]], i64 0, i64 0
+// CHECK-NEXT: [[TMP3:%.*]] = ptrtoint i32* [[D0]] to i64
+// CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_KMP_DEPEND_INFO:%.*]], %struct.kmp_depend_info* [[TMP2]], i64 0
+// CHECK-NEXT: [[TMP5:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP4]], i32 0, i32 0
+// CHECK-NEXT: store i64 [[TMP3]], i64* [[TMP5]], align 8
+// CHECK-NEXT: [[TMP6:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP4]], i32 0, i32 1
+// CHECK-NEXT: store i64 4, i64* [[TMP6]], align 8
+// CHECK-NEXT: [[TMP7:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP4]], i32 0, i32 2
+// CHECK-NEXT: store i8 1, i8* [[TMP7]], align 8
+// CHECK-NEXT: [[TMP8:%.*]] = ptrtoint i32* [[D1]] to i64
+// CHECK-NEXT: [[TMP9:%.*]] = getelementptr [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP2]], i64 1
+// CHECK-NEXT: [[TMP10:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP9]], i32 0, i32 0
+// CHECK-NEXT: store i64 [[TMP8]], i64* [[TMP10]], align 8
+// CHECK-NEXT: [[TMP11:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP9]], i32 0, i32 1
+// CHECK-NEXT: store i64 4, i64* [[TMP11]], align 8
+// CHECK-NEXT: [[TMP12:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP9]], i32 0, i32 2
+// CHECK-NEXT: store i8 1, i8* [[TMP12]], align 8
+// CHECK-NEXT: store i64 2, i64* [[DEP_COUNTER_ADDR]], align 8
+// CHECK-NEXT: [[TMP13:%.*]] = bitcast %struct.kmp_depend_info* [[TMP2]] to i8*
+// CHECK-NEXT: [[INTEROP8:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM9:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_use(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM9]], i8** [[INTEROP8]], i32 -1, i32 2, i8* [[TMP13]], i32 1)
+// CHECK-NEXT: [[TMP14:%.*]] = getelementptr inbounds [2 x %struct.kmp_depend_info], [2 x %struct.kmp_depend_info]* [[DOTDEP_ARR_ADDR10]], i64 0, i64 0
+// CHECK-NEXT: [[TMP15:%.*]] = ptrtoint i32* [[D0]] to i64
+// CHECK-NEXT: [[TMP16:%.*]] = getelementptr [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP14]], i64 0
+// CHECK-NEXT: [[TMP17:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP16]], i32 0, i32 0
+// CHECK-NEXT: store i64 [[TMP15]], i64* [[TMP17]], align 8
+// CHECK-NEXT: [[TMP18:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP16]], i32 0, i32 1
+// CHECK-NEXT: store i64 4, i64* [[TMP18]], align 8
+// CHECK-NEXT: [[TMP19:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP16]], i32 0, i32 2
+// CHECK-NEXT: store i8 1, i8* [[TMP19]], align 8
+// CHECK-NEXT: [[TMP20:%.*]] = ptrtoint i32* [[D1]] to i64
+// CHECK-NEXT: [[TMP21:%.*]] = getelementptr [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP14]], i64 1
+// CHECK-NEXT: [[TMP22:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP21]], i32 0, i32 0
+// CHECK-NEXT: store i64 [[TMP20]], i64* [[TMP22]], align 8
+// CHECK-NEXT: [[TMP23:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP21]], i32 0, i32 1
+// CHECK-NEXT: store i64 4, i64* [[TMP23]], align 8
+// CHECK-NEXT: [[TMP24:%.*]] = getelementptr inbounds [[STRUCT_KMP_DEPEND_INFO]], %struct.kmp_depend_info* [[TMP21]], i32 0, i32 2
+// CHECK-NEXT: store i8 1, i8* [[TMP24]], align 8
+// CHECK-NEXT: store i64 2, i64* [[DEP_COUNTER_ADDR11]], align 8
+// CHECK-NEXT: [[TMP25:%.*]] = bitcast %struct.kmp_depend_info* [[TMP14]] to i8*
+// CHECK-NEXT: [[INTEROP12:%.*]] = getelementptr inbounds [[STRUCT_S]], %struct.S* [[THIS1]], i32 0, i32 0
+// CHECK-NEXT: [[OMP_GLOBAL_THREAD_NUM13:%.*]] = call i32 @__kmpc_global_thread_num(%struct.ident_t* @[[GLOB1]])
+// CHECK-NEXT: call void @__tgt_interop_destroy(%struct.ident_t* @[[GLOB1]], i32 [[OMP_GLOBAL_THREAD_NUM13]], i8** [[INTEROP12]], i32 -1, i32 2, i8* [[TMP25]], i32 0)
+// CHECK-NEXT: ret void
+//
diff --git a/clang/test/OpenMP/interop_messages.cpp b/clang/test/OpenMP/interop_messages.cpp
index 50f1efb5a6a9b..8707b5d89cf38 100644
--- a/clang/test/OpenMP/interop_messages.cpp
+++ b/clang/test/OpenMP/interop_messages.cpp
@@ -1,5 +1,6 @@
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - -DWITHDEF %s
// RUN: %clang_cc1 -verify -fopenmp -std=c++11 -o - -DWITHOUTDEF %s
+// RUN: %clang_cc1 -verify -fopenmp -std=c99 -x c -o - -DCTEST %s
#ifdef WITHDEF
typedef void *omp_interop_t;
@@ -55,13 +56,13 @@ void foo(int *Ap) {
#pragma omp interop destroy(SVar) destroy(Another)
int a, b;
- //expected-error at +1 {{expected variable of type 'omp_interop_t'}}
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
#pragma omp interop init(target:a+b) init(target:Another)
- //expected-error at +1 {{expected variable of type 'omp_interop_t'}}
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
#pragma omp interop use(a+b) use(Another)
- //expected-error at +1 {{expected variable of type 'omp_interop_t'}}
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
#pragma omp interop destroy(a+b) destroy(Another)
const omp_interop_t C = (omp_interop_t)5;
@@ -115,6 +116,61 @@ void foo(int *Ap) {
//expected-error at +1 {{directive '#pragma omp interop' cannot contain more than one 'nowait' clause}}
#pragma omp interop nowait init(target:InteropVar) nowait
}
+
+struct S {
+ void foo();
+ omp_interop_t InteropVar;
+ omp_interop_t func();
+ static omp_interop_t sfunc();
+};
+
+struct T {
+ static void static_member_func();
+};
+
+void T::static_member_func() {
+ S s;
+ omp_interop_t o;
+
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
+ #pragma omp interop init(target:s.InteropVar) init(target:o)
+}
+
+void S::foo() {
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop init(target:InteropVar) init(target:InteropVar)
+
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop use(InteropVar) use(InteropVar)
+
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop destroy(InteropVar) destroy(InteropVar)
+
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop init(target:InteropVar) use(InteropVar)
+
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop init(target:InteropVar) destroy(InteropVar)
+
+ //expected-error at +1 {{interop variable 'InteropVar' used in multiple action clauses}}
+ #pragma omp interop use(InteropVar) destroy(InteropVar)
+
+ //expected-error at +1 {{expected variable, static data member, or non-static data member of current class of type 'omp_interop_t'}}
+ #pragma omp interop init(target:InteropVar) init(target:func())
+
+ //expected-error at +1 {{expected variable, static data member, or non-static data member of current class of type 'omp_interop_t'}}
+ #pragma omp interop init(target:InteropVar) init(target:sfunc())
+}
+
+void foo2() {
+ S s;
+ omp_interop_t another;
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
+ #pragma omp interop init(target:s.InteropVar) init(target:another)
+
+ //expected-error at +1 {{expected variable or static data member of type 'omp_interop_t'}}
+ #pragma omp interop init(target: S::sfunc()) init(target:another)
+}
#endif
#ifdef WITHOUTDEF
void foo() {
@@ -127,3 +183,20 @@ void foo() {
#pragma omp interop destroy(InteropVar) nowait
}
#endif
+#ifdef CTEST
+typedef void *omp_interop_t;
+omp_interop_t bar();
+struct S {
+ omp_interop_t o;
+};
+void foo() {
+ omp_interop_t o;
+ struct S s;
+
+ //expected-error at +1 {{expected variable of type 'omp_interop_t'}}
+ #pragma omp interop init(target:o) init(target:bar())
+
+ //expected-error at +1 {{expected variable of type 'omp_interop_t'}}
+ #pragma omp interop init(target:o) init(target:s.o)
+}
+#endif
More information about the cfe-commits
mailing list