[OPENMP50]Add basic support for array-shaping operation.
Summary:
Added basic representation and parsing/sema handling of array-shaping
operations. Array shaping expression is an expression of form ([s0]..[sn])base,
where s0, ..., sn must be a positive integer, base - a pointer. This
expression is a kind of cast operation that converts pointer expression
into an array-like kind of expression.
Reviewers: rjmccall, rsmith, jdoerfert
Subscribers: guansong, arphaman, cfe-commits, caomhin, kkwli0
Tags: #clang
Differential Revision: https://reviews.llvm.org/D74144
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 53c62a1..fad2ae1 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1299,6 +1299,7 @@
// Some might be dependent for other reasons.
case Expr::ArraySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
case Expr::BinaryOperatorClass:
case Expr::DependentCoawaitExprClass:
case Expr::CompoundAssignOperatorClass:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index 756833c..44f51f1 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4798,6 +4798,75 @@
VK_LValue, OK_Ordinary, ColonLoc, RBLoc);
}
+ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> Brackets) {
+ if (Base->getType()->isPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Base);
+ if (Result.isInvalid())
+ return ExprError();
+ Base = Result.get();
+ }
+ QualType BaseTy = Base->getType();
+ // Delay analysis of the types/expressions if instantiation/specialization is
+ // required.
+ if (!BaseTy->isPointerType() && Base->isTypeDependent())
+ return OMPArrayShapingExpr::Create(Context, Context.DependentTy, Base,
+ LParenLoc, RParenLoc, Dims, Brackets);
+ if (!BaseTy->isPointerType())
+ return ExprError(Diag(Base->getExprLoc(),
+ diag::err_omp_non_pointer_type_array_shaping_base)
+ << Base->getSourceRange());
+ SmallVector<Expr *, 4> NewDims;
+ bool ErrorFound = false;
+ for (Expr *Dim : Dims) {
+ if (Dim->getType()->isPlaceholderType()) {
+ ExprResult Result = CheckPlaceholderExpr(Dim);
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ continue;
+ }
+ Result = DefaultLvalueConversion(Result.get());
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ continue;
+ }
+ Dim = Result.get();
+ }
+ if (!Dim->isTypeDependent()) {
+ ExprResult Result =
+ PerformOpenMPImplicitIntegerConversion(Dim->getExprLoc(), Dim);
+ if (Result.isInvalid()) {
+ ErrorFound = true;
+ Diag(Dim->getExprLoc(), diag::err_omp_typecheck_shaping_not_integer)
+ << Dim->getSourceRange();
+ continue;
+ }
+ Dim = Result.get();
+ Expr::EvalResult EvResult;
+ if (!Dim->isValueDependent() && Dim->EvaluateAsInt(EvResult, Context)) {
+ // OpenMP 5.0, [2.1.4 Array Shaping]
+ // Each si is an integral type expression that must evaluate to a
+ // positive integer.
+ llvm::APSInt Value = EvResult.Val.getInt();
+ if (!Value.isStrictlyPositive()) {
+ Diag(Dim->getExprLoc(), diag::err_omp_shaping_dimension_not_positive)
+ << Value.toString(/*Radix=*/10, /*Signed=*/true)
+ << Dim->getSourceRange();
+ ErrorFound = true;
+ continue;
+ }
+ }
+ }
+ NewDims.push_back(Dim);
+ }
+ if (ErrorFound)
+ return ExprError();
+ return OMPArrayShapingExpr::Create(Context, Context.OMPArrayShapingTy, Base,
+ LParenLoc, RParenLoc, NewDims, Brackets);
+}
+
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -5558,6 +5627,7 @@
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
return true;
}
@@ -18433,6 +18503,10 @@
Diag(E->getBeginLoc(), diag::err_omp_array_section_use);
return ExprError();
+ // Expressions of unknown type.
+ case BuiltinType::OMPArrayShaping:
+ return ExprError(Diag(E->getBeginLoc(), diag::err_omp_array_shaping_use));
+
// Everything else should be impossible.
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
case BuiltinType::Id:
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 14aa446..f9e8e3d 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -15824,7 +15824,8 @@
(OMPDependTFound &&
DSAStack->getOMPDependT().getTypePtr() == ExprTy.getTypePtr())) {
Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << 1 << RefExpr->getSourceRange();
+ << (LangOpts.OpenMP >= 50 ? 1 : 0) << 1
+ << RefExpr->getSourceRange();
continue;
}
@@ -15837,6 +15838,7 @@
->isPointerType() &&
!ASE->getBase()->getType().getNonReferenceType()->isArrayType())) {
Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0)
<< (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
continue;
}
@@ -15847,8 +15849,10 @@
Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
RefExpr->IgnoreParenImpCasts());
}
- if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr)) {
+ if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
+ !isa<OMPArrayShapingExpr>(SimpleExpr)) {
Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0)
<< (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
continue;
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index dda3a39..82cfa24 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2379,6 +2379,18 @@
ColonLoc, Length, RBracketLoc);
}
+ /// Build a new array shaping expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide different behavior.
+ ExprResult RebuildOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> BracketsRanges) {
+ return getSema().ActOnOMPArrayShapingExpr(Base, LParenLoc, RParenLoc, Dims,
+ BracketsRanges);
+ }
+
/// Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -10017,6 +10029,31 @@
Length.get(), E->getRBracketLoc());
}
+template <typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
+ ExprResult Base = getDerived().TransformExpr(E->getBase());
+ if (Base.isInvalid())
+ return ExprError();
+
+ SmallVector<Expr *, 4> Dims;
+ bool ErrorFound = false;
+ for (Expr *Dim : E->getDimensions()) {
+ ExprResult DimRes = getDerived().TransformExpr(Dim);
+ if (DimRes.isInvalid()) {
+ ErrorFound = true;
+ continue;
+ }
+ Dims.push_back(DimRes.get());
+ }
+
+ if (ErrorFound)
+ return ExprError();
+ return getDerived().RebuildOMPArrayShapingExpr(Base.get(), E->getLParenLoc(),
+ E->getRParenLoc(), Dims,
+ E->getBracketsRanges());
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {