[clang] 3e1392f - [OpenACC] Allow sub-arrays in declare/use_device as an extension
via cfe-commits
cfe-commits at lists.llvm.org
Fri Jul 25 13:16:38 PDT 2025
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 at +1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
+ // expected-warning at +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 at +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 at +2{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}}
- // expected-error at +1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
+ // expected-warning at +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 at +2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}}
- // expected-error at +1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
+ // expected-warning at +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 at +1{{OpenACC variable in 'use_device' clause is not a valid variable name or array name}}
+ // expected-warning at +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 at +1{{no valid clauses specified in OpenACC 'declare' directive}}
#pragma acc declare
namespace NS {
@@ -265,8 +266,8 @@ void use() {
// expected-error at +1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}}
#pragma acc declare create(GlobalArray[0])
-// expected-error at +1{{OpenACC variable on 'declare' construct is not a valid variable name or array name}}
-#pragma acc declare create(GlobalArray[0: 1])
+// expected-warning at +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 at +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 at +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;
More information about the cfe-commits
mailing list