Author: erichkeane Date: 2025-08-04T11:42:33-07:00 New Revision: 4e0b68cef0bdf0d806cd778fbf0b7ddd80b44b4d
URL: https://github.com/llvm/llvm-project/commit/4e0b68cef0bdf0d806cd778fbf0b7ddd80b44b4d DIFF: https://github.com/llvm/llvm-project/commit/4e0b68cef0bdf0d806cd778fbf0b7ddd80b44b4d.diff LOG: [OpenACC] Implement warning restrictions for 'firstprivate' 'firstprivate' can't be generated unless we have a copy constructor, so this patch implements the restriction as a warning, and prevents the item from being added to the AST. Added: Modified: clang/include/clang/Basic/DiagnosticSemaKinds.td clang/include/clang/Sema/SemaOpenACC.h clang/lib/Sema/SemaOpenACC.cpp clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp Removed: ################################################################################ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 0ba06d6f2dee3..9ce142e7b37cc 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -13531,7 +13531,8 @@ def err_acc_device_type_multiple_archs def warn_acc_var_referenced_lacks_op : Warning<"variable of type %0 referenced in OpenACC '%1' clause does not " "have a %enum_select<AccVarReferencedReason>{%DefCtor{default " - "constructor}|%Dtor{destructor}}2; reference has no effect">, + "constructor}|%CopyCtor{copy constructor}|%Dtor{destructor}}2; " + "reference has no effect">, InGroup<DiagGroup<"openacc-var-lacks-operation">>, DefaultError; diff --git a/clang/include/clang/Sema/SemaOpenACC.h b/clang/include/clang/Sema/SemaOpenACC.h index f51045d26e23b..e9e4e6c2b380c 100644 --- a/clang/include/clang/Sema/SemaOpenACC.h +++ b/clang/include/clang/Sema/SemaOpenACC.h @@ -176,10 +176,6 @@ class SemaOpenACC : public SemaBase { void checkFor(); - // void checkRangeFor(); ?? ERICH - // const ValueDecl *checkInit(); - // void checkCond(const ValueDecl *Init); - // void checkInc(const ValueDecl *Init); public: // Checking for non-instantiation version of a Range-for. ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc, diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 8f32817aec48f..8212646facd86 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -642,21 +642,13 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr, if (!InnerExpr || InnerExpr->isTypeDependent()) return VarExpr; - const auto *RD = InnerExpr->getType()->getAsCXXRecordDecl(); + auto *RD = InnerExpr->getType()->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. if (!RD) return VarExpr; - // TODO: OpenACC: - // Private must have default ctor + dtor in InnerExpr - // FirstPrivate must have copyctor + dtor in InnerExpr - // Reduction must have copyctor + dtor + operation in InnerExpr - - // TODO OpenACC: It isn't clear what the requirements are for default - // constructor/copy constructor are for First private and reduction, but - // private requires a default constructor. if (CK == OpenACCClauseKind::Private) { bool HasNonDeletedDefaultCtor = llvm::find_if(RD->ctors(), [](const CXXConstructorDecl *CD) { @@ -669,6 +661,26 @@ ExprResult CheckVarType(SemaOpenACC &S, OpenACCClauseKind CK, Expr *VarExpr, << clang::diag::AccVarReferencedReason::DefCtor; return ExprError(); } + } else if (CK == OpenACCClauseKind::FirstPrivate) { + if (!RD->hasSimpleCopyConstructor()) { + Sema::SpecialMemberOverloadResult SMOR = S.SemaRef.LookupSpecialMember( + RD, CXXSpecialMemberKind::CopyConstructor, /*ConstArg=*/true, + /*VolatileArg=*/false, /*RValueThis=*/false, /*ConstThis=*/false, + /*VolatileThis=*/false); + + 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; + return ExprError(); + } + } + } else if (CK == OpenACCClauseKind::Reduction) { + // TODO: OpenACC: + // Reduction must have copyctor + dtor + operation in InnerExpr I think? + // Need to confirm when implementing this part. } // All 3 things need to make sure they have a dtor. diff --git a/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp index e0aee123fe754..ad3cb8ba5d3ff 100644 --- a/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp +++ b/clang/test/SemaOpenACC/private_firstprivate_reduction_required_ops.cpp @@ -35,6 +35,17 @@ struct ImplicitDelDtor { DeletedDtor d; }; +struct DeletedCopy { + DeletedCopy(const DeletedCopy&) = delete; +}; + +struct DefaultedCopy { + DefaultedCopy(const DefaultedCopy&) = default; +}; +struct UserCopy { + UserCopy(const UserCopy&); +}; + void private_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC, ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD, @@ -101,3 +112,78 @@ void inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, // expected-note@+1{{in instantiation}} private_templ(IDD); } + +void firstprivate_uses(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, + DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC, + ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD, + ImplicitDelDtor &IDD, DeletedCopy &DelCopy, + DefaultedCopy &DefCopy, UserCopy &UDCopy) { +#pragma acc parallel firstprivate(CDT) + ; + +#pragma acc parallel firstprivate(IDC) + ; + +#pragma acc parallel firstprivate(DefC) + ; + +#pragma acc parallel firstprivate(IC) + ; + +#pragma acc parallel firstprivate(DelC) + ; + +#pragma acc parallel firstprivate(ID) + ; + +#pragma acc parallel firstprivate(DefD) + ; + + // expected-error@+1{{variable of type 'DeletedDtor' referenced in OpenACC 'firstprivate' clause does not have a destructor; reference has no effect}} +#pragma acc parallel firstprivate(DelD) + ; + + // expected-error@+1{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}} +#pragma acc parallel firstprivate(IDD) + ; + + // expected-error@+1{{variable of type 'DeletedCopy' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}} +#pragma acc parallel firstprivate(DelCopy) + ; +#pragma acc parallel firstprivate(DefCopy) + ; +#pragma acc parallel firstprivate(UDCopy) + ; +} + +template<typename T> +void firstprivate_template(T& t) { +#pragma acc parallel firstprivate(t) // #FIRSTPRIV + ; +} + +void firstprivate_inst(ImplicitCtorDtor &CDT, ImplDeletedCtor &IDC, + DefaultedCtor &DefC, ImpledCtor &IC, DeletedCtor &DelC, + ImpledDtor &ID, DefaultedDtor &DefD, DeletedDtor &DelD, + ImplicitDelDtor &IDD, DeletedCopy &DelCopy, + DefaultedCopy &DefCopy, UserCopy &UDCopy) { + firstprivate_template(CDT); + firstprivate_template(IDC); + firstprivate_template(DefC); + firstprivate_template(IC); + firstprivate_template(DelC); + firstprivate_template(ID); + firstprivate_template(DefD); + // expected-error@#FIRSTPRIV{{variable of type 'DeletedDtor' referenced in OpenACC 'firstprivate' clause does not have a destructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + firstprivate_template(DelD); + // expected-error@#FIRSTPRIV{{variable of type 'ImplicitDelDtor' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + firstprivate_template(IDD); + // expected-error@#FIRSTPRIV{{variable of type 'DeletedCopy' referenced in OpenACC 'firstprivate' clause does not have a copy constructor; reference has no effect}} + // expected-note@+1{{in instantiation}} + firstprivate_template(DelCopy); + firstprivate_template(DefCopy); + firstprivate_template(UDCopy); +} + _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits