[clang] f08df46 - [OPENMP50]Add initial support for OpenMP 5.0 iterator.
Alexey Bataev via cfe-commits
cfe-commits at lists.llvm.org
Wed Apr 1 10:01:50 PDT 2020
Author: Alexey Bataev
Date: 2020-04-01T12:53:55-04:00
New Revision: f08df464ae89972a777c0a7e299a2c153a9829d8
URL: https://github.com/llvm/llvm-project/commit/f08df464ae89972a777c0a7e299a2c153a9829d8
DIFF: https://github.com/llvm/llvm-project/commit/f08df464ae89972a777c0a7e299a2c153a9829d8.diff
LOG: [OPENMP50]Add initial support for OpenMP 5.0 iterator.
Added basic parsing/semantic analysis/(de)serialization support for
iterator expression introduced in OpenMP 5.0.
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/OpenMPClause.h
clang/include/clang/AST/RecursiveASTVisitor.h
clang/include/clang/AST/TextNodeDumper.h
clang/include/clang/Basic/DiagnosticParseKinds.td
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/OpenMPClause.cpp
clang/lib/AST/StmtPrinter.cpp
clang/lib/AST/StmtProfile.cpp
clang/lib/AST/TextNodeDumper.cpp
clang/lib/AST/Type.cpp
clang/lib/AST/TypeLoc.cpp
clang/lib/Parse/ParseOpenMP.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/ASTWriter.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/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 641f058dafaa..0acd50021ed8 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2180,7 +2180,12 @@ enum CXCursorKind {
*/
CXCursor_OMPArrayShapingExpr = 150,
- CXCursor_LastExpr = CXCursor_OMPArrayShapingExpr,
+ /**
+ * OpenMP 5.0 [2.1.6 Iterators]
+ */
+ CXCursor_OMPIteratorExpr = 151,
+
+ CXCursor_LastExpr = CXCursor_OMPIteratorExpr,
/* Statements */
CXCursor_FirstStmt = 200,
diff --git a/clang/include/clang/AST/ASTContext.h b/clang/include/clang/AST/ASTContext.h
index ebb5ca593843..6813ab58874e 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, OMPArrayShapingTy;
+ CanQualType OMPArraySectionTy, OMPArrayShapingTy, OMPIteratorTy;
#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 f42503773945..f8eb4ec19c8f 100644
--- a/clang/include/clang/AST/BuiltinTypes.def
+++ b/clang/include/clang/AST/BuiltinTypes.def
@@ -316,8 +316,11 @@ PLACEHOLDER_TYPE(OMPArraySection, OMPArraySectionTy)
// A placeholder type for OpenMP array shaping operation.
PLACEHOLDER_TYPE(OMPArrayShaping, OMPArrayShapingTy)
+// A placeholder type for OpenMP iterators.
+PLACEHOLDER_TYPE(OMPIterator, OMPIteratorTy)
+
#ifdef LAST_BUILTIN_TYPE
-LAST_BUILTIN_TYPE(OMPArrayShaping)
+LAST_BUILTIN_TYPE(OMPIterator)
#undef LAST_BUILTIN_TYPE
#endif
diff --git a/clang/include/clang/AST/ComputeDependence.h b/clang/include/clang/AST/ComputeDependence.h
index 63947eaff73b..ab742c9b70dd 100644
--- a/clang/include/clang/AST/ComputeDependence.h
+++ b/clang/include/clang/AST/ComputeDependence.h
@@ -88,6 +88,7 @@ class PseudoObjectExpr;
class AtomicExpr;
class OMPArraySectionExpr;
class OMPArrayShapingExpr;
+class OMPIteratorExpr;
class ObjCArrayLiteral;
class ObjCDictionaryLiteral;
class ObjCBoxedExpr;
@@ -174,6 +175,7 @@ ExprDependence computeDependence(AtomicExpr *E);
ExprDependence computeDependence(OMPArraySectionExpr *E);
ExprDependence computeDependence(OMPArrayShapingExpr *E);
+ExprDependence computeDependence(OMPIteratorExpr *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 4a0cd07f1dab..6059df8b33e7 100644
--- a/clang/include/clang/AST/ExprOpenMP.h
+++ b/clang/include/clang/AST/ExprOpenMP.h
@@ -205,6 +205,173 @@ class OMPArrayShapingExpr final
return const_child_range(Begin, Begin + NumDims + 1);
}
};
+
+/// OpenMP 5.0 [2.1.6 Iterators]
+/// Iterators are identifiers that expand to multiple values in the clause on
+/// which they appear.
+/// The syntax of the iterator modifier is as follows:
+/// \code
+/// iterator(iterators-definition)
+/// \endcode
+/// where iterators-definition is one of the following:
+/// \code
+/// iterator-specifier [, iterators-definition ]
+/// \endcode
+/// where iterator-specifier is one of the following:
+/// \code
+/// [ iterator-type ] identifier = range-specification
+/// \endcode
+/// where identifier is a base language identifier.
+/// iterator-type is a type name.
+/// range-specification is of the form begin:end[:step], where begin and end are
+/// expressions for which their types can be converted to iterator-type and step
+/// is an integral expression.
+/// In an iterator-specifier, if the iterator-type is not specified then the
+/// type of that iterator is of int type.
+/// The iterator-type must be an integral or pointer type.
+/// The iterator-type must not be const qualified.
+class OMPIteratorExpr final
+ : public Expr,
+ private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *,
+ SourceLocation> {
+public:
+ /// Iterator range representation begin:end[:step].
+ struct IteratorRange {
+ Expr *Begin = nullptr;
+ Expr *End = nullptr;
+ Expr *Step = nullptr;
+ };
+ /// Iterator definition representation.
+ struct IteratorDefinition {
+ Decl *IteratorDecl = nullptr;
+ IteratorRange Range;
+ SourceLocation AssignmentLoc;
+ SourceLocation ColonLoc, SecondColonLoc;
+ };
+
+private:
+ friend TrailingObjects;
+ friend class ASTStmtReader;
+ friend class ASTStmtWriter;
+
+ /// Offset in the list of expressions for subelements of the ranges.
+ enum class RangeExprOffset {
+ Begin = 0,
+ End = 1,
+ Step = 2,
+ Total = 3,
+ };
+ /// Offset in the list of locations for subelements of colon symbols
+ /// locations.
+ enum class RangeLocOffset {
+ AssignLoc = 0,
+ FirstColonLoc = 1,
+ SecondColonLoc = 2,
+ Total = 3,
+ };
+ /// Location of 'iterator' keyword.
+ SourceLocation IteratorKwLoc;
+ /// Location of '('.
+ SourceLocation LPLoc;
+ /// Location of ')'.
+ SourceLocation RPLoc;
+ /// Number of iterator definitions.
+ unsigned NumIterators = 0;
+
+ OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc,
+ SourceLocation L, SourceLocation R,
+ ArrayRef<OMPIteratorExpr::IteratorDefinition> Data);
+
+ /// Construct an empty expression.
+ explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators)
+ : Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {}
+
+ /// Sets basic declaration for the specified iterator definition.
+ void setIteratorDeclaration(unsigned I, Decl *D);
+
+ /// Sets the location of the assignment symbol for the specified iterator
+ /// definition.
+ void setAssignmentLoc(unsigned I, SourceLocation Loc);
+
+ /// Sets begin, end and optional step expressions for specified iterator
+ /// definition.
+ void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc,
+ Expr *End, SourceLocation SecondColonLoc, Expr *Step);
+
+ unsigned numTrailingObjects(OverloadToken<Decl *>) const {
+ return NumIterators;
+ }
+
+ unsigned numTrailingObjects(OverloadToken<Expr *>) const {
+ return NumIterators * static_cast<int>(RangeExprOffset::Total);
+ }
+
+ unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
+ return NumIterators * static_cast<int>(RangeLocOffset::Total);
+ }
+
+public:
+ static OMPIteratorExpr *Create(const ASTContext &Context, QualType T,
+ SourceLocation IteratorKwLoc, SourceLocation L,
+ SourceLocation R,
+ ArrayRef<IteratorDefinition> Data);
+
+ static OMPIteratorExpr *CreateEmpty(const ASTContext &Context,
+ unsigned NumIterators);
+
+ SourceLocation getLParenLoc() const { return LPLoc; }
+ void setLParenLoc(SourceLocation L) { LPLoc = L; }
+
+ SourceLocation getRParenLoc() const { return RPLoc; }
+ void setRParenLoc(SourceLocation L) { RPLoc = L; }
+
+ SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; }
+ void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; }
+ SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; }
+ SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; }
+
+ /// Gets the iterator declaration for the given iterator.
+ Decl *getIteratorDecl(unsigned I);
+ const Decl *getIteratorDecl(unsigned I) const {
+ return const_cast<OMPIteratorExpr *>(this)->getIteratorDecl(I);
+ }
+
+ /// Gets the iterator range for the given iterator.
+ IteratorRange getIteratorRange(unsigned I);
+ const IteratorRange getIteratorRange(unsigned I) const {
+ return const_cast<OMPIteratorExpr *>(this)->getIteratorRange(I);
+ }
+
+ /// Gets the location of '=' for the given iterator definition.
+ SourceLocation getAssignLoc(unsigned I) const;
+ /// Gets the location of the first ':' in the range for the given iterator
+ /// definition.
+ SourceLocation getColonLoc(unsigned I) const;
+ /// Gets the location of the second ':' (if any) in the range for the given
+ /// iteratori definition.
+ SourceLocation getSecondColonLoc(unsigned I) const;
+
+ /// Returns number of iterator definitions.
+ unsigned numOfIterators() const { return NumIterators; }
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPIteratorExprClass;
+ }
+
+ // Iterators
+ child_range children() {
+ Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
+ return child_range(
+ Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
+ }
+ const_child_range children() const {
+ Stmt *const *Begin =
+ reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
+ return const_child_range(
+ Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
+ }
+};
+
} // end namespace clang
#endif
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 0d4b69911f19..028af6ac9a72 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -4372,6 +4372,9 @@ class OMPDependClause final
/// Set colon location.
void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; }
+ /// Sets optional dependency modifier.
+ void setModifier(Expr *DepModifier);
+
public:
/// Creates clause with a list of variables \a VL.
///
@@ -4387,7 +4390,7 @@ class OMPDependClause final
/// clause.
static OMPDependClause *Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc,
- SourceLocation EndLoc,
+ SourceLocation EndLoc, Expr *DepModifier,
OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VL, unsigned NumLoops);
@@ -4404,6 +4407,12 @@ class OMPDependClause final
/// Get dependency type.
OpenMPDependClauseKind getDependencyKind() const { return DepKind; }
+ /// Return optional depend modifier.
+ Expr *getModifier();
+ const Expr *getModifier() const {
+ return const_cast<OMPDependClause *>(this)->getModifier();
+ }
+
/// Get dependency type location.
SourceLocation getDependencyLoc() const { return DepLoc; }
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 46661e59f181..345333849659 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -2552,6 +2552,7 @@ DEF_TRAVERSE_STMT(AddrLabelExpr, {})
DEF_TRAVERSE_STMT(ArraySubscriptExpr, {})
DEF_TRAVERSE_STMT(OMPArraySectionExpr, {})
DEF_TRAVERSE_STMT(OMPArrayShapingExpr, {})
+DEF_TRAVERSE_STMT(OMPIteratorExpr, {})
DEF_TRAVERSE_STMT(BlockExpr, {
TRY_TO(TraverseDecl(S->getBlockDecl()));
diff --git a/clang/include/clang/AST/TextNodeDumper.h b/clang/include/clang/AST/TextNodeDumper.h
index b08d1e482be8..0fb4baf0ca4d 100644
--- a/clang/include/clang/AST/TextNodeDumper.h
+++ b/clang/include/clang/AST/TextNodeDumper.h
@@ -274,6 +274,7 @@ class TextNodeDumper
void VisitObjCSubscriptRefExpr(const ObjCSubscriptRefExpr *Node);
void VisitObjCIvarRefExpr(const ObjCIvarRefExpr *Node);
void VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node);
+ void VisitOMPIteratorExpr(const OMPIteratorExpr *Node);
void VisitRValueReferenceType(const ReferenceType *T);
void VisitArrayType(const ArrayType *T);
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 6eb320a85a30..f3741531c8b5 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1220,6 +1220,10 @@ def err_omp_expected_identifier_for_critical : Error<
"expected identifier specifying the name of the 'omp critical' directive">;
def err_omp_expected_reduction_identifier : Error<
"expected identifier or one of the following operators: '+', '-', '*', '&', '|', '^', '&&', or '||'">;
+def err_omp_expected_equal_in_iterator : Error<
+ "expected '=' in iterator specifier">;
+def err_omp_expected_punc_after_iterator : Error<
+ "expected ',' or ')' after iterator specifier">;
def err_omp_decl_in_declare_simd_variant : Error<
"function declaration is expected after 'declare %select{simd|variant}0' directive">;
def err_omp_unknown_map_type : Error<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 951a955984f6..901ac758b383 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -9760,6 +9760,14 @@ def note_omp_conversion_here : Note<
def err_omp_ambiguous_conversion : Error<
"ambiguous conversion from type %0 to an integral or unscoped "
"enumeration type">;
+def err_omp_iterator_not_integral_or_pointer : Error<
+ "expected integral or pointer type as the iterator-type, not %0">;
+def err_omp_iterator_constant : Error<
+ "expected non-constant type as the iterator-type, constant %0 is provided">;
+def err_omp_iterator_step_not_integral : Error<
+ "iterator step expression %0 is not the integral expression">;
+def err_omp_iterator_step_constant_zero : Error<
+ "iterator step expression %0 evaluates to 0">;
def err_omp_required_access : Error<
"%0 variable must be %1">;
def err_omp_const_variable : Error<
@@ -9953,6 +9961,7 @@ 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_iterator_use : Error<"OpenMP iterator 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<
@@ -10031,6 +10040,10 @@ def err_omp_depend_sink_source_not_allowed : Error<
"'depend(%select{source|sink:vec}0)' clause%select{|s}0 cannot be mixed with 'depend(%select{sink:vec|source}0)' clause%select{s|}0">;
def err_omp_depend_zero_length_array_section_not_allowed : Error<
"zero-length array section is not allowed in 'depend' clause">;
+def err_omp_depend_sink_source_with_modifier : Error<
+ "depend modifier cannot be used with 'sink' or 'source' depend type">;
+def err_omp_depend_modifier_not_iterator : Error<
+ "expected iterator specification as depend modifier">;
def err_omp_linear_ordered : Error<
"'linear' clause cannot be specified along with 'ordered' clause with a parameter">;
def err_omp_unexpected_schedule_modifier : Error<
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index ba1b5ebd6305..aecf24f89033 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -70,6 +70,7 @@ def OffsetOfExpr : StmtNode<Expr>;
def UnaryExprOrTypeTraitExpr : StmtNode<Expr>;
def ArraySubscriptExpr : StmtNode<Expr>;
def OMPArraySectionExpr : StmtNode<Expr>;
+def OMPIteratorExpr : StmtNode<Expr>;
def CallExpr : StmtNode<Expr>;
def MemberExpr : StmtNode<Expr>;
def CastExpr : StmtNode<Expr, 1>;
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index 290da0006116..ca0a5fd68994 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3086,6 +3086,11 @@ class Parser : public CodeCompletionHandler {
OMPClause *ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind, bool ParseOnly);
+ /// Parses and creates OpenMP 5.0 iterators expression:
+ /// <iterators> = 'iterator' '(' { [ <iterator-type> ] identifier =
+ /// <range-specification> }+ ')'
+ ExprResult ParseOpenMPIteratorsExpr();
+
public:
/// Parses simple expression in parens for single-expression clauses of OpenMP
/// constructs.
@@ -3095,7 +3100,7 @@ class Parser : public CodeCompletionHandler {
/// Data used for parsing list of variables in OpenMP clauses.
struct OpenMPVarListDataTy {
- Expr *TailExpr = nullptr;
+ Expr *DepModOrTailExpr = nullptr;
SourceLocation ColonLoc;
SourceLocation RLoc;
CXXScopeSpec ReductionOrMapperIdScopeSpec;
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 9a41356ddb70..e1365e84a0b3 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -25,6 +25,7 @@
#include "clang/AST/ExprCXX.h"
#include "clang/AST/ExprConcepts.h"
#include "clang/AST/ExprObjC.h"
+#include "clang/AST/ExprOpenMP.h"
#include "clang/AST/ExternalASTSource.h"
#include "clang/AST/LocInfoType.h"
#include "clang/AST/MangleNumberingContext.h"
@@ -4904,6 +4905,21 @@ class Sema final {
ArrayRef<Expr *> Dims,
ArrayRef<SourceRange> Brackets);
+ /// Data structure for iterator expression.
+ struct OMPIteratorData {
+ IdentifierInfo *DeclIdent = nullptr;
+ SourceLocation DeclIdentLoc;
+ ParsedType Type;
+ OMPIteratorExpr::IteratorRange Range;
+ SourceLocation AssignLoc;
+ SourceLocation ColonLoc;
+ SourceLocation SecColonLoc;
+ };
+
+ ExprResult ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+ SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<OMPIteratorData> Data);
+
// This struct is for use by ActOnMemberAccess to allow
// BuildMemberReferenceExpr to be able to reinvoke ActOnMemberAccess after
// changing the access operator from a '.' to a '->' (to see if that is the
@@ -10572,7 +10588,7 @@ class Sema final {
SourceLocation StartLoc, SourceLocation LParenLoc, SourceLocation EndLoc);
OMPClause *ActOnOpenMPVarListClause(
- OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *TailExpr,
+ OpenMPClauseKind Kind, ArrayRef<Expr *> Vars, Expr *DepModOrTailExpr,
const OMPVarListLocTy &Locs, SourceLocation ColonLoc,
CXXScopeSpec &ReductionOrMapperIdScopeSpec,
DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier,
@@ -10670,10 +10686,10 @@ class Sema final {
SourceLocation EndLoc);
/// Called on well-formed 'depend' clause.
OMPClause *
- ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
- SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc);
+ ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc);
/// Called on well-formed 'device' clause.
OMPClause *ActOnOpenMPDeviceClause(OpenMPDeviceClauseModifier Modifier,
Expr *Device, SourceLocation StartLoc,
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 68bcb26b6df5..e6e9c8570cc8 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1019,6 +1019,9 @@ namespace serialization {
/// The placeholder type for OpenMP array shaping operation.
PREDEF_TYPE_OMP_ARRAY_SHAPING = 70,
+ /// The placeholder type for OpenMP iterator expression.
+ PREDEF_TYPE_OMP_ITERATOR = 71,
+
/// OpenCL image types with auto numeration
#define IMAGE_TYPE(ImgType, Id, SingletonId, Access, Suffix) \
PREDEF_TYPE_##Id##_ID,
@@ -1872,6 +1875,7 @@ namespace serialization {
STMT_OMP_TARGET_TEAMS_DISTRIBUTE_SIMD_DIRECTIVE,
EXPR_OMP_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING,
+ EXPR_OMP_ITERATOR,
// ARC
EXPR_OBJC_BRIDGED_CAST, // ObjCBridgedCastExpr
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 8bee34e65754..1e81e0a67b4d 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -1389,6 +1389,7 @@ void ASTContext::InitBuiltinTypes(const TargetInfo &Target,
if (LangOpts.OpenMP) {
InitBuiltinType(OMPArraySectionTy, BuiltinType::OMPArraySection);
InitBuiltinType(OMPArrayShapingTy, BuiltinType::OMPArrayShaping);
+ InitBuiltinType(OMPIteratorTy, BuiltinType::OMPIterator);
}
// C99 6.2.5p11.
diff --git a/clang/lib/AST/ComputeDependence.cpp b/clang/lib/AST/ComputeDependence.cpp
index a023ed173184..3a326f62a2ec 100644
--- a/clang/lib/AST/ComputeDependence.cpp
+++ b/clang/lib/AST/ComputeDependence.cpp
@@ -372,6 +372,22 @@ ExprDependence clang::computeDependence(OMPArrayShapingExpr *E) {
return D;
}
+ExprDependence clang::computeDependence(OMPIteratorExpr *E) {
+ auto D = toExprDependence(E->getType()->getDependence());
+ for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
+ if (auto *VD = cast_or_null<ValueDecl>(E->getIteratorDecl(I)))
+ D |= toExprDependence(VD->getType()->getDependence());
+ OMPIteratorExpr::IteratorRange IR = E->getIteratorRange(I);
+ if (Expr *BE = IR.Begin)
+ D |= BE->getDependence();
+ if (Expr *EE = IR.End)
+ D |= EE->getDependence();
+ if (Expr *SE = IR.Step)
+ D |= SE->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 fb63897d871f..53ec3b7a93db 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -3399,6 +3399,7 @@ bool Expr::HasSideEffects(const ASTContext &Ctx,
case ArraySubscriptExprClass:
case OMPArraySectionExprClass:
case OMPArrayShapingExprClass:
+ case OMPIteratorExprClass:
case MemberExprClass:
case ConditionalOperatorClass:
case BinaryConditionalOperatorClass:
@@ -4617,3 +4618,118 @@ OMPArrayShapingExpr *OMPArrayShapingExpr::CreateEmpty(const ASTContext &Context,
alignof(OMPArrayShapingExpr));
return new (Mem) OMPArrayShapingExpr(EmptyShell(), NumDims);
}
+
+void OMPIteratorExpr::setIteratorDeclaration(unsigned I, Decl *D) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<Decl *>()[I] = D;
+}
+
+void OMPIteratorExpr::setAssignmentLoc(unsigned I, SourceLocation Loc) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::AssignLoc)] = Loc;
+}
+
+void OMPIteratorExpr::setIteratorRange(unsigned I, Expr *Begin,
+ SourceLocation ColonLoc, Expr *End,
+ SourceLocation SecondColonLoc,
+ Expr *Step) {
+ assert(I < NumIterators &&
+ "Idx is greater or equal the number of iterators definitions.");
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Begin)] =
+ Begin;
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::End)] = End;
+ getTrailingObjects<Expr *>()[I * static_cast<int>(RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Step)] = Step;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::FirstColonLoc)] =
+ ColonLoc;
+ getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::SecondColonLoc)] =
+ SecondColonLoc;
+}
+
+Decl *OMPIteratorExpr::getIteratorDecl(unsigned I) {
+ return getTrailingObjects<Decl *>()[I];
+}
+
+OMPIteratorExpr::IteratorRange OMPIteratorExpr::getIteratorRange(unsigned I) {
+ IteratorRange Res;
+ Res.Begin =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Begin)];
+ Res.End =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::End)];
+ Res.Step =
+ getTrailingObjects<Expr *>()[I * static_cast<int>(
+ RangeExprOffset::Total) +
+ static_cast<int>(RangeExprOffset::Step)];
+ return Res;
+}
+
+SourceLocation OMPIteratorExpr::getAssignLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::AssignLoc)];
+}
+
+SourceLocation OMPIteratorExpr::getColonLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::FirstColonLoc)];
+}
+
+SourceLocation OMPIteratorExpr::getSecondColonLoc(unsigned I) const {
+ return getTrailingObjects<
+ SourceLocation>()[I * static_cast<int>(RangeLocOffset::Total) +
+ static_cast<int>(RangeLocOffset::SecondColonLoc)];
+}
+
+OMPIteratorExpr::OMPIteratorExpr(
+ QualType ExprTy, SourceLocation IteratorKwLoc, SourceLocation L,
+ SourceLocation R, ArrayRef<OMPIteratorExpr::IteratorDefinition> Data)
+ : Expr(OMPIteratorExprClass, ExprTy, VK_LValue, OK_Ordinary),
+ IteratorKwLoc(IteratorKwLoc), LPLoc(L), RPLoc(R),
+ NumIterators(Data.size()) {
+ for (unsigned I = 0, End = Data.size(); I < End; ++I) {
+ const IteratorDefinition &D = Data[I];
+ setIteratorDeclaration(I, D.IteratorDecl);
+ setIteratorRange(I, D.Range.Begin, D.ColonLoc, D.Range.End,
+ D.SecondColonLoc, D.Range.Step);
+ }
+ setDependence(computeDependence(this));
+}
+
+OMPIteratorExpr *
+OMPIteratorExpr::Create(const ASTContext &Context, QualType T,
+ SourceLocation IteratorKwLoc, SourceLocation L,
+ SourceLocation R,
+ ArrayRef<OMPIteratorExpr::IteratorDefinition> Data) {
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Decl *, Expr *, SourceLocation>(
+ Data.size(), Data.size() * static_cast<int>(RangeExprOffset::Total),
+ Data.size() * static_cast<int>(RangeLocOffset::Total)),
+ alignof(OMPIteratorExpr));
+ auto *E = new (Mem) OMPIteratorExpr(T, IteratorKwLoc, L, R, Data);
+ return E;
+}
+
+OMPIteratorExpr *OMPIteratorExpr::CreateEmpty(const ASTContext &Context,
+ unsigned NumIterators) {
+ void *Mem = Context.Allocate(
+ totalSizeToAlloc<Decl *, Expr *, SourceLocation>(
+ NumIterators, NumIterators * static_cast<int>(RangeExprOffset::Total),
+ NumIterators * static_cast<int>(RangeLocOffset::Total)),
+ alignof(OMPIteratorExpr));
+ return new (Mem) OMPIteratorExpr(EmptyShell(), NumIterators);
+}
diff --git a/clang/lib/AST/ExprClassification.cpp b/clang/lib/AST/ExprClassification.cpp
index 4505626bb61f..8587a476a5d9 100644
--- a/clang/lib/AST/ExprClassification.cpp
+++ b/clang/lib/AST/ExprClassification.cpp
@@ -141,6 +141,7 @@ static Cl::Kinds ClassifyInternal(ASTContext &Ctx, const Expr *E) {
case Expr::MSPropertySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
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 4a11c846f4ab..c6e1cc7b67df 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -14181,6 +14181,7 @@ static ICEDiag CheckICE(const Expr* E, const ASTContext &Ctx) {
case Expr::ArraySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
case Expr::MemberExprClass:
case Expr::CompoundAssignOperatorClass:
case Expr::CompoundLiteralExprClass:
diff --git a/clang/lib/AST/ItaniumMangle.cpp b/clang/lib/AST/ItaniumMangle.cpp
index 4c05990ee410..cb7bd61574ef 100644
--- a/clang/lib/AST/ItaniumMangle.cpp
+++ b/clang/lib/AST/ItaniumMangle.cpp
@@ -3715,6 +3715,7 @@ void CXXNameMangler::mangleExpression(const Expr *E, unsigned Arity) {
case Expr::RecoveryExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
case Expr::CXXInheritedCtorInitExprClass:
llvm_unreachable("unexpected statement kind");
diff --git a/clang/lib/AST/NSAPI.cpp b/clang/lib/AST/NSAPI.cpp
index 2bfe977a5ba5..3bb3605ea936 100644
--- a/clang/lib/AST/NSAPI.cpp
+++ b/clang/lib/AST/NSAPI.cpp
@@ -484,6 +484,7 @@ NSAPI::getNSNumberFactoryMethodKind(QualType T) const {
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
break;
}
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 4b7ebbb3c26d..eeb690750fb7 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -900,16 +900,19 @@ OMPDepobjClause *OMPDepobjClause::CreateEmpty(const ASTContext &C) {
OMPDependClause *
OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc,
- OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
- SourceLocation ColonLoc, ArrayRef<Expr *> VL,
- unsigned NumLoops) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(VL.size() + NumLoops));
+ Expr *DepModifier, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VL, unsigned NumLoops) {
+ void *Mem = C.Allocate(
+ totalSizeToAlloc<Expr *>(VL.size() + /*depend-modifier*/ 1 + NumLoops),
+ alignof(OMPDependClause));
OMPDependClause *Clause = new (Mem)
OMPDependClause(StartLoc, LParenLoc, EndLoc, VL.size(), NumLoops);
Clause->setVarRefs(VL);
Clause->setDependencyKind(DepKind);
Clause->setDependencyLoc(DepLoc);
Clause->setColonLoc(ColonLoc);
+ Clause->setModifier(DepModifier);
for (unsigned I = 0 ; I < NumLoops; ++I)
Clause->setLoopData(I, nullptr);
return Clause;
@@ -917,7 +920,9 @@ OMPDependClause::Create(const ASTContext &C, SourceLocation StartLoc,
OMPDependClause *OMPDependClause::CreateEmpty(const ASTContext &C, unsigned N,
unsigned NumLoops) {
- void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(N + NumLoops));
+ void *Mem =
+ C.Allocate(totalSizeToAlloc<Expr *>(N + /*depend-modifier*/ 1 + NumLoops),
+ alignof(OMPDependClause));
return new (Mem) OMPDependClause(N, NumLoops);
}
@@ -927,7 +932,7 @@ void OMPDependClause::setLoopData(unsigned NumLoop, Expr *Cnt) {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ auto *It = std::next(getVarRefs().end(), NumLoop + 1);
*It = Cnt;
}
@@ -937,7 +942,7 @@ Expr *OMPDependClause::getLoopData(unsigned NumLoop) {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
@@ -947,10 +952,15 @@ const Expr *OMPDependClause::getLoopData(unsigned NumLoop) const {
NumLoop < NumLoops &&
"Expected sink or source depend + loop index must be less number of "
"loops.");
- auto It = std::next(getVarRefs().end(), NumLoop);
+ const auto *It = std::next(getVarRefs().end(), NumLoop + 1);
return *It;
}
+void OMPDependClause::setModifier(Expr *DepModifier) {
+ *getVarRefs().end() = DepModifier;
+}
+Expr *OMPDependClause::getModifier() { return *getVarRefs().end(); }
+
unsigned OMPClauseMappableExprCommon::getComponentsTotalNumber(
MappableExprComponentListsRef ComponentLists) {
unsigned TotalNum = 0u;
@@ -1727,6 +1737,10 @@ void OMPClausePrinter::VisitOMPDepobjClause(OMPDepobjClause *Node) {
void OMPClausePrinter::VisitOMPDependClause(OMPDependClause *Node) {
OS << "depend(";
+ if (Expr *DepModifier = Node->getModifier()) {
+ DepModifier->printPretty(OS, nullptr, Policy);
+ OS << ", ";
+ }
OS << getOpenMPSimpleClauseTypeName(Node->getClauseKind(),
Node->getDependencyKind());
if (!Node->varlist_empty()) {
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 3d03f3902d61..26e1a5009565 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -1361,6 +1361,24 @@ void StmtPrinter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *Node) {
PrintExpr(Node->getBase());
}
+void StmtPrinter::VisitOMPIteratorExpr(OMPIteratorExpr *Node) {
+ OS << "iterator(";
+ for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
+ auto *VD = cast<ValueDecl>(Node->getIteratorDecl(I));
+ VD->getType().print(OS, Policy);
+ const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
+ OS << " " << VD->getName() << " = ";
+ PrintExpr(Range.Begin);
+ OS << ":";
+ PrintExpr(Range.End);
+ if (Node->getSecondColonLoc(I).isValid())
+ PrintExpr(Range.Step);
+ if (I < E - 1)
+ OS << ", ";
+ }
+ OS << ")";
+}
+
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 054276a98424..fec12ac98b4e 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1198,6 +1198,12 @@ void StmtProfiler::VisitOMPArrayShapingExpr(const OMPArrayShapingExpr *S) {
VisitExpr(S);
}
+void StmtProfiler::VisitOMPIteratorExpr(const OMPIteratorExpr *S) {
+ VisitExpr(S);
+ for (unsigned I = 0, E = S->numOfIterators(); I < E; ++I)
+ VisitDecl(S->getIteratorDecl(I));
+}
+
void StmtProfiler::VisitCallExpr(const CallExpr *S) {
VisitExpr(S);
}
diff --git a/clang/lib/AST/TextNodeDumper.cpp b/clang/lib/AST/TextNodeDumper.cpp
index 6a6d8692228a..dc0dd92f09df 100644
--- a/clang/lib/AST/TextNodeDumper.cpp
+++ b/clang/lib/AST/TextNodeDumper.cpp
@@ -1086,6 +1086,23 @@ void TextNodeDumper::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *Node) {
OS << " " << (Node->getValue() ? "__objc_yes" : "__objc_no");
}
+void TextNodeDumper::VisitOMPIteratorExpr(const OMPIteratorExpr *Node) {
+ OS << " ";
+ for (unsigned I = 0, E = Node->numOfIterators(); I < E; ++I) {
+ Visit(Node->getIteratorDecl(I));
+ OS << " = ";
+ const OMPIteratorExpr::IteratorRange Range = Node->getIteratorRange(I);
+ OS << " begin ";
+ Visit(Range.Begin);
+ OS << " end ";
+ Visit(Range.End);
+ if (Range.Step) {
+ OS << " step ";
+ Visit(Range.Step);
+ }
+ }
+}
+
void TextNodeDumper::VisitRValueReferenceType(const ReferenceType *T) {
if (T->isSpelledAsLValue())
OS << " written as lvalue reference";
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index f90eb5cb9c92..3428437c3146 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -2910,6 +2910,8 @@ StringRef BuiltinType::getName(const PrintingPolicy &Policy) const {
return "<OpenMP array section type>";
case OMPArrayShaping:
return "<OpenMP array shaping type>";
+ case OMPIterator:
+ return "<OpenMP iterator type>";
#define EXT_OPAQUE_TYPE(ExtType, Id, Ext) \
case Id: \
return #ExtType;
@@ -3917,6 +3919,7 @@ bool Type::canHaveNullability(bool ResultIfUnknown) const {
case BuiltinType::NullPtr:
case BuiltinType::OMPArraySection:
case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return false;
}
llvm_unreachable("unknown builtin type");
diff --git a/clang/lib/AST/TypeLoc.cpp b/clang/lib/AST/TypeLoc.cpp
index dd48ae3fc262..50391dba2a05 100644
--- a/clang/lib/AST/TypeLoc.cpp
+++ b/clang/lib/AST/TypeLoc.cpp
@@ -405,6 +405,7 @@ TypeSpecifierType BuiltinTypeLoc::getWrittenTypeSpec() const {
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return TST_unspecified;
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 147d1b271d0c..42083b8b921e 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -755,7 +755,8 @@ static bool parseDeclareSimdClauses(
getOpenMPClauseKind(ClauseName), *Vars, Data))
IsError = true;
if (CKind == OMPC_aligned) {
- Alignments.append(Aligneds.size() - Alignments.size(), Data.TailExpr);
+ Alignments.append(Aligneds.size() - Alignments.size(),
+ Data.DepModOrTailExpr);
} else if (CKind == OMPC_linear) {
assert(0 <= Data.ExtraModifier &&
Data.ExtraModifier <= OMPC_LINEAR_unknown &&
@@ -766,7 +767,7 @@ static bool parseDeclareSimdClauses(
Data.ExtraModifier = OMPC_LINEAR_val;
LinModifiers.append(Linears.size() - LinModifiers.size(),
Data.ExtraModifier);
- Steps.append(Linears.size() - Steps.size(), Data.TailExpr);
+ Steps.append(Linears.size() - Steps.size(), Data.DepModOrTailExpr);
}
} else
// TODO: add parsing of other clauses.
@@ -3054,6 +3055,114 @@ static void parseMapType(Parser &P, Parser::OpenMPVarListDataTy &Data) {
P.ConsumeToken();
}
+/// Parses simple expression in parens for single-expression clauses of OpenMP
+/// constructs.
+/// \param RLoc Returned location of right paren.
+ExprResult Parser::ParseOpenMPIteratorsExpr() {
+ assert(Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator" &&
+ "Expected 'iterator' token.");
+ SourceLocation IteratorKwLoc = ConsumeToken();
+
+ BalancedDelimiterTracker T(*this, tok::l_paren, tok::annot_pragma_openmp_end);
+ if (T.expectAndConsume(diag::err_expected_lparen_after, "iterator"))
+ return ExprError();
+
+ SourceLocation LLoc = T.getOpenLocation();
+ SmallVector<Sema::OMPIteratorData, 4> Data;
+ while (Tok.isNot(tok::r_paren) && Tok.isNot(tok::annot_pragma_openmp_end)) {
+ // Check if the type parsing is required.
+ ParsedType IteratorType;
+ if (Tok.isNot(tok::identifier) || NextToken().isNot(tok::equal)) {
+ // identifier '=' is not found - parse type.
+ TypeResult TR = ParseTypeName();
+ if (TR.isInvalid()) {
+ T.skipToEnd();
+ return ExprError();
+ }
+ IteratorType = TR.get();
+ }
+
+ // Parse identifier.
+ IdentifierInfo *II = nullptr;
+ SourceLocation IdLoc;
+ if (Tok.is(tok::identifier)) {
+ II = Tok.getIdentifierInfo();
+ IdLoc = ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_expected_unqualified_id) << 0;
+ }
+
+ // Parse '='.
+ SourceLocation AssignLoc;
+ if (Tok.is(tok::equal))
+ AssignLoc = ConsumeToken();
+ else
+ Diag(Tok, diag::err_omp_expected_equal_in_iterator);
+
+ // Parse range-specification - <begin> ':' <end> [ ':' <step> ]
+ ColonProtectionRAIIObject ColonRAII(*this);
+ // Parse <begin>
+ SourceLocation Loc = Tok.getLocation();
+ ExprResult LHS = ParseCastExpression(AnyCastExpr);
+ ExprResult Begin = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ Begin = Actions.ActOnFinishFullExpr(Begin.get(), Loc,
+ /*DiscardedValue=*/false);
+ // Parse ':'.
+ SourceLocation ColonLoc;
+ if (Tok.is(tok::colon))
+ ColonLoc = ConsumeToken();
+
+ // Parse <end>
+ Loc = Tok.getLocation();
+ LHS = ParseCastExpression(AnyCastExpr);
+ ExprResult End = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ End = Actions.ActOnFinishFullExpr(End.get(), Loc,
+ /*DiscardedValue=*/false);
+
+ SourceLocation SecColonLoc;
+ ExprResult Step;
+ // Parse optional step.
+ if (Tok.is(tok::colon)) {
+ // Parse ':'
+ ColonLoc = ConsumeToken();
+ // Parse <step>
+ Loc = Tok.getLocation();
+ LHS = ParseCastExpression(AnyCastExpr);
+ Step = Actions.CorrectDelayedTyposInExpr(
+ ParseRHSOfBinaryExpression(LHS, prec::Conditional));
+ Step = Actions.ActOnFinishFullExpr(Step.get(), Loc,
+ /*DiscardedValue=*/false);
+ }
+
+ // Parse ',' or ')'
+ if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
+ Diag(Tok, diag::err_omp_expected_punc_after_iterator);
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+
+ Sema::OMPIteratorData &D = Data.emplace_back();
+ D.DeclIdent = II;
+ D.DeclIdentLoc = IdLoc;
+ D.Type = IteratorType;
+ D.AssignLoc = AssignLoc;
+ D.ColonLoc = ColonLoc;
+ D.SecColonLoc = SecColonLoc;
+ D.Range.Begin = Begin.get();
+ D.Range.End = End.get();
+ D.Range.Step = Step.get();
+ }
+
+ // Parse ')'.
+ SourceLocation RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ RLoc = T.getCloseLocation();
+
+ return Actions.ActOnOMPIteratorExpr(getCurScope(), IteratorKwLoc, LLoc, RLoc,
+ Data);
+}
+
/// Parses clauses with list.
bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
OpenMPClauseKind Kind,
@@ -3069,6 +3178,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
getOpenMPClauseName(Kind)))
return true;
+ bool DependWithIterator = false;
bool NeedRParenForLinear = false;
BalancedDelimiterTracker LinearT(*this, tok::l_paren,
tok::annot_pragma_openmp_end);
@@ -3106,6 +3216,22 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.ReductionOrMapperId =
Actions.GetNameFromUnqualifiedId(UnqualifiedReductionId);
} else if (Kind == OMPC_depend) {
+ if (getLangOpts().OpenMP >= 50) {
+ if (Tok.is(tok::identifier) && PP.getSpelling(Tok) == "iterator") {
+ // Handle optional dependence modifier.
+ // iterator(iterators-definition)
+ // where iterators-definition is iterator-specifier [,
+ // iterators-definition ]
+ // where iterator-specifier is [ iterator-type ] identifier =
+ // range-specification
+ DependWithIterator = true;
+ EnterScope(Scope::OpenMPDirectiveScope | Scope::DeclScope);
+ ExprResult IteratorRes = ParseOpenMPIteratorsExpr();
+ Data.DepModOrTailExpr = IteratorRes.get();
+ // Parse ','
+ ExpectAndConsume(tok::comma);
+ }
+ }
// Handle dependency type for depend clause.
ColonProtectionRAIIObject ColonRAII(*this);
Data.ExtraModifier = getOpenMPSimpleClauseType(
@@ -3227,7 +3353,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
/*DiscardedValue=*/false);
if (Tail.isUsable()) {
if (Tok.is(tok::colon)) {
- Data.TailExpr = Tail.get();
+ Data.DepModOrTailExpr = Tail.get();
Data.ColonLoc = ConsumeToken();
TPA.Commit();
} else {
@@ -3253,6 +3379,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
const bool MayHaveTail = (Kind == OMPC_linear || Kind == OMPC_aligned);
while (IsComma || (Tok.isNot(tok::r_paren) && Tok.isNot(tok::colon) &&
Tok.isNot(tok::annot_pragma_openmp_end))) {
+ ParseScope OMPListScope(this, Scope::OpenMPDirectiveScope);
ColonProtectionRAIIObject ColonRAII(*this, MayHaveTail);
// Parse variable
ExprResult VarExpr =
@@ -3289,7 +3416,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Tail =
Actions.ActOnFinishFullExpr(Tail.get(), ELoc, /*DiscardedValue*/ false);
if (Tail.isUsable())
- Data.TailExpr = Tail.get();
+ Data.DepModOrTailExpr = Tail.get();
else
SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end,
StopBeforeMatch);
@@ -3299,8 +3426,11 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Data.RLoc = Tok.getLocation();
if (!T.consumeClose())
Data.RLoc = T.getCloseLocation();
+ // Exit from scope when the iterator is used in depend clause.
+ if (DependWithIterator)
+ ExitScope();
return (Kind != OMPC_depend && Kind != OMPC_map && Vars.empty()) ||
- (MustHaveTail && !Data.TailExpr) || InvalidReductionId ||
+ (MustHaveTail && !Data.DepModOrTailExpr) || InvalidReductionId ||
IsInvalidMapperModifier;
}
@@ -3372,7 +3502,7 @@ OMPClause *Parser::ParseOpenMPVarListClause(OpenMPDirectiveKind DKind,
return nullptr;
OMPVarListLocTy Locs(Loc, LOpen, Data.RLoc);
return Actions.ActOnOpenMPVarListClause(
- Kind, Vars, Data.TailExpr, Locs, Data.ColonLoc,
+ Kind, Vars, Data.DepModOrTailExpr, Locs, Data.ColonLoc,
Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId,
Data.ExtraModifier, Data.MapTypeModifiers, Data.MapTypeModifiersLoc,
Data.IsMapTypeImplicit, Data.ExtraModifierLoc);
diff --git a/clang/lib/Sema/SemaExceptionSpec.cpp b/clang/lib/Sema/SemaExceptionSpec.cpp
index fad2ae1cc066..0dc0c68205fb 100644
--- a/clang/lib/Sema/SemaExceptionSpec.cpp
+++ b/clang/lib/Sema/SemaExceptionSpec.cpp
@@ -1300,6 +1300,7 @@ CanThrowResult Sema::canThrow(const Stmt *S) {
case Expr::ArraySubscriptExprClass:
case Expr::OMPArraySectionExprClass:
case Expr::OMPArrayShapingExprClass:
+ case Expr::OMPIteratorExprClass:
case Expr::BinaryOperatorClass:
case Expr::DependentCoawaitExprClass:
case Expr::CompoundAssignOperatorClass:
diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp
index c0f8600aa0cc..8d0e97c85771 100644
--- a/clang/lib/Sema/SemaExpr.cpp
+++ b/clang/lib/Sema/SemaExpr.cpp
@@ -4873,6 +4873,131 @@ ExprResult Sema::ActOnOMPArrayShapingExpr(Expr *Base, SourceLocation LParenLoc,
LParenLoc, RParenLoc, NewDims, Brackets);
}
+ExprResult Sema::ActOnOMPIteratorExpr(Scope *S, SourceLocation IteratorKwLoc,
+ SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<OMPIteratorData> Data) {
+ SmallVector<OMPIteratorExpr::IteratorDefinition, 4> ID;
+ bool IsCorrect = true;
+ for (const OMPIteratorData &D : Data) {
+ TypeSourceInfo *TInfo = nullptr;
+ SourceLocation StartLoc;
+ QualType DeclTy;
+ if (!D.Type.getAsOpaquePtr()) {
+ // OpenMP 5.0, 2.1.6 Iterators
+ // In an iterator-specifier, if the iterator-type is not specified then
+ // the type of that iterator is of int type.
+ DeclTy = Context.IntTy;
+ StartLoc = D.DeclIdentLoc;
+ } else {
+ DeclTy = GetTypeFromParser(D.Type, &TInfo);
+ StartLoc = TInfo->getTypeLoc().getBeginLoc();
+ }
+
+ bool IsDeclTyDependent = DeclTy->isDependentType() ||
+ DeclTy->containsUnexpandedParameterPack() ||
+ DeclTy->isInstantiationDependentType();
+ if (!IsDeclTyDependent) {
+ if (!DeclTy->isIntegralType(Context) && !DeclTy->isAnyPointerType()) {
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
+ // The iterator-type must be an integral or pointer type.
+ Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
+ << DeclTy;
+ IsCorrect = false;
+ continue;
+ }
+ if (DeclTy.isConstant(Context)) {
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions, C/C++
+ // The iterator-type must not be const qualified.
+ Diag(StartLoc, diag::err_omp_iterator_not_integral_or_pointer)
+ << DeclTy;
+ IsCorrect = false;
+ continue;
+ }
+ }
+
+ // Iterator declaration.
+ assert(D.DeclIdent && "Identifier expected.");
+ // Always try to create iterator declarator to avoid extra error messages
+ // about unknown declarations use.
+ auto *VD = VarDecl::Create(Context, CurContext, StartLoc, D.DeclIdentLoc,
+ D.DeclIdent, DeclTy, TInfo, SC_None);
+ VD->setImplicit();
+ if (S) {
+ // Check for conflicting previous declaration.
+ DeclarationNameInfo NameInfo(VD->getDeclName(), D.DeclIdentLoc);
+ LookupResult Previous(*this, NameInfo, LookupOrdinaryName,
+ ForVisibleRedeclaration);
+ Previous.suppressDiagnostics();
+ LookupName(Previous, S);
+
+ FilterLookupForScope(Previous, CurContext, S, /*ConsiderLinkage=*/false,
+ /*AllowInlineNamespace=*/false);
+ if (!Previous.empty()) {
+ NamedDecl *Old = Previous.getRepresentativeDecl();
+ Diag(D.DeclIdentLoc, diag::err_redefinition) << VD->getDeclName();
+ Diag(Old->getLocation(), diag::note_previous_definition);
+ } else {
+ PushOnScopeChains(VD, S);
+ }
+ } else {
+ CurContext->addDecl(VD);
+ }
+ Expr *Begin = D.Range.Begin;
+ if (!IsDeclTyDependent && Begin && !Begin->isTypeDependent()) {
+ ExprResult BeginRes =
+ PerformImplicitConversion(Begin, DeclTy, AA_Converting);
+ Begin = BeginRes.get();
+ }
+ Expr *End = D.Range.End;
+ if (!IsDeclTyDependent && End && !End->isTypeDependent()) {
+ ExprResult EndRes = PerformImplicitConversion(End, DeclTy, AA_Converting);
+ End = EndRes.get();
+ }
+ Expr *Step = D.Range.Step;
+ if (!IsDeclTyDependent && Step && !Step->isTypeDependent()) {
+ if (!Step->getType()->isIntegralType(Context)) {
+ Diag(Step->getExprLoc(), diag::err_omp_iterator_step_not_integral)
+ << Step << Step->getSourceRange();
+ IsCorrect = false;
+ continue;
+ }
+ llvm::APSInt Result;
+ bool IsConstant = Step->isIntegerConstantExpr(Result, Context);
+ // OpenMP 5.0, 2.1.6 Iterators, Restrictions
+ // If the step expression of a range-specification equals zero, the
+ // behavior is unspecified.
+ if (IsConstant && Result.isNullValue()) {
+ Diag(Step->getExprLoc(), diag::err_omp_iterator_step_constant_zero)
+ << Step << Step->getSourceRange();
+ IsCorrect = false;
+ continue;
+ }
+ }
+ if (!Begin || !End || !IsCorrect) {
+ IsCorrect = false;
+ continue;
+ }
+ OMPIteratorExpr::IteratorDefinition &IDElem = ID.emplace_back();
+ IDElem.IteratorDecl = VD;
+ IDElem.AssignmentLoc = D.AssignLoc;
+ IDElem.Range.Begin = Begin;
+ IDElem.Range.End = End;
+ IDElem.Range.Step = Step;
+ IDElem.ColonLoc = D.ColonLoc;
+ IDElem.SecondColonLoc = D.SecColonLoc;
+ }
+ if (!IsCorrect) {
+ // Invalidate all created iterator declarations if error is found.
+ for (const OMPIteratorExpr::IteratorDefinition &D : ID) {
+ if (Decl *ID = D.IteratorDecl)
+ ID->setInvalidDecl();
+ }
+ return ExprError();
+ }
+ return OMPIteratorExpr::Create(Context, Context.OMPIteratorTy, IteratorKwLoc,
+ LLoc, RLoc, ID);
+}
+
ExprResult
Sema::CreateBuiltinArraySubscriptExpr(Expr *Base, SourceLocation LLoc,
Expr *Idx, SourceLocation RLoc) {
@@ -5634,6 +5759,7 @@ static bool isPlaceholderToRemoveAsArg(QualType type) {
case BuiltinType::BuiltinFn:
case BuiltinType::OMPArraySection:
case BuiltinType::OMPArrayShaping:
+ case BuiltinType::OMPIterator:
return true;
}
@@ -18513,6 +18639,9 @@ ExprResult Sema::CheckPlaceholderExpr(Expr *E) {
case BuiltinType::OMPArrayShaping:
return ExprError(Diag(E->getBeginLoc(), diag::err_omp_array_shaping_use));
+ case BuiltinType::OMPIterator:
+ return ExprError(Diag(E->getBeginLoc(), diag::err_omp_iterator_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 7d2ae172fe4d..df56c3be43fc 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -13053,7 +13053,7 @@ OMPClause *Sema::ActOnOpenMPDestroyClause(SourceLocation StartLoc,
}
OMPClause *Sema::ActOnOpenMPVarListClause(
- OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *TailExpr,
+ OpenMPClauseKind Kind, ArrayRef<Expr *> VarList, Expr *DepModOrTailExpr,
const OMPVarListLocTy &Locs, SourceLocation ColonLoc,
CXXScopeSpec &ReductionOrMapperIdScopeSpec,
DeclarationNameInfo &ReductionOrMapperId, int ExtraModifier,
@@ -13103,13 +13103,13 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
assert(0 <= ExtraModifier && ExtraModifier <= OMPC_LINEAR_unknown &&
"Unexpected linear modifier.");
Res = ActOnOpenMPLinearClause(
- VarList, TailExpr, StartLoc, LParenLoc,
+ VarList, DepModOrTailExpr, StartLoc, LParenLoc,
static_cast<OpenMPLinearClauseKind>(ExtraModifier), ExtraModifierLoc,
ColonLoc, EndLoc);
break;
case OMPC_aligned:
- Res = ActOnOpenMPAlignedClause(VarList, TailExpr, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ Res = ActOnOpenMPAlignedClause(VarList, DepModOrTailExpr, StartLoc,
+ LParenLoc, ColonLoc, EndLoc);
break;
case OMPC_copyin:
Res = ActOnOpenMPCopyinClause(VarList, StartLoc, LParenLoc, EndLoc);
@@ -13124,8 +13124,8 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
assert(0 <= ExtraModifier && ExtraModifier <= OMPC_DEPEND_unknown &&
"Unexpected depend modifier.");
Res = ActOnOpenMPDependClause(
- static_cast<OpenMPDependClauseKind>(ExtraModifier), ExtraModifierLoc,
- ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
+ DepModOrTailExpr, static_cast<OpenMPDependClauseKind>(ExtraModifier),
+ ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
break;
case OMPC_map:
assert(0 <= ExtraModifier && ExtraModifier <= OMPC_MAP_unknown &&
@@ -13150,8 +13150,8 @@ OMPClause *Sema::ActOnOpenMPVarListClause(
Res = ActOnOpenMPIsDevicePtrClause(VarList, Locs);
break;
case OMPC_allocate:
- Res = ActOnOpenMPAllocateClause(TailExpr, VarList, StartLoc, LParenLoc,
- ColonLoc, EndLoc);
+ Res = ActOnOpenMPAllocateClause(DepModOrTailExpr, VarList, StartLoc,
+ LParenLoc, ColonLoc, EndLoc);
break;
case OMPC_nontemporal:
Res = ActOnOpenMPNontemporalClause(VarList, StartLoc, LParenLoc, EndLoc);
@@ -15642,7 +15642,7 @@ OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
}
OMPClause *
-Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
+Sema::ActOnOpenMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind,
SourceLocation DepLoc, SourceLocation ColonLoc,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
@@ -15664,12 +15664,26 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
Except.push_back(OMPC_DEPEND_sink);
if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
Except.push_back(OMPC_DEPEND_depobj);
+ std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
+ ? "depend modifier(iterator) or "
+ : "";
Diag(DepLoc, diag::err_omp_unexpected_clause_value)
- << getListOfPossibleValues(OMPC_depend, /*First=*/0,
- /*Last=*/OMPC_DEPEND_unknown, Except)
+ << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
+ /*Last=*/OMPC_DEPEND_unknown,
+ Except)
<< getOpenMPClauseName(OMPC_depend);
return nullptr;
}
+ if (DepModifier &&
+ (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
+ Diag(DepModifier->getExprLoc(),
+ diag::err_omp_depend_sink_source_with_modifier);
+ return nullptr;
+ }
+ if (DepModifier &&
+ !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
+ Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
+
SmallVector<Expr *, 8> Vars;
DSAStackTy::OperatorOffsetTy OpsOffs;
llvm::APSInt DepCounter(/*BitWidth=*/32);
@@ -15878,8 +15892,8 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
return nullptr;
auto *C = OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc,
- DepKind, DepLoc, ColonLoc, Vars,
- TotalDepCount.getZExtValue());
+ DepModifier, DepKind, DepLoc, ColonLoc,
+ Vars, TotalDepCount.getZExtValue());
if ((DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) &&
DSAStack->isParentOrderedRegion())
DSAStack->addDoacrossDependClause(C, OpsOffs);
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 82cfa246e3f7..de05d436d3b9 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1842,12 +1842,13 @@ class TreeTransform {
/// By default, performs semantic analysis to build the new OpenMP clause.
/// Subclasses may override this routine to provide
diff erent behavior.
OMPClause *
- RebuildOMPDependClause(OpenMPDependClauseKind DepKind, SourceLocation DepLoc,
- SourceLocation ColonLoc, ArrayRef<Expr *> VarList,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- return getSema().ActOnOpenMPDependClause(DepKind, DepLoc, ColonLoc, VarList,
- StartLoc, LParenLoc, EndLoc);
+ RebuildOMPDependClause(Expr *DepModifier, OpenMPDependClauseKind DepKind,
+ SourceLocation DepLoc, SourceLocation ColonLoc,
+ ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+ return getSema().ActOnOpenMPDependClause(DepModifier, DepKind, DepLoc,
+ ColonLoc, VarList, StartLoc,
+ LParenLoc, EndLoc);
}
/// Build a new OpenMP 'device' clause.
@@ -2391,6 +2392,17 @@ class TreeTransform {
BracketsRanges);
}
+ /// Build a new iterator expression.
+ ///
+ /// By default, performs semantic analysis to build the new expression.
+ /// Subclasses may override this routine to provide
diff erent behavior.
+ ExprResult RebuildOMPIteratorExpr(
+ SourceLocation IteratorKwLoc, SourceLocation LLoc, SourceLocation RLoc,
+ ArrayRef<Sema::OMPIteratorData> Data) {
+ return getSema().ActOnOMPIteratorExpr(/*Scope=*/nullptr, IteratorKwLoc,
+ LLoc, RLoc, Data);
+ }
+
/// Build a new call expression.
///
/// By default, performs semantic analysis to build the new expression.
@@ -9291,6 +9303,13 @@ template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
llvm::SmallVector<Expr *, 16> Vars;
+ Expr *DepModifier = C->getModifier();
+ if (DepModifier) {
+ ExprResult DepModRes = getDerived().TransformExpr(DepModifier);
+ if (DepModRes.isInvalid())
+ return nullptr;
+ DepModifier = DepModRes.get();
+ }
Vars.reserve(C->varlist_size());
for (auto *VE : C->varlists()) {
ExprResult EVar = getDerived().TransformExpr(cast<Expr>(VE));
@@ -9299,8 +9318,9 @@ TreeTransform<Derived>::TransformOMPDependClause(OMPDependClause *C) {
Vars.push_back(EVar.get());
}
return getDerived().RebuildOMPDependClause(
- C->getDependencyKind(), C->getDependencyLoc(), C->getColonLoc(), Vars,
- C->getBeginLoc(), C->getLParenLoc(), C->getEndLoc());
+ DepModifier, C->getDependencyKind(), C->getDependencyLoc(),
+ C->getColonLoc(), Vars, C->getBeginLoc(), C->getLParenLoc(),
+ C->getEndLoc());
}
template <typename Derived>
@@ -10054,6 +10074,65 @@ TreeTransform<Derived>::TransformOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
E->getBracketsRanges());
}
+template <typename Derived>
+ExprResult
+TreeTransform<Derived>::TransformOMPIteratorExpr(OMPIteratorExpr *E) {
+ unsigned NumIterators = E->numOfIterators();
+ SmallVector<Sema::OMPIteratorData, 4> Data(NumIterators);
+
+ bool ErrorFound = false;
+ bool NeedToRebuild = getDerived().AlwaysRebuild();
+ for (unsigned I = 0; I < NumIterators; ++I) {
+ auto *D = cast<VarDecl>(E->getIteratorDecl(I));
+ Data[I].DeclIdent = D->getIdentifier();
+ Data[I].DeclIdentLoc = D->getLocation();
+ if (D->getLocation() == D->getBeginLoc()) {
+ assert(SemaRef.Context.hasSameType(D->getType(), SemaRef.Context.IntTy) &&
+ "Implicit type must be int.");
+ } else {
+ TypeSourceInfo *TSI = getDerived().TransformType(D->getTypeSourceInfo());
+ QualType DeclTy = getDerived().TransformType(D->getType());
+ Data[I].Type = SemaRef.CreateParsedType(DeclTy, TSI);
+ }
+ OMPIteratorExpr::IteratorRange Range = E->getIteratorRange(I);
+ ExprResult Begin = getDerived().TransformExpr(Range.Begin);
+ ExprResult End = getDerived().TransformExpr(Range.End);
+ ExprResult Step = getDerived().TransformExpr(Range.Step);
+ ErrorFound = ErrorFound ||
+ !(!D->getTypeSourceInfo() || (Data[I].Type.getAsOpaquePtr() &&
+ !Data[I].Type.get().isNull())) ||
+ Begin.isInvalid() || End.isInvalid() || Step.isInvalid();
+ if (ErrorFound)
+ continue;
+ Data[I].Range.Begin = Begin.get();
+ Data[I].Range.End = End.get();
+ Data[I].Range.Step = Step.get();
+ Data[I].AssignLoc = E->getAssignLoc(I);
+ Data[I].ColonLoc = E->getColonLoc(I);
+ Data[I].SecColonLoc = E->getSecondColonLoc(I);
+ NeedToRebuild =
+ NeedToRebuild ||
+ (D->getTypeSourceInfo() && Data[I].Type.get().getTypePtrOrNull() !=
+ D->getType().getTypePtrOrNull()) ||
+ Range.Begin != Data[I].Range.Begin || Range.End != Data[I].Range.End ||
+ Range.Step != Data[I].Range.Step;
+ }
+ if (ErrorFound)
+ return ExprError();
+ if (!NeedToRebuild)
+ return E;
+
+ ExprResult Res = getDerived().RebuildOMPIteratorExpr(
+ E->getIteratorKwLoc(), E->getLParenLoc(), E->getRParenLoc(), Data);
+ if (!Res.isUsable())
+ return Res;
+ auto *IE = cast<OMPIteratorExpr>(Res.get());
+ for (unsigned I = 0; I < NumIterators; ++I)
+ getDerived().transformedLocalDecl(E->getIteratorDecl(I),
+ IE->getIteratorDecl(I));
+ return Res;
+}
+
template<typename Derived>
ExprResult
TreeTransform<Derived>::TransformCallExpr(CallExpr *E) {
diff --git a/clang/lib/Serialization/ASTCommon.cpp b/clang/lib/Serialization/ASTCommon.cpp
index 158a12f0329d..566bda2d71f7 100644
--- a/clang/lib/Serialization/ASTCommon.cpp
+++ b/clang/lib/Serialization/ASTCommon.cpp
@@ -246,6 +246,9 @@ serialization::TypeIdxFromBuiltin(const BuiltinType *BT) {
case BuiltinType::OMPArrayShaping:
ID = PREDEF_TYPE_OMP_ARRAY_SHAPING;
break;
+ case BuiltinType::OMPIterator:
+ ID = PREDEF_TYPE_OMP_ITERATOR;
+ break;
}
return TypeIdx(ID);
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 7437f649a090..d4764229abfc 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -6960,6 +6960,9 @@ QualType ASTReader::GetType(TypeID ID) {
case PREDEF_TYPE_OMP_ARRAY_SHAPING:
T = Context.OMPArraySectionTy;
break;
+ case PREDEF_TYPE_OMP_ITERATOR:
+ T = Context.OMPIteratorTy;
+ break;
#define SVE_TYPE(Name, Id, SingletonId) \
case PREDEF_TYPE_##Id##_ID: \
T = Context.SingletonId; \
@@ -12307,6 +12310,7 @@ void OMPClauseReader::VisitOMPDepobjClause(OMPDepobjClause *C) {
void OMPClauseReader::VisitOMPDependClause(OMPDependClause *C) {
C->setLParenLoc(Record.readSourceLocation());
+ C->setModifier(Record.readSubExpr());
C->setDependencyKind(
static_cast<OpenMPDependClauseKind>(Record.readInt()));
C->setDependencyLoc(Record.readSourceLocation());
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index bc8c231731e8..d5f2213aaabe 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -927,6 +927,24 @@ void ASTStmtReader::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
E->setRParenLoc(readSourceLocation());
}
+void ASTStmtReader::VisitOMPIteratorExpr(OMPIteratorExpr *E) {
+ VisitExpr(E);
+ unsigned NumIterators = Record.readInt();
+ E->setIteratorKwLoc(readSourceLocation());
+ E->setLParenLoc(readSourceLocation());
+ E->setRParenLoc(readSourceLocation());
+ for (unsigned I = 0; I < NumIterators; ++I) {
+ E->setIteratorDeclaration(I, Record.readDeclRef());
+ E->setAssignmentLoc(I, readSourceLocation());
+ Expr *Begin = Record.readSubExpr();
+ Expr *End = Record.readSubExpr();
+ Expr *Step = Record.readSubExpr();
+ SourceLocation ColonLoc = readSourceLocation();
+ SourceLocation SecColonLoc = readSourceLocation();
+ E->setIteratorRange(I, Begin, ColonLoc, End, SecColonLoc, Step);
+ }
+}
+
void ASTStmtReader::VisitCallExpr(CallExpr *E) {
VisitExpr(E);
unsigned NumArgs = Record.readInt();
@@ -2887,6 +2905,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumExprFields]);
break;
+ case EXPR_OMP_ITERATOR:
+ S = OMPIteratorExpr::CreateEmpty(Context,
+ Record[ASTStmtReader::NumExprFields]);
+ break;
+
case EXPR_CALL:
S = CallExpr::CreateEmpty(
Context, /*NumArgs=*/Record[ASTStmtReader::NumExprFields], Empty);
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index f7c58ed11d9f..27f44a706f9f 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -6379,6 +6379,7 @@ void OMPClauseWriter::VisitOMPDependClause(OMPDependClause *C) {
Record.push_back(C->varlist_size());
Record.push_back(C->getNumLoops());
Record.AddSourceLocation(C->getLParenLoc());
+ Record.AddStmt(C->getModifier());
Record.push_back(C->getDependencyKind());
Record.AddSourceLocation(C->getDependencyLoc());
Record.AddSourceLocation(C->getColonLoc());
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 840823298be7..5a56b265b781 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -787,6 +787,25 @@ void ASTStmtWriter::VisitOMPArrayShapingExpr(OMPArrayShapingExpr *E) {
Code = serialization::EXPR_OMP_ARRAY_SHAPING;
}
+void ASTStmtWriter::VisitOMPIteratorExpr(OMPIteratorExpr *E) {
+ VisitExpr(E);
+ Record.push_back(E->numOfIterators());
+ Record.AddSourceLocation(E->getIteratorKwLoc());
+ Record.AddSourceLocation(E->getLParenLoc());
+ Record.AddSourceLocation(E->getRParenLoc());
+ for (unsigned I = 0, End = E->numOfIterators(); I < End; ++I) {
+ Record.AddDeclRef(E->getIteratorDecl(I));
+ Record.AddSourceLocation(E->getAssignLoc(I));
+ OMPIteratorExpr::IteratorRange Range = E->getIteratorRange(I);
+ Record.AddStmt(Range.Begin);
+ Record.AddStmt(Range.End);
+ Record.AddStmt(Range.Step);
+ Record.AddSourceLocation(E->getColonLoc(I));
+ Record.AddSourceLocation(E->getSecondColonLoc(I));
+ }
+ Code = serialization::EXPR_OMP_ITERATOR;
+}
+
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 d16410a19b97..1cf81b54e77d 100644
--- a/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
+++ b/clang/lib/StaticAnalyzer/Checkers/IdenticalExprChecker.cpp
@@ -352,6 +352,7 @@ static bool isIdenticalStmt(const ASTContext &Ctx, const Stmt *Stmt1,
case Stmt::ArraySubscriptExprClass:
case Stmt::OMPArraySectionExprClass:
case Stmt::OMPArrayShapingExprClass:
+ case Stmt::OMPIteratorExprClass:
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 4c0914628a0d..1f0d89d59120 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -1414,6 +1414,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
case Stmt::CXXNullPtrLiteralExprClass:
case Stmt::OMPArraySectionExprClass:
case Stmt::OMPArrayShapingExprClass:
+ case Stmt::OMPIteratorExprClass:
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 a33b16f985a0..1b20b1c525e7 100644
--- a/clang/test/OpenMP/depobj_messages.cpp
+++ b/clang/test/OpenMP/depobj_messages.cpp
@@ -142,7 +142,7 @@ label1 : {
#pragma omp parallel depobj(argc) // expected-warning {{extra tokens at the end of '#pragma omp parallel' are ignored}}
;
#pragma omp depobj(x) seq_cst // expected-error {{unexpected OpenMP clause 'seq_cst' in directive '#pragma omp depobj'}}
-#pragma omp depobj(x) depend(source: x) // expected-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
+#pragma omp depobj(x) depend(source: x) // expected-error {{expected depend modifier(iterator) or 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
#pragma omp depobj(x) update // expected-error {{expected '(' after 'update'}}
#pragma omp depobj(x) update( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'update'}}
#pragma omp depobj(x) update(sink // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'update'}}
diff --git a/clang/test/OpenMP/task_ast_print.cpp b/clang/test/OpenMP/task_ast_print.cpp
index 1da6c5045934..c465a1b1b07f 100644
--- a/clang/test/OpenMP/task_ast_print.cpp
+++ b/clang/test/OpenMP/task_ast_print.cpp
@@ -26,7 +26,7 @@ struct S1 {
template <typename T>
class S7 : public T {
protected:
- T a, b;
+ T a, b, c[10], d[10];
S7() : a(0) {}
public:
@@ -34,7 +34,7 @@ class S7 : public T {
omp_depend_t x;
omp_event_handle_t evt;
#pragma omp taskgroup allocate(b) task_reduction(+:b)
-#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b) allocate(b) depend(depobj:x) detach(evt)
+#pragma omp task private(a) private(this->a) private(T::a) in_reduction(+:this->b) allocate(b) depend(depobj:x) detach(evt) depend(iterator(i=0:10:1, T *k = &a:&b), in: c[i], d[(int)(k-&a)])
for (int k = 0; k < a.a; ++k)
++this->a.a;
}
@@ -47,9 +47,9 @@ class S7 : public T {
};
// CHECK: #pragma omp taskgroup allocate(this->b) task_reduction(+: this->b)
-// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt){{$}}
+// CHECK: #pragma omp task private(this->a) private(this->a) private(T::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10, T * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)]){{$}}
// CHECK: #pragma omp task private(this->a) private(this->a)
-// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a)
+// CHECK: #pragma omp task private(this->a) private(this->a) private(this->S1::a) in_reduction(+: this->b) allocate(this->b) depend(depobj : x) detach(evt) depend(iterator(int i = 0:10, S1 * k = &this->a:&this->b), in : this->c[i],this->d[(int)(k - &this->a)])
class S8 : public S7<S1> {
S8() {}
@@ -176,10 +176,10 @@ int main(int argc, char **argv) {
// CHECK-NEXT: foo();
#pragma omp taskgroup task_reduction(min: arr1)
#pragma omp parallel reduction(+:arr1)
-#pragma omp task in_reduction(min: arr1)
+#pragma omp task in_reduction(min: arr1) depend(iterator(i=0:argc, unsigned j=argc:0:a), out: argv[i][j])
// CHECK-NEXT: #pragma omp taskgroup task_reduction(min: arr1)
// CHECK-NEXT: #pragma omp parallel reduction(+: arr1)
- // CHECK-NEXT: #pragma omp task in_reduction(min: arr1)
+ // CHECK-NEXT: #pragma omp task in_reduction(min: arr1) depend(iterator(int i = 0:argc, unsigned int j = argc:0), out : argv[i][j])
foo();
// CHECK-NEXT: foo();
// CHECK-NEXT: #pragma omp task in_reduction(+: arr1)
diff --git a/clang/test/OpenMP/task_depend_messages.cpp b/clang/test/OpenMP/task_depend_messages.cpp
index f04c167cbdcc..bfb0e771b2ca 100644
--- a/clang/test/OpenMP/task_depend_messages.cpp
+++ b/clang/test/OpenMP/task_depend_messages.cpp
@@ -28,11 +28,11 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp task depend(in : arr[0])
#pragma omp task depend // expected-error {{expected '(' after 'depend'}}
- #pragma omp task depend ( // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
- #pragma omp task depend () // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
- #pragma omp task depend (argc // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
- #pragma omp task depend (source : argc) // 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 (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 ( // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-error {{expected ')'}} expected-note {{to match this '('}} expected-warning {{missing ':' after dependency type - ignoring}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp task depend () // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp task depend (argc // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-error {{expected ')'}} expected-note {{to match this '('}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp task depend (source : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #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 depend modifier(iterator) or '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) // 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}}
@@ -70,7 +70,19 @@ int main(int argc, char **argv, char *env[]) {
#pragma omp task depend(in : ([a])a) // omp45-error {{expected body of lambda expression}} omp50-error {{expected expression with a pointer to a complete type 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 expression with a pointer to a complete type 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}}
+ #pragma omp task depend(iterator // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected '(' after 'iterator'}} omp50-error {{expected ','}}
+ #pragma omp task depend(iterator():argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-error {{expected 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}}
+ #pragma omp task depend(iterator(argc // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{unknown type name 'argc'}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+ #pragma omp task depend(iterator(unsigned argc: // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error {{expected '=' in iterator specifier}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+ #pragma omp task depend(iterator(unsigned argc = // expected-error {{expected ')'}} omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} expected-warning {{missing ':' after dependency type - ignoring}} expected-note {{to match this '('}} omp50-error 2 {{expected expression}} omp50-error {{expected ',' or ')' after iterator specifier}} omp50-error {{expected ')'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}} omp50-note {{to match this '('}}
+ #pragma omp task depend(iterator(vector argc = 0:2):argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{expected integral or pointer type as the iterator-type, not 'vector'}} omp50-error {{expected depend modifier(iterator) or 'in', 'out', 'inout', 'mutexinoutset' or 'depobj' in OpenMP clause 'depend'}} omp50-error {{expected ','}}
+ #pragma omp task depend(iterator(vector *argc = nullptr:nullptr+2:0), in:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{invalid operands to binary expression ('nullptr_t' and 'int')}} omp50-error {{iterator step expression 0 evaluates to 0}}
+ #pragma omp task depend(iterator(vector *argc = 0:vector():argc), in:argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp50-error {{converting 'vector' to incompatible type 'vector *'}}
foo();
+#pragma omp task depend(iterator(unsigned argc = 0:10), in : argc) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}}
+ argc = 0;
+#pragma omp task depend(iterator(i = 0:10, i = 0:10), in : argv[i]) // omp45-error {{expected 'in', 'out', 'inout' or 'mutexinoutset' in OpenMP clause 'depend'}} omp45-error {{use of undeclared identifier 'i'}} omp50-error {{redefinition of 'i'}} omp50-note {{previous definition is here}}
+ i = 0; // expected-error {{use of undeclared identifier 'i'}}
return 0;
}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index bb9fed165679..14814f89d97d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -5185,6 +5185,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPArraySectionExpr");
case CXCursor_OMPArrayShapingExpr:
return cxstring::createRef("OMPArrayShapingExpr");
+ case CXCursor_OMPIteratorExpr:
+ return cxstring::createRef("OMPIteratorExpr");
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 4f4e0c4ea1d5..3bcc7cc7af05 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -427,6 +427,10 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_OMPArrayShapingExpr;
break;
+ case Stmt::OMPIteratorExprClass:
+ K = CXCursor_OMPIteratorExpr;
+ break;
+
case Stmt::BinaryOperatorClass:
K = CXCursor_BinaryOperator;
break;
More information about the cfe-commits
mailing list