aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOpenACC.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaOpenACC.cpp')
-rw-r--r--clang/lib/Sema/SemaOpenACC.cpp114
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;
+}