[clang] 74af2ce - [OpenACC] Fix 'type' checks in private/firstprivate for array types

via cfe-commits cfe-commits at lists.llvm.org
Tue Aug 5 08:25:39 PDT 2025


Author: erichkeane
Date: 2025-08-05T08:25:34-07:00
New Revision: 74af2cec7bbd307d1dcb7f9f3cdf339d551a1f9f

URL: https://github.com/llvm/llvm-project/commit/74af2cec7bbd307d1dcb7f9f3cdf339d551a1f9f
DIFF: https://github.com/llvm/llvm-project/commit/74af2cec7bbd307d1dcb7f9f3cdf339d551a1f9f.diff

LOG: [OpenACC] Fix 'type' checks in private/firstprivate for array types

These would not give a correct initializer, but they are not possible
to generate correctly anyway, so this patch makes sure we look through
the array type to correctly diagnose these.

Added: 
    

Modified: 
    clang/lib/Sema/SemaOpenACC.cpp
    clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp
index 8212646facd86..8c6c9c70f8e2c 100644
--- a/clang/lib/Sema/SemaOpenACC.cpp
+++ b/clang/lib/Sema/SemaOpenACC.cpp
@@ -630,7 +630,7 @@ namespace {
 // private, firstprivate, and reduction, which require certain operators to be
 // available.
 ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
-                        Expr *InnerExpr) {
+                        SourceLocation InnerLoc, QualType InnerTy) {
   // There is nothing to do here, only these three have these sorts of
   // restrictions.
   if (CK != OpenACCClauseKind::Private &&
@@ -639,10 +639,17 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
     return VarExpr;
 
   // We can't test this if it isn't here, or if the type isn't clear yet.
-  if (!InnerExpr || InnerExpr->isTypeDependent())
+  if (InnerTy.isNull() || InnerTy->isDependentType())
     return VarExpr;
 
-  auto *RD = InnerExpr->getType()->getAsCXXRecordDecl();
+  InnerTy = InnerTy.getUnqualifiedType();
+  if (auto *RefTy = InnerTy->getAs<ReferenceType>())
+    InnerTy = RefTy->getPointeeType();
+
+  if (auto *ArrTy = InnerTy->getAsArrayTypeUnsafe())
+    return CheckVarType(S, CK, VarExpr, InnerLoc, ArrTy->getElementType());
+
+  auto *RD = InnerTy->getAsCXXRecordDecl();
 
   // if this isn't a C++ record decl, we can create/copy/destroy this thing at
   // will without problem, so this is a success.
@@ -655,10 +662,8 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
           return CD->isDefaultConstructor() && !CD->isDeleted();
         }) != RD->ctors().end();
     if (!HasNonDeletedDefaultCtor && !RD->needsImplicitDefaultConstructor()) {
-      S.Diag(InnerExpr->getBeginLoc(),
-             clang::diag::warn_acc_var_referenced_lacks_op)
-          << InnerExpr->getType() << CK
-          << clang::diag::AccVarReferencedReason::DefCtor;
+      S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
+          << InnerTy << CK << clang::diag::AccVarReferencedReason::DefCtor;
       return ExprError();
     }
   } else if (CK == OpenACCClauseKind::FirstPrivate) {
@@ -670,16 +675,14 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
 
       if (SMOR.getKind() != Sema::SpecialMemberOverloadResult::Success ||
           SMOR.getMethod()->isDeleted()) {
-        S.Diag(InnerExpr->getBeginLoc(),
-               clang::diag::warn_acc_var_referenced_lacks_op)
-            << InnerExpr->getType() << CK
-            << clang::diag::AccVarReferencedReason::CopyCtor;
+        S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
+            << InnerTy << CK << clang::diag::AccVarReferencedReason::CopyCtor;
         return ExprError();
       }
     }
   } else if (CK == OpenACCClauseKind::Reduction) {
     // TODO: OpenACC:
-    // Reduction must have copyctor + dtor + operation in InnerExpr I think?
+    // Reduction must have copyctor + dtor + operation in InnerTy I think?
     // Need to confirm when implementing this part.
   }
 
@@ -687,14 +690,20 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
   bool DestructorDeleted =
       RD->getDestructor() && RD->getDestructor()->isDeleted();
   if (DestructorDeleted && !RD->needsImplicitDestructor()) {
-    S.Diag(InnerExpr->getBeginLoc(),
-           clang::diag::warn_acc_var_referenced_lacks_op)
-        << InnerExpr->getType() << CK
-        << clang::diag::AccVarReferencedReason::Dtor;
+    S.Diag(InnerLoc, clang::diag::warn_acc_var_referenced_lacks_op)
+        << InnerTy << CK << clang::diag::AccVarReferencedReason::Dtor;
     return ExprError();
   }
   return VarExpr;
 }
+
+ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr,
+                        Expr *InnerExpr) {
+  if (!InnerExpr)
+    return VarExpr;
+  return CheckVarType(S, CK, VarExpr, InnerExpr->getBeginLoc(),
+                      InnerExpr->getType());
+}
 } // namespace
 
 ExprResult SemaOpenACC::ActOnVar(OpenACCDirectiveKind DK, OpenACCClauseKind CK,

diff  --git a/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp
index ad3cb8ba5d3ff..4644bdeeacc0e 100644
--- a/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp
+++ b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp
@@ -11,12 +11,13 @@ struct DefaultedCtor {
 };
 
 struct ImpledCtor {
-  ImpledCtor() = default;
+  ImpledCtor();
 };
 
 
 struct DeletedCtor {
   DeletedCtor() = delete;
+  DeletedCtor(int i);
 };
 
 struct ImpledDtor {
@@ -43,6 +44,7 @@ struct DefaultedCopy {
   DefaultedCopy(const DefaultedCopy&) = default;
 };
 struct UserCopy {
+  UserCopy();
   UserCopy(const UserCopy&);
 };
 
@@ -74,7 +76,7 @@ void private_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
 #pragma acc parallel private(DefD)
   ;
 
-  // expected-error at +1{{variable of type 'DeletedDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}}
+  // expected-error at +1{{variable of type 'DeletedDtor' referenced in OpenACC 'private' clause does not have a}}
 #pragma acc parallel private(DelD)
   ;
 
@@ -113,6 +115,45 @@ void inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
   private_templ(IDD);
 }
 
+void private_arrays() {
+  char *ptr;
+  ImplicitCtorDtor CDTArr[5];
+  ImplDeletedCtor IDCArr[5]{1,2,3,4,5};
+  DefaultedCtor DefCArr[5];
+  ImpledCtor ICArr[5];
+  DeletedCtor DelCArr[5]{1,2,3,4,5};
+  ImpledDtor IDArr[5];
+  DefaultedDtor DefDArr[5];
+  using DelDArrTy = DeletedDtor[5];
+  DelDArrTy &DelDArr = *((DelDArrTy*)ptr);
+  using IDDArrTy = ImplicitDelDtor[5];
+  IDDArrTy &IDDArr = *((IDDArrTy*)ptr);
+
+
+#pragma acc parallel private(CDTArr)
+  ;
+  // expected-error at +1{{variable of type 'ImplDeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}}
+#pragma acc parallel private(IDCArr)
+  ;
+#pragma acc parallel private(DefCArr)
+  ;
+#pragma acc parallel private(ICArr)
+  ;
+  // expected-error at +1{{variable of type 'DeletedCtor' referenced in OpenACC 'private' clause does not have a default constructor; reference has no effect}}
+#pragma acc parallel private(DelCArr)
+  ;
+#pragma acc parallel private(IDArr)
+  ;
+#pragma acc parallel private(DefDArr)
+  ;
+  // expected-error at +1{{variable of type 'DeletedDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}}
+#pragma acc parallel private(DelDArr)
+  ;
+  // expected-error at +1{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'private' clause does not have a destructor; reference has no effect}}
+#pragma acc parallel private(IDDArr)
+  ;
+}
+
 void firstprivate_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
                   DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC,
                   ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD,
@@ -187,3 +228,48 @@ void firstprivate_inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC,
   firstprivate_template(UDCopy);
 }
 
+void firstprivate_arrays() {
+  char *ptr;
+  ImplicitCtorDtor CDTArr[5];
+  ImplDeletedCtor IDCArr[5]{1,2,3,4,5};
+  DefaultedCtor DefCArr[5];
+  ImpledCtor ICArr[5];
+  DeletedCtor DelCArr[5]{1,2,3,4,5};
+  ImpledDtor IDArr[5];
+  DefaultedDtor DefDArr[5];
+  using DelDArrTy = DeletedDtor[5];
+  DelDArrTy &DelDArr = *((DelDArrTy*)ptr);
+  using IDDArrTy = ImplicitDelDtor[5];
+  IDDArrTy &IDDArr = *((IDDArrTy*)ptr);
+  DeletedCopy DelCopyArr[5]{};
+  DefaultedCopy DefCopyArr[5]{};
+  UserCopy UDCopyArr[5]{};
+
+#pragma acc parallel firstprivate(CDTArr)
+  ;
+#pragma acc parallel firstprivate(IDCArr)
+  ;
+#pragma acc parallel firstprivate(DefCArr)
+  ;
+#pragma acc parallel firstprivate(ICArr)
+  ;
+#pragma acc parallel firstprivate(DelCArr)
+  ;
+#pragma acc parallel firstprivate(IDArr)
+  ;
+#pragma acc parallel firstprivate(DefDArr)
+  ;
+  // expected-error at +1{{variable of type 'DeletedDtor' referenced in OpenACC 'firstprivate' clause does not have a destructor; reference has no effect}}
+#pragma acc parallel firstprivate(DelDArr)
+  ;
+  // expected-error at +1{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
+#pragma acc parallel firstprivate(IDDArr)
+  ;
+  // expected-error at +1{{variable of type 'DeletedCopy' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}}
+#pragma acc parallel firstprivate(DelCopyArr)
+  ;
+#pragma acc parallel firstprivate(DefCopyArr)
+  ;
+#pragma acc parallel firstprivate(UDCopyArr)
+  ;
+}


        


More information about the cfe-commits mailing list