https://github.com/kparzysz updated 
https://github.com/llvm/llvm-project/pull/139115

>From fa6e19481f448db273f84d270891e737ff021749 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Wed, 7 May 2025 15:32:08 -0500
Subject: [PATCH 1/6] [clang][OpenMP] Pass OpenMP version to
 getOpenMPDirectiveName

The OpenMP version is stored in language options in Sema. For use in
objects that do not have access to Sema, add OpenMP version field to
PrintingPolicy, giving it 8 bits.

RFC: 
https://discourse.llvm.org/t/rfc-alternative-spellings-of-openmp-directives/85507
---
 clang/include/clang/AST/PrettyPrinter.h |   6 +-
 clang/lib/AST/OpenMPClause.cpp          |   7 +-
 clang/lib/AST/StmtPrinter.cpp           |   4 +-
 clang/lib/Basic/OpenMPKinds.cpp         |   3 +-
 clang/lib/Parse/ParseOpenMP.cpp         | 128 +++++++++++-------
 clang/lib/Sema/SemaOpenMP.cpp           | 167 +++++++++++++++---------
 clang/lib/Sema/TreeTransform.h          |   3 +-
 7 files changed, 202 insertions(+), 116 deletions(-)

diff --git a/clang/include/clang/AST/PrettyPrinter.h 
b/clang/include/clang/AST/PrettyPrinter.h
index 5a98ae1987b16..1f64466956b66 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -59,7 +59,7 @@ struct PrintingPolicy {
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
-      : Indentation(2), SuppressSpecifiers(false),
+      : Indentation(2), OpenMP(LO.OpenMP), SuppressSpecifiers(false),
         SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
         SuppressScope(false), SuppressUnwrittenScope(false),
         SuppressInlineNamespace(SuppressInlineNamespaceMode::Redundant),
@@ -94,6 +94,10 @@ struct PrintingPolicy {
   /// The number of spaces to use to indent each line.
   unsigned Indentation : 8;
 
+  /// Version of the effective OpenMP spec (used to select directive name
+  /// spelling).
+  unsigned OpenMP : 8;
+
   /// Whether we should suppress printing of the actual specifiers for
   /// the given type or declaration.
   ///
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 2226791a70b6e..5ed04d250f5a1 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1821,7 +1821,8 @@ OMPThreadLimitClause 
*OMPThreadLimitClause::CreateEmpty(const ASTContext &C,
 void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
   OS << "if(";
   if (Node->getNameModifier() != OMPD_unknown)
-    OS << getOpenMPDirectiveName(Node->getNameModifier()) << ": ";
+    OS << getOpenMPDirectiveName(Node->getNameModifier(), Policy.OpenMP)
+       << ": ";
   Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
   OS << ")";
 }
@@ -2049,7 +2050,7 @@ void 
OMPClausePrinter::VisitOMPAbsentClause(OMPAbsentClause *Node) {
   for (auto &D : Node->getDirectiveKinds()) {
     if (!First)
       OS << ", ";
-    OS << getOpenMPDirectiveName(D);
+    OS << getOpenMPDirectiveName(D, Policy.OpenMP);
     First = false;
   }
   OS << ")";
@@ -2067,7 +2068,7 @@ void 
OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
   for (auto &D : Node->getDirectiveKinds()) {
     if (!First)
       OS << ", ";
-    OS << getOpenMPDirectiveName(D);
+    OS << getOpenMPDirectiveName(D, Policy.OpenMP);
     First = false;
   }
   OS << ")";
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index c6c49c6c1ba4d..53f7bb2f64249 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -965,13 +965,13 @@ void 
StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
 void StmtPrinter::VisitOMPCancellationPointDirective(
     OMPCancellationPointDirective *Node) {
   Indent() << "#pragma omp cancellation point "
-           << getOpenMPDirectiveName(Node->getCancelRegion());
+           << getOpenMPDirectiveName(Node->getCancelRegion(), Policy.OpenMP);
   PrintOMPExecutableDirective(Node);
 }
 
 void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
   Indent() << "#pragma omp cancel "
-           << getOpenMPDirectiveName(Node->getCancelRegion());
+           << getOpenMPDirectiveName(Node->getCancelRegion(), Policy.OpenMP);
   PrintOMPExecutableDirective(Node);
 }
 
diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp
index 7b90861c78de0..a451fc7c01841 100644
--- a/clang/lib/Basic/OpenMPKinds.cpp
+++ b/clang/lib/Basic/OpenMPKinds.cpp
@@ -850,7 +850,8 @@ void clang::getOpenMPCaptureRegions(
     case OMPD_master:
       return false;
     default:
-      llvm::errs() << getOpenMPDirectiveName(LKind) << '\n';
+      llvm::errs() << getOpenMPDirectiveName(LKind, llvm::omp::FallbackVersion)
+                   << '\n';
       llvm_unreachable("Unexpected directive");
     }
     return false;
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 8d8698e61216f..4f87d6c74b251 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -288,11 +288,12 @@ static DeclarationName parseOpenMPReductionId(Parser &P) {
 ///
 Parser::DeclGroupPtrTy
 Parser::ParseOpenMPDeclareReductionDirective(AccessSpecifier AS) {
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   // Parse '('.
   BalancedDelimiterTracker T(*this, tok::l_paren, 
tok::annot_pragma_openmp_end);
   if (T.expectAndConsume(
           diag::err_expected_lparen_after,
-          getOpenMPDirectiveName(OMPD_declare_reduction).data())) {
+          getOpenMPDirectiveName(OMPD_declare_reduction, OMPVersion).data())) {
     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
     return DeclGroupPtrTy();
   }
@@ -540,10 +541,12 @@ void 
Parser::ParseOpenMPReductionInitializerForDecl(VarDecl *OmpPrivParm) {
 Parser::DeclGroupPtrTy
 Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier AS) {
   bool IsCorrect = true;
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   // Parse '('
   BalancedDelimiterTracker T(*this, tok::l_paren, 
tok::annot_pragma_openmp_end);
-  if (T.expectAndConsume(diag::err_expected_lparen_after,
-                         getOpenMPDirectiveName(OMPD_declare_mapper).data())) {
+  if (T.expectAndConsume(
+          diag::err_expected_lparen_after,
+          getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion).data())) {
     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
     return DeclGroupPtrTy();
   }
@@ -626,7 +629,7 @@ Parser::ParseOpenMPDeclareMapperDirective(AccessSpecifier 
AS) {
   }
   if (Clauses.empty()) {
     Diag(Tok, diag::err_omp_expected_clause)
-        << getOpenMPDirectiveName(OMPD_declare_mapper);
+        << getOpenMPDirectiveName(OMPD_declare_mapper, OMPVersion);
     IsCorrect = false;
   }
 
@@ -745,8 +748,10 @@ static bool parseDeclareSimdClauses(
       P.ConsumeToken();
     } else if (ClauseName == "simdlen") {
       if (SimdLen.isUsable()) {
+        unsigned OMPVersion = P.getActions().getLangOpts().OpenMP;
         P.Diag(Tok, diag::err_omp_more_one_clause)
-            << getOpenMPDirectiveName(OMPD_declare_simd) << ClauseName << 0;
+            << getOpenMPDirectiveName(OMPD_declare_simd, OMPVersion)
+            << ClauseName << 0;
         IsError = true;
       }
       P.ConsumeToken();
@@ -1404,6 +1409,7 @@ bool Parser::parseOMPContextSelectors(SourceLocation Loc, 
OMPTraitInfo &TI) {
 void Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
                                            CachedTokens &Toks,
                                            SourceLocation Loc) {
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   PP.EnterToken(Tok, /*IsReinject*/ true);
   PP.EnterTokenStream(Toks, /*DisableMacroExpansion=*/true,
                       /*IsReinject*/ true);
@@ -1423,7 +1429,7 @@ void 
Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
     EnterExpressionEvaluationContext Unevaluated(
         Actions, Sema::ExpressionEvaluationContext::Unevaluated);
     AssociatedFunction = ParseOpenMPParensExpr(
-        getOpenMPDirectiveName(OMPD_declare_variant), RLoc,
+        getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion), RLoc,
         /*IsAddressOfOperand=*/true);
   }
   if (!AssociatedFunction.isUsable()) {
@@ -1483,7 +1489,7 @@ void 
Parser::ParseOMPDeclareVariantClauses(Parser::DeclGroupPtrTy Ptr,
       case OMPC_append_args:
         if (!AppendArgs.empty()) {
           Diag(AppendArgsLoc, diag::err_omp_more_one_clause)
-              << getOpenMPDirectiveName(OMPD_declare_variant)
+              << getOpenMPDirectiveName(OMPD_declare_variant, OMPVersion)
               << getOpenMPClauseName(CKind) << 0;
           IsError = true;
         }
@@ -1740,8 +1746,9 @@ void 
Parser::ParseOpenMPAssumesDirective(OpenMPDirectiveKind DKind,
     bool NextIsLPar = Tok.is(tok::l_paren);
     // Handle unknown clauses by skipping them.
     if (Idx == -1) {
+      unsigned OMPVersion = Actions.getLangOpts().OpenMP;
       Diag(StartLoc, diag::warn_omp_unknown_assumption_clause_missing_id)
-          << llvm::omp::getOpenMPDirectiveName(DKind)
+          << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion)
           << llvm::omp::getAllAssumeClauseOptions() << NextIsLPar;
       if (NextIsLPar)
         SkipBraces(II ? II->getName() : "", /* IssueNote */ true);
@@ -1854,8 +1861,9 @@ void Parser::ParseOMPDeclareTargetClauses(
       bool IsIndirectClause = getLangOpts().OpenMP >= 51 &&
                               getOpenMPClauseKind(ClauseName) == OMPC_indirect;
       if (DTCI.Indirect && IsIndirectClause) {
+        unsigned OMPVersion = Actions.getLangOpts().OpenMP;
         Diag(Tok, diag::err_omp_more_one_clause)
-            << getOpenMPDirectiveName(OMPD_declare_target)
+            << getOpenMPDirectiveName(OMPD_declare_target, OMPVersion)
             << getOpenMPClauseName(OMPC_indirect) << 0;
         break;
       }
@@ -1988,8 +1996,9 @@ void Parser::skipUntilPragmaOpenMPEnd(OpenMPDirectiveKind 
DKind) {
   if (Tok.is(tok::annot_pragma_openmp_end))
     return;
 
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   Diag(Tok, diag::warn_omp_extra_tokens_at_eol)
-      << getOpenMPDirectiveName(DKind);
+      << getOpenMPDirectiveName(DKind, OMPVersion);
   while (Tok.isNot(tok::annot_pragma_openmp_end))
     ConsumeAnyToken();
 }
@@ -2008,10 +2017,12 @@ void Parser::parseOMPEndDirective(OpenMPDirectiveKind 
BeginKind,
     return;
   }
 
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   Diag(FoundLoc, diag::err_expected_end_declare_target_or_variant)
       << DiagSelection;
   Diag(BeginLoc, diag::note_matching)
-      << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind) + "'").str();
+      << ("'#pragma omp " + getOpenMPDirectiveName(BeginKind, OMPVersion) + 
"'")
+             .str();
   if (SkipUntilOpenMPEnd)
     SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch);
 }
@@ -2070,6 +2081,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
          "Not an OpenMP directive!");
   ParsingOpenMPDirectiveRAII DirScope(*this);
   ParenBraceBracketBalancer BalancerRAIIObj(*this);
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
 
   SourceLocation Loc;
   OpenMPDirectiveKind DKind;
@@ -2163,7 +2175,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
     llvm::SmallBitVector SeenClauses(llvm::omp::Clause_enumSize + 1);
     if (Tok.is(tok::annot_pragma_openmp_end)) {
       Diag(Tok, diag::err_omp_expected_clause)
-          << getOpenMPDirectiveName(OMPD_requires);
+          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
       break;
     }
     while (Tok.isNot(tok::annot_pragma_openmp_end)) {
@@ -2190,7 +2202,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
     // Consume final annot_pragma_openmp_end
     if (Clauses.empty()) {
       Diag(Tok, diag::err_omp_expected_clause)
-          << getOpenMPDirectiveName(OMPD_requires);
+          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
       ConsumeAnnotationToken();
       return nullptr;
     }
@@ -2378,7 +2390,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
   case OMPD_end_declare_target: {
     if (!Actions.OpenMP().isInOpenMPDeclareTargetContext()) {
       Diag(Tok, diag::err_omp_unexpected_directive)
-          << 1 << getOpenMPDirectiveName(DKind);
+          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
       break;
     }
     const SemaOpenMP::DeclareTargetContextInfo &DTCI =
@@ -2388,7 +2400,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
   }
   case OMPD_assume: {
     Diag(Tok, diag::err_omp_unexpected_directive)
-        << 1 << getOpenMPDirectiveName(DKind);
+        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
     break;
   }
   case OMPD_unknown:
@@ -2401,7 +2413,7 @@ Parser::DeclGroupPtrTy 
Parser::ParseOpenMPDeclarativeDirectiveWithExtDecl(
     case Category::Subsidiary:
     case Category::Utility:
       Diag(Tok, diag::err_omp_unexpected_directive)
-          << 1 << getOpenMPDirectiveName(DKind);
+          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
       break;
     case Category::Declarative:
     case Category::Informational:
@@ -2418,6 +2430,7 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
     ParsedStmtContext StmtCtx, OpenMPDirectiveKind DKind, SourceLocation Loc,
     bool ReadDirectiveWithinMetadirective) {
   assert(isOpenMPExecutableDirective(DKind) && "Unexpected directive 
category");
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
 
   bool HasAssociatedStatement = true;
   Association Assoc = getDirectiveAssociation(DKind);
@@ -2431,7 +2444,7 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
-          << getOpenMPDirectiveName(DKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
       if (DKind == OMPD_error) {
         SkipUntil(tok::annot_pragma_openmp_end);
         return StmtError();
@@ -2541,7 +2554,8 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
         if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
             ParsedStmtContext()) {
           Diag(Loc, diag::err_omp_immediate_directive)
-              << getOpenMPDirectiveName(DKind) << 1 << getOpenMPClauseName(CK);
+              << getOpenMPDirectiveName(DKind, OMPVersion) << 1
+              << getOpenMPClauseName(CK);
         }
         HasAssociatedStatement = false;
       }
@@ -2551,7 +2565,7 @@ StmtResult Parser::ParseOpenMPExecutableDirective(
   if ((DKind == OMPD_tile || DKind == OMPD_stripe) &&
       !SeenClauses[unsigned(OMPC_sizes)]) {
     Diag(Loc, diag::err_omp_required_clause)
-        << getOpenMPDirectiveName(DKind) << "sizes";
+        << getOpenMPDirectiveName(DKind, OMPVersion) << "sizes";
   }
 
   StmtResult AssociatedStmt;
@@ -2707,6 +2721,7 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
   SourceLocation Loc = ReadDirectiveWithinMetadirective
                            ? Tok.getLocation()
                            : ConsumeAnnotationToken();
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   OpenMPDirectiveKind DKind = parseOpenMPDirectiveKind(*this);
   if (ReadDirectiveWithinMetadirective && DKind == OMPD_unknown) {
     Diag(Tok, diag::err_omp_unknown_directive);
@@ -2909,7 +2924,7 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
-          << getOpenMPDirectiveName(DKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
     }
     ConsumeToken();
     DeclDirectiveListParserHelper Helper(this, DKind);
@@ -2928,7 +2943,7 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
     if ((StmtCtx & ParsedStmtContext::AllowStandaloneOpenMPDirectives) ==
         ParsedStmtContext()) {
       Diag(Tok, diag::err_omp_immediate_directive)
-          << getOpenMPDirectiveName(DKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion) << 0;
     }
     ConsumeToken();
     DeclDirectiveListParserHelper Helper(this, DKind);
@@ -3001,7 +3016,7 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
 
     if (HasImplicitMappings) {
       Diag(Tok, diag::err_omp_unexpected_directive)
-          << 1 << getOpenMPDirectiveName(DKind);
+          << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
       SkipUntil(tok::annot_pragma_openmp_end);
       break;
     }
@@ -3020,7 +3035,7 @@ StmtResult 
Parser::ParseOpenMPDeclarativeOrExecutableDirective(
   case OMPD_end_declare_variant:
   case OMPD_declare_variant:
     Diag(Tok, diag::err_omp_unexpected_directive)
-        << 1 << getOpenMPDirectiveName(DKind);
+        << 1 << getOpenMPDirectiveName(DKind, OMPVersion);
     SkipUntil(tok::annot_pragma_openmp_end);
     break;
   case OMPD_assume: {
@@ -3049,10 +3064,11 @@ bool Parser::ParseOpenMPSimpleVarList(
     const llvm::function_ref<void(CXXScopeSpec &, DeclarationNameInfo)>
         &Callback,
     bool AllowScopeSpecifier) {
+  unsigned OMPVersion = Actions.getLangOpts().OpenMP;
   // Parse '('.
   BalancedDelimiterTracker T(*this, tok::l_paren, 
tok::annot_pragma_openmp_end);
   if (T.expectAndConsume(diag::err_expected_lparen_after,
-                         getOpenMPDirectiveName(Kind).data()))
+                         getOpenMPDirectiveName(Kind, OMPVersion).data()))
     return true;
   bool IsCorrect = true;
   bool NoIdentIsFound = true;
@@ -3205,11 +3221,14 @@ OMPClause 
*Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
   OMPClause *Clause = nullptr;
   bool ErrorFound = false;
   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);
+        << getOpenMPClauseName(CKind)
+        << getOpenMPDirectiveName(DKind, OMPVersion);
     ErrorFound = true;
     WrongDirective = true;
   }
@@ -3264,7 +3283,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
     // At most one message clause can appear on the directive
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
 
@@ -3298,7 +3318,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
     // At most one bind clause can appear on a loop directive.
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
 
@@ -3320,7 +3341,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
     if ((getLangOpts().OpenMP < 50 || CKind != OMPC_defaultmap) &&
         (CKind != OMPC_order || getLangOpts().OpenMP >= 51) && !FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
     [[fallthrough]];
@@ -3359,7 +3381,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
     //   Each of the requires clauses can appear at most once on the directive.
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
 
@@ -3369,12 +3392,13 @@ OMPClause 
*Parser::ParseOpenMPClause(OpenMPDirectiveKind DKind,
     // OpenMP [6.0, self_maps clause]
     if (getLangOpts().OpenMP < 60) {
       Diag(Tok, diag::err_omp_expected_clause)
-          << getOpenMPDirectiveName(OMPD_requires);
+          << getOpenMPDirectiveName(OMPD_requires, OMPVersion);
       ErrorFound = true;
     }
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
     Clause = ParseOpenMPClause(CKind, WrongDirective);
@@ -3382,7 +3406,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_update:
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
 
@@ -3394,7 +3419,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_thread_limit:
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
     [[fallthrough]];
@@ -3433,7 +3459,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_sizes:
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
 
@@ -3442,7 +3469,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_permutation:
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
     Clause = ParseOpenMPPermutationClause();
@@ -3454,7 +3482,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
     if (DKind != OMPD_interop) {
       if (!FirstClause) {
         Diag(Tok, diag::err_omp_more_one_clause)
-            << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 
0;
+            << getOpenMPDirectiveName(DKind, OMPVersion)
+            << getOpenMPClauseName(CKind) << 0;
         ErrorFound = true;
       }
       Clause = ParseOpenMPClause(CKind, WrongDirective);
@@ -3474,7 +3503,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_match:
     if (!WrongDirective)
       Diag(Tok, diag::err_omp_unexpected_clause)
-          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+          << getOpenMPClauseName(CKind)
+          << getOpenMPDirectiveName(DKind, OMPVersion);
     SkipUntil(tok::comma, tok::annot_pragma_openmp_end, StopBeforeMatch);
     break;
   case OMPC_absent:
@@ -3490,7 +3520,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
       if (DK == OMPD_unknown) {
         skipUntilPragmaOpenMPEnd(OMPD_assume);
         Diag(Tok, diag::err_omp_unexpected_clause)
-            << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+            << getOpenMPClauseName(CKind)
+            << getOpenMPDirectiveName(DKind, OMPVersion);
         break;
       }
       if (isOpenMPExecutableDirective(DK)) {
@@ -3498,7 +3529,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
         ConsumeToken();
       } else {
         Diag(Tok, diag::err_omp_unexpected_clause)
-            << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+            << getOpenMPClauseName(CKind)
+            << getOpenMPDirectiveName(DKind, OMPVersion);
       }
     } while (TryConsumeToken(tok::comma));
     RLoc = Tok.getLocation();
@@ -3513,7 +3545,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
   case OMPC_no_parallelism: {
     if (!FirstClause) {
       Diag(Tok, diag::err_omp_more_one_clause)
-          << getOpenMPDirectiveName(DKind) << getOpenMPClauseName(CKind) << 0;
+          << getOpenMPDirectiveName(DKind, OMPVersion)
+          << getOpenMPClauseName(CKind) << 0;
       ErrorFound = true;
     }
     SourceLocation Loc = ConsumeToken();
@@ -3531,7 +3564,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
       // to explicitly check whether this clause is applied to an `omp target`
       // without `teams` and emit an error.
       Diag(Tok, diag::err_omp_unexpected_clause)
-          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+          << getOpenMPClauseName(CKind)
+          << getOpenMPDirectiveName(DKind, OMPVersion);
       ErrorFound = true;
       WrongDirective = true;
     }
@@ -3540,7 +3574,8 @@ OMPClause *Parser::ParseOpenMPClause(OpenMPDirectiveKind 
DKind,
           << getOpenMPClauseName(CKind) << "target teams";
     if (!ErrorFound && !getLangOpts().OpenMPExtensions) {
       Diag(Tok, diag::err_omp_unexpected_clause_extension_only)
-          << getOpenMPClauseName(CKind) << getOpenMPDirectiveName(DKind);
+          << getOpenMPClauseName(CKind)
+          << getOpenMPDirectiveName(DKind, OMPVersion);
       ErrorFound = true;
     }
     Clause = ParseOpenMPClause(CKind, WrongDirective);
@@ -5077,11 +5112,14 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind 
DKind,
       ConsumeToken();
     else if (Tok.isNot(tok::r_paren) &&
              Tok.isNot(tok::annot_pragma_openmp_end) &&
-             (!MayHaveTail || Tok.isNot(tok::colon)))
+             (!MayHaveTail || Tok.isNot(tok::colon))) {
+      unsigned OMPVersion = Actions.getLangOpts().OpenMP;
       Diag(Tok, diag::err_omp_expected_punc)
-          << ((Kind == OMPC_flush) ? getOpenMPDirectiveName(OMPD_flush)
-                                   : getOpenMPClauseName(Kind))
+          << ((Kind == OMPC_flush)
+                  ? getOpenMPDirectiveName(OMPD_flush, OMPVersion)
+                  : getOpenMPClauseName(Kind))
           << (Kind == OMPC_flush);
+    }
   }
 
   // Parse ')' for linear clause with modifier.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 835dba22a858d..61cc367d18d33 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -3069,6 +3069,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
                                                const DeclarationNameInfo &Id,
                                                OpenMPDirectiveKind Kind) {
   ASTContext &Context = getASTContext();
+  unsigned OMPVersion = getLangOpts().OpenMP;
   LookupResult Lookup(SemaRef, Id, Sema::LookupOrdinaryName);
   SemaRef.LookupParsedName(Lookup, CurScope, &ScopeSpec,
                            /*ObjectType=*/QualType(),
@@ -3106,7 +3107,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
   //   Variables must be file-scope, namespace-scope, or static block-scope.
   if (Kind == OMPD_threadprivate && !VD->hasGlobalStorage()) {
     Diag(Id.getLoc(), diag::err_omp_global_var_arg)
-        << getOpenMPDirectiveName(Kind) << !VD->isStaticLocal();
+        << getOpenMPDirectiveName(Kind, OMPVersion) << !VD->isStaticLocal();
     bool IsDecl =
         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
     Diag(VD->getLocation(),
@@ -3123,7 +3124,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
   if (CanonicalVD->getDeclContext()->isTranslationUnit() &&
       !SemaRef.getCurLexicalContext()->isTranslationUnit()) {
     Diag(Id.getLoc(), diag::err_omp_var_scope)
-        << getOpenMPDirectiveName(Kind) << VD;
+        << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
     bool IsDecl =
         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
     Diag(VD->getLocation(),
@@ -3138,7 +3139,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
   if (CanonicalVD->isStaticDataMember() &&
       !CanonicalVD->getDeclContext()->Equals(SemaRef.getCurLexicalContext())) {
     Diag(Id.getLoc(), diag::err_omp_var_scope)
-        << getOpenMPDirectiveName(Kind) << VD;
+        << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
     bool IsDecl =
         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
     Diag(VD->getLocation(),
@@ -3155,7 +3156,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
        !SemaRef.getCurLexicalContext()->Encloses(
            CanonicalVD->getDeclContext()))) {
     Diag(Id.getLoc(), diag::err_omp_var_scope)
-        << getOpenMPDirectiveName(Kind) << VD;
+        << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
     bool IsDecl =
         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
     Diag(VD->getLocation(),
@@ -3169,7 +3170,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
   if (CanonicalVD->isLocalVarDecl() && CurScope &&
       !SemaRef.isDeclInScope(ND, SemaRef.getCurLexicalContext(), CurScope)) {
     Diag(Id.getLoc(), diag::err_omp_var_scope)
-        << getOpenMPDirectiveName(Kind) << VD;
+        << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
     bool IsDecl =
         VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly;
     Diag(VD->getLocation(),
@@ -3184,7 +3185,7 @@ ExprResult SemaOpenMP::ActOnOpenMPIdExpression(Scope 
*CurScope,
   if (Kind == OMPD_threadprivate && VD->isUsed() &&
       !DSAStack->isThreadPrivate(VD)) {
     Diag(Id.getLoc(), diag::err_omp_var_used)
-        << getOpenMPDirectiveName(Kind) << VD;
+        << getOpenMPDirectiveName(Kind, OMPVersion) << VD;
     return ExprError();
   }
 
@@ -3266,8 +3267,10 @@ SemaOpenMP::CheckOMPThreadPrivateDecl(SourceLocation Loc,
     // OpenMP [2.9.2, Restrictions, C/C++, p.10]
     //   A threadprivate variable must not have a reference type.
     if (VD->getType()->isReferenceType()) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       Diag(ILoc, diag::err_omp_ref_type_arg)
-          << getOpenMPDirectiveName(OMPD_threadprivate) << VD->getType();
+          << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion)
+          << VD->getType();
       bool IsDecl =
           VD->isThisDeclarationADefinition(Context) == 
VarDecl::DeclarationOnly;
       Diag(VD->getLocation(),
@@ -3513,10 +3516,12 @@ void 
SemaOpenMP::ActOnOpenMPAssumesDirective(SourceLocation Loc,
                                              OpenMPDirectiveKind DKind,
                                              ArrayRef<std::string> Assumptions,
                                              bool SkippedClauses) {
-  if (!SkippedClauses && Assumptions.empty())
+  if (!SkippedClauses && Assumptions.empty()) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(Loc, diag::err_omp_no_clause_for_directive)
         << llvm::omp::getAllAssumeClauseOptions()
-        << llvm::omp::getOpenMPDirectiveName(DKind);
+        << llvm::omp::getOpenMPDirectiveName(DKind, OMPVersion);
+  }
 
   auto *AA =
       OMPAssumeAttr::Create(getASTContext(), llvm::join(Assumptions, ","), 
Loc);
@@ -3664,9 +3669,10 @@ static void reportOriginalDsa(Sema &SemaRef, const 
DSAStackTy *Stack,
     Reason = PDSA_LocalVarPrivate;
   }
   if (Reason != PDSA_Implicit) {
+    unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
     SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa)
         << Reason << ReportHint
-        << getOpenMPDirectiveName(Stack->getCurrentDirective());
+        << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
   } else if (DVar.ImplicitDSALoc.isValid()) {
     SemaRef.Diag(DVar.ImplicitDSALoc, diag::note_omp_implicit_dsa)
         << getOpenMPClauseNameForDiag(DVar.CKind);
@@ -4683,8 +4689,9 @@ StmtResult SemaOpenMP::ActOnOpenMPRegionEnd(StmtResult S,
   if (isOpenMPWorksharingDirective(DSAStack->getCurrentDirective()) &&
       isOpenMPSimdDirective(DSAStack->getCurrentDirective()) && OC &&
       OC->getNumForLoops()) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(OC->getBeginLoc(), diag::err_omp_ordered_simd)
-        << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+        << getOpenMPDirectiveName(DSAStack->getCurrentDirective(), OMPVersion);
     ErrorFound = true;
   }
   if (ErrorFound) {
@@ -4764,8 +4771,9 @@ static bool checkCancelRegion(Sema &SemaRef, 
OpenMPDirectiveKind CurrentRegion,
       CancelRegion == OMPD_sections || CancelRegion == OMPD_taskgroup)
     return false;
 
+  unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
   SemaRef.Diag(StartLoc, diag::err_omp_wrong_cancel_region)
-      << getOpenMPDirectiveName(CancelRegion);
+      << getOpenMPDirectiveName(CancelRegion, OMPVersion);
   return true;
 }
 
@@ -4796,17 +4804,18 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
   ArrayRef<OpenMPDirectiveKind> ParentLOC =
       getLeafOrCompositeConstructs(ParentRegion, LeafOrComposite);
   OpenMPDirectiveKind EnclosingConstruct = ParentLOC.back();
+  unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
 
-  if (SemaRef.LangOpts.OpenMP >= 50 && Stack->isParentOrderConcurrent() &&
+  if (OMPVersion >= 50 && Stack->isParentOrderConcurrent() &&
       !isOpenMPOrderConcurrentNestableDirective(CurrentRegion,
                                                 SemaRef.LangOpts)) {
     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region_order)
-        << getOpenMPDirectiveName(CurrentRegion);
+        << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
     return true;
   }
   if (isOpenMPSimdDirective(ParentRegion) &&
-      ((SemaRef.LangOpts.OpenMP <= 45 && CurrentRegion != OMPD_ordered) ||
-       (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion != OMPD_ordered &&
+      ((OMPVersion <= 45 && CurrentRegion != OMPD_ordered) ||
+       (OMPVersion >= 50 && CurrentRegion != OMPD_ordered &&
         CurrentRegion != OMPD_simd && CurrentRegion != OMPD_atomic &&
         CurrentRegion != OMPD_scan))) {
     // OpenMP [2.16, Nesting of Regions]
@@ -4824,7 +4833,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     SemaRef.Diag(StartLoc, (CurrentRegion != OMPD_simd)
                                ? diag::err_omp_prohibited_region_simd
                                : diag::warn_omp_nesting_simd)
-        << (SemaRef.LangOpts.OpenMP >= 50 ? 1 : 0);
+        << (OMPVersion >= 50 ? 1 : 0);
     return CurrentRegion != OMPD_simd;
   }
   if (EnclosingConstruct == OMPD_atomic) {
@@ -4841,7 +4850,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     if (EnclosingConstruct != OMPD_sections) {
       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_section_directive)
           << (ParentRegion != OMPD_unknown)
-          << getOpenMPDirectiveName(ParentRegion);
+          << getOpenMPDirectiveName(ParentRegion, OMPVersion);
       return true;
     }
     return false;
@@ -4856,14 +4865,14 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     return false;
   // Checks needed for mapping "loop" construct. Please check mapLoopConstruct
   // for a detailed explanation
-  if (SemaRef.LangOpts.OpenMP >= 50 && CurrentRegion == OMPD_loop &&
+  if (OMPVersion >= 50 && CurrentRegion == OMPD_loop &&
       (BindKind == OMPC_BIND_parallel || BindKind == OMPC_BIND_teams) &&
       (isOpenMPWorksharingDirective(ParentRegion) ||
        EnclosingConstruct == OMPD_loop)) {
     int ErrorMsgNumber = (BindKind == OMPC_BIND_parallel) ? 1 : 4;
     SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
-        << true << getOpenMPDirectiveName(ParentRegion) << ErrorMsgNumber
-        << getOpenMPDirectiveName(CurrentRegion);
+        << true << getOpenMPDirectiveName(ParentRegion, OMPVersion)
+        << ErrorMsgNumber << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
     return true;
   }
   if (CurrentRegion == OMPD_cancellation_point ||
@@ -4882,7 +4891,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     ArrayRef<OpenMPDirectiveKind> Leafs = 
getLeafConstructsOrSelf(ParentRegion);
     if (CancelRegion == OMPD_taskgroup) {
       NestingProhibited = EnclosingConstruct != OMPD_task &&
-                          (SemaRef.getLangOpts().OpenMP < 50 ||
+                          (OMPVersion < 50 ||
                            EnclosingConstruct != OMPD_taskloop);
     } else if (CancelRegion == OMPD_sections) {
       NestingProhibited = EnclosingConstruct != OMPD_section &&
@@ -4969,13 +4978,13 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     // If specified, a teams construct must be contained within a target
     // construct.
     NestingProhibited =
-        (SemaRef.LangOpts.OpenMP <= 45 && EnclosingConstruct != OMPD_target) ||
-        (SemaRef.LangOpts.OpenMP >= 50 && EnclosingConstruct != OMPD_unknown &&
+        (OMPVersion <= 45 && EnclosingConstruct != OMPD_target) ||
+        (OMPVersion >= 50 && EnclosingConstruct != OMPD_unknown &&
          EnclosingConstruct != OMPD_target);
     OrphanSeen = ParentRegion == OMPD_unknown;
     Recommend = ShouldBeInTargetRegion;
   } else if (CurrentRegion == OMPD_scan) {
-    if (SemaRef.LangOpts.OpenMP >= 50) {
+    if (OMPVersion >= 50) {
       // OpenMP spec 5.0 and 5.1 require scan to be directly enclosed by for,
       // simd, or for simd. This has to take into account combined directives.
       // In 5.2 this seems to be implied by the fact that the specified
@@ -5045,11 +5054,11 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
   if (NestingProhibited) {
     if (OrphanSeen) {
       SemaRef.Diag(StartLoc, diag::err_omp_orphaned_device_directive)
-          << getOpenMPDirectiveName(CurrentRegion) << Recommend;
+          << getOpenMPDirectiveName(CurrentRegion, OMPVersion) << Recommend;
     } else {
       SemaRef.Diag(StartLoc, diag::err_omp_prohibited_region)
-          << CloseNesting << getOpenMPDirectiveName(OffendingRegion)
-          << Recommend << getOpenMPDirectiveName(CurrentRegion);
+          << CloseNesting << getOpenMPDirectiveName(OffendingRegion, 
OMPVersion)
+          << Recommend << getOpenMPDirectiveName(CurrentRegion, OMPVersion);
     }
     return true;
   }
@@ -5068,6 +5077,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind 
Kind,
   llvm::IndexedMap<const OMPIfClause *, Kind2Unsigned> FoundNameModifiers;
   FoundNameModifiers.resize(llvm::omp::Directive_enumSize + 1);
   SmallVector<SourceLocation, 4> NameModifierLoc;
+  unsigned OMPVersion = S.getLangOpts().OpenMP;
   for (const OMPClause *C : Clauses) {
     if (const auto *IC = dyn_cast_or_null<OMPIfClause>(C)) {
       // At most one if clause without a directive-name-modifier can appear on
@@ -5076,9 +5086,9 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind 
Kind,
       auto &FNM = FoundNameModifiers[CurNM];
       if (FNM) {
         S.Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
-            << getOpenMPDirectiveName(Kind)
+            << getOpenMPDirectiveName(Kind, OMPVersion)
             << getOpenMPClauseNameForDiag(OMPC_if) << (CurNM != OMPD_unknown)
-            << getOpenMPDirectiveName(CurNM);
+            << getOpenMPDirectiveName(CurNM, OMPVersion);
         ErrorFound = true;
       } else if (CurNM != OMPD_unknown) {
         NameModifierLoc.push_back(IC->getNameModifierLoc());
@@ -5094,7 +5104,8 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind 
Kind,
       if (!llvm::is_contained(AllowedNameModifiers, CurNM)) {
         S.Diag(IC->getNameModifierLoc(),
                diag::err_omp_wrong_if_directive_name_modifier)
-            << getOpenMPDirectiveName(CurNM) << getOpenMPDirectiveName(Kind);
+            << getOpenMPDirectiveName(CurNM, OMPVersion)
+            << getOpenMPDirectiveName(Kind, OMPVersion);
         ErrorFound = true;
       }
     }
@@ -5116,7 +5127,7 @@ static bool checkIfClauses(Sema &S, OpenMPDirectiveKind 
Kind,
         OpenMPDirectiveKind NM = AllowedNameModifiers[Cnt];
         if (!FoundNameModifiers[NM]) {
           Values += "'";
-          Values += getOpenMPDirectiveName(NM);
+          Values += getOpenMPDirectiveName(NM, OMPVersion);
           Values += "'";
           if (AllowedCnt + 2 == TotalAllowedNum)
             Values += " or ";
@@ -5320,9 +5331,10 @@ static void checkAllocateClauses(Sema &S, DSAStackTy 
*Stack,
     if (AllocatorKind == OMPAllocateDeclAttr::OMPThreadMemAlloc &&
         (isOpenMPTaskingDirective(Stack->getCurrentDirective()) ||
          isOpenMPTargetExecutionDirective(Stack->getCurrentDirective()))) {
+      unsigned OMPVersion = S.getLangOpts().OpenMP;
       S.Diag(AC->getAllocator()->getExprLoc(),
              diag::warn_omp_allocate_thread_on_task_target_directive)
-          << getOpenMPDirectiveName(Stack->getCurrentDirective());
+          << getOpenMPDirectiveName(Stack->getCurrentDirective(), OMPVersion);
     }
     for (Expr *E : AC->varlist()) {
       SourceLocation ELoc;
@@ -9138,9 +9150,10 @@ void 
SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
             !isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown &&
             DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) &&
           (DVar.CKind != OMPC_private || DVar.RefExpr)) {
+        unsigned OMPVersion = getLangOpts().OpenMP;
         Diag(Init->getBeginLoc(), diag::err_omp_loop_var_dsa)
             << getOpenMPClauseNameForDiag(DVar.CKind)
-            << getOpenMPDirectiveName(DKind)
+            << getOpenMPDirectiveName(DKind, OMPVersion)
             << getOpenMPClauseNameForDiag(PredeterminedCKind);
         if (DVar.RefExpr == nullptr)
           DVar.CKind = PredeterminedCKind;
@@ -9195,9 +9208,10 @@ static bool checkOpenMPIterationSpace(
   auto *CXXFor = dyn_cast_or_null<CXXForRangeStmt>(S);
   // Ranged for is supported only in OpenMP 5.0.
   if (!For && (SemaRef.LangOpts.OpenMP <= 45 || !CXXFor)) {
+    unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
     SemaRef.Diag(S->getBeginLoc(), diag::err_omp_not_for)
         << (CollapseLoopCountExpr != nullptr || OrderedLoopCountExpr != 
nullptr)
-        << getOpenMPDirectiveName(DKind) << TotalNestedLoopCount
+        << getOpenMPDirectiveName(DKind, OMPVersion) << TotalNestedLoopCount
         << (CurrentNestedLoopCount > 0) << CurrentNestedLoopCount;
     if (TotalNestedLoopCount > 1) {
       if (CollapseLoopCountExpr && OrderedLoopCountExpr)
@@ -10482,6 +10496,7 @@ static bool checkSectionsDirective(Sema &SemaRef, 
OpenMPDirectiveKind DKind,
     return true;
 
   assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");
+  unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
   auto BaseStmt = AStmt;
   while (auto *CS = dyn_cast_or_null<CapturedStmt>(BaseStmt))
     BaseStmt = CS->getCapturedStmt();
@@ -10496,7 +10511,7 @@ static bool checkSectionsDirective(Sema &SemaRef, 
OpenMPDirectiveKind DKind,
         if (SectionStmt)
           SemaRef.Diag(SectionStmt->getBeginLoc(),
                        diag::err_omp_sections_substmt_not_section)
-              << getOpenMPDirectiveName(DKind);
+              << getOpenMPDirectiveName(DKind, OMPVersion);
         return true;
       }
       cast<OMPSectionDirective>(SectionStmt)
@@ -10504,7 +10519,7 @@ static bool checkSectionsDirective(Sema &SemaRef, 
OpenMPDirectiveKind DKind,
     }
   } else {
     SemaRef.Diag(AStmt->getBeginLoc(), 
diag::err_omp_sections_not_compound_stmt)
-        << getOpenMPDirectiveName(DKind);
+        << getOpenMPDirectiveName(DKind, OMPVersion);
     return true;
   }
   return false;
@@ -10609,8 +10624,9 @@ static bool checkGenericLoopLastprivate(Sema &S, 
ArrayRef<OMPClause *> Clauses,
         if (ValueDecl *D = Res.first) {
           auto &&Info = Stack->isLoopControlVariable(D);
           if (!Info.first) {
+            unsigned OMPVersion = S.getLangOpts().OpenMP;
             S.Diag(ELoc, diag::err_omp_lastprivate_loop_var_non_loop_iteration)
-                << getOpenMPDirectiveName(K);
+                << getOpenMPDirectiveName(K, OMPVersion);
             ErrorFound = true;
           }
         }
@@ -11114,6 +11130,7 @@ StmtResult 
SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
     else
       OrderClause = C;
   }
+  unsigned OMPVersion = getLangOpts().OpenMP;
   OpenMPClauseKind MemOrderKind = OMPC_unknown;
   SourceLocation MemOrderLoc;
   for (const OMPClause *C : Clauses) {
@@ -11123,7 +11140,7 @@ StmtResult 
SemaOpenMP::ActOnOpenMPFlushDirective(ArrayRef<OMPClause *> Clauses,
         C->getClauseKind() == OMPC_seq_cst /*OpenMP 5.1*/) {
       if (MemOrderKind != OMPC_unknown) {
         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
-            << getOpenMPDirectiveName(OMPD_flush) << 1
+            << getOpenMPDirectiveName(OMPD_flush, OMPVersion) << 1
             << SourceRange(C->getBeginLoc(), C->getEndLoc());
         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
             << getOpenMPClauseNameForDiag(MemOrderKind);
@@ -11178,9 +11195,11 @@ StmtResult 
SemaOpenMP::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
   if (Scope *S = DSAStack->getCurScope()) {
     Scope *ParentS = S->getParent();
     if (!ParentS || ParentS->getParent() != ParentS->getBreakParent() ||
-        !ParentS->getBreakParent()->isOpenMPLoopScope())
+        !ParentS->getBreakParent()->isOpenMPLoopScope()) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       return StmtError(Diag(StartLoc, diag::err_omp_orphaned_device_directive)
-                       << getOpenMPDirectiveName(OMPD_scan) << 5);
+                       << getOpenMPDirectiveName(OMPD_scan, OMPVersion) << 5);
+    }
   }
   // Check that only one instance of scan directives is used in the same outer
   // region.
@@ -11218,8 +11237,9 @@ 
SemaOpenMP::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
       if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
           (DOC && (ODK.isSource(DOC)))) {
         if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
+          unsigned OMPVersion = getLangOpts().OpenMP;
           Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
-              << getOpenMPDirectiveName(OMPD_ordered)
+              << getOpenMPDirectiveName(OMPD_ordered, OMPVersion)
               << getOpenMPClauseNameForDiag(DC ? OMPC_depend : OMPC_doacross)
               << 2;
           ErrorFound = true;
@@ -12374,6 +12394,7 @@ StmtResult 
SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
                                                   SourceLocation StartLoc,
                                                   SourceLocation EndLoc) {
   ASTContext &Context = getASTContext();
+  unsigned OMPVersion = getLangOpts().OpenMP;
   // Register location of the first atomic directive.
   DSAStack->addAtomicDirectiveLoc(StartLoc);
   if (!AStmt)
@@ -12433,7 +12454,7 @@ StmtResult 
SemaOpenMP::ActOnOpenMPAtomicDirective(ArrayRef<OMPClause *> Clauses,
     case OMPC_relaxed: {
       if (MemOrderKind != OMPC_unknown) {
         Diag(C->getBeginLoc(), diag::err_omp_several_mem_order_clauses)
-            << getOpenMPDirectiveName(OMPD_atomic) << 0
+            << getOpenMPDirectiveName(OMPD_atomic, OMPVersion) << 0
             << SourceRange(C->getBeginLoc(), C->getEndLoc());
         Diag(MemOrderLoc, diag::note_omp_previous_mem_order_clause)
             << getOpenMPClauseNameForDiag(MemOrderKind);
@@ -13091,8 +13112,9 @@ 
SemaOpenMP::ActOnOpenMPTargetDataDirective(ArrayRef<OMPClause *> Clauses,
       Expected = "'map' or 'use_device_ptr'";
     else
       Expected = "'map', 'use_device_ptr', or 'use_device_addr'";
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
-        << Expected << getOpenMPDirectiveName(OMPD_target_data);
+        << Expected << getOpenMPDirectiveName(OMPD_target_data, OMPVersion);
     return StmtError();
   }
 
@@ -13113,8 +13135,10 @@ StmtResult 
SemaOpenMP::ActOnOpenMPTargetEnterDataDirective(
   // OpenMP [2.10.2, Restrictions, p. 99]
   // At least one map clause must appear on the directive.
   if (!hasClauses(Clauses, OMPC_map)) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
-        << "'map'" << getOpenMPDirectiveName(OMPD_target_enter_data);
+        << "'map'"
+        << getOpenMPDirectiveName(OMPD_target_enter_data, OMPVersion);
     return StmtError();
   }
 
@@ -13133,8 +13157,9 @@ StmtResult 
SemaOpenMP::ActOnOpenMPTargetExitDataDirective(
   // OpenMP [2.10.3, Restrictions, p. 102]
   // At least one map clause must appear on the directive.
   if (!hasClauses(Clauses, OMPC_map)) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
-        << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data);
+        << "'map'" << getOpenMPDirectiveName(OMPD_target_exit_data, 
OMPVersion);
     return StmtError();
   }
 
@@ -17097,9 +17122,10 @@ 
SemaOpenMP::ActOnOpenMPInteropDirective(ArrayRef<OMPClause *> Clauses,
   // OpenMP 5.1 [2.15.1, interop Construct, Restrictions]
   // At least one action-clause must appear on a directive.
   if (!hasClauses(Clauses, OMPC_init, OMPC_use, OMPC_destroy, OMPC_nowait)) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     StringRef Expected = "'init', 'use', 'destroy', or 'nowait'";
     Diag(StartLoc, diag::err_omp_no_clause_for_directive)
-        << Expected << getOpenMPDirectiveName(OMPD_interop);
+        << Expected << getOpenMPDirectiveName(OMPD_interop, OMPVersion);
     return StmtError();
   }
 
@@ -17266,9 +17292,10 @@ OMPClause *SemaOpenMP::ActOnOpenMPDestroyClause(Expr 
*InteropVar,
                                                 SourceLocation EndLoc) {
   if (!InteropVar && getLangOpts().OpenMP >= 52 &&
       DSAStack->getCurrentDirective() == OMPD_depobj) {
+    unsigned OMPVersion = getLangOpts().OpenMP;
     Diag(StartLoc, diag::err_omp_expected_clause_argument)
         << getOpenMPClauseNameForDiag(OMPC_destroy)
-        << getOpenMPDirectiveName(OMPD_depobj);
+        << getOpenMPDirectiveName(OMPD_depobj, OMPVersion);
     return nullptr;
   }
   if (InteropVar &&
@@ -17610,6 +17637,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
                                                 SourceLocation EndLoc) {
   SmallVector<Expr *, 8> Vars;
   SmallVector<Expr *, 8> PrivateCopies;
+  unsigned OMPVersion = getLangOpts().OpenMP;
   bool IsImplicitClause =
       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
   for (Expr *RefExpr : VarList) {
@@ -17671,7 +17699,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
         isOpenMPTaskingDirective(CurrDir)) {
       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
           << getOpenMPClauseNameForDiag(OMPC_private) << Type
-          << getOpenMPDirectiveName(CurrDir);
+          << getOpenMPDirectiveName(CurrDir, OMPVersion);
       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
                                VarDecl::DeclarationOnly;
       Diag(D->getLocation(),
@@ -17702,7 +17730,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList,
         Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
             << getOpenMPClauseNameForDiag(OMPC_private)
             << getOpenMPClauseNameForDiag(ConflictKind)
-            << getOpenMPDirectiveName(CurrDir);
+            << getOpenMPDirectiveName(CurrDir, OMPVersion);
         reportOriginalDsa(SemaRef, DSAStack, D, DVar);
         continue;
       }
@@ -17764,6 +17792,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
   bool IsImplicitClause =
       StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid();
   SourceLocation ImplicitClauseLoc = DSAStack->getConstructLoc();
+  unsigned OMPVersion = getLangOpts().OpenMP;
 
   for (Expr *RefExpr : VarList) {
     assert(RefExpr && "NULL expr in OpenMP firstprivate clause.");
@@ -17905,7 +17934,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
              isOpenMPWorksharingDirective(DVar.DKind) ||
              isOpenMPTeamsDirective(DVar.DKind))) {
           Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate)
-              << getOpenMPDirectiveName(DVar.DKind);
+              << getOpenMPDirectiveName(DVar.DKind, OMPVersion);
           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
           continue;
         }
@@ -17934,7 +17963,8 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
           Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
               << getOpenMPClauseNameForDiag(OMPC_firstprivate)
               << getOpenMPClauseNameForDiag(ConflictKind)
-              << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+              << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+                                        OMPVersion);
           reportOriginalDsa(SemaRef, DSAStack, D, DVar);
           continue;
         }
@@ -17946,7 +17976,8 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList,
         isOpenMPTaskingDirective(DSAStack->getCurrentDirective())) {
       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
           << getOpenMPClauseNameForDiag(OMPC_firstprivate) << Type
-          << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+          << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+                                    OMPVersion);
       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
                                VarDecl::DeclarationOnly;
       Diag(D->getLocation(),
@@ -19999,9 +20030,10 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPCopyinClause(ArrayRef<Expr *> VarList,
     // OpenMP [2.14.4.1, Restrictions, C/C++, p.1]
     //  A list item that appears in a copyin clause must be threadprivate.
     if (!DSAStack->isThreadPrivate(VD)) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       Diag(ELoc, diag::err_omp_required_access)
           << getOpenMPClauseNameForDiag(OMPC_copyin)
-          << getOpenMPDirectiveName(OMPD_threadprivate);
+          << getOpenMPDirectiveName(OMPD_threadprivate, OMPVersion);
       continue;
     }
 
@@ -20108,9 +20140,11 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList,
 
     // Variably modified types are not supported.
     if (!Type->isAnyPointerType() && Type->isVariablyModifiedType()) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       Diag(ELoc, diag::err_omp_variably_modified_type_not_supported)
           << getOpenMPClauseNameForDiag(OMPC_copyprivate) << Type
-          << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+          << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+                                    OMPVersion);
       bool IsDecl = !VD || VD->isThisDeclarationADefinition(getASTContext()) ==
                                VarDecl::DeclarationOnly;
       Diag(D->getLocation(),
@@ -21682,6 +21716,7 @@ static void checkMappableExpressionList(
   // We only expect mappable expressions in 'to', 'from', and 'map' clauses.
   assert((CKind == OMPC_map || CKind == OMPC_to || CKind == OMPC_from) &&
          "Unexpected clause kind with mappable expressions!");
+  unsigned OMPVersion = SemaRef.getLangOpts().OpenMP;
 
   // If the identifier of user-defined mapper is not specified, it is 
"default".
   // We do not change the actual name in this clause to distinguish whether a
@@ -21886,7 +21921,7 @@ static void checkMappableExpressionList(
         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
             << (IsMapTypeImplicit ? 1 : 0)
             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
-            << getOpenMPDirectiveName(DKind);
+            << getOpenMPDirectiveName(DKind, OMPVersion);
         continue;
       }
 
@@ -21901,7 +21936,7 @@ static void checkMappableExpressionList(
         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
             << (IsMapTypeImplicit ? 1 : 0)
             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
-            << getOpenMPDirectiveName(DKind);
+            << getOpenMPDirectiveName(DKind, OMPVersion);
         continue;
       }
 
@@ -21916,7 +21951,7 @@ static void checkMappableExpressionList(
                      diag::err_omp_invalid_map_type_modifier_for_directive)
             << getOpenMPSimpleClauseTypeName(OMPC_map,
                                              OMPC_MAP_MODIFIER_ompx_hold)
-            << getOpenMPDirectiveName(DKind);
+            << getOpenMPDirectiveName(DKind, OMPVersion);
         continue;
       }
 
@@ -21931,7 +21966,7 @@ static void checkMappableExpressionList(
         SemaRef.Diag(StartLoc, diag::err_omp_invalid_map_type_for_directive)
             << (IsMapTypeImplicit ? 1 : 0)
             << getOpenMPSimpleClauseTypeName(OMPC_map, MapType)
-            << getOpenMPDirectiveName(DKind);
+            << getOpenMPDirectiveName(DKind, OMPVersion);
         continue;
       }
 
@@ -21951,7 +21986,8 @@ static void checkMappableExpressionList(
           SemaRef.Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
               << getOpenMPClauseNameForDiag(DVar.CKind)
               << getOpenMPClauseNameForDiag(OMPC_map)
-              << getOpenMPDirectiveName(DSAS->getCurrentDirective());
+              << getOpenMPDirectiveName(DSAS->getCurrentDirective(),
+                                        OMPVersion);
           reportOriginalDsa(SemaRef, DSAS, CurDeclaration, DVar);
           continue;
         }
@@ -22890,8 +22926,9 @@ void 
SemaOpenMP::DiagnoseUnterminatedOpenMPDeclareTarget() {
   if (DeclareTargetNesting.empty())
     return;
   DeclareTargetContextInfo &DTCI = DeclareTargetNesting.back();
+  unsigned OMPVersion = getLangOpts().OpenMP;
   Diag(DTCI.Loc, diag::warn_omp_unterminated_declare_target)
-      << getOpenMPDirectiveName(DTCI.Kind);
+      << getOpenMPDirectiveName(DTCI.Kind, OMPVersion);
 }
 
 NamedDecl *SemaOpenMP::lookupOpenMPDeclareTargetName(
@@ -23406,10 +23443,12 @@ 
SemaOpenMP::ActOnOpenMPIsDevicePtrClause(ArrayRef<Expr *> VarList,
     // sharing attribute.
     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
     if (isOpenMPPrivate(DVar.CKind)) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
           << getOpenMPClauseNameForDiag(DVar.CKind)
           << getOpenMPClauseNameForDiag(OMPC_is_device_ptr)
-          << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+          << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+                                    OMPVersion);
       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
       continue;
     }
@@ -23482,10 +23521,12 @@ 
SemaOpenMP::ActOnOpenMPHasDeviceAddrClause(ArrayRef<Expr *> VarList,
     // sharing attribute.
     DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(D, /*FromParent=*/false);
     if (isOpenMPPrivate(DVar.CKind)) {
+      unsigned OMPVersion = getLangOpts().OpenMP;
       Diag(ELoc, diag::err_omp_variable_in_given_clause_and_dsa)
           << getOpenMPClauseNameForDiag(DVar.CKind)
           << getOpenMPClauseNameForDiag(OMPC_has_device_addr)
-          << getOpenMPDirectiveName(DSAStack->getCurrentDirective());
+          << getOpenMPDirectiveName(DSAStack->getCurrentDirective(),
+                                    OMPVersion);
       reportOriginalDsa(SemaRef, DSAStack, D, DVar);
       continue;
     }
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 8b4b79c6ec039..0af897ad9a540 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -9581,8 +9581,9 @@ template <typename Derived>
 StmtResult
 TreeTransform<Derived>::TransformOMPMetaDirective(OMPMetaDirective *D) {
   // TODO: Fix This
+  unsigned OMPVersion = getDerived().getSema().getLangOpts().OpenMP;
   SemaRef.Diag(D->getBeginLoc(), diag::err_omp_instantiation_not_supported)
-      << getOpenMPDirectiveName(D->getDirectiveKind());
+      << getOpenMPDirectiveName(D->getDirectiveKind(), OMPVersion);
   return StmtError();
 }
 

>From c3d5f38e65ea6997496066da8c4ba736e7910104 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Wed, 7 May 2025 15:32:08 -0500
Subject: [PATCH 2/6] format

---
 clang/lib/Sema/SemaOpenMP.cpp | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 61cc367d18d33..49aaceebcdba5 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -4890,9 +4890,9 @@ static bool checkNestingOfRegions(Sema &SemaRef, const 
DSAStackTy *Stack,
     // construct-type-clause.
     ArrayRef<OpenMPDirectiveKind> Leafs = 
getLeafConstructsOrSelf(ParentRegion);
     if (CancelRegion == OMPD_taskgroup) {
-      NestingProhibited = EnclosingConstruct != OMPD_task &&
-                          (OMPVersion < 50 ||
-                           EnclosingConstruct != OMPD_taskloop);
+      NestingProhibited =
+          EnclosingConstruct != OMPD_task &&
+          (OMPVersion < 50 || EnclosingConstruct != OMPD_taskloop);
     } else if (CancelRegion == OMPD_sections) {
       NestingProhibited = EnclosingConstruct != OMPD_section &&
                           EnclosingConstruct != OMPD_sections;

>From 97ca62188c045992ea083ad601b94dc85c0a5cec Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Thu, 8 May 2025 13:15:31 -0500
Subject: [PATCH 3/6] Store OMP version in OMPClausePrinter, remove it from
 PrintingPolicy

---
 clang/include/clang/AST/OpenMPClause.h  |  6 ++++--
 clang/include/clang/AST/PrettyPrinter.h |  6 +-----
 clang/lib/AST/DeclPrinter.cpp           |  6 +++---
 clang/lib/AST/OpenMPClause.cpp          |  6 +++---
 clang/lib/AST/StmtPrinter.cpp           | 13 ++++++++-----
 5 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/clang/include/clang/AST/OpenMPClause.h 
b/clang/include/clang/AST/OpenMPClause.h
index 572e62249b46f..757873fd6d414 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -9475,6 +9475,7 @@ class ConstOMPClauseVisitor :
 class OMPClausePrinter final : public OMPClauseVisitor<OMPClausePrinter> {
   raw_ostream &OS;
   const PrintingPolicy &Policy;
+  unsigned Version;
 
   /// Process clauses with list of variables.
   template <typename T> void VisitOMPClauseList(T *Node, char StartSym);
@@ -9482,8 +9483,9 @@ class OMPClausePrinter final : public 
OMPClauseVisitor<OMPClausePrinter> {
   template <typename T> void VisitOMPMotionClause(T *Node);
 
 public:
-  OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
-      : OS(OS), Policy(Policy) {}
+  OMPClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy,
+                   unsigned OpenMPVersion)
+      : OS(OS), Policy(Policy), Version(OpenMPVersion) {}
 
 #define GEN_CLANG_CLAUSE_CLASS
 #define CLAUSE_CLASS(Enum, Str, Class) void Visit##Class(Class *S);
diff --git a/clang/include/clang/AST/PrettyPrinter.h 
b/clang/include/clang/AST/PrettyPrinter.h
index 1f64466956b66..5a98ae1987b16 100644
--- a/clang/include/clang/AST/PrettyPrinter.h
+++ b/clang/include/clang/AST/PrettyPrinter.h
@@ -59,7 +59,7 @@ struct PrintingPolicy {
 
   /// Create a default printing policy for the specified language.
   PrintingPolicy(const LangOptions &LO)
-      : Indentation(2), OpenMP(LO.OpenMP), SuppressSpecifiers(false),
+      : Indentation(2), SuppressSpecifiers(false),
         SuppressTagKeyword(LO.CPlusPlus), IncludeTagDefinition(false),
         SuppressScope(false), SuppressUnwrittenScope(false),
         SuppressInlineNamespace(SuppressInlineNamespaceMode::Redundant),
@@ -94,10 +94,6 @@ struct PrintingPolicy {
   /// The number of spaces to use to indent each line.
   unsigned Indentation : 8;
 
-  /// Version of the effective OpenMP spec (used to select directive name
-  /// spelling).
-  unsigned OpenMP : 8;
-
   /// Whether we should suppress printing of the actual specifiers for
   /// the given type or declaration.
   ///
diff --git a/clang/lib/AST/DeclPrinter.cpp b/clang/lib/AST/DeclPrinter.cpp
index 22da5bf251ecd..3616419dce4ec 100644
--- a/clang/lib/AST/DeclPrinter.cpp
+++ b/clang/lib/AST/DeclPrinter.cpp
@@ -1827,7 +1827,7 @@ void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl 
*D) {
     Out << ")";
   }
   if (!D->clauselist_empty()) {
-    OMPClausePrinter Printer(Out, Policy);
+    OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP);
     for (OMPClause *C : D->clauselists()) {
       Out << " ";
       Printer.Visit(C);
@@ -1838,7 +1838,7 @@ void DeclPrinter::VisitOMPAllocateDecl(OMPAllocateDecl 
*D) {
 void DeclPrinter::VisitOMPRequiresDecl(OMPRequiresDecl *D) {
   Out << "#pragma omp requires ";
   if (!D->clauselist_empty()) {
-    OMPClausePrinter Printer(Out, Policy);
+    OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP);
     for (auto I = D->clauselist_begin(), E = D->clauselist_end(); I != E; ++I)
       Printer.Visit(*I);
   }
@@ -1891,7 +1891,7 @@ void 
DeclPrinter::VisitOMPDeclareMapperDecl(OMPDeclareMapperDecl *D) {
     Out << D->getVarName();
     Out << ")";
     if (!D->clauselist_empty()) {
-      OMPClausePrinter Printer(Out, Policy);
+      OMPClausePrinter Printer(Out, Policy, Context.getLangOpts().OpenMP);
       for (auto *C : D->clauselists()) {
         Out << " ";
         Printer.Visit(C);
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 5ed04d250f5a1..3674f6c8b4df0 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1821,7 +1821,7 @@ OMPThreadLimitClause 
*OMPThreadLimitClause::CreateEmpty(const ASTContext &C,
 void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
   OS << "if(";
   if (Node->getNameModifier() != OMPD_unknown)
-    OS << getOpenMPDirectiveName(Node->getNameModifier(), Policy.OpenMP)
+    OS << getOpenMPDirectiveName(Node->getNameModifier(), Version)
        << ": ";
   Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
   OS << ")";
@@ -2050,7 +2050,7 @@ void 
OMPClausePrinter::VisitOMPAbsentClause(OMPAbsentClause *Node) {
   for (auto &D : Node->getDirectiveKinds()) {
     if (!First)
       OS << ", ";
-    OS << getOpenMPDirectiveName(D, Policy.OpenMP);
+    OS << getOpenMPDirectiveName(D, Version);
     First = false;
   }
   OS << ")";
@@ -2068,7 +2068,7 @@ void 
OMPClausePrinter::VisitOMPContainsClause(OMPContainsClause *Node) {
   for (auto &D : Node->getDirectiveKinds()) {
     if (!First)
       OS << ", ";
-    OS << getOpenMPDirectiveName(D, Policy.OpenMP);
+    OS << getOpenMPDirectiveName(D, Version);
     First = false;
   }
   OS << ")";
diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 53f7bb2f64249..fcd986b16b66d 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -73,13 +73,16 @@ namespace {
     PrintingPolicy Policy;
     std::string NL;
     const ASTContext *Context;
+    unsigned Version;
 
   public:
-    StmtPrinter(raw_ostream &os, PrinterHelper *helper,
+    StmtPrinter(raw_ostream & os, PrinterHelper * helper,
                 const PrintingPolicy &Policy, unsigned Indentation = 0,
                 StringRef NL = "\n", const ASTContext *Context = nullptr)
         : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
-          NL(NL), Context(Context) {}
+          NL(NL), Context(Context),
+          Version(Context ? Context->getLangOpts().OpenMP
+                          : llvm::omp::FallbackVersion) {}
 
     void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); }
 
@@ -737,7 +740,7 @@ void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop 
*Node) {
 
 void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
                                               bool ForceNoStmt) {
-  OMPClausePrinter Printer(OS, Policy);
+  OMPClausePrinter Printer(OS, Policy, Version);
   ArrayRef<OMPClause *> Clauses = S->clauses();
   for (auto *Clause : Clauses)
     if (Clause && !Clause->isImplicit()) {
@@ -965,13 +968,13 @@ void 
StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
 void StmtPrinter::VisitOMPCancellationPointDirective(
     OMPCancellationPointDirective *Node) {
   Indent() << "#pragma omp cancellation point "
-           << getOpenMPDirectiveName(Node->getCancelRegion(), Policy.OpenMP);
+           << getOpenMPDirectiveName(Node->getCancelRegion(), Version);
   PrintOMPExecutableDirective(Node);
 }
 
 void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
   Indent() << "#pragma omp cancel "
-           << getOpenMPDirectiveName(Node->getCancelRegion(), Policy.OpenMP);
+           << getOpenMPDirectiveName(Node->getCancelRegion(), Version);
   PrintOMPExecutableDirective(Node);
 }
 

>From 37349d4b4341a9f0cdfc94ffd181b6de99eb60f9 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Thu, 8 May 2025 13:19:01 -0500
Subject: [PATCH 4/6] format

---
 clang/lib/AST/StmtPrinter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index fcd986b16b66d..626e845de981a 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -76,7 +76,7 @@ namespace {
     unsigned Version;
 
   public:
-    StmtPrinter(raw_ostream & os, PrinterHelper * helper,
+    StmtPrinter(raw_ostream &os, PrinterHelper *helper,
                 const PrintingPolicy &Policy, unsigned Indentation = 0,
                 StringRef NL = "\n", const ASTContext *Context = nullptr)
         : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),

>From 68c7d9ed0aa80991748371e4839ee7c1c3934b23 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Thu, 8 May 2025 13:25:39 -0500
Subject: [PATCH 5/6] more format

---
 clang/lib/AST/OpenMPClause.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 3674f6c8b4df0..c1682888934e5 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -1821,8 +1821,7 @@ OMPThreadLimitClause 
*OMPThreadLimitClause::CreateEmpty(const ASTContext &C,
 void OMPClausePrinter::VisitOMPIfClause(OMPIfClause *Node) {
   OS << "if(";
   if (Node->getNameModifier() != OMPD_unknown)
-    OS << getOpenMPDirectiveName(Node->getNameModifier(), Version)
-       << ": ";
+    OS << getOpenMPDirectiveName(Node->getNameModifier(), Version) << ": ";
   Node->getCondition()->printPretty(OS, nullptr, Policy, 0);
   OS << ")";
 }

>From 49be4a458512a1cf312c40bdf5cf88541a4b1243 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <krzysztof.parzys...@amd.com>
Date: Thu, 8 May 2025 13:54:11 -0500
Subject: [PATCH 6/6] Don't put OpenMP "Version" in StmtPrinter

---
 clang/lib/AST/StmtPrinter.cpp | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp
index 626e845de981a..dc8af1586624b 100644
--- a/clang/lib/AST/StmtPrinter.cpp
+++ b/clang/lib/AST/StmtPrinter.cpp
@@ -73,16 +73,13 @@ namespace {
     PrintingPolicy Policy;
     std::string NL;
     const ASTContext *Context;
-    unsigned Version;
 
   public:
     StmtPrinter(raw_ostream &os, PrinterHelper *helper,
                 const PrintingPolicy &Policy, unsigned Indentation = 0,
                 StringRef NL = "\n", const ASTContext *Context = nullptr)
         : OS(os), IndentLevel(Indentation), Helper(helper), Policy(Policy),
-          NL(NL), Context(Context),
-          Version(Context ? Context->getLangOpts().OpenMP
-                          : llvm::omp::FallbackVersion) {}
+          NL(NL), Context(Context) {}
 
     void PrintStmt(Stmt *S) { PrintStmt(S, Policy.Indentation); }
 
@@ -740,7 +737,9 @@ void StmtPrinter::VisitOMPCanonicalLoop(OMPCanonicalLoop 
*Node) {
 
 void StmtPrinter::PrintOMPExecutableDirective(OMPExecutableDirective *S,
                                               bool ForceNoStmt) {
-  OMPClausePrinter Printer(OS, Policy, Version);
+  unsigned OpenMPVersion =
+      Context ? Context->getLangOpts().OpenMP : llvm::omp::FallbackVersion;
+  OMPClausePrinter Printer(OS, Policy, OpenMPVersion);
   ArrayRef<OMPClause *> Clauses = S->clauses();
   for (auto *Clause : Clauses)
     if (Clause && !Clause->isImplicit()) {
@@ -967,14 +966,18 @@ void 
StmtPrinter::VisitOMPTeamsDirective(OMPTeamsDirective *Node) {
 
 void StmtPrinter::VisitOMPCancellationPointDirective(
     OMPCancellationPointDirective *Node) {
+  unsigned OpenMPVersion =
+      Context ? Context->getLangOpts().OpenMP : llvm::omp::FallbackVersion;
   Indent() << "#pragma omp cancellation point "
-           << getOpenMPDirectiveName(Node->getCancelRegion(), Version);
+           << getOpenMPDirectiveName(Node->getCancelRegion(), OpenMPVersion);
   PrintOMPExecutableDirective(Node);
 }
 
 void StmtPrinter::VisitOMPCancelDirective(OMPCancelDirective *Node) {
+  unsigned OpenMPVersion =
+      Context ? Context->getLangOpts().OpenMP : llvm::omp::FallbackVersion;
   Indent() << "#pragma omp cancel "
-           << getOpenMPDirectiveName(Node->getCancelRegion(), Version);
+           << getOpenMPDirectiveName(Node->getCancelRegion(), OpenMPVersion);
   PrintOMPExecutableDirective(Node);
 }
 

_______________________________________________
llvm-branch-commits mailing list
llvm-branch-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to