forked from OSchip/llvm-project
[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
This commit is contained in:
parent
c6c5944d05
commit
dd4c838da3
|
@ -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<
|
||||
|
|
|
@ -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,17 +17290,21 @@ 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())
|
||||
return true;
|
||||
SourceLocation ELoc;
|
||||
SourceRange ERange;
|
||||
Expr *RefExpr = InteropVarExpr;
|
||||
auto Res =
|
||||
getPrivateItem(SemaRef, RefExpr, ELoc, ERange,
|
||||
/*AllowArraySection=*/false, /*DiagType=*/"omp_interop_t");
|
||||
|
||||
const auto *DRE = dyn_cast<DeclRefExpr>(InteropVarExpr);
|
||||
if (!DRE || !isa<VarDecl>(DRE->getDecl())) {
|
||||
SemaRef.Diag(VarLoc, diag::err_omp_interop_variable_expected) << 0;
|
||||
return false;
|
||||
if (Res.second) {
|
||||
// It will be analyzed later.
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!Res.first)
|
||||
return false;
|
||||
|
||||
// Interop variable should be of type omp_interop_t.
|
||||
bool HasError = false;
|
||||
QualType InteropType;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
//
|
||||
|
|
|
@ -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@+1 {{expected variable of type 'omp_interop_t'}}
|
||||
//expected-error@+1 {{expected variable or static data member of type 'omp_interop_t'}}
|
||||
#pragma omp interop init(target:a+b) init(target:Another)
|
||||
|
||||
//expected-error@+1 {{expected variable of type 'omp_interop_t'}}
|
||||
//expected-error@+1 {{expected variable or static data member of type 'omp_interop_t'}}
|
||||
#pragma omp interop use(a+b) use(Another)
|
||||
|
||||
//expected-error@+1 {{expected variable of type 'omp_interop_t'}}
|
||||
//expected-error@+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@+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@+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@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop init(target:InteropVar) init(target:InteropVar)
|
||||
|
||||
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop use(InteropVar) use(InteropVar)
|
||||
|
||||
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop destroy(InteropVar) destroy(InteropVar)
|
||||
|
||||
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop init(target:InteropVar) use(InteropVar)
|
||||
|
||||
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop init(target:InteropVar) destroy(InteropVar)
|
||||
|
||||
//expected-error@+1 {{interop variable 'InteropVar' used in multiple action clauses}}
|
||||
#pragma omp interop use(InteropVar) destroy(InteropVar)
|
||||
|
||||
//expected-error@+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@+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@+1 {{expected variable or static data member of type 'omp_interop_t'}}
|
||||
#pragma omp interop init(target:s.InteropVar) init(target:another)
|
||||
|
||||
//expected-error@+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@+1 {{expected variable of type 'omp_interop_t'}}
|
||||
#pragma omp interop init(target:o) init(target:bar())
|
||||
|
||||
//expected-error@+1 {{expected variable of type 'omp_interop_t'}}
|
||||
#pragma omp interop init(target:o) init(target:s.o)
|
||||
}
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue