[clang] 7ac9efb - [OPENMP50]Add basic support for array-shaping operation.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 30 06:28:38 PDT 2020
Author: Alexey Bataev
Date: 2020-03-30T09:18:24-04:00
New Revision: 7ac9efb0c322bacd4f09e6aed82466116b685892
URL: https://github.com/llvm/llvm-project/commit/7ac9efb0c322bacd4f09e6aed82466116b685892
DIFF: https://github.com/llvm/llvm-project/commit/7ac9efb0c322bacd4f09e6aed82466116b685892.diff
LOG: [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
Added:
Modified:
clang/include/clang-c/Index.h
clang/include/clang/AST/ASTContext.h
clang/include/clang/AST/BuiltinTypes.def
clang/include/clang/AST/ComputeDependence.h
clang/include/clang/AST/ExprOpenMP.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/include/clang/Basic/StmtNodes.td
clang/include/clang/Parse/Parser.h
clang/include/clang/Sema/Sema.h
clang/include/clang/Serialization/ASTBitCodes.h
clang/lib/AST/ASTContext.cpp
clang/lib/AST/ComputeDependence.cpp
clang/lib/AST/Expr.cpp
clang/lib/AST/ExprClassification.cpp
clang/lib/AST/ExprConstant.cpp
clang/lib/AST/ItaniumMangle.cpp
clang/lib/AST/NSAPI.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/AST/Type.cpp
clang/lib/AST/TypeLoc.cpp
clang/lib/Parse/ParseExpr.cpp
clang/lib/Sema/SemaExceptionSpec.cpp
clang/lib/Sema/SemaExpr.cpp
clang/lib/Sema/SemaOpenMP.cpp
clang/lib/Sema/TreeTransform.h
clang/lib/Serialization/ASTCommon.cpp
clang/lib/Serialization/ASTReader.cpp
clang/lib/Serialization/ASTReaderStmt.cpp
clang/lib/Serialization/ASTWriterStmt.cpp
clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
clang/test/OpenMP/depobj_messages.cpp
clang/test/OpenMP/parallel_reduction_messages.c
clang/test/OpenMP/task_ast_print.cpp
clang/test/OpenMP/task_depend_messages.cpp
clang/tools/libclang/CIndex.cpp
clang/tools/libclang/CXCursor.cpp
Removed:
################################################################################
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index cca7198d2f9f..641f058dafaa 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2176,7 +2176,11 @@ enum CXCursorKind {
*/
CXCursor_FixedPointLiteral = 149,
- CXCursor_LastExpr = CXCursor_FixedPointLiteral,
+ /** OpenMP 5.0 [2.1.4, Array Shaping].
+ */
+ CXCursor_OMPArrayShapingExpr = 150,
+
+ CXCursor_LastExpr = CXCursor_OMPArrayShapingExpr,
/* Statements */
CXCursor_FirstStmt = 200,
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ca0f991c24e3..ebb5ca593843 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -970,7 +970,7 @@ class ASTContext : public RefCountedBase<ASTContext> {
#include "clang/Basic/OpenCLImageTypes.def"
CanQualType OCLSamplerTy, OCLEventTy, OCLClkEventTy;
CanQualType OCLQueueTy, OCLReserveIDTy;
- CanQualType OMPArraySectionTy;
+ CanQualType OMPArraySectionTy, OMPArrayShapingTy;
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
CanQualType Id##Ty;
#include "clang/Basic/OpenCLExtensionTypes.def"
diff --git a/clang/include/clang/AST/BuiltinTypes.def b/clang/include/clang/AST/BuiltinTypes.def
index 74a45ee4ccc0..f42503773945 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -313,8 +313,11 @@ PLACEHOLDER_TYPE(ARCUnbridgedCast, ARCUnbridgedCastTy)
// A placeholder type for OpenMP array sections.
PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
+// A placeholder type for OpenMP array shaping operation.
+PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
+
#ifdef LAST_BUILTIN_TYPE
-LAST_BUILTIN_TYPE(OMPArraySection)
+LAST_BUILTIN_TYPE(OMPArrayShaping)
#undef LAST_BUILTIN_TYPE
#endif
diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h
index 02f826438d4d..63947eaff73b 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -87,6 +87,7 @@ class ParenListExpr;
class PseudoObjectExpr;
class AtomicExpr;
class OMPArraySectionExpr;
+class OMPArrayShapingExpr;
class ObjCArrayLiteral;
class ObjCDictionaryLiteral;
class ObjCBoxedExpr;
@@ -172,6 +173,7 @@ ExprDependence computeDependence(PseudoObjectExpr *E);
ExprDependence computeDependence(AtomicExpr *E);
ExprDependence computeDependence(OMPArraySectionExpr *E);
+ExprDependence computeDependence(OMPArrayShapingExpr *E);
ExprDependence computeDependence(ObjCArrayLiteral *E);
ExprDependence computeDependence(ObjCDictionaryLiteral *E);
diff --git a/clang/include/clang/AST/ExprOpenMP.h b/clang/include/clang/AST/ExprOpenMP.h
index f971ed8457bc..4a0cd07f1dab 100644
--- a/clang/include/clang/AST/ExprOpenMP.h
+++ b/clang/include/clang/AST/ExprOpenMP.h
@@ -116,6 +116,95 @@ class OMPArraySectionExpr : public Expr {
return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
}
};
+
+/// An explicit cast in C or a C-style cast in C++, which uses the syntax
+/// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
+class OMPArrayShapingExpr final
+ : public Expr,
+ private llvm::TrailingObjects<OMPArrayShapingExpr, Expr *, SourceRange> {
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+ /// Base node.
+ SourceLocation LPLoc; /// The location of the left paren
+ SourceLocation RPLoc; /// The location of the right paren
+ unsigned NumDims = 0; /// Number of dimensions in the shaping expression.
+
+ /// Construct full expression.
+ OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L,
+ SourceLocation R, ArrayRef<Expr *> Dims);
+
+ /// Construct an empty expression.
+ explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims)
+ : Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {}
+
+ /// Sets the dimensions for the array shaping.
+ void setDimensions(ArrayRef<Expr *> Dims);
+
+ /// Sets the base expression for array shaping operation.
+ void setBase(Expr *Op) { getTrailingObjects<Expr *>()[NumDims] = Op; }
+
+ /// Sets source ranges for the brackets in the array shaping operation.
+ void setBracketsRanges(ArrayRef<SourceRange> BR);
+
+ unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+ // Add an extra one for the base expression.
+ return NumDims + 1;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
+ return NumDims;
+ }
+
+public:
+ static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T,
+ Expr *Op, SourceLocation L,
+ SourceLocation R, ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> BracketRanges);
+
+ static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumDims);
+
+ SourceLocation getLParenLoc() const { return LPLoc; }
+ void setLParenLoc(SourceLocation L) { LPLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RPLoc; }
+ void setRParenLoc(SourceLocation L) { RPLoc = L; }
+
+ SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY {
+ return getBase()->getEndLoc();
+ }
+
+ /// Fetches the dimensions for array shaping expression.
+ ArrayRef<Expr *> getDimensions() const {
+ return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims);
+ }
+
+ /// Fetches source ranges for the brackets os the array shaping expression.
+ ArrayRef<SourceRange> getBracketsRanges() const {
+ return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims);
+ }
+
+ /// Fetches base expression of array shaping expression.
+ Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; }
+ const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPArrayShapingExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
+ return child_range(Begin, Begin + NumDims + 1);
+ }
+ const_child_range children() const {
+ Stmt *const *Begin =
+ reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
+ return const_child_range(Begin, Begin + NumDims + 1);
+ }
+};
} // end namespace clang
#endif
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 2f598564f307..46661e59f181 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2551,6 +2551,7 @@ DEF_TRAVERSE_STMT(CXXMemberCallExpr, {})
DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
+DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index cdc0d9688c08..26a9cabfc741 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9685,7 +9685,7 @@ def err_omp_expected_var_name_member_expr : Error<
def err_omp_expected_var_name_member_expr_or_array_item : Error<
"expected variable name%select{|, data member of current class}0, array element or array section">;
def err_omp_expected_addressable_lvalue_or_array_item : Error<
- "expected addressable lvalue expression, array element or array section%select{| of non 'omp_depend_t' type}0">;
+ "expected addressable lvalue expression, array element%select{ or array section|, array section or array shaping expression}0%select{| of non 'omp_depend_t' type}1">;
def err_omp_expected_named_var_member_or_array_expression: Error<
"expected expression containing only member accesses and/or array sections based on named variables">;
def err_omp_bit_fields_forbidden_in_clause : Error<
@@ -9952,10 +9952,15 @@ def err_omp_declare_mapper_redefinition : Error<
def err_omp_invalid_mapper: Error<
"cannot find a valid user-defined mapper for type %0 with name %1">;
def err_omp_array_section_use : Error<"OpenMP array section is not allowed here">;
+def err_omp_array_shaping_use : Error<"OpenMP array shaping operation is not allowed here">;
def err_omp_typecheck_section_value : Error<
"subscripted value is not an array or pointer">;
def err_omp_typecheck_section_not_integer : Error<
"array section %select{lower bound|length}0 is not an integer">;
+def err_omp_typecheck_shaping_not_integer : Error<
+ "array shaping operation dimension is not an integer">;
+def err_omp_shaping_dimension_not_positive : Error<
+ "array shaping dimension is evaluated to a non-positive value %0">;
def err_omp_section_function_type : Error<
"section of pointer to function type %0">;
def warn_omp_section_is_char : Warning<"array section %select{lower bound|length}0 is of type 'char'">,
@@ -10190,14 +10195,15 @@ def err_omp_flush_order_clause_and_list : Error<
def note_omp_flush_order_clause_here : Note<
"memory order clause '%0' is specified here">;
def err_omp_non_lvalue_in_map_or_motion_clauses: Error<
- "expected addressable lvalue in '%0' clause"
- >;
+ "expected addressable lvalue in '%0' clause">;
def err_omp_event_var_expected : Error<
"expected variable of the 'omp_event_handle_t' type%select{|, not %1}0">;
def warn_nested_declare_variant
: Warning<"nesting `omp begin/end declare variant` is not supported yet; "
"nested context ignored">,
InGroup<SourceUsesOpenMP>;
+def err_omp_non_pointer_type_array_shaping_base : Error<
+ "expected pointer type expression as a base of an array shaping operation">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 478179d4131f..ba1b5ebd6305 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -81,6 +81,7 @@ def BinaryConditionalOperator : StmtNode<AbstractConditionalOperator>;
def ImplicitCastExpr : StmtNode<CastExpr>;
def ExplicitCastExpr : StmtNode<CastExpr, 1>;
def CStyleCastExpr : StmtNode<ExplicitCastExpr>;
+def OMPArrayShapingExpr : StmtNode<Expr>;
def CompoundLiteralExpr : StmtNode<Expr>;
def ExtVectorElementExpr : StmtNode<Expr>;
def InitListExpr : StmtNode<Expr>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 333c96e8cd27..c64a01b73a4a 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3010,6 +3010,10 @@ class Parser : public CodeCompletionHandler {
DeclarationName &Name,
AccessSpecifier AS = AS_none);
+ /// Tries to parse cast part of OpenMP array shaping operation:
+ /// '[' expression ']' { '[' expression ']' } ')'.
+ bool tryParseOpenMPArrayShapingCastPart();
+
/// Parses simple list of variables.
///
/// \param Kind Kind of the directive.
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index ecda3f4692a5..9a41356ddb70 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -4899,6 +4899,10 @@ class Sema final {
ExprResult ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
Expr *LowerBound, SourceLocation ColonLoc,
Expr *Length, SourceLocation RBLoc);
+ ExprResult ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
+ SourceLocation RParenLoc,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> Brackets);
// This struct is for use by ActOnMemberAccess to allow
// BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index f185c1a16834..68bcb26b6df5 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1016,6 +1016,9 @@ namespace serialization {
/// \brief The '_Sat unsigned long _Fract' type
PREDEF_TYPE_SAT_ULONG_FRACT_ID = 69,
+ /// The placeholder type for OpenMP array shaping operation.
+ PREDEF_TYPE_OMP_ARRAY_SHAPING = 70,
+
/// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
@@ -1868,6 +1871,7 @@ namespace serialization {
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_PARALLEL_FOR_SIMD_DIRECTIVE,
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
EXPR_OMP_ARRAY_SECTION,
+ EXPR_OMP_ARRAY_SHAPING,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 461b155df7bf..8bee34e65754 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1386,8 +1386,10 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
InitBuiltinType(BuiltinFnTy, BuiltinType::BuiltinFn);
// Placeholder type for OMP array sections.
- if (LangOpts.OpenMP)
+ if (LangOpts.OpenMP) {
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
+ InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
+ }
// C99 6.2.5p11.
FloatComplexTy = getComplexType(FloatTy);
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index b51164e54926..a023ed173184 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -363,6 +363,15 @@ ExprDependence clang::computeDependence(OMPArraySectionExpr *E) {
return D;
}
+ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
+ auto D = E->getBase()->getDependence() |
+ toExprDependence(E->getType()->getDependence());
+ for (Expr *Dim: E->getDimensions())
+ if (Dim)
+ D |= Dim->getDependence();
+ return D;
+}
+
/// Compute the type-, value-, and instantiation-dependence of a
/// declaration reference
/// based on the declaration being referenced.
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index f0f22b6e4690..fb63897d871f 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3398,6 +3398,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ParenExprClass:
case ArraySubscriptExprClass:
case OMPArraySectionExprClass:
+ case OMPArrayShapingExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
@@ -4569,3 +4570,50 @@ RecoveryExpr *RecoveryExpr::CreateEmpty(ASTContext &Ctx, unsigned NumSubExprs) {
alignof(RecoveryExpr));
return new (Mem) RecoveryExpr(EmptyShell());
}
+
+void OMPArrayShapingExpr::setDimensions(ArrayRef<Expr *> Dims) {
+ assert(
+ NumDims == Dims.size() &&
+ "Preallocated number of dimensions is
diff erent from the provided one.");
+ llvm::copy(Dims, getTrailingObjects<Expr *>());
+}
+
+void OMPArrayShapingExpr::setBracketsRanges(ArrayRef<SourceRange> BR) {
+ assert(
+ NumDims == BR.size() &&
+ "Preallocated number of dimensions is
diff erent from the provided one.");
+ llvm::copy(BR, getTrailingObjects<SourceRange>());
+}
+
+OMPArrayShapingExpr::OMPArrayShapingExpr(QualType ExprTy, Expr *Op,
+ SourceLocation L, SourceLocation R,
+ ArrayRef<Expr *> Dims)
+ : Expr(OMPArrayShapingExprClass, ExprTy, VK_LValue, OK_Ordinary), LPLoc(L),
+ RPLoc(R), NumDims(Dims.size()) {
+ setBase(Op);
+ setDimensions(Dims);
+ setDependence(computeDependence(this));
+}
+
+OMPArrayShapingExpr *
+OMPArrayShapingExpr::Create(const ASTContext &Context, QualType T, Expr *Op,
+ SourceLocation L, SourceLocation R,
+ ArrayRef<Expr *> Dims,
+ ArrayRef<SourceRange> BracketRanges) {
+ assert(Dims.size() == BracketRanges.size() &&
+ "Different number of dimensions and brackets ranges.");
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Expr *, SourceRange>(Dims.size() + 1, Dims.size()),
+ alignof(OMPArrayShapingExpr));
+ auto *E = new (Mem) OMPArrayShapingExpr(T, Op, L, R, Dims);
+ E->setBracketsRanges(BracketRanges);
+ return E;
+}
+
+OMPArrayShapingExpr *OMPArrayShapingExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumDims) {
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Expr *, SourceRange>(NumDims + 1, NumDims),
+ alignof(OMPArrayShapingExpr));
+ return new (Mem) OMPArrayShapingExpr(EmptyShell(), NumDims);
+}
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 58e70347292c..4505626bb61f 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -140,6 +140,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::MSPropertyRefExprClass:
case Expr::MSPropertySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
return Cl::CL_LValue;
// C99 6.5.2.5p5 says that compound literals are lvalues.
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 53e168a81bc3..4a11c846f4ab 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14180,6 +14180,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::StringLiteralClass:
case Expr::ArraySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
case Expr::MemberExprClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 9c1e6b503eaa..4c05990ee410 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3714,6 +3714,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::TypoExprClass: // This should no longer exist in the AST by now.
case Expr::RecoveryExprClass:
case Expr::OMPArraySectionExprClass:
+ case Expr::OMPArrayShapingExprClass:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index ae6ff04f5126..2bfe977a5ba5 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -483,6 +483,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::PseudoObject:
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
break;
}
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 80fdc09a8a6c..3d03f3902d61 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1350,6 +1350,17 @@ void StmtPrinter::VisitOMPArraySectionExpr(OMPArraySectionExpr *Node) {
OS << "]";
}
+void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
+ OS << "(";
+ for (Expr *E : Node->getDimensions()) {
+ OS << "[";
+ PrintExpr(E);
+ OS << "]";
+ }
+ OS << ")";
+ PrintExpr(Node->getBase());
+}
+
void StmtPrinter::PrintCallArgs(CallExpr *Call) {
for (unsigned i = 0, e = Call->getNumArgs(); i != e; ++i) {
if (isa<CXXDefaultArgExpr>(Call->getArg(i))) {
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 5e87eb3e237c..054276a98424 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1194,6 +1194,10 @@ void StmtProfiler::VisitOMPArraySectionExpr(const OMPArraySectionExpr *S) {
VisitExpr(S);
}
+void StmtProfiler::VisitOMPArrayShapingExpr(const OMPArrayShapingExpr *S) {
+ VisitExpr(S);
+}
+
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 279c0d140959..f90eb5cb9c92 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2908,6 +2908,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "reserve_id_t";
case OMPArraySection:
return "<OpenMP array section type>";
+ case OMPArrayShaping:
+ return "<OpenMP array shaping type>";
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case Id: \
return #ExtType;
@@ -3914,6 +3916,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case BuiltinType::BuiltinFn:
case BuiltinType::NullPtr:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
return false;
}
llvm_unreachable("unknown builtin type");
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index 665a86f2c143..dd48ae3fc262 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -404,6 +404,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
#include "clang/Basic/AArch64SVEACLETypes.def"
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
return TST_unspecified;
}
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp
index 4cb828cd23cc..80592671dcd0 100644
--- a/clang/lib/Parse/ParseExpr.cpp
+++ b/clang/lib/Parse/ParseExpr.cpp
@@ -2648,6 +2648,33 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
return ParsePostfixExpressionSuffix(Res.get());
}
+bool Parser::tryParseOpenMPArrayShapingCastPart() {
+ assert(Tok.is(tok::l_square) && "Expected open bracket");
+ bool ErrorFound = true;
+ TentativeParsingAction TPA(*this);
+ do {
+ if (Tok.isNot(tok::l_square))
+ break;
+ // Consume '['
+ ConsumeBracket();
+ // Skip inner expression.
+ while (!SkipUntil(tok::r_square, tok::annot_pragma_openmp_end,
+ StopAtSemi | StopBeforeMatch))
+ ;
+ if (Tok.isNot(tok::r_square))
+ break;
+ // Consume ']'
+ ConsumeBracket();
+ // Found ')' - done.
+ if (Tok.is(tok::r_paren)) {
+ ErrorFound = false;
+ break;
+ }
+ } while (Tok.isNot(tok::annot_pragma_openmp_end));
+ TPA.Revert();
+ return !ErrorFound;
+}
+
/// ParseParenExpression - This parses the unit that starts with a '(' token,
/// based on what is allowed by ExprType. The actual thing parsed is returned
/// in ExprType. If stopIfCastExpr is true, it will only return the parsed type,
@@ -2672,6 +2699,8 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() {
/// '(' '...' fold-operator cast-expression ')'
/// '(' cast-expression fold-operator '...'
/// fold-operator cast-expression ')'
+/// [OPENMP] Array shaping operation
+/// '(' '[' expression ']' { '[' expression ']' } cast-expression
/// \endverbatim
ExprResult
Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
@@ -2948,6 +2977,38 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr,
Result = Actions.ActOnParenListExpr(OpenLoc, Tok.getLocation(),
ArgExprs);
}
+ } else if (getLangOpts().OpenMP >= 50 && OpenMPDirectiveParsing &&
+ ExprType == CastExpr && Tok.is(tok::l_square) &&
+ tryParseOpenMPArrayShapingCastPart()) {
+ bool ErrorFound = false;
+ SmallVector<Expr *, 4> OMPDimensions;
+ SmallVector<SourceRange, 4> OMPBracketsRanges;
+ do {
+ BalancedDelimiterTracker TS(*this, tok::l_square);
+ TS.consumeOpen();
+ ExprResult NumElements =
+ Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ if (!NumElements.isUsable()) {
+ ErrorFound = true;
+ while (!SkipUntil(tok::r_square, tok::r_paren,
+ StopAtSemi | StopBeforeMatch))
+ ;
+ }
+ TS.consumeClose();
+ OMPDimensions.push_back(NumElements.get());
+ OMPBracketsRanges.push_back(TS.getRange());
+ } while (Tok.isNot(tok::r_paren));
+ // Match the ')'.
+ T.consumeClose();
+ RParenLoc = T.getCloseLocation();
+ Result = Actions.CorrectDelayedTyposInExpr(ParseExpression());
+ if (ErrorFound) {
+ Result = ExprError();
+ } else if (!Result.isInvalid()) {
+ Result = Actions.ActOnOMPArrayShapingExpr(
+ Result.get(), OpenLoc, RParenLoc, OMPDimensions, OMPBracketsRanges);
+ }
+ return Result;
} else {
InMessageExpressionRAIIObject InMessage(*this, false);
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index 53c62a1a4017..fad2ae1cc066 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1299,6 +1299,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
// 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 756833c44380..44f51f1a432d 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4798,6 +4798,75 @@ ExprResult Sema::ActOnOMPArraySectionExpr(Expr *Base, SourceLocation LBLoc,
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 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
case BuiltinType::BoundMember:
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
+ case BuiltinType::OMPArrayShaping:
return true;
}
@@ -18433,6 +18503,10 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
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 14aa446cc6ef..f9e8e3d6ccc8 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -15824,7 +15824,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
(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 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
->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 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
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 dda3a3934d3b..82cfa246e3f7 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2379,6 +2379,18 @@ class TreeTransform {
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
diff erent 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 @@ TreeTransform<Derived>::TransformOMPArraySectionExpr(OMPArraySectionExpr *E) {
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) {
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index f93f1f77405d..158a12f0329d 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -243,6 +243,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::OMPArraySection:
ID = PREDEF_TYPE_OMP_ARRAY_SECTION;
break;
+ case BuiltinType::OMPArrayShaping:
+ ID = PREDEF_TYPE_OMP_ARRAY_SHAPING;
+ break;
}
return TypeIdx(ID);
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index c2d28f436241..7437f649a090 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6957,6 +6957,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_OMP_ARRAY_SECTION:
T = Context.OMPArraySectionTy;
break;
+ case PREDEF_TYPE_OMP_ARRAY_SHAPING:
+ T = Context.OMPArraySectionTy;
+ break;
#define SVE_TYPE(Name, Id, SingletonId) \
case PREDEF_TYPE_##Id##_ID: \
T = Context.SingletonId; \
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 3f56968a51dc..bc8c231731e8 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -911,6 +911,22 @@ void ASTStmtReader::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
E->setRBracketLoc(readSourceLocation());
}
+void ASTStmtReader::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
+ VisitExpr(E);
+ unsigned NumDims = Record.readInt();
+ E->setBase(Record.readSubExpr());
+ SmallVector<Expr *, 4> Dims(NumDims);
+ for (unsigned I = 0; I < NumDims; ++I)
+ Dims[I] = Record.readSubExpr();
+ E->setDimensions(Dims);
+ SmallVector<SourceRange, 4> SRs(NumDims);
+ for (unsigned I = 0; I < NumDims; ++I)
+ SRs[I] = readSourceRange();
+ E->setBracketsRanges(SRs);
+ E->setLParenLoc(readSourceLocation());
+ E->setRParenLoc(readSourceLocation());
+}
+
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
unsigned NumArgs = Record.readInt();
@@ -2866,6 +2882,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
S = new (Context) OMPArraySectionExpr(Empty);
break;
+ case EXPR_OMP_ARRAY_SHAPING:
+ S = OMPArrayShapingExpr::CreateEmpty(
+ Context, Record[ASTStmtReader::NumExprFields]);
+ break;
+
case EXPR_CALL:
S = CallExpr::CreateEmpty(
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index d64e2330850a..840823298be7 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -774,6 +774,19 @@ void ASTStmtWriter::VisitOMPArraySectionExpr(OMPArraySectionExpr *E) {
Code = serialization::EXPR_OMP_ARRAY_SECTION;
}
+void ASTStmtWriter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->getDimensions().size());
+ Record.AddStmt(E->getBase());
+ for (Expr *Dim : E->getDimensions())
+ Record.AddStmt(Dim);
+ for (SourceRange SR : E->getBracketsRanges())
+ Record.AddSourceRange(SR);
+ Record.AddSourceLocation(E->getLParenLoc());
+ Record.AddSourceLocation(E->getRParenLoc());
+ Code = serialization::EXPR_OMP_ARRAY_SHAPING;
+}
+
void ASTStmtWriter::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
Record.push_back(E->getNumArgs());
diff --git a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
index f226609d8027..d16410a19b97 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -351,6 +351,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
case Stmt::CallExprClass:
case Stmt::ArraySubscriptExprClass:
case Stmt::OMPArraySectionExprClass:
+ case Stmt::OMPArrayShapingExprClass:
case Stmt::ImplicitCastExprClass:
case Stmt::ParenExprClass:
case Stmt::BreakStmtClass:
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
index 5405c812faca..4c0914628a0d 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1413,6 +1413,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::SubstNonTypeTemplateParmExprClass:
case Stmt::CXXNullPtrLiteralExprClass:
case Stmt::OMPArraySectionExprClass:
+ case Stmt::OMPArrayShapingExprClass:
case Stmt::TypeTraitExprClass: {
Bldr.takeNodes(Pred);
ExplodedNodeSet preVisit;
diff --git a/clang/test/OpenMP/depobj_messages.cpp b/clang/test/OpenMP/depobj_messages.cpp
index ad28dffe184a..a33b16f985a0 100644
--- a/clang/test/OpenMP/depobj_messages.cpp
+++ b/clang/test/OpenMP/depobj_messages.cpp
@@ -158,7 +158,7 @@ label1 : {
#pragma omp depend(out:x) depobj(x) // expected-error {{expected an OpenMP directive}}
#pragma omp destroy depobj(x) // expected-error {{expected an OpenMP directive}}
#pragma omp update(out) depobj(x) // expected-error {{expected an OpenMP directive}}
-#pragma omp depobj depend(in:x) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected addressable lvalue expression, array element or array section of non 'omp_depend_t' type}}
+#pragma omp depobj depend(in:x) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}} expected-error {{expected addressable lvalue expression, array element, array section or array shaping expression of non 'omp_depend_t' type}}
#pragma omp depobj destroy (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
#pragma omp depobj update(in) (x) // expected-error {{expected depobj expression}} expected-warning {{extra tokens at the end of '#pragma omp depobj' are ignored}}
return tmain(argc); // expected-note {{in instantiation of function template specialization 'tmain<int>' requested here}}
diff --git a/clang/test/OpenMP/parallel_reduction_messages.c b/clang/test/OpenMP/parallel_reduction_messages.c
index b5e66672cde9..5d6010d59d50 100644
--- a/clang/test/OpenMP/parallel_reduction_messages.c
+++ b/clang/test/OpenMP/parallel_reduction_messages.c
@@ -2,7 +2,7 @@
int incomplete[];
-void test() {
+void test(int *p) {
int a;
#pragma omp parallel reduction( // expected-error {{expected identifier}} expected-error {{expected ')'}} expected-warning {{missing ':' after reduction identifier - ignoring}} expected-note {{to match this '('}}
;
@@ -16,7 +16,7 @@ void test() {
;
#pragma omp parallel reduction(inscan, + : a) // expected-error {{'inscan' modifier can be used only in 'omp for', 'omp simd', 'omp for simd', 'omp parallel for', or 'omp parallel for simd' directive}}
;
-#pragma omp parallel reduction(+ : incomplete) // expected-error {{a reduction list item with incomplete type 'int []'}}
+#pragma omp parallel reduction(+ : incomplete, ([10])p) // expected-error {{a reduction list item with incomplete type 'int []'}} expected-error {{expected variable name, array element or array section}}
;
}
diff --git a/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp
index 41c9bd0b308d..0f11b390f7fa 100644
--- a/clang/test/OpenMP/task_ast_print.cpp
+++ b/clang/test/OpenMP/task_ast_print.cpp
@@ -99,7 +99,7 @@ T tmain(T argc, T *argv) {
T arr[argc];
omp_depend_t x;
omp_event_handle_t evt;
-#pragma omp task untied depend(in : argc, argv[b:argc], arr[:]) if (task : argc > 0) depend(depobj: x) detach(evt)
+#pragma omp task untied depend(in : argc, argv[b:argc], arr[:], ([argc][sizeof(T)])argv) if (task : argc > 0) depend(depobj: x) detach(evt)
a = 2;
#pragma omp task default(none), private(argc, b) firstprivate(argv) shared(d) if (argc > 0) final(S<T>::TS > 0) priority(argc)
foo();
@@ -116,7 +116,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: T arr[argc];
// CHECK-NEXT: omp_depend_t x;
// CHECK-NEXT: omp_event_handle_t evt;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x) detach(evt)
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(T)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<T>::TS > 0) priority(argc)
// CHECK-NEXT: foo()
@@ -130,7 +130,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: int arr[argc];
// CHECK-NEXT: omp_depend_t x;
// CHECK-NEXT: omp_event_handle_t evt;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x) detach(evt)
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(int)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<int>::TS > 0) priority(argc)
// CHECK-NEXT: foo()
@@ -144,7 +144,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: long arr[argc];
// CHECK-NEXT: omp_depend_t x;
// CHECK-NEXT: omp_event_handle_t evt;
-// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:]) if(task: argc > 0) depend(depobj : x) detach(evt)
+// CHECK-NEXT: #pragma omp task untied depend(in : argc,argv[b:argc],arr[:],([argc][sizeof(long)])argv) if(task: argc > 0) depend(depobj : x) detach(evt)
// CHECK-NEXT: a = 2;
// CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv) shared(d) if(argc > 0) final(S<long>::TS > 0) priority(argc)
// CHECK-NEXT: foo()
@@ -164,14 +164,14 @@ int main(int argc, char **argv) {
#pragma omp threadprivate(a)
Enum ee;
// CHECK: Enum ee;
-#pragma omp task untied mergeable depend(out:argv[:a][1], (arr)[0:]) if(task: argc > 0) priority(f) depend(depobj:y)
- // CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[:a][1],(arr)[0:]) if(task: argc > 0) priority(f) depend(depobj : y)
+#pragma omp task untied mergeable depend(out:argv[:a][1], (arr)[0:],([argc][10])argv) if(task: argc > 0) priority(f) depend(depobj:y)
+ // CHECK-NEXT: #pragma omp task untied mergeable depend(out : argv[:a][1],(arr)[0:],([argc][10])argv) if(task: argc > 0) priority(f) depend(depobj : y)
a = 2;
// CHECK-NEXT: a = 2;
#pragma omp taskgroup task_reduction(min: arr1)
-#pragma omp task default(none), private(argc, b) firstprivate(argv, evt) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1), detach(evt)
+#pragma omp task default(none), private(argc, b) firstprivate(argv, evt) if (argc > 0) final(a > 0) depend(inout : a, argv[:argc],arr[:a], ([10][argc])argv) priority(23) in_reduction(min: arr1), detach(evt)
// CHECK-NEXT: #pragma omp taskgroup task_reduction(min: arr1)
- // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv,evt) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a]) priority(23) in_reduction(min: arr1) detach(evt)
+ // CHECK-NEXT: #pragma omp task default(none) private(argc,b) firstprivate(argv,evt) if(argc > 0) final(a > 0) depend(inout : a,argv[:argc],arr[:a],([10][argc])argv) priority(23) in_reduction(min: arr1) detach(evt)
foo();
// CHECK-NEXT: foo();
#pragma omp taskgroup task_reduction(min: arr1)
diff --git a/clang/test/OpenMP/task_depend_messages.cpp b/clang/test/OpenMP/task_depend_messages.cpp
index ea55cdaa84af..7d976eca2ec1 100644
--- a/clang/test/OpenMP/task_depend_messages.cpp
+++ b/clang/test/OpenMP/task_depend_messages.cpp
@@ -35,14 +35,14 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp task depend (source) // expected-error {{expected expression}} expected-warning {{missing ':' after dependency type - ignoring}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
#pragma omp task depend (in : argc)) // expected-warning {{extra tokens at the end of '#pragma omp task' are ignored}}
#pragma omp task depend (out: ) // expected-error {{expected expression}}
- #pragma omp task depend (inout : foobool(argc)), depend (in, argc) // expected-error {{expected addressable lvalue expression, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
+ #pragma omp task depend (inout : foobool(argc)), depend (in, argc) // omp50-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} omp45-error {{expected addressable lvalue expression, array element or array section}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected expression}}
#pragma omp task depend (out :S1) // expected-error {{'S1' does not refer to a value}}
#pragma omp task depend(in : argv[1][1] = '2')
- #pragma omp task depend (in : vec[1]) // expected-error {{expected addressable lvalue expression, array element or array section}}
+ #pragma omp task depend (in : vec[1]) // omp50-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} omp45-error {{expected addressable lvalue expression, array element or array section}}
#pragma omp task depend (in : argv[0])
#pragma omp task depend (in : ) // expected-error {{expected expression}}
#pragma omp task depend (in : main)
- #pragma omp task depend(in : a[0]) // expected-error{{expected addressable lvalue expression, array element or array section}}
+ #pragma omp task depend(in : a[0]) // omp50-error {{expected addressable lvalue expression, array element, array section or array shaping expression}} omp45-error {{expected addressable lvalue expression, array element or array section}}
#pragma omp task depend (in : vec[1:2]) // expected-error {{ value is not an array or pointer}}
#pragma omp task depend (in : argv[ // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
#pragma omp task depend (in : argv[: // expected-error {{expected expression}} expected-error {{expected ']'}} expected-error {{expected ')'}} expected-note {{to match this '['}} expected-note {{to match this '('}}
@@ -62,6 +62,14 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp task depend(depobj:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not 'int'}}
#pragma omp task depend(depobj : argv[ : argc][1 : argc - 1]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected lvalue expression of 'omp_depend_t' type, not '<OpenMP array section type>'}}
#pragma omp task depend(depobj : arr[0]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
+ #pragma omp task depend(in : ([ // expected-error {{expected variable name or 'this' in lambda capture list}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task depend(in : ([] // expected-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}}
+ #pragma omp task depend(in : ([]) // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}}
+ #pragma omp task depend(in : ([])a // omp45-error {{expected body of lambda expression}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected expression}}
+ #pragma omp task depend(in : ([])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression}}
+ #pragma omp task depend(in : ([a])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected pointer type expression as a base of an array shaping operation}}
+ #pragma omp task depend(in : ([a])argc) // omp45-error {{expected body of lambda expression}} omp50-error {{expected pointer type expression as a base of an array shaping operation}}
+ #pragma omp task depend(in : ([-1][0])argv) // omp45-error {{expected variable name or 'this' in lambda capture list}} omp45-error {{expected ')'}} omp45-note {{to match this '('}} omp50-error {{array shaping dimension is evaluated to a non-positive value -1}} omp50-error {{array shaping dimension is evaluated to a non-positive value 0}}
foo();
return 0;
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index c878f454aad0..bb9fed165679 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5183,6 +5183,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("ArraySubscriptExpr");
case CXCursor_OMPArraySectionExpr:
return cxstring::createRef("OMPArraySectionExpr");
+ case CXCursor_OMPArrayShapingExpr:
+ return cxstring::createRef("OMPArrayShapingExpr");
case CXCursor_BinaryOperator:
return cxstring::createRef("BinaryOperator");
case CXCursor_CompoundAssignOperator:
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index 1f6304a08bca..4f4e0c4ea1d5 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -423,6 +423,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_OMPArraySectionExpr;
break;
+ case Stmt::OMPArrayShapingExprClass:
+ K = CXCursor_OMPArrayShapingExpr;
+ break;
+
case Stmt::BinaryOperatorClass:
K = CXCursor_BinaryOperator;
break;
More information about the cfe-commits
mailing list