[llvm-branch-commits] [clang] [llvm] [clang][OpenMP] Use different ids for block and s/a ORDERED directive (PR #214728)
Krzysztof Parzyszek via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Fri Aug 7 09:22:38 PDT 2026
https://github.com/kparzysz updated https://github.com/llvm/llvm-project/pull/214728
>From e554990a40dd05cf2174c7cd7b34b5aaabeb7a81 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Thu, 6 Aug 2026 13:29:52 -0500
Subject: [PATCH 1/4] [clang][OpenMP] Use different ids for block and s/a
ORDERED directive
Use OMPD_ordered_blockassoc for the block-associated ORDERED directive,
and OMPD_ordered_standalone for the standalone variant.
This still uses a single AST class for both though. The directive
kind stored in can now take either of the two values.
---
clang/include/clang/AST/StmtOpenMP.h | 10 +++-
clang/lib/AST/StmtOpenMP.cpp | 12 +++-
clang/lib/Basic/OpenMPKinds.cpp | 2 +-
clang/lib/CodeGen/CGOpenMPRuntime.cpp | 16 +++--
clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp | 6 +-
clang/lib/CodeGen/CGStmtOpenMP.cpp | 3 +-
clang/lib/Parse/ParseOpenMP.cpp | 59 +++++++++++--------
clang/lib/Sema/SemaOpenMP.cpp | 53 ++++++++++-------
clang/lib/Sema/TreeTransform.h | 2 +-
.../Frontend/OpenMP/DirectiveNameParser.cpp | 6 +-
10 files changed, 107 insertions(+), 62 deletions(-)
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index dbc76e7df8ecd..2d0cfb1580aeb 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -554,6 +554,9 @@ class OMPExecutableDirective : public Stmt {
}
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+ void setDirectiveKind(OpenMPDirectiveKind D) const {
+ const_cast<OMPExecutableDirective *>(this)->Kind = D;
+ }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
@@ -2947,14 +2950,15 @@ class OMPOrderedDirective : public OMPExecutableDirective {
///
OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
: OMPExecutableDirective(OMPOrderedDirectiveClass,
- llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
+ llvm::omp::OMPD_ordered_standalone, StartLoc,
+ EndLoc) {}
/// Build an empty directive.
///
explicit OMPOrderedDirective()
: OMPExecutableDirective(OMPOrderedDirectiveClass,
- llvm::omp::OMPD_ordered, SourceLocation(),
- SourceLocation()) {}
+ llvm::omp::OMPD_ordered_standalone,
+ SourceLocation(), SourceLocation()) {}
public:
/// Creates directive.
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index 9d6b315effb41..e4144cb544a9d 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -1062,17 +1062,23 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
- return createDirective<OMPOrderedDirective>(
+ auto *D = createDirective<OMPOrderedDirective>(
C, Clauses, cast_or_null<CapturedStmt>(AssociatedStmt),
/*NumChildren=*/0, StartLoc, EndLoc);
+ if (AssociatedStmt)
+ D->setDirectiveKind(OMPD_ordered_blockassoc);
+ return D;
}
OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
bool IsStandalone,
EmptyShell) {
- return createEmptyDirective<OMPOrderedDirective>(C, NumClauses,
- !IsStandalone);
+ auto *D =
+ createEmptyDirective<OMPOrderedDirective>(C, NumClauses, !IsStandalone);
+ if (!IsStandalone)
+ D->setDirectiveKind(OMPD_ordered_blockassoc);
+ return D;
}
OMPAtomicDirective *
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 1a2a963243f6c..8292a21286e7a 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -995,7 +995,7 @@ void clang::getOpenMPCaptureRegions(
case OMPD_dispatch:
case OMPD_distribute:
case OMPD_for:
- case OMPD_ordered:
+ case OMPD_ordered_blockassoc:
case OMPD_scope:
case OMPD_sections:
case OMPD_simd:
diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
index 51f1e8b22fcfc..409c222da87fc 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -2429,10 +2429,10 @@ void CGOpenMPRuntime::emitOrderedRegion(CodeGenFunction &CGF,
CGM.getModule(), OMPRTL___kmpc_end_ordered),
Args);
OrderedOpGen.setAction(Action);
- emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
+ emitInlinedDirective(CGF, OMPD_ordered_blockassoc, OrderedOpGen);
return;
}
- emitInlinedDirective(CGF, OMPD_ordered, OrderedOpGen);
+ emitInlinedDirective(CGF, OMPD_ordered_blockassoc, OrderedOpGen);
}
unsigned CGOpenMPRuntime::getDefaultFlagsForBarriers(OpenMPDirectiveKind Kind) {
@@ -6545,7 +6545,8 @@ const Expr *CGOpenMPRuntime::getNumTeamsExprForTargetDirective(
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
@@ -10509,7 +10510,8 @@ getNestedDistributeDirective(ASTContext &Ctx, const OMPExecutableDirective &D) {
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
@@ -11274,7 +11276,8 @@ void CGOpenMPRuntime::scanForTargetRegionsFunctions(const Stmt *S,
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
@@ -11849,7 +11852,8 @@ void CGOpenMPRuntime::emitTargetDataStandAloneCall(
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
diff --git a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
index 8f9000660d86b..20ce5fe268880 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntimeGPU.cpp
@@ -562,7 +562,8 @@ static bool hasNestedSPMDDirective(ASTContext &Ctx,
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
@@ -650,7 +651,8 @@ static bool supportsSPMDExecutionMode(ASTContext &Ctx,
case OMPD_parallel_for_simd:
case OMPD_cancel:
case OMPD_cancellation_point:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_threadprivate:
case OMPD_allocate:
case OMPD_task:
diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp
index 97c43b4c0b384..c7c13af972255 100644
--- a/clang/lib/CodeGen/CGStmtOpenMP.cpp
+++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp
@@ -1703,7 +1703,8 @@ void CodeGenFunction::EmitOMPReductionClauseInit(
case OMPD_flush:
case OMPD_depobj:
case OMPD_scan:
- case OMPD_ordered:
+ case OMPD_ordered_standalone:
+ case OMPD_ordered_blockassoc:
case OMPD_atomic:
case OMPD_teams:
case OMPD_target:
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index a6c639bf0b3aa..616bd87124210 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -63,13 +63,9 @@ static OpenMPDirectiveKind checkOpenMPDirectiveName(Parser &P,
StringRef Name) {
unsigned Version = P.getLangOpts().OpenMP;
auto [D, VR] = getOpenMPDirectiveKindAndVersions(Name);
- // There are multiple kinds corresponding to "ordered", and it's
- // unspecified which one we get, so normalize it to OMPD_ordered.
- if (D == Directive::OMPD_ordered_blockassoc ||
- D == Directive::OMPD_ordered_standalone)
- D = OMPD_ordered;
- if (Kind == Directive::OMPD_ordered_standalone)
- Kind = OMPD_ordered;
+ // "ORDERED" is parsed as OMPD_ordered_standalone.
+ if (D == Directive::OMPD_ordered || D == Directive::OMPD_ordered_blockassoc)
+ D = Directive::OMPD_ordered_standalone;
assert(D == Kind && "Directive kind mismatch");
// Ignore the case Version > VR.Max: In OpenMP 6.0 all prior spellings
// are explicitly allowed.
@@ -2301,11 +2297,9 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
bool HasAssociatedStatement = true;
Association Assoc = getDirectiveAssociation(DKind);
- // OMPD_ordered has None as association, but it comes in two variants,
- // the second of which is associated with a block.
// OMPD_scan and OMPD_section are both "separating", but section is treated
// as if it was associated with a statement, while scan is not.
- if (DKind != OMPD_ordered && DKind != OMPD_section &&
+ if (DKind != OMPD_ordered_standalone && DKind != OMPD_section &&
(Assoc == Association::None || Assoc == Association::Separating)) {
if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
ParsedStmtContext()) {
@@ -2424,7 +2418,9 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
// Consume final annot_pragma_openmp_end.
ConsumeAnnotationToken();
- if (DKind == OMPD_ordered) {
+ assert(DKind != OMPD_ordered_blockassoc &&
+ "Wrong kind for ordered directive");
+ if (DKind == OMPD_ordered_standalone) {
// If the depend or doacross clause is specified, the ordered construct
// is a stand-alone directive.
for (auto CK : {OMPC_depend, OMPC_doacross}) {
@@ -2438,6 +2434,9 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
HasAssociatedStatement = false;
}
}
+
+ if (HasAssociatedStatement)
+ DKind = OMPD_ordered_blockassoc;
}
if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
@@ -3231,14 +3230,27 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
bool WrongDirective = false;
unsigned OMPVersion = Actions.getLangOpts().OpenMP;
- // Check if clause is allowed for the given directive.
- if (CKind != OMPC_unknown &&
- !isAllowedClauseForDirective(DKind, CKind, getLangOpts().OpenMP)) {
- Diag(Tok, diag::err_omp_unexpected_clause)
- << getOpenMPClauseName(CKind)
- << getOpenMPDirectiveName(DKind, OMPVersion);
- ErrorFound = true;
- WrongDirective = true;
+ auto checkClauseValid = [&](OpenMPDirectiveKind D, OpenMPClauseKind C) {
+ if (!isAllowedClauseForDirective(D, C, OMPVersion)) {
+ Diag(Tok, diag::err_omp_unexpected_clause)
+ << getOpenMPClauseName(C) << getOpenMPDirectiveName(D, OMPVersion);
+ ErrorFound = true;
+ WrongDirective = true;
+ }
+ };
+
+ if (CKind != OMPC_unknown) {
+ // Check if clause is allowed for the given directive.
+ assert(DKind != OMPD_ordered_blockassoc &&
+ "Wrong kind for ordered directive");
+ if (DKind == OMPD_ordered_standalone) {
+ // Initially OMPD_ordered_standalone is used for ORDERED, before the
+ // actual kind can be determined.
+ if (!isAllowedClauseForDirective(DKind, CKind, OMPVersion))
+ checkClauseValid(OMPD_ordered_blockassoc, CKind);
+ } else {
+ checkClauseValid(DKind, CKind);
+ }
}
switch (CKind) {
@@ -3482,7 +3494,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
case OMPC_affinity:
case OMPC_doacross:
case OMPC_enter:
- if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered &&
+ if (getLangOpts().OpenMP >= 52 && DKind == OMPD_ordered_standalone &&
CKind == OMPC_depend)
Diag(Tok, diag::warn_omp_depend_in_ordered_deprecated);
Clause = ParseOpenMPVarListClause(DKind, CKind, WrongDirective);
@@ -5008,7 +5020,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
} else {
ConsumeToken();
// Special processing for depend(source) clause.
- if (DKind == OMPD_ordered && Kind == OMPC_depend &&
+ if (DKind == OMPD_ordered_standalone && Kind == OMPC_depend &&
Data.ExtraModifier == OMPC_DEPEND_source) {
// Parse ')'.
T.consumeClose();
@@ -5018,8 +5030,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Tok.is(tok::colon)) {
Data.ColonLoc = ConsumeToken();
} else if (Kind != OMPC_doacross || Tok.isNot(tok::r_paren)) {
- Diag(Tok, DKind == OMPD_ordered ? diag::warn_pragma_expected_colon_r_paren
- : diag::warn_pragma_expected_colon)
+ Diag(Tok, DKind == OMPD_ordered_standalone
+ ? diag::warn_pragma_expected_colon_r_paren
+ : diag::warn_pragma_expected_colon)
<< (Kind == OMPC_depend ? "dependency type" : "dependence-type");
}
if (Kind == OMPC_doacross) {
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 76bb0d38d428f..9c7be1e46298e 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -1256,6 +1256,10 @@ class DSAStackTy {
}
assert((StackLevel > 0 && I != EndI) || (StackLevel == 0 && I == EndI));
}
+ void setOrderedToBlockAssociated() {
+ assert(getCurrentDirective() == OMPD_ordered_standalone);
+ getTopOfStack().Directive = OMPD_ordered_blockassoc;
+ }
};
bool isImplicitTaskingRegion(OpenMPDirectiveKind DKind) {
@@ -4617,6 +4621,10 @@ static void processCapturedRegions(Sema &SemaRef, OpenMPDirectiveKind DKind,
void SemaOpenMP::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind,
Scope *CurScope) {
+ if (DKind == OMPD_ordered_blockassoc &&
+ DSAStack->getCurrentDirective() == OMPD_ordered_standalone) {
+ DSAStack->setOrderedToBlockAssociated();
+ }
switch (DKind) {
case OMPD_atomic:
case OMPD_critical:
@@ -5040,8 +5048,8 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
return true;
}
if (isOpenMPSimdDirective(ParentRegion) &&
- ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
- (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
+ ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered_blockassoc) ||
+ (OMPVersion >= 50 && CurrentRegion != OMPD_ordered_blockassoc &&
CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
CurrentRegion != OMPD_scan))) {
// OpenMP [2.16, Nesting of Regions]
@@ -5165,12 +5173,13 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// OpenMP 5.1 [2.22, Nesting of Regions]
// A barrier region may not be closely nested inside a worksharing, loop,
// task, taskloop, critical, ordered, atomic, or masked region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPGenericLoopDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- llvm::is_contained({OMPD_masked, OMPD_master,
- OMPD_critical, OMPD_ordered},
- EnclosingConstruct);
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPGenericLoopDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ llvm::is_contained(
+ {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
+ EnclosingConstruct);
} else if (isOpenMPWorksharingDirective(CurrentRegion) &&
!isOpenMPParallelDirective(CurrentRegion) &&
!isOpenMPTeamsDirective(CurrentRegion)) {
@@ -5178,14 +5187,16 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
// A loop region that binds to a parallel region or a worksharing region
// may not be closely nested inside a worksharing, loop, task, taskloop,
// critical, ordered, atomic, or masked region.
- NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) ||
- isOpenMPGenericLoopDirective(ParentRegion) ||
- isOpenMPTaskingDirective(ParentRegion) ||
- llvm::is_contained({OMPD_masked, OMPD_master,
- OMPD_critical, OMPD_ordered},
- EnclosingConstruct);
+ NestingProhibited =
+ isOpenMPWorksharingDirective(ParentRegion) ||
+ isOpenMPGenericLoopDirective(ParentRegion) ||
+ isOpenMPTaskingDirective(ParentRegion) ||
+ llvm::is_contained(
+ {OMPD_masked, OMPD_master, OMPD_critical, OMPD_ordered_blockassoc},
+ EnclosingConstruct);
Recommend = ShouldBeInParallelRegion;
- } else if (CurrentRegion == OMPD_ordered) {
+ } else if (CurrentRegion == OMPD_ordered_blockassoc ||
+ CurrentRegion == OMPD_ordered_standalone) {
// OpenMP [2.16, Nesting of Regions]
// An ordered region may not be closely nested inside a critical,
// atomic, or explicit task region.
@@ -6584,7 +6595,8 @@ StmtResult SemaOpenMP::ActOnOpenMPExecutableDirective(
"No associated statement allowed for 'omp scan' directive");
Res = ActOnOpenMPScanDirective(ClausesWithImplicit, StartLoc, EndLoc);
break;
- case OMPD_ordered:
+ case OMPD_ordered_blockassoc:
+ case OMPD_ordered_standalone:
Res = ActOnOpenMPOrderedDirective(ClausesWithImplicit, AStmt, StartLoc,
EndLoc);
break;
@@ -11744,7 +11756,8 @@ SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
unsigned OMPVersion = getLangOpts().OpenMP;
Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
- << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
+ << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+ OMPVersion)
<< getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
<< 2;
ErrorFound = true;
@@ -22297,7 +22310,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
SourceLocation EndLoc) {
OpenMPDependClauseKind DepKind = Data.DepKind;
SourceLocation DepLoc = Data.DepLoc;
- if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
Diag(DepLoc, diag::err_omp_unexpected_clause_value)
<< "'source' or 'sink'" << getOpenMPClauseNameForDiag(OMPC_depend);
@@ -22308,7 +22321,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPDependClause(
Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
return nullptr;
}
- if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
+ if ((DSAStack->getCurrentDirective() != OMPD_ordered_standalone ||
DSAStack->getCurrentDirective() == OMPD_depobj) &&
(DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
DepKind == OMPC_DEPEND_sink ||
@@ -26292,7 +26305,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPDoacrossClause(
SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
- if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ if (DSAStack->getCurrentDirective() == OMPD_ordered_standalone &&
DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink &&
DepType != OMPC_DOACROSS_sink_omp_cur_iteration &&
DepType != OMPC_DOACROSS_source_omp_cur_iteration) {
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 2083fcd372e81..db2d24fdbfcce 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -10284,7 +10284,7 @@ StmtResult
TreeTransform<Derived>::TransformOMPOrderedDirective(OMPOrderedDirective *D) {
DeclarationNameInfo DirName;
getDerived().getSema().OpenMP().StartOpenMPDSABlock(
- OMPD_ordered, DirName, nullptr, D->getBeginLoc());
+ D->getDirectiveKind(), DirName, nullptr, D->getBeginLoc());
StmtResult Res = getDerived().TransformOMPExecutableDirective(D);
getDerived().getSema().OpenMP().EndOpenMPDSABlock(Res.get());
return Res;
diff --git a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
index 62e24825111f6..3f743e27ea37f 100644
--- a/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
+++ b/llvm/lib/Frontend/OpenMP/DirectiveNameParser.cpp
@@ -19,10 +19,12 @@ namespace llvm::omp {
DirectiveNameParser::DirectiveNameParser(SourceLanguage L) {
// Take every directive, get its name in every version, break the name up
// into whitespace-separated tokens, and insert each token.
- for (size_t I : llvm::seq<size_t>(Directive_enumSize)) {
- auto D = static_cast<Directive>(I);
+ for (Directive D : directives()) {
if (D == Directive::OMPD_unknown || !(getDirectiveLanguages(D) & L))
continue;
+ // Parse "ORDERED" as OMPD_ordered_standalone.
+ if (D == OMPD_ordered_blockassoc)
+ continue;
for (unsigned Ver : getOpenMPVersions())
insertName(getOpenMPDirectiveName(D, Ver), D);
}
>From eb7cf575bf5badf622b1a81f25f3c734e70ac7af Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 7 Aug 2026 08:58:46 -0500
Subject: [PATCH 2/4] Add comment
---
clang/include/clang/AST/StmtOpenMP.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index 2d0cfb1580aeb..dedf90b248bc7 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -554,6 +554,8 @@ class OMPExecutableDirective : public Stmt {
}
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
+ /// Horrible temporary hack to allow OMPOrderedDirective to be used
+ /// with both OMPD_ordered_standalone and OMPD_ordered_blockassoc.
void setDirectiveKind(OpenMPDirectiveKind D) const {
const_cast<OMPExecutableDirective *>(this)->Kind = D;
}
>From 007ba20080e5fb07e3d727da3f2006679d34b59e Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 7 Aug 2026 11:04:12 -0500
Subject: [PATCH 3/4] Avoid horrible hack by using separate opcodes for the two
ordered kinds
---
clang/bindings/python/clang/cindex.py | 7 +++++--
clang/include/clang-c/Index.h | 8 ++++++--
clang/include/clang/AST/StmtOpenMP.h | 15 +++++----------
.../include/clang/Serialization/ASTBitCodes.h | 3 ++-
clang/lib/AST/StmtOpenMP.cpp | 19 +++++++++----------
clang/lib/Serialization/ASTReaderStmt.cpp | 12 +++++++++---
clang/lib/Serialization/ASTWriterStmt.cpp | 4 +++-
clang/tools/libclang/CIndex.cpp | 3 ++-
clang/tools/libclang/CXCursor.cpp | 3 ++-
9 files changed, 43 insertions(+), 31 deletions(-)
diff --git a/clang/bindings/python/clang/cindex.py b/clang/bindings/python/clang/cindex.py
index 126c7bf44d1d1..bc00dd770ce3b 100644
--- a/clang/bindings/python/clang/cindex.py
+++ b/clang/bindings/python/clang/cindex.py
@@ -1261,8 +1261,8 @@ def is_unexposed(self):
# Windows Structured Exception Handling's leave statement.
SEH_LEAVE_STMT = 247
- # OpenMP ordered directive.
- OMP_ORDERED_DIRECTIVE = 248
+ # OpenMP ordered-standalone directive.
+ OMP_ORDERED_STANDALONE_DIRECTIVE = 248
# OpenMP atomic directive.
OMP_ATOMIC_DIRECTIVE = 249
@@ -1456,6 +1456,9 @@ def is_unexposed(self):
# OpenMP split directive.
OMP_SPLIT_DIRECTIVE = 312
+ # OpenMP ordered-blockassoc directive.
+ OMP_ORDERED_BLOCK_ASSOC_DIRECTIVE = 313
+
# OpenACC Compute Construct.
OPEN_ACC_COMPUTE_DIRECTIVE = 320
diff --git a/clang/include/clang-c/Index.h b/clang/include/clang-c/Index.h
index 8427236e0b444..1c8d097f1beab 100644
--- a/clang/include/clang-c/Index.h
+++ b/clang/include/clang-c/Index.h
@@ -1910,9 +1910,9 @@ enum CXCursorKind {
*/
CXCursor_SEHLeaveStmt = 247,
- /** OpenMP ordered directive.
+ /** OpenMP ordered-standalone directive.
*/
- CXCursor_OMPOrderedDirective = 248,
+ CXCursor_OMPOrderedStandaloneDirective = 248,
/** OpenMP atomic directive.
*/
@@ -2170,6 +2170,10 @@ enum CXCursorKind {
*/
CXCursor_OMPSplitDirective = 312,
+ /** OpenMP ordered-blockassoc directive.
+ */
+ CXCursor_OMPOrderedBlockAssocDirective = 313,
+
/** OpenACC Compute Construct.
*/
CXCursor_OpenACCComputeConstruct = 320,
diff --git a/clang/include/clang/AST/StmtOpenMP.h b/clang/include/clang/AST/StmtOpenMP.h
index dedf90b248bc7..076a28021bfda 100644
--- a/clang/include/clang/AST/StmtOpenMP.h
+++ b/clang/include/clang/AST/StmtOpenMP.h
@@ -554,11 +554,6 @@ class OMPExecutableDirective : public Stmt {
}
OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
- /// Horrible temporary hack to allow OMPOrderedDirective to be used
- /// with both OMPD_ordered_standalone and OMPD_ordered_blockassoc.
- void setDirectiveKind(OpenMPDirectiveKind D) const {
- const_cast<OMPExecutableDirective *>(this)->Kind = D;
- }
static bool classof(const Stmt *S) {
return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
@@ -2950,16 +2945,16 @@ class OMPOrderedDirective : public OMPExecutableDirective {
/// \param StartLoc Starting location of the directive kind.
/// \param EndLoc Ending location of the directive.
///
- OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
+ OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc,
+ OpenMPDirectiveKind OrderedKind)
: OMPExecutableDirective(OMPOrderedDirectiveClass,
- llvm::omp::OMPD_ordered_standalone, StartLoc,
+ OrderedKind, StartLoc,
EndLoc) {}
/// Build an empty directive.
///
- explicit OMPOrderedDirective()
- : OMPExecutableDirective(OMPOrderedDirectiveClass,
- llvm::omp::OMPD_ordered_standalone,
+ explicit OMPOrderedDirective(OpenMPDirectiveKind OrderedKind)
+ : OMPExecutableDirective(OMPOrderedDirectiveClass, OrderedKind,
SourceLocation(), SourceLocation()) {}
public:
diff --git a/clang/include/clang/Serialization/ASTBitCodes.h b/clang/include/clang/Serialization/ASTBitCodes.h
index 7dee847e44410..b582cbdadc070 100644
--- a/clang/include/clang/Serialization/ASTBitCodes.h
+++ b/clang/include/clang/Serialization/ASTBitCodes.h
@@ -2004,7 +2004,8 @@ enum StmtCode {
STMT_OMP_FLUSH_DIRECTIVE,
STMT_OMP_DEPOBJ_DIRECTIVE,
STMT_OMP_SCAN_DIRECTIVE,
- STMT_OMP_ORDERED_DIRECTIVE,
+ STMT_OMP_ORDERED_STANDALONE_DIRECTIVE,
+ STMT_OMP_ORDERED_BLOCK_ASSOC_DIRECTIVE,
STMT_OMP_ATOMIC_DIRECTIVE,
STMT_OMP_TARGET_DIRECTIVE,
STMT_OMP_TARGET_DATA_DIRECTIVE,
diff --git a/clang/lib/AST/StmtOpenMP.cpp b/clang/lib/AST/StmtOpenMP.cpp
index e4144cb544a9d..252b5d60ff6dc 100644
--- a/clang/lib/AST/StmtOpenMP.cpp
+++ b/clang/lib/AST/StmtOpenMP.cpp
@@ -1062,23 +1062,22 @@ OMPOrderedDirective *OMPOrderedDirective::Create(const ASTContext &C,
SourceLocation EndLoc,
ArrayRef<OMPClause *> Clauses,
Stmt *AssociatedStmt) {
- auto *D = createDirective<OMPOrderedDirective>(
+ OpenMPDirectiveKind DKind =
+ AssociatedStmt ? OMPD_ordered_blockassoc : OMPD_ordered_standalone;
+ return createDirective<OMPOrderedDirective>(
C, Clauses, cast_or_null<CapturedStmt>(AssociatedStmt),
- /*NumChildren=*/0, StartLoc, EndLoc);
- if (AssociatedStmt)
- D->setDirectiveKind(OMPD_ordered_blockassoc);
- return D;
+ /*NumChildren=*/0, StartLoc, EndLoc, DKind);
}
OMPOrderedDirective *OMPOrderedDirective::CreateEmpty(const ASTContext &C,
unsigned NumClauses,
bool IsStandalone,
EmptyShell) {
- auto *D =
- createEmptyDirective<OMPOrderedDirective>(C, NumClauses, !IsStandalone);
- if (!IsStandalone)
- D->setDirectiveKind(OMPD_ordered_blockassoc);
- return D;
+ OpenMPDirectiveKind DKind =
+ !IsStandalone ? OMPD_ordered_blockassoc : OMPD_ordered_standalone;
+
+ return createEmptyDirective<OMPOrderedDirective>(C, NumClauses, !IsStandalone,
+ /*NumChildren=*/0, DKind);
}
OMPAtomicDirective *
diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp
index 6cde6c1816dc7..c25e77779589b 100644
--- a/clang/lib/Serialization/ASTReaderStmt.cpp
+++ b/clang/lib/Serialization/ASTReaderStmt.cpp
@@ -3877,11 +3877,17 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) {
Context, Record[ASTStmtReader::NumStmtFields], Empty);
break;
- case STMT_OMP_ORDERED_DIRECTIVE: {
+ case STMT_OMP_ORDERED_STANDALONE_DIRECTIVE: {
unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
- bool HasAssociatedStmt = Record[ASTStmtReader::NumStmtFields + 2];
S = OMPOrderedDirective::CreateEmpty(Context, NumClauses,
- !HasAssociatedStmt, Empty);
+ /*IsStandalone=*/true, Empty);
+ break;
+ }
+
+ case STMT_OMP_ORDERED_BLOCK_ASSOC_DIRECTIVE: {
+ unsigned NumClauses = Record[ASTStmtReader::NumStmtFields];
+ S = OMPOrderedDirective::CreateEmpty(Context, NumClauses,
+ /*IsStandalone=*/false, Empty);
break;
}
diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp
index 10443d42df8c0..bfa755ba8abeb 100644
--- a/clang/lib/Serialization/ASTWriterStmt.cpp
+++ b/clang/lib/Serialization/ASTWriterStmt.cpp
@@ -2796,7 +2796,9 @@ void ASTStmtWriter::VisitOMPScanDirective(OMPScanDirective *D) {
void ASTStmtWriter::VisitOMPOrderedDirective(OMPOrderedDirective *D) {
VisitStmt(D);
VisitOMPExecutableDirective(D);
- Code = serialization::STMT_OMP_ORDERED_DIRECTIVE;
+ Code = D->getDirectiveKind() == llvm::omp::OMPD_ordered_standalone
+ ? serialization::STMT_OMP_ORDERED_STANDALONE_DIRECTIVE
+ : serialization::STMT_OMP_ORDERED_BLOCK_ASSOC_DIRECTIVE;
}
void ASTStmtWriter::VisitOMPTeamsDirective(OMPTeamsDirective *D) {
diff --git a/clang/tools/libclang/CIndex.cpp b/clang/tools/libclang/CIndex.cpp
index 034f89029122c..418824caa007d 100644
--- a/clang/tools/libclang/CIndex.cpp
+++ b/clang/tools/libclang/CIndex.cpp
@@ -6389,7 +6389,8 @@ CXString clang_getCursorKindSpelling(enum CXCursorKind Kind) {
return cxstring::createRef("OMPDepobjDirective");
case CXCursor_OMPScanDirective:
return cxstring::createRef("OMPScanDirective");
- case CXCursor_OMPOrderedDirective:
+ case CXCursor_OMPOrderedStandaloneDirective:
+ case CXCursor_OMPOrderedBlockAssocDirective:
return cxstring::createRef("OMPOrderedDirective");
case CXCursor_OMPAtomicDirective:
return cxstring::createRef("OMPAtomicDirective");
diff --git a/clang/tools/libclang/CXCursor.cpp b/clang/tools/libclang/CXCursor.cpp
index fb0b3c1502574..9f60db71b061d 100644
--- a/clang/tools/libclang/CXCursor.cpp
+++ b/clang/tools/libclang/CXCursor.cpp
@@ -776,7 +776,8 @@ CXCursor cxcursor::MakeCXCursor(const Stmt *S, const Decl *Parent,
K = CXCursor_OMPScanDirective;
break;
case Stmt::OMPOrderedDirectiveClass:
- K = CXCursor_OMPOrderedDirective;
+ // FIXME: Pick the right one once the class is split into two.
+ K = CXCursor_OMPOrderedStandaloneDirective;
break;
case Stmt::OMPAtomicDirectiveClass:
K = CXCursor_OMPAtomicDirective;
>From 2ec728d816bdba1f6ea58acb4a27aef8ce237fef Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 7 Aug 2026 11:22:26 -0500
Subject: [PATCH 4/4] Update clang/lib/Parse/ParseOpenMP.cpp
Co-authored-by: Alexey Bataev <a.bataev at outlook.com>
---
clang/lib/Parse/ParseOpenMP.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 616bd87124210..d6fb4202275d8 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -3230,7 +3230,7 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
bool WrongDirective = false;
unsigned OMPVersion = Actions.getLangOpts().OpenMP;
- auto checkClauseValid = [&](OpenMPDirectiveKind D, OpenMPClauseKind C) {
+ auto CheckClauseValid = [&](OpenMPDirectiveKind D, OpenMPClauseKind C) {
if (!isAllowedClauseForDirective(D, C, OMPVersion)) {
Diag(Tok, diag::err_omp_unexpected_clause)
<< getOpenMPClauseName(C) << getOpenMPDirectiveName(D, OMPVersion);
More information about the llvm-branch-commits
mailing list