Author: erichkeane Date: 2025-07-25T13:16:34-07:00 New Revision: 3e1392fb4b6afa4e1b212d04fb4881656d846736
URL: https://github.com/llvm/llvm-project/commit/3e1392fb4b6afa4e1b212d04fb4881656d846736 DIFF: https://github.com/llvm/llvm-project/commit/3e1392fb4b6afa4e1b212d04fb4881656d846736.diff LOG: [OpenACC] Allow sub-arrays in declare/use_device as an extension These two both allow arrays as their variable references, but it is a common thing to use sub-arrays as a way to get a pointer to act as an array with other compilers. This patch adds these, with an extension-warning. Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaOpenACC.cpp clang/lib/Sema/SemaOpenACCClause.cpp clang/test/CIR/CodeGenOpenACC/host_data.c clang/test/SemaOpenACC/data-construct-use_device-clause.c clang/test/SemaOpenACC/data-construct.cpp clang/test/SemaOpenACC/declare-construct.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 4b2ebe662a8a7..3663611c682ce 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13257,6 +13257,11 @@ def err_acc_not_a_var_ref def err_acc_not_a_var_ref_use_device_declare : Error<"OpenACC variable %select{in 'use_device' clause|on 'declare' " "construct}0 is not a valid variable name or array name">; +def ext_acc_array_section_use_device_declare + : Extension< + "sub-array as a variable %select{in 'use_device' clause|on " + "'declare' construct}0 is not a valid variable name or array name">, + InGroup<DiagGroup<"openacc-extension">>; def err_acc_not_a_var_ref_cache : Error<"OpenACC variable in 'cache' directive is not a valid sub-array or " "array element">; diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 128a5db57bf73..8bfea623103e4 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -699,11 +699,19 @@ ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK, // OpenACC3.3 2.13: // A 'var' in a 'declare' directive must be a variable or array name. if ((CK == OpenACCClauseKind::UseDevice || - DK == OpenACCDirectiveKind::Declare) && - isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) { - Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device_declare) - << (DK == OpenACCDirectiveKind::Declare); - return ExprError(); + DK == OpenACCDirectiveKind::Declare)) { + if (isa<ArraySubscriptExpr>(CurVarExpr)) { + Diag(VarExpr->getExprLoc(), + diag::err_acc_not_a_var_ref_use_device_declare) + << (DK == OpenACCDirectiveKind::Declare); + return ExprError(); + } + // As an extension, we allow 'array sections'/'sub-arrays' here, as that is + // effectively defining an array, and are in common use. + if (isa<ArraySectionExpr>(CurVarExpr)) + Diag(VarExpr->getExprLoc(), + diag::ext_acc_array_section_use_device_declare) + << (DK == OpenACCDirectiveKind::Declare); } // Sub-arrays/subscript-exprs are fine as long as the base is a diff --git a/clang/lib/Sema/SemaOpenACCClause.cpp b/clang/lib/Sema/SemaOpenACCClause.cpp index 469dba8f0710c..b54a0124e9495 100644 --- a/clang/lib/Sema/SemaOpenACCClause.cpp +++ b/clang/lib/Sema/SemaOpenACCClause.cpp @@ -2254,7 +2254,13 @@ bool SemaOpenACC::CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause, continue; } } else { - const auto *DRE = cast<DeclRefExpr>(VarExpr); + + const Expr *VarExprTemp = VarExpr; + + while (const auto *ASE = dyn_cast<ArraySectionExpr>(VarExprTemp)) + VarExprTemp = ASE->getBase()->IgnoreParenImpCasts(); + + const auto *DRE = cast<DeclRefExpr>(VarExprTemp); if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) { CurDecl = Var->getCanonicalDecl(); diff --git a/clang/test/CIR/CodeGenOpenACC/host_data.c b/clang/test/CIR/CodeGenOpenACC/host_data.c index aeaf3d2f047b5..fa06d2a1cbd26 100644 --- a/clang/test/CIR/CodeGenOpenACC/host_data.c +++ b/clang/test/CIR/CodeGenOpenACC/host_data.c @@ -1,13 +1,15 @@ // RUN: %clang_cc1 -fopenacc -Wno-openacc-self-if-potential-conflict -emit-cir -fclangir %s -o - | FileCheck %s -void acc_host_data(int cond, int var1, int var2) { - // CHECK: cir.func{{.*}} @acc_host_data(%[[ARG_COND:.*]]: !s32i {{.*}}, %[[ARG_V1:.*]]: !s32i {{.*}}, %[[ARG_V2:.*]]: !s32i {{.*}}) { +void acc_host_data(int cond, int var1, int var2, int *arr) { + // CHECK: cir.func{{.*}} @acc_host_data(%[[ARG_COND:.*]]: !s32i {{.*}}, %[[ARG_V1:.*]]: !s32i {{.*}}, %[[ARG_V2:.*]]: !s32i {{.*}}, %[[ARG_ARR:.*]]: !cir.ptr<!s32i> {{.*}}) { // CHECK-NEXT: %[[COND:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["cond", init] // CHECK-NEXT: %[[V1:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["var1", init] // CHECK-NEXT: %[[V2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["var2", init] + // CHECK-NEXT: %[[ARR:.*]] = cir.alloca !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>>, ["arr", init] // CHECK-NEXT: cir.store %[[ARG_COND]], %[[COND]] : !s32i, !cir.ptr<!s32i> // CHECK-NEXT: cir.store %[[ARG_V1]], %[[V1]] : !s32i, !cir.ptr<!s32i> // CHECK-NEXT: cir.store %[[ARG_V2]], %[[V2]] : !s32i, !cir.ptr<!s32i> + // CHECK-NEXT: cir.store %[[ARG_ARR]], %[[ARR]] : !cir.ptr<!s32i>, !cir.ptr<!cir.ptr<!s32i>> #pragma acc host_data use_device(var1) {} @@ -52,4 +54,18 @@ void acc_host_data(int cond, int var1, int var2) { // CHECK-NEXT: acc.host_data if(%[[COND_CAST]]) dataOperands(%[[USE_DEV1]], %[[USE_DEV2]] : !cir.ptr<!s32i>, !cir.ptr<!s32i>) { // CHECK-NEXT: acc.terminator // CHECK-NEXT: } attributes {ifPresent} + +#pragma acc host_data use_device(arr[0:var1]) + {} + // CHECK-NEXT: %[[ZERO:.*]] = cir.const #cir.int<0> + // CHECK-NEXT: %[[ZERO_CAST:.*]] = builtin.unrealized_conversion_cast %[[ZERO]] : !s32i to si32 + // CHECK-NEXT: %[[VAR1_LOAD:.*]] = cir.load{{.*}} %[[V1]] : !cir.ptr<!s32i>, !s32i + // CHECK-NEXT: %[[VAR1_CAST:.*]] = builtin.unrealized_conversion_cast %[[VAR1_LOAD]] : !s32i to si32 + // CHECK-NEXT: %[[CONST_ZERO:.*]] = arith.constant 0 + // CHECK-NEXT: %[[CONST_ONE:.*]] = arith.constant 1 + // CHECK-NEXT: %[[BOUNDS:.*]] = acc.bounds lowerbound(%[[ZERO_CAST]] : si32) extent(%[[VAR1_CAST]] : si32) stride(%[[CONST_ONE]] : i64) startIdx(%[[CONST_ZERO]] : i64) + // CHECK-NEXT: %[[USE_DEV1:.*]] = acc.use_device varPtr(%[[ARR]] : !cir.ptr<!cir.ptr<!s32i>>) bounds(%[[BOUNDS]]) -> !cir.ptr<!cir.ptr<!s32i>> {name = "arr[0:var1]"} + // CHECK-NEXT: acc.host_data dataOperands(%[[USE_DEV1]] : !cir.ptr<!cir.ptr<!s32i>>) + // CHECK-NEXT: acc.terminator + // CHECK-NEXT: } loc } diff --git a/clang/test/SemaOpenACC/data-construct-use_device-clause.c b/clang/test/SemaOpenACC/data-construct-use_device-clause.c index 9239757b8e85d..65eaf4e18b4cf 100644 --- a/clang/test/SemaOpenACC/data-construct-use_device-clause.c +++ b/clang/test/SemaOpenACC/data-construct-use_device-clause.c @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fopenacc -verify +// RUN: %clang_cc1 %s -fopenacc -verify -Wopenacc-extension typedef struct IsComplete { struct S { int A; } CompositeMember; @@ -23,7 +23,7 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo #pragma acc host_data use_device(LocalComposite.ScalarMember, LocalComposite.ScalarMember) ; - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(LocalArray[2:1]) // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} @@ -35,12 +35,12 @@ void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete Compo ; // expected-error@+2{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}} - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(PointerParam[2:]) ; // expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}} - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(ArrayParam[2:5]) ; diff --git a/clang/test/SemaOpenACC/data-construct.cpp b/clang/test/SemaOpenACC/data-construct.cpp index 394ebb0e52b56..da7b80a674f7b 100644 --- a/clang/test/SemaOpenACC/data-construct.cpp +++ b/clang/test/SemaOpenACC/data-construct.cpp @@ -1,4 +1,4 @@ -// RUN: %clang_cc1 %s -fopenacc -verify -Wno-empty-body -Wno-unused-value +// RUN: %clang_cc1 %s -fopenacc -verify -Wno-empty-body -Wno-unused-value -Wopenacc-extension void HasStmt() { { @@ -185,7 +185,7 @@ void HostDataRules() { #pragma acc host_data use_device(Array) ; - // expected-error@+1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}} + // expected-warning@+1{{sub-array as a variable in 'use_device' clause is not a valid variable name or array name}} #pragma acc host_data use_device(Array[1:1]) ; diff --git a/clang/test/SemaOpenACC/declare-construct.cpp b/clang/test/SemaOpenACC/declare-construct.cpp index 6f21aedc39b45..6828ecdf9ebc1 100644 --- a/clang/test/SemaOpenACC/declare-construct.cpp +++ b/clang/test/SemaOpenACC/declare-construct.cpp @@ -1,7 +1,8 @@ -// RUN: %clang_cc1 %s -fopenacc -verify +// RUN: %clang_cc1 %s -fopenacc -verify -Wopenacc-extension int *Global; int GlobalArray[5]; +int GlobalArray2[5]; // expected-error@+1{{no valid clauses specified in OpenACC 'declare' directive}} #pragma acc declare namespace NS { @@ -265,8 +266,8 @@ void use() { // expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} #pragma acc declare create(GlobalArray[0]) -// expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} -#pragma acc declare create(GlobalArray[0: 1]) +// expected-warning@+1{{sub-array as a variable on 'declare' construct is not a valid variable name or array name}} +#pragma acc declare create(GlobalArray[0: 1]) // #GLOBALARRAYREF struct S { int I; }; // expected-error@+1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}} @@ -288,8 +289,12 @@ void ExternVar() { #pragma acc declare copy(I) copyin(I2), copyout(I3), create(I4), present(I5), deviceptr(I6), device_resident(I7), link(I8) } +// expected-error@+2{{variable referenced in 'link' clause of OpenACC 'declare' directive was already referenced}} +// expected-note@#GLOBALARRAYREF{{previous reference is here}} +#pragma acc declare link(GlobalArray) + // Link can only have global, namespace, or extern vars. -#pragma acc declare link(Global, GlobalArray) +#pragma acc declare link(Global, GlobalArray2) struct Struct2 { static const int StaticMem = 5; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits