[clang] [llvm] [OpenMP] OpenMP 5.1 "assume" directive parsing support (PR #92731)
Julian Brown via cfe-commits
cfe-commits at lists.llvm.org
Thu Aug 1 14:07:24 PDT 2024
https://github.com/jtb20 updated https://github.com/llvm/llvm-project/pull/92731
>From 73257cd3390361fa71735a39290dd47427916734 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 14:49:28 -0500
Subject: [PATCH 1/8] [OpenMP][clang] Add 'holds' clause for 'omp assume'
directive
---
clang/include/clang/AST/OpenMPClause.h | 27 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 5 ++++
clang/include/clang/Sema/SemaOpenMP.h | 4 +++
clang/lib/AST/OpenMPClause.cpp | 6 +++++
clang/lib/AST/StmtProfile.cpp | 2 ++
clang/lib/Parse/ParseOpenMP.cpp | 6 +++++
clang/lib/Sema/SemaOpenMP.cpp | 9 +++++++
clang/lib/Sema/TreeTransform.h | 17 ++++++++++++
clang/lib/Serialization/ASTReader.cpp | 8 ++++++
clang/lib/Serialization/ASTWriter.cpp | 5 ++++
clang/tools/libclang/CIndex.cpp | 2 ++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 10 +++++++
12 files changed, 101 insertions(+)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index b029c72fa7d8f..47c2fd4400d52 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -2013,6 +2013,33 @@ class OMPMergeableClause : public OMPClause {
}
};
+/// This represents the 'holds' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume holds(<expr>)
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'holds' clause.
+class OMPHoldsClause final
+ : public OMPOneStmtClause<llvm::omp::OMPC_holds, OMPClause> {
+ friend class OMPClauseReader;
+
+public:
+ /// Build 'holds' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPHoldsClause(Expr *E, SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc)
+ : OMPOneStmtClause(E, StartLoc, LParenLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPHoldsClause() : OMPOneStmtClause() {}
+
+ Expr *getExpr() const { return getStmtAs<Expr>(); }
+ void setExpr(Expr *E) { setStmt(E); }
+};
+
/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index dcf5dbf449f8b..73ece1e72bbf1 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3480,6 +3480,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPHoldsClause(OMPHoldsClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index aa61dae9415e2..7c793cf3077a6 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -940,6 +940,10 @@ class SemaOpenMP : public SemaBase {
SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'holds' clause.
+ OMPClause *ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc);
OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 042a5df5906ca..e83c81136c34b 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1937,6 +1937,12 @@ void OMPClausePrinter::VisitOMPFailClause(OMPFailClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPHoldsClause(OMPHoldsClause *Node) {
+ OS << "holds(";
+ Node->getExpr()->printPretty(OS, nullptr, Policy, 0);
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index f1e723b4242ee..97e4b3749f94c 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -584,6 +584,8 @@ void OMPClauseProfiler::VisitOMPCompareClause(const OMPCompareClause *) {}
void OMPClauseProfiler::VisitOMPFailClause(const OMPFailClause *) {}
+void OMPClauseProfiler::VisitOMPHoldsClause(const OMPHoldsClause *) {}
+
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index e975e96c5c7e4..afcbc93696de2 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3206,6 +3206,9 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_if:
Clause = ParseOpenMPSingleExprWithArgClause(DKind, CKind, WrongDirective);
break;
+ case OMPC_holds:
+ Clause = ParseOpenMPSingleExprClause(CKind, WrongDirective);
+ break;
case OMPC_nowait:
case OMPC_untied:
case OMPC_mergeable:
@@ -3408,6 +3411,9 @@ ExprResult Parser::ParseOpenMPParensExpr(StringRef ClauseName,
/// align-clause
/// 'align' '(' positive-integer-constant ')'
///
+/// holds-clause
+/// 'holds' '(' expression ')'
+///
OMPClause *Parser::ParseOpenMPSingleExprClause(OpenMPClauseKind Kind,
bool ParseOnly) {
SourceLocation Loc = ConsumeToken();
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 4f50efda155fb..fcc328187f6d6 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -14964,6 +14964,9 @@ OMPClause *SemaOpenMP::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind,
case OMPC_ompx_dyn_cgroup_mem:
Res = ActOnOpenMPXDynCGroupMemClause(Expr, StartLoc, LParenLoc, EndLoc);
break;
+ case OMPC_holds:
+ Res = ActOnOpenMPHoldsClause(Expr, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_grainsize:
case OMPC_num_tasks:
case OMPC_device:
@@ -23126,6 +23129,12 @@ OMPClause *SemaOpenMP::ActOnOpenMPXBareClause(SourceLocation StartLoc,
return new (getASTContext()) OMPXBareClause(StartLoc, EndLoc);
}
+OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
+}
+
ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 8d3e1edf7a45d..eec4856f77a6e 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -2486,6 +2486,14 @@ class TreeTransform {
DepType, DepLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
}
+ /// Build a new OpenMP 'holds' clause.
+ OMPClause *RebuildOMPHoldsClause(Expr *A, SourceLocation StartLoc,
+ SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ return getSema().OpenMP().ActOnOpenMPHoldsClause(A, StartLoc, LParenLoc,
+ EndLoc);
+ }
+
/// Rebuild the operand to an Objective-C \@synchronized statement.
///
/// By default, performs semantic analysis to build the new statement.
@@ -10240,6 +10248,15 @@ OMPClause *TreeTransform<Derived>::TransformOMPFailClause(OMPFailClause *C) {
return C;
}
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPHoldsClause(OMPHoldsClause *C) {
+ ExprResult E = getDerived().TransformExpr(C->getExpr());
+ if (E.isInvalid())
+ return nullptr;
+ return getDerived().RebuildOMPHoldsClause(E.get(), C->getBeginLoc(),
+ C->getLParenLoc(), C->getEndLoc());
+}
+
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 85ff3ab8974ee..656a59f5e0cba 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10463,6 +10463,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_acq_rel:
C = new (Context) OMPAcqRelClause();
break;
+ case llvm::omp::OMPC_holds:
+ C = new (Context) OMPHoldsClause();
+ break;
case llvm::omp::OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
@@ -10863,6 +10866,11 @@ void OMPClauseReader::VisitOMPFailClause(OMPFailClause *C) {
C->setFailParameter(CKind);
}
+void OMPClauseReader::VisitOMPHoldsClause(OMPHoldsClause *C) {
+ C->setExpr(Record.readExpr());
+ C->setLParenLoc(Record.readSourceLocation());
+}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index f0f9d397f1717..c4ac867ddb7f2 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7204,6 +7204,11 @@ void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
+void OMPClauseWriter::VisitOMPHoldsClause(OMPHoldsClause *C) {
+ Record.AddStmt(C->getExpr());
+ Record.AddSourceLocation(C->getLParenLoc());
+}
+
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 937d7ff09e4ee..906c9a81f7a72 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2425,6 +2425,8 @@ void OMPClauseEnqueue::VisitOMPCompareClause(const OMPCompareClause *) {}
void OMPClauseEnqueue::VisitOMPFailClause(const OMPFailClause *) {}
+void OMPClauseEnqueue::VisitOMPHoldsClause(const OMPHoldsClause *) {}
+
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 99cef340f40df..b762fb34a1cb9 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -196,6 +196,9 @@ def OMPC_Hint : Clause<"hint"> {
let clangClass = "OMPHintClause";
let flangClass = "ConstantExpr";
}
+def OMPC_Holds : Clause<"holds"> {
+ let clangClass = "OMPHoldsClause";
+}
def OMPC_If : Clause<"if"> {
let clangClass = "OMPIfClause";
let flangClass = "OmpIfClause";
@@ -510,6 +513,13 @@ def OMP_EndAssumes : Directive<"end assumes"> {
let association = AS_Delimited;
let category = OMP_Assumes.category;
}
+def OMP_Assume : Directive<"assume"> {
+ let association = AS_Block;
+ let category = CA_Informational;
+ let allowedOnceClauses = [
+ VersionedClause<OMPC_Holds, 51>,
+ ];
+}
def OMP_Atomic : Directive<"atomic"> {
let allowedClauses = [
VersionedClause<OMPC_Capture>,
>From 53b85da46765f75d483e90b67773ee4092f1e04d Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 14:55:33 -0500
Subject: [PATCH 2/8] [OpenMP][clang] Add 'absent' clause for 'omp assume'
directive
---
clang/include/clang/AST/OpenMPClause.h | 103 ++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 5 +
clang/include/clang/Sema/SemaOpenMP.h | 4 +
clang/lib/AST/OpenMPClause.cpp | 30 +++++
clang/lib/AST/StmtProfile.cpp | 2 +
clang/lib/Parse/ParseOpenMP.cpp | 29 +++++
clang/lib/Sema/SemaOpenMP.cpp | 11 ++
clang/lib/Sema/TreeTransform.h | 6 +
clang/lib/Serialization/ASTReader.cpp | 16 +++
clang/lib/Serialization/ASTWriter.cpp | 8 ++
clang/tools/libclang/CIndex.cpp | 2 +
llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 +
12 files changed, 220 insertions(+)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 47c2fd4400d52..a7d21c59a94bd 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -342,6 +342,66 @@ template <class T> class OMPVarListClause : public OMPClause {
}
};
+/// Class that represents a list of directive kinds (parallel, target, etc.)
+/// as used in \c absent, \c contains clauses.
+template <class T> class OMPDirectiveListClause : public OMPClause {
+ /// Location of '('.
+ SourceLocation LParenLoc;
+
+protected:
+ /// Number of directive kinds listed in the clause
+ unsigned NumKinds;
+
+public:
+ /// Build a clause with \a NumKinds directive kinds.
+ ///
+ /// \param K The clause kind.
+ /// \param StartLoc Starting location of the clause (the clause keyword).
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumKinds Number of directive kinds listed in the clause.
+ OMPDirectiveListClause(OpenMPClauseKind K, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc,
+ unsigned NumKinds)
+ : OMPClause(K, StartLoc, EndLoc), LParenLoc(LParenLoc),
+ NumKinds(NumKinds) {}
+
+ child_range children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+
+ const_child_range children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+
+ child_range used_children() {
+ return child_range(child_iterator(), child_iterator());
+ }
+ const_child_range used_children() const {
+ return const_child_range(const_child_iterator(), const_child_iterator());
+ }
+
+ MutableArrayRef<OpenMPDirectiveKind> getDirectiveKinds() {
+ return MutableArrayRef<OpenMPDirectiveKind>(
+ static_cast<T *>(this)
+ ->template getTrailingObjects<OpenMPDirectiveKind>(),
+ NumKinds);
+ }
+
+ void setDirectiveKinds(ArrayRef<OpenMPDirectiveKind> DK) {
+ assert(
+ DK.size() == NumKinds &&
+ "Number of directive kinds is not the same as the preallocated buffer");
+ std::copy(DK.begin(), DK.end(),
+ static_cast<T *>(this)
+ ->template getTrailingObjects<OpenMPDirectiveKind>());
+ }
+
+ SourceLocation getLParenLoc() { return LParenLoc; }
+
+ void setLParenLoc(SourceLocation S) { LParenLoc = S; }
+};
+
/// This represents 'allocator' clause in the '#pragma omp ...'
/// directive.
///
@@ -2013,6 +2073,49 @@ class OMPMergeableClause : public OMPClause {
}
};
+/// This represents the 'absent' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume absent(<directive-name list>)
+/// \endcode
+/// In this example directive '#pragma omp assume' has an 'absent' clause.
+class OMPAbsentClause final
+ : public OMPDirectiveListClause<OMPAbsentClause>,
+ private llvm::TrailingObjects<OMPAbsentClause, OpenMPDirectiveKind> {
+ friend OMPDirectiveListClause;
+ friend TrailingObjects;
+
+ /// Build 'absent' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumKinds Number of directive kinds listed in the clause.
+ OMPAbsentClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned NumKinds)
+ : OMPDirectiveListClause<OMPAbsentClause>(
+ llvm::omp::OMPC_absent, StartLoc, LParenLoc, EndLoc, NumKinds) {}
+
+ /// Build an empty clause.
+ OMPAbsentClause(unsigned NumKinds)
+ : OMPDirectiveListClause<OMPAbsentClause>(
+ llvm::omp::OMPC_absent, SourceLocation(), SourceLocation(),
+ SourceLocation(), NumKinds) {}
+
+public:
+ static OMPAbsentClause *Create(const ASTContext &C,
+ ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc, SourceLocation LLoc,
+ SourceLocation RLoc);
+
+ static OMPAbsentClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);
+
+ static bool classof(const OMPClause *C) {
+ return C->getClauseKind() == llvm::omp::OMPC_absent;
+ }
+};
+
/// This represents the 'holds' clause in the '#pragma omp assume'
/// directive.
///
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 73ece1e72bbf1..a0049c8542173 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3480,6 +3480,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPAcqRelClause(OMPAcqRelClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPAbsentClause(OMPAbsentClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPHoldsClause(OMPHoldsClause *) {
return true;
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 7c793cf3077a6..06636b8429811 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -944,6 +944,10 @@ class SemaOpenMP : public SemaBase {
OMPClause *ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
SourceLocation LParenLoc,
SourceLocation EndLoc);
+ /// Called on well-formed 'absent' or 'contains' clauses.
+ OMPClause *ActOnOpenMPDirectivePresenceClause(
+ OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc);
OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index e83c81136c34b..94c206d98fbed 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1720,6 +1720,24 @@ const Expr *OMPDoacrossClause::getLoopData(unsigned NumLoop) const {
return *It;
}
+OMPAbsentClause *OMPAbsentClause::Create(const ASTContext &C,
+ ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc,
+ SourceLocation LLoc,
+ SourceLocation RLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
+ alignof(OMPAbsentClause));
+ auto *AC = new (Mem) OMPAbsentClause(Loc, LLoc, RLoc, DKVec.size());
+ AC->setDirectiveKinds(DKVec);
+ return AC;
+}
+
+OMPAbsentClause *OMPAbsentClause::CreateEmpty(const ASTContext &C, unsigned K) {
+ void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
+ alignof(OMPAbsentClause));
+ return new (Mem) OMPAbsentClause(K);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
@@ -1937,6 +1955,18 @@ void OMPClausePrinter::VisitOMPFailClause(OMPFailClause *Node) {
}
}
+void OMPClausePrinter::VisitOMPAbsentClause(OMPAbsentClause *Node) {
+ OS << "absent(";
+ bool First = true;
+ for (auto &D : Node->getDirectiveKinds()) {
+ if (!First)
+ OS << ", ";
+ OS << getOpenMPDirectiveName(D);
+ First = false;
+ }
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPHoldsClause(OMPHoldsClause *Node) {
OS << "holds(";
Node->getExpr()->printPretty(OS, nullptr, Policy, 0);
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 97e4b3749f94c..f6329ef9a9cf2 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -584,6 +584,8 @@ void OMPClauseProfiler::VisitOMPCompareClause(const OMPCompareClause *) {}
void OMPClauseProfiler::VisitOMPFailClause(const OMPFailClause *) {}
+void OMPClauseProfiler::VisitOMPAbsentClause(const OMPAbsentClause *) {}
+
void OMPClauseProfiler::VisitOMPHoldsClause(const OMPHoldsClause *) {}
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index afcbc93696de2..e4386e98c802d 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3326,6 +3326,35 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
+ case OMPC_absent: {
+ SourceLocation Loc = ConsumeToken();
+ SourceLocation LLoc = Tok.getLocation();
+ SourceLocation RLoc;
+ llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
+ BalancedDelimiterTracker T(*this, tok::l_paren);
+ T.consumeOpen();
+ do {
+ OpenMPDirectiveKind DK = getOpenMPDirectiveKind(PP.getSpelling(Tok));
+ if (DK == OMPD_unknown) {
+ skipUntilPragmaOpenMPEnd(OMPD_assume);
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ break;
+ }
+ if (isOpenMPExecutableDirective(DK)) {
+ DKVec.push_back(DK);
+ ConsumeToken();
+ } else {
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+ }
+ } while (TryConsumeToken(tok::comma));
+ RLoc = Tok.getLocation();
+ T.consumeClose();
+ Clause = Actions.OpenMP().ActOnOpenMPDirectivePresenceClause(
+ CKind, DKVec, Loc, LLoc, RLoc);
+ break;
+ }
case OMPC_ompx_attribute:
Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
break;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index fcc328187f6d6..4b5b437d7d28c 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23135,6 +23135,17 @@ OMPClause *SemaOpenMP::ActOnOpenMPHoldsClause(Expr *E, SourceLocation StartLoc,
return new (getASTContext()) OMPHoldsClause(E, StartLoc, LParenLoc, EndLoc);
}
+OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
+ OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
+ switch (CK) {
+ case OMPC_absent:
+ return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
+ default:
+ llvm_unreachable("Unexpected OpenMP clause");
+ }
+}
+
ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index eec4856f77a6e..06418c3fda932 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10248,6 +10248,12 @@ OMPClause *TreeTransform<Derived>::TransformOMPFailClause(OMPFailClause *C) {
return C;
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPAbsentClause(OMPAbsentClause *C) {
+ return C;
+}
+
template <typename Derived>
OMPClause *TreeTransform<Derived>::TransformOMPHoldsClause(OMPHoldsClause *C) {
ExprResult E = getDerived().TransformExpr(C->getExpr());
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 656a59f5e0cba..91ce1c4a32a8c 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10463,6 +10463,11 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_acq_rel:
C = new (Context) OMPAcqRelClause();
break;
+ case llvm::omp::OMPC_absent: {
+ unsigned NumKinds = Record.readInt();
+ C = OMPAbsentClause::CreateEmpty(Context, NumKinds);
+ break;
+ }
case llvm::omp::OMPC_holds:
C = new (Context) OMPHoldsClause();
break;
@@ -10866,6 +10871,17 @@ void OMPClauseReader::VisitOMPFailClause(OMPFailClause *C) {
C->setFailParameter(CKind);
}
+void OMPClauseReader::VisitOMPAbsentClause(OMPAbsentClause *C) {
+ unsigned Count = C->getDirectiveKinds().size();
+ C->setLParenLoc(Record.readSourceLocation());
+ llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
+ DKVec.reserve(Count);
+ for (unsigned I = 0; I < Count; I++) {
+ DKVec.push_back(Record.readEnum<OpenMPDirectiveKind>());
+ }
+ C->setDirectiveKinds(DKVec);
+}
+
void OMPClauseReader::VisitOMPHoldsClause(OMPHoldsClause *C) {
C->setExpr(Record.readExpr());
C->setLParenLoc(Record.readSourceLocation());
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index c4ac867ddb7f2..88acdfe8e7fdc 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7204,6 +7204,14 @@ void OMPClauseWriter::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseWriter::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
+void OMPClauseWriter::VisitOMPAbsentClause(OMPAbsentClause *C) {
+ Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto K : C->getDirectiveKinds()) {
+ Record.writeEnum(K);
+ }
+}
+
void OMPClauseWriter::VisitOMPHoldsClause(OMPHoldsClause *C) {
Record.AddStmt(C->getExpr());
Record.AddSourceLocation(C->getLParenLoc());
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 906c9a81f7a72..6f444ea436733 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2425,6 +2425,8 @@ void OMPClauseEnqueue::VisitOMPCompareClause(const OMPCompareClause *) {}
void OMPClauseEnqueue::VisitOMPFailClause(const OMPFailClause *) {}
+void OMPClauseEnqueue::VisitOMPAbsentClause(const OMPAbsentClause *) {}
+
void OMPClauseEnqueue::VisitOMPHoldsClause(const OMPHoldsClause *) {}
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index b762fb34a1cb9..214fc7df4c0fe 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -32,6 +32,9 @@ def OpenMP : DirectiveLanguage {
// Sorted alphabetically wrt clause spelling.
//===----------------------------------------------------------------------===//
+def OMPC_Absent : Clause<"absent"> {
+ let clangClass = "OMPAbsentClause";
+}
def OMPC_Acquire : Clause<"acquire"> {
let clangClass = "OMPAcquireClause";
}
@@ -517,6 +520,7 @@ def OMP_Assume : Directive<"assume"> {
let association = AS_Block;
let category = CA_Informational;
let allowedOnceClauses = [
+ VersionedClause<OMPC_Absent, 51>,
VersionedClause<OMPC_Holds, 51>,
];
}
>From 1129752b48a9157df410ae048e783dba0f4f01ad Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 14:59:48 -0500
Subject: [PATCH 3/8] [OpenMP][clang] Add 'contains' clause for 'omp assume'
directive
---
clang/include/clang/AST/OpenMPClause.h | 43 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 5 +++
clang/lib/AST/OpenMPClause.cpp | 29 +++++++++++++
clang/lib/AST/StmtProfile.cpp | 2 +
clang/lib/Parse/ParseOpenMP.cpp | 3 +-
clang/lib/Sema/SemaOpenMP.cpp | 2 +
clang/lib/Sema/TreeTransform.h | 6 +++
clang/lib/Serialization/ASTReader.cpp | 16 +++++++
clang/lib/Serialization/ASTWriter.cpp | 8 ++++
clang/tools/libclang/CIndex.cpp | 2 +
llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 ++
11 files changed, 119 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index a7d21c59a94bd..dbd2bf3275c76 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -2116,6 +2116,49 @@ class OMPAbsentClause final
}
};
+/// This represents the 'contains' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume contains(<directive-name list>)
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'contains' clause.
+class OMPContainsClause final
+ : public OMPDirectiveListClause<OMPContainsClause>,
+ private llvm::TrailingObjects<OMPContainsClause, OpenMPDirectiveKind> {
+ friend OMPDirectiveListClause;
+ friend TrailingObjects;
+
+ /// Build 'contains' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param LParenLoc Location of '('.
+ /// \param EndLoc Ending location of the clause.
+ /// \param NumKinds Number of directive kinds listed in the clause.
+ OMPContainsClause(SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc, unsigned NumKinds)
+ : OMPDirectiveListClause<OMPContainsClause>(
+ llvm::omp::OMPC_contains, StartLoc, LParenLoc, EndLoc, NumKinds) {}
+
+ /// Build an empty clause.
+ OMPContainsClause(unsigned NumKinds)
+ : OMPDirectiveListClause<OMPContainsClause>(
+ llvm::omp::OMPC_contains, SourceLocation(), SourceLocation(),
+ SourceLocation(), NumKinds) {}
+
+public:
+ static OMPContainsClause *Create(const ASTContext &C,
+ ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc, SourceLocation LLoc,
+ SourceLocation RLoc);
+
+ static OMPContainsClause *CreateEmpty(const ASTContext &C, unsigned NumKinds);
+
+ static bool classof(const OMPClause *C) {
+ return C->getClauseKind() == llvm::omp::OMPC_contains;
+ }
+};
+
/// This represents the 'holds' clause in the '#pragma omp assume'
/// directive.
///
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index a0049c8542173..3c28a65af5ae5 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3490,6 +3490,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPHoldsClause(OMPHoldsClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPContainsClause(OMPContainsClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 94c206d98fbed..7330da5953814 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1738,6 +1738,23 @@ OMPAbsentClause *OMPAbsentClause::CreateEmpty(const ASTContext &C, unsigned K) {
return new (Mem) OMPAbsentClause(K);
}
+OMPContainsClause *OMPContainsClause::Create(
+ const ASTContext &C, ArrayRef<OpenMPDirectiveKind> DKVec,
+ SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc) {
+ void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(DKVec.size()),
+ alignof(OMPContainsClause));
+ auto *CC = new (Mem) OMPContainsClause(Loc, LLoc, RLoc, DKVec.size());
+ CC->setDirectiveKinds(DKVec);
+ return CC;
+}
+
+OMPContainsClause *OMPContainsClause::CreateEmpty(const ASTContext &C,
+ unsigned K) {
+ void *Mem = C.Allocate(totalSizeToAlloc<OpenMPDirectiveKind>(K),
+ alignof(OMPContainsClause));
+ return new (Mem) OMPContainsClause(K);
+}
+
//===----------------------------------------------------------------------===//
// OpenMP clauses printing methods
//===----------------------------------------------------------------------===//
@@ -1973,6 +1990,18 @@ void OMPClausePrinter::VisitOMPHoldsClause(OMPHoldsClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
+ OS << "contains";
+ bool First = true;
+ for (auto &D : Node->getDirectiveKinds()) {
+ if (!First)
+ OS << ", ";
+ OS << getOpenMPDirectiveName(D);
+ First = false;
+ }
+ OS << ")";
+}
+
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index f6329ef9a9cf2..72975886b4447 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -588,6 +588,8 @@ void OMPClauseProfiler::VisitOMPAbsentClause(const OMPAbsentClause *) {}
void OMPClauseProfiler::VisitOMPHoldsClause(const OMPHoldsClause *) {}
+void OMPClauseProfiler::VisitOMPContainsClause(const OMPContainsClause *) {}
+
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index e4386e98c802d..5c1aeebb71bd1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3326,7 +3326,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
<< getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
break;
- case OMPC_absent: {
+ case OMPC_absent:
+ case OMPC_contains: {
SourceLocation Loc = ConsumeToken();
SourceLocation LLoc = Tok.getLocation();
SourceLocation RLoc;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 4b5b437d7d28c..bfe9493f398f4 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23141,6 +23141,8 @@ OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
switch (CK) {
case OMPC_absent:
return OMPAbsentClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
+ case OMPC_contains:
+ return OMPContainsClause::Create(getASTContext(), DKVec, Loc, LLoc, RLoc);
default:
llvm_unreachable("Unexpected OpenMP clause");
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 06418c3fda932..899662a26cdad 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10263,6 +10263,12 @@ OMPClause *TreeTransform<Derived>::TransformOMPHoldsClause(OMPHoldsClause *C) {
C->getLParenLoc(), C->getEndLoc());
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPContainsClause(OMPContainsClause *C) {
+ return C;
+}
+
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index 91ce1c4a32a8c..bb5bd0e3744d4 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10471,6 +10471,11 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_holds:
C = new (Context) OMPHoldsClause();
break;
+ case llvm::omp::OMPC_contains: {
+ unsigned NumKinds = Record.readInt();
+ C = OMPContainsClause::CreateEmpty(Context, NumKinds);
+ break;
+ }
case llvm::omp::OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
@@ -10887,6 +10892,17 @@ void OMPClauseReader::VisitOMPHoldsClause(OMPHoldsClause *C) {
C->setLParenLoc(Record.readSourceLocation());
}
+void OMPClauseReader::VisitOMPContainsClause(OMPContainsClause *C) {
+ unsigned Count = C->getDirectiveKinds().size();
+ C->setLParenLoc(Record.readSourceLocation());
+ llvm::SmallVector<OpenMPDirectiveKind, 4> DKVec;
+ DKVec.reserve(Count);
+ for (unsigned I = 0; I < Count; I++) {
+ DKVec.push_back(Record.readEnum<OpenMPDirectiveKind>());
+ }
+ C->setDirectiveKinds(DKVec);
+}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 88acdfe8e7fdc..9a9823bd8c0a9 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7217,6 +7217,14 @@ void OMPClauseWriter::VisitOMPHoldsClause(OMPHoldsClause *C) {
Record.AddSourceLocation(C->getLParenLoc());
}
+void OMPClauseWriter::VisitOMPContainsClause(OMPContainsClause *C) {
+ Record.push_back(static_cast<uint64_t>(C->getDirectiveKinds().size()));
+ Record.AddSourceLocation(C->getLParenLoc());
+ for (auto K : C->getDirectiveKinds()) {
+ Record.writeEnum(K);
+ }
+}
+
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 6f444ea436733..d024a9a430a1d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2429,6 +2429,8 @@ void OMPClauseEnqueue::VisitOMPAbsentClause(const OMPAbsentClause *) {}
void OMPClauseEnqueue::VisitOMPHoldsClause(const OMPHoldsClause *) {}
+void OMPClauseEnqueue::VisitOMPContainsClause(const OMPContainsClause *) {}
+
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 214fc7df4c0fe..e2e282d23ecea 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -90,6 +90,9 @@ def OMPC_CancellationConstructType : Clause<"cancellation_construct_type"> {
OMP_CANCELLATION_CONSTRUCT_None
];
}
+def OMPC_Contains : Clause<"contains"> {
+ let clangClass = "OMPContainsClause";
+}
def OMPC_Capture : Clause<"capture"> {
let clangClass = "OMPCaptureClause";
}
@@ -521,6 +524,7 @@ def OMP_Assume : Directive<"assume"> {
let category = CA_Informational;
let allowedOnceClauses = [
VersionedClause<OMPC_Absent, 51>,
+ VersionedClause<OMPC_Contains, 51>,
VersionedClause<OMPC_Holds, 51>,
];
}
>From 435cd121ecb8ae91d548165f7a199d369c157009 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 15:05:44 -0500
Subject: [PATCH 4/8] [OpenMP][clang] Add 'no_openmp' clause for 'omp assume'
directive
---
clang/include/clang/AST/OpenMPClause.h | 21 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 5 +++++
clang/include/clang/Sema/SemaOpenMP.h | 3 +++
clang/lib/AST/OpenMPClause.cpp | 4 ++++
clang/lib/AST/StmtProfile.cpp | 2 ++
clang/lib/Parse/ParseOpenMP.cpp | 11 ++++++++++
clang/lib/Sema/SemaOpenMP.cpp | 11 ++++++++++
clang/lib/Sema/TreeTransform.h | 5 +++++
clang/lib/Serialization/ASTReader.cpp | 5 +++++
clang/lib/Serialization/ASTWriter.cpp | 2 ++
clang/tools/libclang/CIndex.cpp | 2 ++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 ++++
12 files changed, 75 insertions(+)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index dbd2bf3275c76..26e80626a46ad 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -2186,6 +2186,27 @@ class OMPHoldsClause final
void setExpr(Expr *E) { setStmt(E); }
};
+/// This represents the 'no_openmp' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume no_openmp
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'no_openmp' clause.
+class OMPNoOpenMPClause final
+ : public OMPNoChildClause<llvm::omp::OMPC_no_openmp> {
+public:
+ /// Build 'no_openmp' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPNoOpenMPClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPNoChildClause(StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPNoOpenMPClause() : OMPNoChildClause() {}
+};
+
/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 3c28a65af5ae5..7e105bc5548e0 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3495,6 +3495,11 @@ bool RecursiveASTVisitor<Derived>::VisitOMPContainsClause(OMPContainsClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 06636b8429811..176ca70aa28dd 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -948,6 +948,9 @@ class SemaOpenMP : public SemaBase {
OMPClause *ActOnOpenMPDirectivePresenceClause(
OpenMPClauseKind CK, llvm::ArrayRef<OpenMPDirectiveKind> DKVec,
SourceLocation Loc, SourceLocation LLoc, SourceLocation RLoc);
+ OMPClause *ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
+ SourceLocation Loc,
+ SourceLocation RLoc);
OMPClause *ActOnOpenMPSingleExprWithArgClause(
OpenMPClauseKind Kind, ArrayRef<unsigned> Arguments, Expr *Expr,
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 7330da5953814..85f444b90520d 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2002,6 +2002,10 @@ void OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
OS << ")";
}
+void OMPClausePrinter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
+ OS << "no_openmp";
+}
+
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 72975886b4447..3cd98e8711fbb 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -590,6 +590,8 @@ void OMPClauseProfiler::VisitOMPHoldsClause(const OMPHoldsClause *) {}
void OMPClauseProfiler::VisitOMPContainsClause(const OMPContainsClause *) {}
+void OMPClauseProfiler::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
+
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 5c1aeebb71bd1..bc37a04211bd2 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3356,6 +3356,17 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
CKind, DKVec, Loc, LLoc, RLoc);
break;
}
+ case OMPC_no_openmp: {
+ if (!FirstClause) {
+ Diag(Tok, diag::err_omp_more_one_clause)
+ << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+ ErrorFound = true;
+ }
+ SourceLocation Loc = ConsumeToken();
+ Clause = Actions.OpenMP().ActOnOpenMPNullaryAssumptionClause(
+ CKind, Loc, Tok.getLocation());
+ break;
+ }
case OMPC_ompx_attribute:
Clause = ParseOpenMPOMPXAttributesClause(WrongDirective);
break;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index bfe9493f398f4..2134cb0a220fd 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23148,6 +23148,17 @@ OMPClause *SemaOpenMP::ActOnOpenMPDirectivePresenceClause(
}
}
+OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
+ SourceLocation Loc,
+ SourceLocation RLoc) {
+ switch (CK) {
+ case OMPC_no_openmp:
+ return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
+ default:
+ llvm_unreachable("Unexpected OpenMP clause");
+ }
+}
+
ExprResult SemaOpenMP::ActOnOMPArraySectionExpr(
Expr *Base, SourceLocation LBLoc, Expr *LowerBound,
SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, Expr *Length,
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 899662a26cdad..e8a7b8cae2922 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10269,6 +10269,11 @@ TreeTransform<Derived>::TransformOMPContainsClause(OMPContainsClause *C) {
return C;
}
+template <typename Derived>
+OMPClause *
+TreeTransform<Derived>::TransformOMPNoOpenMPClause(OMPNoOpenMPClause *C) {
+ return C;
+}
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index bb5bd0e3744d4..d2908237d5fd8 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10476,6 +10476,9 @@ OMPClause *OMPClauseReader::readClause() {
C = OMPContainsClause::CreateEmpty(Context, NumKinds);
break;
}
+ case llvm::omp::OMPC_no_openmp:
+ C = new (Context) OMPNoOpenMPClause();
+ break;
case llvm::omp::OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
@@ -10903,6 +10906,8 @@ void OMPClauseReader::VisitOMPContainsClause(OMPContainsClause *C) {
C->setDirectiveKinds(DKVec);
}
+void OMPClauseReader::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 9a9823bd8c0a9..0c6f8ad6d4d74 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7225,6 +7225,8 @@ void OMPClauseWriter::VisitOMPContainsClause(OMPContainsClause *C) {
}
}
+void OMPClauseWriter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
+
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index d024a9a430a1d..4d2f5b015d02e 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2431,6 +2431,8 @@ void OMPClauseEnqueue::VisitOMPHoldsClause(const OMPHoldsClause *) {}
void OMPClauseEnqueue::VisitOMPContainsClause(const OMPContainsClause *) {}
+void OMPClauseEnqueue::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
+
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index e2e282d23ecea..7b8b1ac717972 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -269,6 +269,9 @@ def OMPC_Mergeable : Clause<"mergeable"> {
def OMPC_Message : Clause<"message"> {
let clangClass = "OMPMessageClause";
}
+def OMPC_NoOpenMP : Clause<"no_openmp"> {
+ let clangClass = "OMPNoOpenMPClause";
+}
def OMPC_Nocontext : Clause<"nocontext"> {
let clangClass = "OMPNocontextClause";
let flangClass = "ScalarLogicalExpr";
@@ -526,6 +529,7 @@ def OMP_Assume : Directive<"assume"> {
VersionedClause<OMPC_Absent, 51>,
VersionedClause<OMPC_Contains, 51>,
VersionedClause<OMPC_Holds, 51>,
+ VersionedClause<OMPC_NoOpenMP, 51>,
];
}
def OMP_Atomic : Directive<"atomic"> {
>From 8719c3494d6e244244fe5a9d88210e0b62cf65be Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 15:09:01 -0500
Subject: [PATCH 5/8] [OpenMP][clang] Add 'no_openmp_routines' clause for 'omp
assume' directive
---
clang/include/clang/AST/OpenMPClause.h | 22 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 6 +++++
clang/lib/AST/OpenMPClause.cpp | 5 +++++
clang/lib/AST/StmtProfile.cpp | 3 +++
clang/lib/Parse/ParseOpenMP.cpp | 3 ++-
clang/lib/Sema/SemaOpenMP.cpp | 2 ++
clang/lib/Sema/TreeTransform.h | 5 +++++
clang/lib/Serialization/ASTReader.cpp | 6 +++++
clang/lib/Serialization/ASTWriter.cpp | 3 +++
clang/tools/libclang/CIndex.cpp | 3 +++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 ++++
11 files changed, 61 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index 26e80626a46ad..f7e3e0b35b60b 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -2207,6 +2207,28 @@ class OMPNoOpenMPClause final
OMPNoOpenMPClause() : OMPNoChildClause() {}
};
+/// This represents the 'no_openmp_routines' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume no_openmp_routines
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'no_openmp_routines'
+/// clause.
+class OMPNoOpenMPRoutinesClause final
+ : public OMPNoChildClause<llvm::omp::OMPC_no_openmp_routines> {
+public:
+ /// Build 'no_openmp_routines' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPNoOpenMPRoutinesClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPNoChildClause(StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
+};
+
/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 7e105bc5548e0..00614859c4349 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3500,6 +3500,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPRoutinesClause(
+ OMPNoOpenMPRoutinesClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 85f444b90520d..b170c651b31ca 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2006,6 +2006,11 @@ void OMPClausePrinter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {
OS << "no_openmp";
}
+void OMPClausePrinter::VisitOMPNoOpenMPRoutinesClause(
+ OMPNoOpenMPRoutinesClause *) {
+ OS << "no_openmp_routines";
+}
+
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 3cd98e8711fbb..80ab0c4488ea3 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -592,6 +592,9 @@ void OMPClauseProfiler::VisitOMPContainsClause(const OMPContainsClause *) {}
void OMPClauseProfiler::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
+void OMPClauseProfiler::VisitOMPNoOpenMPRoutinesClause(
+ const OMPNoOpenMPRoutinesClause *) {}
+
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index bc37a04211bd2..879c2a7ecca20 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3356,7 +3356,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
CKind, DKVec, Loc, LLoc, RLoc);
break;
}
- case OMPC_no_openmp: {
+ case OMPC_no_openmp:
+ case OMPC_no_openmp_routines: {
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 2134cb0a220fd..d482a861286ab 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23154,6 +23154,8 @@ OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
switch (CK) {
case OMPC_no_openmp:
return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
+ case OMPC_no_openmp_routines:
+ return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
default:
llvm_unreachable("Unexpected OpenMP clause");
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e8a7b8cae2922..4952e86117d0b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10275,6 +10275,11 @@ TreeTransform<Derived>::TransformOMPNoOpenMPClause(OMPNoOpenMPClause *C) {
return C;
}
template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPNoOpenMPRoutinesClause(
+ OMPNoOpenMPRoutinesClause *C) {
+ return C;
+}
+template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
// No need to rebuild this clause, no template-dependent parameters.
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index d2908237d5fd8..f1816cb453908 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10479,6 +10479,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_no_openmp:
C = new (Context) OMPNoOpenMPClause();
break;
+ case llvm::omp::OMPC_no_openmp_routines:
+ C = new (Context) OMPNoOpenMPRoutinesClause();
+ break;
case llvm::omp::OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
@@ -10908,6 +10911,9 @@ void OMPClauseReader::VisitOMPContainsClause(OMPContainsClause *C) {
void OMPClauseReader::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
+void OMPClauseReader::VisitOMPNoOpenMPRoutinesClause(
+ OMPNoOpenMPRoutinesClause *) {}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index 0c6f8ad6d4d74..d8d29a499be0b 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7227,6 +7227,9 @@ void OMPClauseWriter::VisitOMPContainsClause(OMPContainsClause *C) {
void OMPClauseWriter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
+void OMPClauseWriter::VisitOMPNoOpenMPRoutinesClause(
+ OMPNoOpenMPRoutinesClause *) {}
+
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 4d2f5b015d02e..cb1711d1928ab 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2433,6 +2433,9 @@ void OMPClauseEnqueue::VisitOMPContainsClause(const OMPContainsClause *) {}
void OMPClauseEnqueue::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
+void OMPClauseEnqueue::VisitOMPNoOpenMPRoutinesClause(
+ const OMPNoOpenMPRoutinesClause *) {}
+
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index 7b8b1ac717972..b0ebf1a88ebf2 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -272,6 +272,9 @@ def OMPC_Message : Clause<"message"> {
def OMPC_NoOpenMP : Clause<"no_openmp"> {
let clangClass = "OMPNoOpenMPClause";
}
+def OMPC_NoOpenMPRoutines : Clause<"no_openmp_routines"> {
+ let clangClass = "OMPNoOpenMPRoutinesClause";
+}
def OMPC_Nocontext : Clause<"nocontext"> {
let clangClass = "OMPNocontextClause";
let flangClass = "ScalarLogicalExpr";
@@ -530,6 +533,7 @@ def OMP_Assume : Directive<"assume"> {
VersionedClause<OMPC_Contains, 51>,
VersionedClause<OMPC_Holds, 51>,
VersionedClause<OMPC_NoOpenMP, 51>,
+ VersionedClause<OMPC_NoOpenMPRoutines, 51>,
];
}
def OMP_Atomic : Directive<"atomic"> {
>From e086183ff8ab2f8e74d7c9f10faef591c65dd8be Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 15:12:27 -0500
Subject: [PATCH 6/8] [OpenMP][clang] Add 'no_parallelism' clause for 'omp
assume' directive
---
clang/include/clang/AST/OpenMPClause.h | 22 +++++++++++++++++++
clang/include/clang/AST/RecursiveASTVisitor.h | 6 +++++
clang/lib/AST/OpenMPClause.cpp | 4 ++++
clang/lib/AST/StmtProfile.cpp | 3 +++
clang/lib/Parse/ParseOpenMP.cpp | 3 ++-
clang/lib/Sema/SemaOpenMP.cpp | 2 ++
clang/lib/Sema/TreeTransform.h | 6 +++++
clang/lib/Serialization/ASTReader.cpp | 5 +++++
clang/lib/Serialization/ASTWriter.cpp | 2 ++
clang/tools/libclang/CIndex.cpp | 3 +++
llvm/include/llvm/Frontend/OpenMP/OMP.td | 4 ++++
11 files changed, 59 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang/AST/OpenMPClause.h b/clang/include/clang/AST/OpenMPClause.h
index f7e3e0b35b60b..3a8337abfe687 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -2229,6 +2229,28 @@ class OMPNoOpenMPRoutinesClause final
OMPNoOpenMPRoutinesClause() : OMPNoChildClause() {}
};
+/// This represents the 'no_parallelism' clause in the '#pragma omp assume'
+/// directive.
+///
+/// \code
+/// #pragma omp assume no_parallelism
+/// \endcode
+/// In this example directive '#pragma omp assume' has a 'no_parallelism'
+/// clause.
+class OMPNoParallelismClause final
+ : public OMPNoChildClause<llvm::omp::OMPC_no_parallelism> {
+public:
+ /// Build 'no_parallelism' clause.
+ ///
+ /// \param StartLoc Starting location of the clause.
+ /// \param EndLoc Ending location of the clause.
+ OMPNoParallelismClause(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPNoChildClause(StartLoc, EndLoc) {}
+
+ /// Build an empty clause.
+ OMPNoParallelismClause() : OMPNoChildClause() {}
+};
+
/// This represents 'read' clause in the '#pragma omp atomic' directive.
///
/// \code
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index 00614859c4349..ad379c5437d78 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3506,6 +3506,12 @@ bool RecursiveASTVisitor<Derived>::VisitOMPNoOpenMPRoutinesClause(
return true;
}
+template <typename Derived>
+bool RecursiveASTVisitor<Derived>::VisitOMPNoParallelismClause(
+ OMPNoParallelismClause *) {
+ return true;
+}
+
template <typename Derived>
bool RecursiveASTVisitor<Derived>::VisitOMPAcquireClause(OMPAcquireClause *) {
return true;
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index b170c651b31ca..7268070e3a27d 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2011,6 +2011,10 @@ void OMPClausePrinter::VisitOMPNoOpenMPRoutinesClause(
OS << "no_openmp_routines";
}
+void OMPClausePrinter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {
+ OS << "no_parallelism";
+}
+
void OMPClausePrinter::VisitOMPSeqCstClause(OMPSeqCstClause *) {
OS << "seq_cst";
}
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 80ab0c4488ea3..27a6ade9559e8 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -595,6 +595,9 @@ void OMPClauseProfiler::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
void OMPClauseProfiler::VisitOMPNoOpenMPRoutinesClause(
const OMPNoOpenMPRoutinesClause *) {}
+void OMPClauseProfiler::VisitOMPNoParallelismClause(
+ const OMPNoParallelismClause *) {}
+
void OMPClauseProfiler::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseProfiler::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 879c2a7ecca20..2cb5dfe32c449 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3357,7 +3357,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
break;
}
case OMPC_no_openmp:
- case OMPC_no_openmp_routines: {
+ case OMPC_no_openmp_routines:
+ case OMPC_no_parallelism: {
if (!FirstClause) {
Diag(Tok, diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index d482a861286ab..67d1ff660c636 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -23156,6 +23156,8 @@ OMPClause *SemaOpenMP::ActOnOpenMPNullaryAssumptionClause(OpenMPClauseKind CK,
return new (getASTContext()) OMPNoOpenMPClause(Loc, RLoc);
case OMPC_no_openmp_routines:
return new (getASTContext()) OMPNoOpenMPRoutinesClause(Loc, RLoc);
+ case OMPC_no_parallelism:
+ return new (getASTContext()) OMPNoParallelismClause(Loc, RLoc);
default:
llvm_unreachable("Unexpected OpenMP clause");
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 4952e86117d0b..e4e4f68b45bcb 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10279,6 +10279,12 @@ OMPClause *TreeTransform<Derived>::TransformOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *C) {
return C;
}
+template <typename Derived>
+OMPClause *TreeTransform<Derived>::TransformOMPNoParallelismClause(
+ OMPNoParallelismClause *C) {
+ return C;
+}
+
template <typename Derived>
OMPClause *
TreeTransform<Derived>::TransformOMPSeqCstClause(OMPSeqCstClause *C) {
diff --git a/clang/lib/Serialization/ASTReader.cpp b/clang/lib/Serialization/ASTReader.cpp
index f1816cb453908..657ea305f52cf 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -10482,6 +10482,9 @@ OMPClause *OMPClauseReader::readClause() {
case llvm::omp::OMPC_no_openmp_routines:
C = new (Context) OMPNoOpenMPRoutinesClause();
break;
+ case llvm::omp::OMPC_no_parallelism:
+ C = new (Context) OMPNoParallelismClause();
+ break;
case llvm::omp::OMPC_acquire:
C = new (Context) OMPAcquireClause();
break;
@@ -10914,6 +10917,8 @@ void OMPClauseReader::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
void OMPClauseReader::VisitOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *) {}
+void OMPClauseReader::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {}
+
void OMPClauseReader::VisitOMPSeqCstClause(OMPSeqCstClause *) {}
void OMPClauseReader::VisitOMPAcqRelClause(OMPAcqRelClause *) {}
diff --git a/clang/lib/Serialization/ASTWriter.cpp b/clang/lib/Serialization/ASTWriter.cpp
index d8d29a499be0b..8aa23865d75aa 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -7230,6 +7230,8 @@ void OMPClauseWriter::VisitOMPNoOpenMPClause(OMPNoOpenMPClause *) {}
void OMPClauseWriter::VisitOMPNoOpenMPRoutinesClause(
OMPNoOpenMPRoutinesClause *) {}
+void OMPClauseWriter::VisitOMPNoParallelismClause(OMPNoParallelismClause *) {}
+
void OMPClauseWriter::VisitOMPAcquireClause(OMPAcquireClause *) {}
void OMPClauseWriter::VisitOMPReleaseClause(OMPReleaseClause *) {}
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index cb1711d1928ab..cb2e14e5f3e5a 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2436,6 +2436,9 @@ void OMPClauseEnqueue::VisitOMPNoOpenMPClause(const OMPNoOpenMPClause *) {}
void OMPClauseEnqueue::VisitOMPNoOpenMPRoutinesClause(
const OMPNoOpenMPRoutinesClause *) {}
+void OMPClauseEnqueue::VisitOMPNoParallelismClause(
+ const OMPNoParallelismClause *) {}
+
void OMPClauseEnqueue::VisitOMPSeqCstClause(const OMPSeqCstClause *) {}
void OMPClauseEnqueue::VisitOMPAcqRelClause(const OMPAcqRelClause *) {}
diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td
index b0ebf1a88ebf2..2cbcbd883fb2e 100644
--- a/llvm/include/llvm/Frontend/OpenMP/OMP.td
+++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td
@@ -275,6 +275,9 @@ def OMPC_NoOpenMP : Clause<"no_openmp"> {
def OMPC_NoOpenMPRoutines : Clause<"no_openmp_routines"> {
let clangClass = "OMPNoOpenMPRoutinesClause";
}
+def OMPC_NoParallelism : Clause<"no_parallelism"> {
+ let clangClass = "OMPNoParallelismClause";
+}
def OMPC_Nocontext : Clause<"nocontext"> {
let clangClass = "OMPNocontextClause";
let flangClass = "ScalarLogicalExpr";
@@ -534,6 +537,7 @@ def OMP_Assume : Directive<"assume"> {
VersionedClause<OMPC_Holds, 51>,
VersionedClause<OMPC_NoOpenMP, 51>,
VersionedClause<OMPC_NoOpenMPRoutines, 51>,
+ VersionedClause<OMPC_NoParallelism, 51>,
];
}
def OMP_Atomic : Directive<"atomic"> {
>From c0b873358bb56e2ab9c83491e5382e62812417c4 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 15:14:09 -0500
Subject: [PATCH 7/8] [OpenMP][clang] OpenMP 5.1 "assume" directive parsing
support
This patch supports parsing of "omp assume" directives. These are meant
to be hints to a compiler's optimisers: as such, it is legitimate
(if not very useful) to ignore them. This version of the patch
implements new AST nodes for the "assume" directive and the various
clauses it accepts as arguments, and adds new (C++ module) tests for
serialization/deserialization of said nodes.
The patch now uses tail allocation for the directive kind list.
Unlike the "omp [begin/end] assumes" directives, "omp assume" is
associated with a compound statement, i.e. it can appear within a
function. The "holds" assumption could (theoretically) be mapped
onto the existing builtin "__builtin_assume", though the latter applies
to a single point in the program, and the former to a range (i.e. the
whole of the associated compound statement).
The "assume" directive appears to be distinct from the [[omp::assume]]
annotation.
This patch fixes sollve's OpenMP 5.1 "omp assume"-based tests.
---
clang/include/clang-c/Index.h | 4 +
clang/include/clang/AST/RecursiveASTVisitor.h | 3 +
clang/include/clang/AST/StmtOpenMP.h | 30 +++++++
clang/include/clang/Basic/OpenMPKinds.h | 2 +
clang/include/clang/Basic/StmtNodes.td | 1 +
clang/include/clang/Parse/Parser.h | 4 +
clang/include/clang/Sema/SemaOpenMP.h | 8 ++
.../include/clang/Serialization/ASTBitCodes.h | 1 +
clang/lib/AST/StmtOpenMP.cpp | 17 ++++
clang/lib/AST/StmtPrinter.cpp | 5 ++
clang/lib/AST/StmtProfile.cpp | 4 +
clang/lib/Basic/OpenMPKinds.cpp | 8 ++
clang/lib/CodeGen/CGStmt.cpp | 3 +
clang/lib/CodeGen/CGStmtOpenMP.cpp | 7 +-
clang/lib/CodeGen/CodeGenFunction.h | 1 +
clang/lib/Parse/ParseOpenMP.cpp | 78 ++++++++++++++++++
clang/lib/Sema/SemaOpenMP.cpp | 32 ++++++++
clang/lib/Sema/TreeTransform.h | 82 +++++++++++++++++++
clang/lib/Serialization/ASTReaderStmt.cpp | 11 +++
clang/lib/Serialization/ASTWriterStmt.cpp | 6 ++
clang/tools/libclang/CIndex.cpp | 7 ++
21 files changed, 313 insertions(+), 1 deletion(-)
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 115f5ab090f96..4b4adbfb236e7 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -2154,6 +2154,10 @@ enum CXCursorKind {
*/
CXCursor_OMPInterchangeDirective = 308,
+ /** OpenMP assume directive.
+ */
+ CXCursor_OMPAssumeDirective = 309,
+
/** OpenACC Compute Construct.
*/
CXCursor_OpenACCComputeConstruct = 320,
diff --git a/clang/include/clang/AST/RecursiveASTVisitor.h b/clang/include/clang/AST/RecursiveASTVisitor.h
index ad379c5437d78..f469cd9094558 100644
--- a/clang/include/clang/AST/RecursiveASTVisitor.h
+++ b/clang/include/clang/AST/RecursiveASTVisitor.h
@@ -3238,6 +3238,9 @@ DEF_TRAVERSE_STMT(OMPParallelGenericLoopDirective,
DEF_TRAVERSE_STMT(OMPTargetParallelGenericLoopDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
+DEF_TRAVERSE_STMT(OMPAssumeDirective,
+ { TRY_TO(TraverseOMPExecutableDirective(S)); })
+
DEF_TRAVERSE_STMT(OMPErrorDirective,
{ TRY_TO(TraverseOMPExecutableDirective(S)); })
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index f313c480f9a08..0ca3732a1ac3a 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -6468,6 +6468,36 @@ class OMPErrorDirective final : public OMPExecutableDirective {
return T->getStmtClass() == OMPErrorDirectiveClass;
}
};
+
+// It's not really an executable directive, but it seems convenient to use
+// that as the parent class.
+class OMPAssumeDirective : public OMPExecutableDirective {
+ friend class ASTStmtReader;
+ friend class OMPExecutableDirective;
+
+private:
+ OMPAssumeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ : OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
+ StartLoc, EndLoc) {}
+
+ explicit OMPAssumeDirective()
+ : OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
+ SourceLocation(), SourceLocation()) {}
+
+public:
+ static OMPAssumeDirective *Create(const ASTContext &Ctx,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt);
+
+ static OMPAssumeDirective *CreateEmpty(const ASTContext &C,
+ unsigned NumClauses, EmptyShell);
+
+ static bool classof(const Stmt *T) {
+ return T->getStmtClass() == OMPAssumeDirectiveClass;
+ }
+};
+
} // end namespace clang
#endif
diff --git a/clang/include/clang/Basic/OpenMPKinds.h b/clang/include/clang/Basic/OpenMPKinds.h
index 1d7192c4bdf9d..e8775fa3358e7 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -377,6 +377,8 @@ bool checkFailClauseParameter(OpenMPClauseKind FailClauseParameter);
/// otherwise - false.
bool isOpenMPExecutableDirective(OpenMPDirectiveKind DKind);
+bool isOpenMPInformationalDirective(OpenMPDirectiveKind DKind);
+
/// Checks if the specified directive can capture variables.
/// \param DKind Specified directive.
/// \return true - if the above condition is met for this directive
diff --git a/clang/include/clang/Basic/StmtNodes.td b/clang/include/clang/Basic/StmtNodes.td
index 9bf23fae50a9e..e4e4343ec6f92 100644
--- a/clang/include/clang/Basic/StmtNodes.td
+++ b/clang/include/clang/Basic/StmtNodes.td
@@ -298,6 +298,7 @@ def OMPTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPTargetTeamsGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
def OMPTargetParallelGenericLoopDirective : StmtNode<OMPLoopDirective>;
+def OMPAssumeDirective : StmtNode<OMPExecutableDirective>;
def OMPErrorDirective : StmtNode<OMPExecutableDirective>;
// OpenACC Constructs.
diff --git a/clang/include/clang/Parse/Parser.h b/clang/include/clang/Parse/Parser.h
index ba7d6866ebacd..154ac5fe839c5 100644
--- a/clang/include/clang/Parse/Parser.h
+++ b/clang/include/clang/Parse/Parser.h
@@ -3532,6 +3532,10 @@ class Parser : public CodeCompletionHandler {
OpenMPDirectiveKind DKind, SourceLocation Loc,
bool ReadDirectiveWithinMetadirective);
+ StmtResult ParseOpenMPInformationalDirective(
+ ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
+ bool ReadDirectiveWithinMetadirective);
+
/// Parses clause of kind \a CKind for directive of a kind \a Kind.
///
/// \param DKind Kind of current directive.
diff --git a/clang/include/clang/Sema/SemaOpenMP.h b/clang/include/clang/Sema/SemaOpenMP.h
index 176ca70aa28dd..e59152ecc78f0 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -399,6 +399,14 @@ class SemaOpenMP : public SemaBase {
OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
OpenMPDirectiveKind CancelRegion, ArrayRef<OMPClause *> Clauses,
Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
+ StmtResult ActOnOpenMPInformationalDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+ StmtResult ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc);
+
/// Called on well-formed '\#pragma omp parallel' after parsing
/// of the associated statement.
StmtResult ActOnOpenMPParallelDirective(ArrayRef<OMPClause *> Clauses,
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 5dd0ba33f8a9c..24ae6b768d379 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -1964,6 +1964,7 @@ enum StmtCode {
STMT_OMP_TARGET_TEAMS_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_PARALLEL_GENERIC_LOOP_DIRECTIVE,
STMT_OMP_TARGET_PARALLEL_GENERIC_LOOP_DIRECTIVE,
+ STMT_OMP_ASSUME_DIRECTIVE,
EXPR_ARRAY_SECTION,
EXPR_OMP_ARRAY_SHAPING,
EXPR_OMP_ITERATOR,
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index 451a9fe9fe3d2..5adfd91957460 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -799,6 +799,23 @@ OMPTaskyieldDirective *OMPTaskyieldDirective::CreateEmpty(const ASTContext &C,
return new (C) OMPTaskyieldDirective();
}
+OMPAssumeDirective *OMPAssumeDirective::Create(const ASTContext &C,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt) {
+ return createDirective<OMPAssumeDirective>(C, Clauses, AStmt,
+ /*NumChildren=*/0, StartLoc,
+ EndLoc);
+}
+
+OMPAssumeDirective *OMPAssumeDirective::CreateEmpty(const ASTContext &C,
+ unsigned NumClauses,
+ EmptyShell) {
+ return createEmptyDirective<OMPAssumeDirective>(C, NumClauses,
+ /*HasAssociatedStmt=*/true);
+}
+
OMPErrorDirective *OMPErrorDirective::Create(const ASTContext &C,
SourceLocation StartLoc,
SourceLocation EndLoc,
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 69e0b763e8ddc..014d02220d291 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -867,6 +867,11 @@ void StmtPrinter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *Node) {
PrintOMPExecutableDirective(Node);
}
+void StmtPrinter::VisitOMPAssumeDirective(OMPAssumeDirective *Node) {
+ Indent() << "#pragma omp assume";
+ PrintOMPExecutableDirective(Node);
+}
+
void StmtPrinter::VisitOMPErrorDirective(OMPErrorDirective *Node) {
Indent() << "#pragma omp error";
PrintOMPExecutableDirective(Node);
diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp
index 27a6ade9559e8..09562aadc728a 100644
--- a/clang/lib/AST/StmtProfile.cpp
+++ b/clang/lib/AST/StmtProfile.cpp
@@ -1082,6 +1082,10 @@ void StmtProfiler::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *S) {
VisitOMPExecutableDirective(S);
}
+void StmtProfiler::VisitOMPAssumeDirective(const OMPAssumeDirective *S) {
+ VisitOMPExecutableDirective(S);
+}
+
void StmtProfiler::VisitOMPErrorDirective(const OMPErrorDirective *S) {
VisitOMPExecutableDirective(S);
}
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index b141e48e77e3c..2910f4ed642d1 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -710,6 +710,13 @@ bool clang::isOpenMPExecutableDirective(OpenMPDirectiveKind DKind) {
return Cat == Category::Executable || Cat == Category::Subsidiary;
}
+bool clang::isOpenMPInformationalDirective(OpenMPDirectiveKind DKind) {
+ if (DKind == OMPD_error)
+ return true;
+ Category Cat = getDirectiveCategory(DKind);
+ return Cat == Category::Informational;
+}
+
bool clang::isOpenMPCapturingDirective(OpenMPDirectiveKind DKind) {
if (isOpenMPExecutableDirective(DKind)) {
switch (DKind) {
@@ -726,6 +733,7 @@ bool clang::isOpenMPCapturingDirective(OpenMPDirectiveKind DKind) {
case OMPD_section:
case OMPD_taskwait:
case OMPD_taskyield:
+ case OMPD_assume:
return false;
default:
return !isOpenMPLoopTransformationDirective(DKind);
diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp
index 30b6fce5d016a..68386957bc2d9 100644
--- a/clang/lib/CodeGen/CGStmt.cpp
+++ b/clang/lib/CodeGen/CGStmt.cpp
@@ -446,6 +446,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S, ArrayRef<const Attr *> Attrs) {
case Stmt::OMPParallelMaskedDirectiveClass:
EmitOMPParallelMaskedDirective(cast<OMPParallelMaskedDirective>(*S));
break;
+ case Stmt::OMPAssumeDirectiveClass:
+ EmitOMPAssumeDirective(cast<OMPAssumeDirective>(*S));
+ break;
case Stmt::OpenACCComputeConstructClass:
EmitOpenACCComputeConstruct(cast<OpenACCComputeConstruct>(*S));
break;
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index b1ac9361957ff..96012af7be001 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -8288,7 +8288,8 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
D.getDirectiveKind() == OMPD_section ||
D.getDirectiveKind() == OMPD_master ||
D.getDirectiveKind() == OMPD_masked ||
- D.getDirectiveKind() == OMPD_unroll) {
+ D.getDirectiveKind() == OMPD_unroll ||
+ D.getDirectiveKind() == OMPD_assume) {
EmitStmt(D.getAssociatedStmt());
} else {
auto LPCRegion =
@@ -8303,3 +8304,7 @@ void CodeGenFunction::EmitSimpleOMPExecutableDirective(
// Check for outer lastprivate conditional update.
checkForLastprivateConditionalUpdate(*this, D);
}
+
+void CodeGenFunction::EmitOMPAssumeDirective(const OMPAssumeDirective &S) {
+ EmitStmt(S.getAssociatedStmt());
+}
diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h
index 60885f7f9df41..5d713f0b9bb5c 100644
--- a/clang/lib/CodeGen/CodeGenFunction.h
+++ b/clang/lib/CodeGen/CodeGenFunction.h
@@ -3904,6 +3904,7 @@ class CodeGenFunction : public CodeGenTypeCache {
void EmitOMPTeamsGenericLoopDirective(const OMPTeamsGenericLoopDirective &S);
void EmitOMPInteropDirective(const OMPInteropDirective &S);
void EmitOMPParallelMaskedDirective(const OMPParallelMaskedDirective &S);
+ void EmitOMPAssumeDirective(const OMPAssumeDirective &S);
/// Emit device code for the target directive.
static void EmitOMPTargetDeviceFunction(CodeGenModule &CGM,
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 2cb5dfe32c449..0602d8666684c 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2371,6 +2371,11 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
ParseOMPEndDeclareTargetDirective(DTCI.Kind, DKind, DTCI.Loc);
return nullptr;
}
+ case OMPD_assume: {
+ Diag(Tok, diag::err_omp_unexpected_directive)
+ << 1 << getOpenMPDirectiveName(DKind);
+ break;
+ }
case OMPD_unknown:
Diag(Tok, diag::err_omp_unknown_directive);
break;
@@ -2572,6 +2577,71 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
return Directive;
}
+StmtResult Parser::ParseOpenMPInformationalDirective(
+ ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
+ bool ReadDirectiveWithinMetadirective) {
+ assert(isOpenMPInformationalDirective(DKind) &&
+ "Unexpected directive category");
+
+ bool HasAssociatedStatement = true;
+ Association Assoc = getDirectiveAssociation(DKind);
+
+ SmallVector<OMPClause *, 5> Clauses;
+ llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
+ DeclarationNameInfo DirName;
+ unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope |
+ Scope::CompoundStmtScope | Scope::OpenMPDirectiveScope;
+ ParseScope OMPDirectiveScope(this, ScopeFlags);
+
+ Actions.OpenMP().StartOpenMPDSABlock(DKind, DirName, Actions.getCurScope(),
+ Loc);
+
+ while (Tok.isNot(tok::annot_pragma_openmp_end)) {
+ if (ReadDirectiveWithinMetadirective && Tok.is(tok::r_paren)) {
+ while (Tok.isNot(tok::annot_pragma_openmp_end))
+ ConsumeAnyToken();
+ break;
+ }
+
+ OpenMPClauseKind CKind = Tok.isAnnotation()
+ ? OMPC_unknown
+ : getOpenMPClauseKind(PP.getSpelling(Tok));
+ Actions.OpenMP().StartOpenMPClause(CKind);
+ OMPClause *Clause =
+ ParseOpenMPClause(DKind, CKind, !SeenClauses[unsigned(CKind)]);
+ SeenClauses[unsigned(CKind)] = true;
+ if (Clause)
+ Clauses.push_back(Clause);
+
+ if (Tok.is(tok::comma))
+ ConsumeToken();
+ Actions.OpenMP().EndOpenMPClause();
+ }
+
+ SourceLocation EndLoc = Tok.getLocation();
+ ConsumeAnnotationToken();
+
+ StmtResult AssociatedStmt;
+ if (HasAssociatedStatement) {
+ Actions.OpenMP().ActOnOpenMPRegionStart(DKind, getCurScope());
+ ParsingOpenMPDirectiveRAII NormalScope(*this, /*Value=*/false);
+ {
+ Sema::CompoundScopeRAII Scope(Actions);
+ AssociatedStmt = ParseStatement();
+ }
+ AssociatedStmt =
+ Actions.OpenMP().ActOnOpenMPRegionEnd(AssociatedStmt, Clauses);
+ }
+
+ StmtResult Directive = Actions.OpenMP().ActOnOpenMPInformationalDirective(
+ DKind, DirName, Clauses, AssociatedStmt.get(), Loc, EndLoc);
+
+ Actions.OpenMP().EndOpenMPDSABlock(Directive.get());
+ OMPDirectiveScope.Exit();
+
+ return Directive;
+}
+
/// Parsing of declarative or executable OpenMP directives.
///
/// threadprivate-directive:
@@ -2920,6 +2990,14 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective(
<< 1 << getOpenMPDirectiveName(DKind);
SkipUntil(tok::annot_pragma_openmp_end);
break;
+ case OMPD_assume: {
+ ConsumeToken();
+ Directive = ParseOpenMPInformationalDirective(
+ StmtCtx, DKind, Loc, ReadDirectiveWithinMetadirective);
+ assert(!Directive.isUnset() &&
+ "Informational directive remains unprocessed");
+ return Directive;
+ }
case OMPD_unknown:
default:
Diag(Tok, diag::err_omp_unknown_directive);
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 67d1ff660c636..ff580983898cb 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3563,6 +3563,17 @@ void SemaOpenMP::ActOnOpenMPEndAssumesDirective() {
OMPAssumeScoped.pop_back();
}
+StmtResult SemaOpenMP::ActOnOpenMPAssumeDirective(ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ if (!AStmt)
+ return StmtError();
+
+ return OMPAssumeDirective::Create(getASTContext(), StartLoc, EndLoc, Clauses,
+ AStmt);
+}
+
OMPRequiresDecl *
SemaOpenMP::CheckOMPRequiresDecl(SourceLocation Loc,
ArrayRef<OMPClause *> ClauseList) {
@@ -4387,6 +4398,7 @@ void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
case OMPD_unroll:
case OMPD_reverse:
case OMPD_interchange:
+ case OMPD_assume:
break;
default:
processCapturedRegions(SemaRef, DKind, CurScope,
@@ -6931,6 +6943,26 @@ SemaOpenMP::DeclGroupPtrTy SemaOpenMP::ActOnOpenMPDeclareSimdDirective(
return DG;
}
+StmtResult SemaOpenMP::ActOnOpenMPInformationalDirective(
+ OpenMPDirectiveKind Kind, const DeclarationNameInfo &DirName,
+ ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+ assert(isOpenMPInformationalDirective(Kind) &&
+ "Unexpected directive category");
+
+ StmtResult Res = StmtError();
+
+ switch (Kind) {
+ case OMPD_assume:
+ Res = ActOnOpenMPAssumeDirective(Clauses, AStmt, StartLoc, EndLoc);
+ break;
+ default:
+ llvm_unreachable("Unknown OpenMP directive");
+ }
+
+ return Res;
+}
+
static void setPrototype(Sema &S, FunctionDecl *FD, FunctionDecl *FDWithProto,
QualType NewType) {
assert(NewType->isFunctionProtoType() &&
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index e4e4f68b45bcb..40e549463103b 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -803,6 +803,8 @@ class TreeTransform {
StmtResult TransformOMPExecutableDirective(OMPExecutableDirective *S);
+ StmtResult TransformOMPInformationalDirective(OMPExecutableDirective *S);
+
// FIXME: We use LLVM_ATTRIBUTE_NOINLINE because inlining causes a ridiculous
// amount of stack usage with clang.
#define STMT(Node, Parent) \
@@ -1678,6 +1680,18 @@ class TreeTransform {
Kind, DirName, CancelRegion, Clauses, AStmt, StartLoc, EndLoc);
}
+ /// Build a new OpenMP informational directive.
+ StmtResult RebuildOMPInformationalDirective(OpenMPDirectiveKind Kind,
+ DeclarationNameInfo DirName,
+ ArrayRef<OMPClause *> Clauses,
+ Stmt *AStmt,
+ SourceLocation StartLoc,
+ SourceLocation EndLoc) {
+
+ return getSema().OpenMP().ActOnOpenMPInformationalDirective(
+ Kind, DirName, Clauses, AStmt, StartLoc, EndLoc);
+ }
+
/// Build a new OpenMP 'if' clause.
///
/// By default, performs semantic analysis to build the new OpenMP clause.
@@ -9193,6 +9207,63 @@ StmtResult TreeTransform<Derived>::TransformOMPExecutableDirective(
AssociatedStmt.get(), D->getBeginLoc(), D->getEndLoc());
}
+/// This is mostly the same as above, but allows 'informational' class
+/// directives when rebuilding the stmt. It still takes an
+/// OMPExecutableDirective-type argument because we're reusing that as the
+/// superclass for the 'assume' directive at present, instead of defining a
+/// mostly-identical OMPInformationalDirective parent class.
+template <typename Derived>
+StmtResult TreeTransform<Derived>::TransformOMPInformationalDirective(
+ OMPExecutableDirective *D) {
+
+ // Transform the clauses
+ llvm::SmallVector<OMPClause *, 16> TClauses;
+ ArrayRef<OMPClause *> Clauses = D->clauses();
+ TClauses.reserve(Clauses.size());
+ for (ArrayRef<OMPClause *>::iterator I = Clauses.begin(), E = Clauses.end();
+ I != E; ++I) {
+ if (*I) {
+ getDerived().getSema().OpenMP().StartOpenMPClause((*I)->getClauseKind());
+ OMPClause *Clause = getDerived().TransformOMPClause(*I);
+ getDerived().getSema().OpenMP().EndOpenMPClause();
+ if (Clause)
+ TClauses.push_back(Clause);
+ } else {
+ TClauses.push_back(nullptr);
+ }
+ }
+ StmtResult AssociatedStmt;
+ if (D->hasAssociatedStmt() && D->getAssociatedStmt()) {
+ getDerived().getSema().OpenMP().ActOnOpenMPRegionStart(
+ D->getDirectiveKind(),
+ /*CurScope=*/nullptr);
+ StmtResult Body;
+ {
+ Sema::CompoundScopeRAII CompoundScope(getSema());
+ Stmt *CS = nullptr;
+ if (D->getDirectiveKind() == OMPD_assume)
+ CS = D->getAssociatedStmt();
+ else
+ llvm_unreachable("Unexpected informational directive");
+ Body = getDerived().TransformStmt(CS);
+ }
+ AssociatedStmt =
+ getDerived().getSema().OpenMP().ActOnOpenMPRegionEnd(Body, TClauses);
+ if (AssociatedStmt.isInvalid()) {
+ return StmtError();
+ }
+ }
+ if (TClauses.size() != Clauses.size()) {
+ return StmtError();
+ }
+
+ DeclarationNameInfo DirName;
+
+ return getDerived().RebuildOMPInformationalDirective(
+ D->getDirectiveKind(), DirName, TClauses, AssociatedStmt.get(),
+ D->getBeginLoc(), D->getEndLoc());
+}
+
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPMetaDirective(OMPMetaDirective *D) {
@@ -9454,6 +9525,17 @@ TreeTransform<Derived>::TransformOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
return Res;
}
+template <typename Derived>
+StmtResult
+TreeTransform<Derived>::TransformOMPAssumeDirective(OMPAssumeDirective *D) {
+ DeclarationNameInfo DirName;
+ getDerived().getSema().OpenMP().StartOpenMPDSABlock(
+ OMPD_assume, DirName, nullptr, D->getBeginLoc());
+ StmtResult Res = getDerived().TransformOMPInformationalDirective(D);
+ getDerived().getSema().OpenMP().EndOpenMPDSABlock(Res.get());
+ return Res;
+}
+
template <typename Derived>
StmtResult
TreeTransform<Derived>::TransformOMPErrorDirective(OMPErrorDirective *D) {
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index e1cba9e612be3..a33f2a41a6549 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -2536,6 +2536,11 @@ void ASTStmtReader::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
VisitOMPExecutableDirective(D);
}
+void ASTStmtReader::VisitOMPAssumeDirective(OMPAssumeDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+}
+
void ASTStmtReader::VisitOMPErrorDirective(OMPErrorDirective *D) {
VisitStmt(D);
// The NumClauses field was read in ReadStmtFromStream.
@@ -3913,6 +3918,12 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
break;
}
+ case STMT_OMP_ASSUME_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ S = OMPAssumeDirective::CreateEmpty(Context, NumClauses, Empty);
+ break;
+ }
+
case EXPR_CXX_OPERATOR_CALL: {
auto NumArgs = Record[ASTStmtReader::NumExprFields];
BitsUnpacker CallExprBits(Record[ASTStmtReader::NumExprFields + 1]);
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index ec667b58337ff..038616a675b72 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2606,6 +2606,12 @@ void ASTStmtWriter::VisitOMPTaskwaitDirective(OMPTaskwaitDirective *D) {
Code = serialization::STMT_OMP_TASKWAIT_DIRECTIVE;
}
+void ASTStmtWriter::VisitOMPAssumeDirective(OMPAssumeDirective *D) {
+ VisitStmt(D);
+ VisitOMPExecutableDirective(D);
+ Code = serialization::STMT_OMP_ASSUME_DIRECTIVE;
+}
+
void ASTStmtWriter::VisitOMPErrorDirective(OMPErrorDirective *D) {
VisitStmt(D);
Record.push_back(D->getNumClauses());
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index cb2e14e5f3e5a..40c74d49e41e9 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -2200,6 +2200,7 @@ class EnqueueVisitor : public ConstStmtVisitor<EnqueueVisitor, void>,
void VisitOMPTaskyieldDirective(const OMPTaskyieldDirective *D);
void VisitOMPBarrierDirective(const OMPBarrierDirective *D);
void VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D);
+ void VisitOMPAssumeDirective(const OMPAssumeDirective *D);
void VisitOMPErrorDirective(const OMPErrorDirective *D);
void VisitOMPTaskgroupDirective(const OMPTaskgroupDirective *D);
void
@@ -3324,6 +3325,10 @@ void EnqueueVisitor::VisitOMPTaskwaitDirective(const OMPTaskwaitDirective *D) {
VisitOMPExecutableDirective(D);
}
+void EnqueueVisitor::VisitOMPAssumeDirective(const OMPAssumeDirective *D) {
+ VisitOMPAssumeDirective(D);
+}
+
void EnqueueVisitor::VisitOMPErrorDirective(const OMPErrorDirective *D) {
VisitOMPExecutableDirective(D);
}
@@ -6160,6 +6165,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPBarrierDirective");
case CXCursor_OMPTaskwaitDirective:
return cxstring::createRef("OMPTaskwaitDirective");
+ case CXCursor_OMPAssumeDirective:
+ return cxstring::createRef("OMPAssumeDirective");
case CXCursor_OMPErrorDirective:
return cxstring::createRef("OMPErrorDirective");
case CXCursor_OMPTaskgroupDirective:
>From 58252e5d94612bcf39ffbce3c8ff7be538ca6b25 Mon Sep 17 00:00:00 2001
From: Julian Brown <julian.brown at amd.com>
Date: Thu, 1 Aug 2024 14:40:50 -0500
Subject: [PATCH 8/8] [OpenMP][clang] New tests for 'omp assume' directive
---
clang/test/OpenMP/assume_lambda.cpp | 31 ++++++++
clang/test/OpenMP/assume_messages.c | 30 ++++++++
clang/test/OpenMP/assume_messages_attr.c | 30 ++++++++
.../OpenMP/assume_serialize_deserialize.cpp | 31 ++++++++
.../assume_serialize_deserialize_tmpl.cpp | 72 +++++++++++++++++++
clang/test/OpenMP/assume_template.cpp | 42 +++++++++++
6 files changed, 236 insertions(+)
create mode 100644 clang/test/OpenMP/assume_lambda.cpp
create mode 100644 clang/test/OpenMP/assume_messages.c
create mode 100644 clang/test/OpenMP/assume_messages_attr.c
create mode 100644 clang/test/OpenMP/assume_serialize_deserialize.cpp
create mode 100644 clang/test/OpenMP/assume_serialize_deserialize_tmpl.cpp
create mode 100644 clang/test/OpenMP/assume_template.cpp
diff --git a/clang/test/OpenMP/assume_lambda.cpp b/clang/test/OpenMP/assume_lambda.cpp
new file mode 100644
index 0000000000000..4000dc1600b23
--- /dev/null
+++ b/clang/test/OpenMP/assume_lambda.cpp
@@ -0,0 +1,31 @@
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -ast-print %s | FileCheck %s
+// expected-no-diagnostics
+
+extern int bar(int);
+
+int foo(int arg)
+{
+ #pragma omp assume no_openmp_routines
+ {
+ auto fn = [](int x) { return bar(x); };
+// CHECK: auto fn = [](int x) {
+ return fn(5);
+ }
+}
+
+class C {
+public:
+ int foo(int a);
+};
+
+// We're really just checking that this parses. All the assumptions are thrown
+// away immediately for now.
+int C::foo(int a)
+{
+ #pragma omp assume holds(sizeof(void*) == 8) absent(parallel)
+ {
+ auto fn = [](int x) { return bar(x); };
+// CHECK: auto fn = [](int x) {
+ return fn(5);
+ }
+}
diff --git a/clang/test/OpenMP/assume_messages.c b/clang/test/OpenMP/assume_messages.c
new file mode 100644
index 0000000000000..65b003863c089
--- /dev/null
+++ b/clang/test/OpenMP/assume_messages.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c -std=c99 %s
+
+#pragma omp assume no_openmp // expected-error {{unexpected OpenMP directive '#pragma omp assume'}}
+
+void foo(void) {
+ #pragma omp assume hold(1==1) // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void bar(void) {
+ #pragma omp assume absent(target)
+} // expected-error {{expected statement}}
+
+void qux(void) {
+ #pragma omp assume extra_bits // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void quux(void) {
+ // This form of spelling for assumption clauses is supported for
+ // "omp assumes" (as a non-standard extension), but not here.
+ #pragma omp assume ext_spelled_like_this // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void dups(void) {
+ #pragma omp assume no_openmp no_openmp // // expected-error {{directive '#pragma omp assume' cannot contain more than one 'no_openmp' clause}}
+ {}
+}
diff --git a/clang/test/OpenMP/assume_messages_attr.c b/clang/test/OpenMP/assume_messages_attr.c
new file mode 100644
index 0000000000000..a2e61a8cf412f
--- /dev/null
+++ b/clang/test/OpenMP/assume_messages_attr.c
@@ -0,0 +1,30 @@
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp -x c -std=c99 %s
+// RUN: %clang_cc1 -triple=x86_64-linux-gnu -verify -fopenmp-simd -x c -std=c99 %s
+
+[[omp::directive(assume no_openmp)]] // expected-error {{unexpected OpenMP directive '#pragma omp assume'}}
+
+void foo(void) {
+ [[omp::directive(assume hold(1==1))]] // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void bar(void) {
+ [[omp::directive(assume absent(target))]]
+} // expected-error {{expected statement}}
+
+void qux(void) {
+ [[omp::directive(assume extra_bits)]] // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void quux(void) {
+ // This form of spelling for assumption clauses is supported for
+ // "omp assumes" (as a non-standard extension), but not here.
+ [[omp::directive(assume ext_spelled_like_this)]] // expected-warning {{extra tokens at the end of '#pragma omp assume' are ignored}}
+ {}
+}
+
+void dups(void) {
+ [[omp::directive(assume no_openmp no_openmp)]] // expected-error {{directive '#pragma omp assume' cannot contain more than one 'no_openmp' clause}}
+ {}
+}
diff --git a/clang/test/OpenMP/assume_serialize_deserialize.cpp b/clang/test/OpenMP/assume_serialize_deserialize.cpp
new file mode 100644
index 0000000000000..d74de48047bd1
--- /dev/null
+++ b/clang/test/OpenMP/assume_serialize_deserialize.cpp
@@ -0,0 +1,31 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -fopenmp -triple x86_64-unknown-linux-gnu %t/AssumeMod.cppm -emit-module-interface -o %t/AssumeMod.pcm
+// RUN: %clang_cc1 -std=c++20 -fopenmp -triple x86_64-unknown-linux-gnu %t/UseAssumeMod.cpp -fmodule-file=AssumeMod=%t/AssumeMod.pcm -ast-dump-all | FileCheck %t/AssumeMod.cppm
+
+// expected-no-diagnostics
+
+//--- AssumeMod.cppm
+module;
+export module AssumeMod;
+export int foo(int y) {
+ int x = -1;
+#pragma omp assume holds(y == 5)
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:5:1, col:33>
+// CHECK-NEXT: OMPHoldsClause 0x{{.*}} <col:20, col:32>
+ {
+ x = y;
+ }
+ return x;
+}
+//--- UseAssumeMod.cpp
+import AssumeMod;
+
+extern "C" int printf(const char* fmt, ...);
+
+int main() {
+ printf ("foo(5)=%d\n", foo (5));
+ return 0;
+}
diff --git a/clang/test/OpenMP/assume_serialize_deserialize_tmpl.cpp b/clang/test/OpenMP/assume_serialize_deserialize_tmpl.cpp
new file mode 100644
index 0000000000000..db0b47210bd41
--- /dev/null
+++ b/clang/test/OpenMP/assume_serialize_deserialize_tmpl.cpp
@@ -0,0 +1,72 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: cd %t
+
+// RUN: %clang_cc1 -std=c++20 -fopenmp -triple x86_64-unknown-linux-gnu %t/AssumeMod.cppm -emit-module-interface -o %t/AssumeMod.pcm
+// RUN: %clang_cc1 -std=c++20 -fopenmp -triple x86_64-unknown-linux-gnu %t/UseAssumeMod.cpp -fmodule-file=AssumeMod=%t/AssumeMod.pcm -ast-dump-all | FileCheck %t/AssumeMod.cppm
+
+// expected-no-diagnostics
+
+//--- AssumeMod.cppm
+module;
+export module AssumeMod;
+export template<int N> int foo(int y) {
+ int x = -1;
+#pragma omp assume holds(y == N)
+ {
+ x = y;
+ }
+ return x;
+}
+
+export template<bool B> void bar(int *z) {
+ if constexpr (B) {
+#pragma omp assume no_openmp
+ {
+ z[0]++;
+ }
+ } else {
+#pragma omp assume contains(target, parallel) absent(loop)
+ {
+ z[1] += 2;
+ }
+ }
+}
+
+// CHECK: FunctionTemplateDecl 0x{{.*}}
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:5:1, col:33>
+// CHECK-NEXT: OMPHoldsClause 0x{{.*}} <col:20, col:32>
+
+// CHECK: FunctionDecl 0x{{.*}} implicit_instantiation
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:5:1, col:33>
+// CHECK-NEXT: OMPHoldsClause 0x{{.*}} <col:20, col:32>
+
+// CHECK: FunctionTemplateDecl 0x{{.*}}
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:14:1, col:29>
+// CHECK-NEXT: OMPNo_openmpClause 0x{{.*}} <col:20, col:29>
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:19:1, col:59>
+// CHECK-NEXT: OMPContainsClause 0x{{.*}} <col:20, col:45>
+// CHECK-NEXT: OMPAbsentClause 0x{{.*}} <col:47, col:58>
+
+// CHECK: FunctionDecl 0x{{.*}} implicit_instantiation
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:14:1, col:29>
+// CHECK-NEXT: OMPNo_openmpClause 0x{{.*}} <col:20, col:29>
+
+// CHECK: FunctionDecl 0x{{.*}} implicit_instantiation
+// CHECK: OMPAssumeDirective 0x{{.*}} <line:19:1, col:59>
+// CHECK-NEXT: OMPContainsClause 0x{{.*}} <col:20, col:45>
+// CHECK-NEXT: OMPAbsentClause 0x{{.*}} <col:47, col:58>
+
+//--- UseAssumeMod.cpp
+import AssumeMod;
+
+extern "C" int printf(const char* fmt, ...);
+
+int main() {
+ printf ("foo(5)=%d\n", foo<5> (5));
+ int arr[2] = { 0, 0 };
+ bar<true>(arr);
+ bar<false>(arr);
+ printf ("arr[0]=%d, arr[1]=%d\n", arr[0], arr[1]);
+ return 0;
+}
diff --git a/clang/test/OpenMP/assume_template.cpp b/clang/test/OpenMP/assume_template.cpp
new file mode 100644
index 0000000000000..20d1c5d437145
--- /dev/null
+++ b/clang/test/OpenMP/assume_template.cpp
@@ -0,0 +1,42 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s
+// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -verify %s -ast-print | FileCheck %s
+// expected-no-diagnostics
+
+#ifndef HEADER
+#define HEADER
+
+extern int qux(int);
+
+template<typename T>
+int foo(T arg)
+{
+ #pragma omp assume no_openmp_routines
+ {
+ auto fn = [](int x) { return qux(x); };
+// CHECK: auto fn = [](int x) {
+ return fn(5);
+ }
+}
+
+template<typename T>
+class C {
+ T m;
+
+public:
+ T bar(T a);
+};
+
+// We're really just checking this parses. All the assumptions are thrown
+// away immediately for now.
+template<typename T>
+T C<T>::bar(T a)
+{
+ #pragma omp assume holds(sizeof(T) == 8) absent(parallel)
+ {
+ return (T)qux((int)a);
+// CHECK: return (T)qux((int)a);
+ }
+}
+
+#endif
More information about the cfe-commits
mailing list