diff options
Diffstat (limited to 'clang/lib/Sema/SemaOpenACC.cpp')
-rw-r--r-- | clang/lib/Sema/SemaOpenACC.cpp | 114 |
1 files changed, 95 insertions, 19 deletions
diff --git a/clang/lib/Sema/SemaOpenACC.cpp b/clang/lib/Sema/SemaOpenACC.cpp index 8bfea62..62fe3d1 100644 --- a/clang/lib/Sema/SemaOpenACC.cpp +++ b/clang/lib/Sema/SemaOpenACC.cpp @@ -17,6 +17,7 @@ #include "clang/Basic/DiagnosticSema.h" #include "clang/Basic/OpenACCKinds.h" #include "clang/Basic/SourceManager.h" +#include "clang/Sema/Initialization.h" #include "clang/Sema/Scope.h" #include "clang/Sema/Sema.h" #include "llvm/ADT/StringExtras.h" @@ -629,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 && @@ -638,50 +639,71 @@ 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; - const 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. 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) { 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) { + 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(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 InnerTy I think? + // Need to confirm when implementing this part. } // All 3 things need to make sure they have a dtor. 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, @@ -2552,3 +2574,57 @@ ExprResult SemaOpenACC::ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc) { return BuildOpenACCAsteriskSizeExpr(AsteriskLoc); } + +VarDecl *SemaOpenACC::CreateInitRecipe(OpenACCClauseKind CK, + const Expr *VarExpr) { + // Strip off any array subscripts/array section exprs to get to the type of + // the variable. + while (isa_and_present<ArraySectionExpr, ArraySubscriptExpr>(VarExpr)) { + if (const auto *AS = dyn_cast<ArraySectionExpr>(VarExpr)) + VarExpr = AS->getBase()->IgnoreParenImpCasts(); + else if (const auto *Sub = dyn_cast<ArraySubscriptExpr>(VarExpr)) + VarExpr = Sub->getBase()->IgnoreParenImpCasts(); + } + + // If for some reason the expression is invalid, or this is dependent, just + // fill in with nullptr. We'll count on TreeTransform to make this if + // necessary. + if (!VarExpr || VarExpr->getType()->isDependentType()) + return nullptr; + + QualType VarTy = + VarExpr->getType().getNonReferenceType().getUnqualifiedType(); + + VarDecl *Recipe = VarDecl::Create( + getASTContext(), SemaRef.getCurContext(), VarExpr->getBeginLoc(), + VarExpr->getBeginLoc(), + &getASTContext().Idents.get("openacc.private.init"), VarTy, + getASTContext().getTrivialTypeSourceInfo(VarTy), SC_Auto); + + ExprResult Init; + + if (CK == OpenACCClauseKind::Private) { + // Trap errors so we don't get weird ones here. If we can't init, we'll just + // swallow the errors. + Sema::TentativeAnalysisScope Trap{SemaRef}; + InitializedEntity Entity = InitializedEntity::InitializeVariable(Recipe); + InitializationKind Kind = + InitializationKind::CreateDefault(Recipe->getLocation()); + + InitializationSequence InitSeq(SemaRef.SemaRef, Entity, Kind, {}); + Init = InitSeq.Perform(SemaRef.SemaRef, Entity, Kind, {}); + } else if (CK == OpenACCClauseKind::FirstPrivate) { + // TODO: OpenACC: Implement this to do a 'copy' operation. + } else if (CK == OpenACCClauseKind::Reduction) { + // TODO: OpenACC: Implement this for whatever reduction needs. + } else { + llvm_unreachable("Unknown clause kind in CreateInitRecipe"); + } + + if (Init.get()) { + Recipe->setInit(Init.get()); + Recipe->setInitStyle(VarDecl::CallInit); + } + + return Recipe; +} |