diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -3749,8 +3749,8 @@ let Documentation = [OMPDeclareTargetDocs]; let Args = [ EnumArgument<"MapType", "MapTypeTy", - [ "to", "link" ], - [ "MT_To", "MT_Link" ]>, + [ "to", "enter", "link" ], + [ "MT_To", "MT_Enter", "MT_Link" ]>, EnumArgument<"DevType", "DevTypeTy", [ "host", "nohost", "any" ], [ "DT_Host", "DT_NoHost", "DT_Any" ]>, diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td --- a/clang/include/clang/Basic/DiagnosticParseKinds.td +++ b/clang/include/clang/Basic/DiagnosticParseKinds.td @@ -1383,12 +1383,22 @@ : Note<"the ignored tokens spans until here">; def err_omp_declare_target_unexpected_clause: Error< "unexpected '%0' clause, only %select{'device_type'|'to' or 'link'|'to', 'link' or 'device_type'|'device_type', 'indirect'|'to', 'link', 'device_type' or 'indirect'}1 clauses expected">; +def err_omp_declare_target_unexpected_clause_52: Error< + "unexpected '%0' clause, only %select{'device_type'|'enter' or 'link'|'enter', 'link' or 'device_type'|'device_type', 'indirect'|'enter', 'link', 'device_type' or 'indirect'}1 clauses expected">; def err_omp_begin_declare_target_unexpected_implicit_to_clause: Error< "unexpected '(', only 'to', 'link' or 'device_type' clauses expected for 'begin declare target' directive">; def err_omp_declare_target_unexpected_clause_after_implicit_to: Error< "unexpected clause after an implicit 'to' clause">; +def err_omp_declare_target_unexpected_clause_after_implicit_enter: Error< + "unexpected clause after an implicit 'enter' clause">; def err_omp_declare_target_missing_to_or_link_clause: Error< "expected at least one %select{'to' or 'link'|'to', 'link' or 'indirect'}0 clause">; +def err_omp_declare_target_missing_enter_or_link_clause: Error< + "expected at least one %select{'enter' or 'link'|'enter', 'link' or 'indirect'}0 clause">; +def err_omp_declare_target_unexpected_to_clause: Error< + "unexpected 'to' clause, use 'enter' instead">; +def err_omp_declare_target_unexpected_enter_clause: Error< + "unexpected 'enter' clause, use 'to' instead">; def err_omp_declare_target_multiple : Error< "%0 appears multiple times in clauses on the same declare target directive">; def err_omp_declare_target_indirect_device_type: Error< diff --git a/clang/lib/AST/AttrImpl.cpp b/clang/lib/AST/AttrImpl.cpp --- a/clang/lib/AST/AttrImpl.cpp +++ b/clang/lib/AST/AttrImpl.cpp @@ -137,7 +137,7 @@ // Use fake syntax because it is for testing and debugging purpose only. if (getDevType() != DT_Any) OS << " device_type(" << ConvertDevTypeTyToStr(getDevType()) << ")"; - if (getMapType() != MT_To) + if (getMapType() != MT_To && getMapType() != MT_Enter) OS << ' ' << ConvertMapTypeTyToStr(getMapType()); if (Expr *E = getIndirectExpr()) { OS << " indirect("; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2495,14 +2495,16 @@ const VarDecl *VD, QualType T) { llvm::Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); - // Return an invalid address if variable is MT_To and unified - // memory is not enabled. For all other cases: MT_Link and - // MT_To with unified memory, return a valid address. - if (!Res || (*Res == OMPDeclareTargetDeclAttr::MT_To && + // Return an invalid address if variable is MT_To (or MT_Enter starting with + // OpenMP 5.2) and unified memory is not enabled. For all other cases: MT_Link + // and MT_To (or MT_Enter) with unified memory, return a valid address. + if (!Res || ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && !CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) return Address::invalid(); assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) && "Expected link clause OR to clause with unified memory enabled."); QualType PtrTy = CGF.getContext().getPointerType(VD->getType()); diff --git a/clang/lib/CodeGen/CGOpenMPRuntime.cpp b/clang/lib/CodeGen/CGOpenMPRuntime.cpp --- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp +++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp @@ -1627,7 +1627,8 @@ llvm::Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (Res && (*Res == OMPDeclareTargetDeclAttr::MT_Link || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory))) { SmallString<64> PtrName; { @@ -1840,7 +1841,8 @@ Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) return CGM.getLangOpts().OpenMPIsDevice; VD = VD->getDefinition(CGM.getContext()); @@ -7461,7 +7463,8 @@ if (llvm::Optional Res = OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) { RequiresReference = true; BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); @@ -10325,7 +10328,8 @@ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration( cast(GD.getDecl())); if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) { DeferredGlobalVariables.insert(cast(GD.getDecl())); return true; @@ -10362,7 +10366,8 @@ int64_t VarSize; llvm::GlobalValue::LinkageTypes Linkage; - if (*Res == OMPDeclareTargetDeclAttr::MT_To && + if ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && !HasRequiresUnifiedSharedMemory) { Flags = llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo; VarName = CGM.getMangledName(VD); @@ -10393,7 +10398,8 @@ } } else { assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && "Declare target attribute must link or to with unified memory."); if (*Res == OMPDeclareTargetDeclAttr::MT_Link) @@ -10430,12 +10436,14 @@ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD); if (!Res) continue; - if (*Res == OMPDeclareTargetDeclAttr::MT_To && + if ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && !HasRequiresUnifiedSharedMemory) { CGM.EmitGlobal(VD); } else { assert((*Res == OMPDeclareTargetDeclAttr::MT_Link || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && HasRequiresUnifiedSharedMemory)) && "Expected link clause or to clause with unified memory."); (void)CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -3305,12 +3305,14 @@ OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) { bool UnifiedMemoryEnabled = getOpenMPRuntime().hasRequiresUnifiedSharedMemory(); - if (*Res == OMPDeclareTargetDeclAttr::MT_To && + if ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && !UnifiedMemoryEnabled) { (void)GetAddrOfGlobalVar(VD); } else { assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) || - (*Res == OMPDeclareTargetDeclAttr::MT_To && + ((*Res == OMPDeclareTargetDeclAttr::MT_To || + *Res == OMPDeclareTargetDeclAttr::MT_Enter) && UnifiedMemoryEnabled)) && "Link clause or to clause with unified memory expected."); (void)getOpenMPRuntime().getAddrOfDeclareTargetVar(VD); diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -1801,9 +1801,21 @@ << getOpenMPClauseName(OMPC_indirect) << 0; break; } - bool IsToOrLinkClause = + bool IsToEnterOrLinkClause = OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT); - assert((!IsDeviceTypeClause || !IsToOrLinkClause) && "Cannot be both!"); + assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) && + "Cannot be both!"); + + // Starting with OpenMP 5.2 the `to` clause has been replaced by the + // `enter` clause. + if (getLangOpts().OpenMP >= 52 && ClauseName == "to") { + Diag(Tok, diag::err_omp_declare_target_unexpected_to_clause); + break; + } + if (getLangOpts().OpenMP <= 51 && ClauseName == "enter") { + Diag(Tok, diag::err_omp_declare_target_unexpected_enter_clause); + break; + } if (!IsDeviceTypeClause && !IsIndirectClause && DTCI.Kind == OMPD_begin_declare_target) { @@ -1811,16 +1823,18 @@ << ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0); break; } - if (!IsDeviceTypeClause && !IsToOrLinkClause && !IsIndirectClause) { - Diag(Tok, diag::err_omp_declare_target_unexpected_clause) + if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) { + Diag(Tok, getLangOpts().OpenMP >= 52 + ? diag::err_omp_declare_target_unexpected_clause_52 + : diag::err_omp_declare_target_unexpected_clause) << ClauseName - << (getLangOpts().OpenMP >= 51 ? 4 - : getLangOpts().OpenMP >= 50 ? 2 - : 1); + << (getLangOpts().OpenMP >= 51 + ? 4 + : getLangOpts().OpenMP >= 50 ? 2 : 1); break; } - if (IsToOrLinkClause || IsIndirectClause) + if (IsToEnterOrLinkClause || IsIndirectClause) HasToOrLinkOrIndirectClause = true; if (IsIndirectClause) { @@ -1883,8 +1897,13 @@ break; } if (!HasIdentifier && Tok.isNot(tok::annot_pragma_openmp_end)) { - Diag(Tok, - diag::err_omp_declare_target_unexpected_clause_after_implicit_to); + Diag( + Tok, + getLangOpts().OpenMP >= 52 + ? diag:: + err_omp_declare_target_unexpected_clause_after_implicit_enter + : diag:: + err_omp_declare_target_unexpected_clause_after_implicit_to); break; } @@ -1899,7 +1918,10 @@ // For declare target require at least 'to' or 'link' to be present. if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause && !HasToOrLinkOrIndirectClause) - Diag(DTCI.Loc, diag::err_omp_declare_target_missing_to_or_link_clause) + Diag(DTCI.Loc, + getLangOpts().OpenMP >= 52 + ? diag::err_omp_declare_target_missing_enter_or_link_clause + : diag::err_omp_declare_target_missing_to_or_link_clause) << (getLangOpts().OpenMP >= 51 ? 1 : 0); SkipUntil(tok::annot_pragma_openmp_end, StopBeforeMatch); diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -22670,7 +22670,8 @@ (SemaRef.getCurLambda(/*IgnoreNonLambdaCapturingScope=*/true) || SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) && VD->hasGlobalStorage()) { - if (!MapTy || *MapTy != OMPDeclareTargetDeclAttr::MT_To) { + if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To && + *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) { // OpenMP 5.0, 2.12.7 declare target Directive, Restrictions // If a lambda declaration and definition appears between a // declare target directive and the matching end declare target @@ -22751,8 +22752,11 @@ IsIndirect = true; } auto *A = OMPDeclareTargetDeclAttr::CreateImplicit( - Context, OMPDeclareTargetDeclAttr::MT_To, DTCI.DT, IndirectE, - IsIndirect, Level, SourceRange(DTCI.Loc, DTCI.Loc)); + Context, + getLangOpts().OpenMP >= 52 ? OMPDeclareTargetDeclAttr::MT_Enter + : OMPDeclareTargetDeclAttr::MT_To, + DTCI.DT, IndirectE, IsIndirect, Level, + SourceRange(DTCI.Loc, DTCI.Loc)); D->addAttr(A); if (ASTMutationListener *ML = Context.getASTMutationListener()) ML->DeclarationMarkedOpenMPDeclareTarget(D, A); diff --git a/clang/test/OpenMP/declare_target_ast_print.cpp b/clang/test/OpenMP/declare_target_ast_print.cpp --- a/clang/test/OpenMP/declare_target_ast_print.cpp +++ b/clang/test/OpenMP/declare_target_ast_print.cpp @@ -4,10 +4,13 @@ // RUN: %clang_cc1 -verify -fopenmp -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=51 -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP51 +// RUN: %clang_cc1 -verify -fopenmp -fopenmp-version=52 -I %S/Inputs -ast-print %s | FileCheck %s --check-prefix=CHECK --check-prefix=OMP52 // RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP50 // RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s // RUN: %clang_cc1 -fopenmp -fopenmp-version=51 -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP51 +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -fopenmp-version=52 -std=c++11 -include-pch %t -fsyntax-only -I %S/Inputs -verify %s -ast-print | FileCheck %s --check-prefix=CHECK --check-prefix=OMP52 // RUN: %clang_cc1 -verify -fopenmp-simd -I %S/Inputs -ast-print %s | FileCheck %s // RUN: %clang_cc1 -fopenmp-simd -x c++ -std=c++11 -I %S/Inputs -emit-pch -o %t %s @@ -77,6 +80,48 @@ } #endif // _OPENMP +#if _OPENMP == 202111 +extern "C" { +void boo_c() {} +#pragma omp declare target enter(boo_c) indirect +// OMP52: #pragma omp declare target indirect +// OMP52: void boo_c() { +// OMP52: } +// OMP52: #pragma omp end declare target +#pragma omp declare target indirect +void yoo(){} +#pragma omp end declare target +// OMP52: #pragma omp declare target indirect +// OMP52: void yoo() { +// OMP52: } +// OMP52: #pragma omp end declare target +} +extern "C++" { +void boo_cpp() {} +#pragma omp declare target enter(boo_cpp) indirect +// OMP52: #pragma omp declare target indirect +// OMP52: void boo_cpp() { +// OMP52: } +// OMP52: #pragma omp end declare target + +constexpr bool f() {return false;} +#pragma omp begin declare target indirect(f()) +void zoo() {} +void xoo(); +#pragma omp end declare target +#pragma omp declare target enter(zoo) indirect(false) +// OMP52: #pragma omp declare target indirect(f()) +// OMP52: #pragma omp declare target indirect(false) +// OMP52: void zoo() { +// OMP52: } +// OMP52: #pragma omp end declare target +// OMP52: #pragma omp declare target indirect(f()) +// OMP52: void xoo(); +// OMP52: #pragma omp end declare target + +} +#endif // _OPENMP + int out_decl_target = 0; #pragma omp declare target (out_decl_target) @@ -185,7 +230,11 @@ int b1, b2, b3; void f2() { } +#if _OPENMP == 202111 +#pragma omp declare target enter(b1) enter(b2), enter(b3, f2) +#else #pragma omp declare target to(b1) to(b2), to(b3, f2) +#endif // _OPENMP == 202111 // CHECK: #pragma omp declare target{{$}} // CHECK: int b1; // CHECK: #pragma omp end declare target{{$}} @@ -288,7 +337,11 @@ #pragma omp declare target int abc1() { return 1; } +#if _OPENMP == 202111 +#pragma omp declare target enter(abc1) device_type(nohost) +#else #pragma omp declare target to(abc1) device_type(nohost) +#endif // _OPENMP == 202111 #pragma omp end declare target // CHECK-NEXT: #pragma omp declare target