[clang] [llvm] [clang][OpenMP] Parse/Sema for OpenMP 6.0 declare_target 'local' clause (PR #186281)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 16 08:16:28 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang-codegen
Author: David Pagan (ddpagan)
<details>
<summary>Changes</summary>
Parse and perform semantic checks for declare_target 'local' clause. When compiling for device offloading, generate a warning that 'local' is not yet fully supported. On the host, 'local' is/will be a no-op, so no warning is generated.
NOTE: The minimal CodeGen changes allow 'local' to flow through as equivalent to the 'enter' clause after warning is generated.
Testing:
- Updated messages and ast tests for declare target/declare_target
- ninja check-all.
---
Patch is 43.24 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/186281.diff
12 Files Affected:
- (modified) clang/include/clang/Basic/Attr.td (+9-11)
- (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+9-6)
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+12-4)
- (modified) clang/lib/CodeGen/CGExpr.cpp (+7-4)
- (modified) clang/lib/CodeGen/CGOpenMPRuntime.cpp (+9-4)
- (modified) clang/lib/CodeGen/CodeGenModule.cpp (+4-2)
- (modified) clang/lib/Parse/ParseOpenMP.cpp (+39-21)
- (modified) clang/lib/Sema/SemaOpenMP.cpp (+25-4)
- (modified) clang/test/AST/dump.cpp (+26-1)
- (modified) clang/test/OpenMP/declare_target_ast_print.cpp (+49-1)
- (modified) clang/test/OpenMP/declare_target_messages.cpp (+119-20)
- (modified) llvm/include/llvm/Frontend/OpenMP/OMP.td (+1)
``````````diff
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 8ab4aaa6f5781..61194e3c2c940 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4715,17 +4715,15 @@ def OMPDeclareTargetDecl : InheritableAttr {
let SemaHandler = 0;
let Subjects = SubjectList<[Function, SharedVar]>;
let Documentation = [OMPDeclareTargetDocs];
- let Args = [
- EnumArgument<"MapType", "MapTypeTy", /*is_string=*/false,
- [ "to", "enter", "link" ],
- [ "MT_To", "MT_Enter", "MT_Link" ]>,
- EnumArgument<"DevType", "DevTypeTy", /*is_string=*/false,
- [ "host", "nohost", "any" ],
- [ "DT_Host", "DT_NoHost", "DT_Any" ]>,
- ExprArgument<"IndirectExpr">,
- BoolArgument<"Indirect">,
- UnsignedArgument<"Level">
- ];
+ let Args = [EnumArgument<
+ "MapType", "MapTypeTy",
+ /*is_string=*/false, ["to", "enter", "link", "local"],
+ ["MT_To", "MT_Enter", "MT_Link", "MT_Local"]>,
+ EnumArgument<"DevType", "DevTypeTy",
+ /*is_string=*/false, ["host", "nohost", "any"],
+ ["DT_Host", "DT_NoHost", "DT_Any"]>,
+ ExprArgument<"IndirectExpr">, BoolArgument<"Indirect">,
+ UnsignedArgument<"Level">];
let AdditionalMembers = [{
void printPrettyPragma(raw_ostream &OS, const PrintingPolicy &Policy) const;
static std::optional<MapTypeTy>
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index de10dbe5d0628..19edc7f7a3b23 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1558,18 +1558,21 @@ def note_omp_assumption_clause_continue_here
: 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_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'|'enter', "
+ "'link', 'device_type', 'indirect' or 'local'}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_wrong_clause_after_implicit_to: Error<
"unexpected clause after an implicit 'to' clause">;
def err_omp_declare_target_wrong_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_missing_required_clause
+ : Error<"expected at least one %select{'to' or 'link'|'to', 'link' or "
+ "'indirect'|'enter', 'link' or 'indirect'|'enter', 'link', "
+ "'indirect' or 'local'}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<
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 0c25eb2443d5e..38efae80429b8 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12127,13 +12127,16 @@ def warn_omp_alignment_not_power_of_two : Warning<
InGroup<OpenMPClauses>;
def err_omp_invalid_target_decl : Error<
"%0 used in declare target directive is not a variable or a function name">;
-def err_omp_declare_target_to_and_link : Error<
- "%0 must not appear in both clauses 'to' and 'link'">;
+def err_omp_declare_target_var_in_both_clauses
+ : Error<"%0 must not appear in both clauses '%1' and '%2'">;
+def err_omp_declare_target_local_host_only
+ : Error<"'local' clause is incompatible with 'device_type(host)'; "
+ "local variables exist only on the device">;
def warn_omp_not_in_target_context : Warning<
"declaration is not declared in any declare target region">,
InGroup<OpenMPTarget>;
-def err_omp_function_in_link_clause : Error<
- "function name is not allowed in 'link' clause">;
+def err_omp_function_in_target_clause_list
+ : Error<"function name is not allowed in '%0' clause">;
def err_omp_aligned_expected_array_or_ptr : Error<
"argument of aligned clause should be array"
"%select{ or pointer|, pointer, reference to array or reference to pointer}1"
@@ -12549,6 +12552,11 @@ def err_omp_declare_target_has_local_vars : Error<
def warn_omp_declare_target_after_first_use : Warning<
"declaration marked as declare target after first use, it may lead to incorrect results">,
InGroup<OpenMPTarget>;
+def warn_omp_declare_target_local_not_implemented
+ : Warning<"'local' clause on 'declare_target' directive is not yet fully "
+ "implemented; "
+ "variable will be treated as 'enter'">,
+ InGroup<OpenMPTarget>;
def err_omp_declare_variant_incompat_attributes : Error<
"'#pragma omp declare variant' is not compatible with any target-specific attributes">;
def warn_omp_declare_variant_score_not_constant
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index 069846b854a87..88b2b6b3c33fb 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -3327,15 +3327,18 @@ static Address emitDeclTargetVarDeclLValue(CodeGenFunction &CGF,
std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD);
// 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.
+ // OpenMP 5.2, or MT_Local in OpenMP 6.0) and unified memory is not enabled.
+ // For all other cases: MT_Link and MT_To (or MT_Enter/MT_Local) with unified
+ // memory, return a valid address.
if (!Res || ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
!CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory()))
return Address::invalid();
assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
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
index 3ec09b4e8c630..fb87a42b1cad2 100644
--- a/clang/lib/CodeGen/CGOpenMPRuntime.cpp
+++ b/clang/lib/CodeGen/CGOpenMPRuntime.cpp
@@ -1529,6 +1529,7 @@ convertCaptureClause(const VarDecl *VD) {
return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryTo;
break;
case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Enter:
+ case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Local:
return llvm::OffloadEntriesInfoManager::OMPTargetGlobalVarEntryEnter;
break;
case OMPDeclareTargetDeclAttr::MapTypeTy::MT_Link:
@@ -7980,7 +7981,8 @@ class MappableExprsHandler {
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(VD)) {
if ((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
CGF.CGM.getOpenMPRuntime().hasRequiresUnifiedSharedMemory())) {
RequiresReference = true;
BP = CGF.CGM.getOpenMPRuntime().getAddrOfDeclareTargetVar(VD);
@@ -11299,7 +11301,8 @@ bool CGOpenMPRuntime::emitTargetGlobalVariable(GlobalDecl GD) {
cast<VarDecl>(GD.getDecl()));
if (!Res || *Res == OMPDeclareTargetDeclAttr::MT_Link ||
((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
HasRequiresUnifiedSharedMemory)) {
DeferredGlobalVariables.insert(cast<VarDecl>(GD.getDecl()));
return true;
@@ -11369,13 +11372,15 @@ void CGOpenMPRuntime::emitDeferredTargetDecls() const {
if (!Res)
continue;
if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
!HasRequiresUnifiedSharedMemory) {
CGM.EmitGlobal(VD);
} else {
assert((*Res == OMPDeclareTargetDeclAttr::MT_Link ||
((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
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
index 3b64be7a477d6..153bfad5fae18 100644
--- a/clang/lib/CodeGen/CodeGenModule.cpp
+++ b/clang/lib/CodeGen/CodeGenModule.cpp
@@ -4407,13 +4407,15 @@ void CodeGenModule::EmitGlobal(GlobalDecl GD) {
bool UnifiedMemoryEnabled =
getOpenMPRuntime().hasRequiresUnifiedSharedMemory();
if ((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
!UnifiedMemoryEnabled) {
(void)GetAddrOfGlobalVar(VD);
} else {
assert(((*Res == OMPDeclareTargetDeclAttr::MT_Link) ||
((*Res == OMPDeclareTargetDeclAttr::MT_To ||
- *Res == OMPDeclareTargetDeclAttr::MT_Enter) &&
+ *Res == OMPDeclareTargetDeclAttr::MT_Enter ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local) &&
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
index 0bb503484299d..29397d67b5bcc 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -1758,14 +1758,14 @@ parseOpenMPSimpleClause(Parser &P, OpenMPClauseKind Kind) {
void Parser::ParseOMPDeclareTargetClauses(
SemaOpenMP::DeclareTargetContextInfo &DTCI) {
SourceLocation DeviceTypeLoc;
- bool RequiresToOrLinkOrIndirectClause = false;
- bool HasToOrLinkOrIndirectClause = false;
+ bool RequiresToLinkLocalOrIndirectClause = false;
+ bool HasToLinkLocalOrIndirectClause = false;
while (Tok.isNot(tok::annot_pragma_openmp_end)) {
OMPDeclareTargetDeclAttr::MapTypeTy MT = OMPDeclareTargetDeclAttr::MT_To;
bool HasIdentifier = Tok.is(tok::identifier);
if (HasIdentifier) {
- // If we see any clause we need a to or link clause.
- RequiresToOrLinkOrIndirectClause = true;
+ // If we see any clause we need a to, link, or local clause.
+ RequiresToLinkLocalOrIndirectClause = true;
IdentifierInfo *II = Tok.getIdentifierInfo();
StringRef ClauseName = II->getName();
bool IsDeviceTypeClause =
@@ -1774,6 +1774,7 @@ 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)
@@ -1781,9 +1782,9 @@ void Parser::ParseOMPDeclareTargetClauses(
<< getOpenMPClauseName(OMPC_indirect) << 0;
break;
}
- bool IsToEnterOrLinkClause =
+ bool IsToEnterLinkOrLocalClause =
OMPDeclareTargetDeclAttr::ConvertStrToMapTypeTy(ClauseName, MT);
- assert((!IsDeviceTypeClause || !IsToEnterOrLinkClause) &&
+ assert((!IsDeviceTypeClause || !IsToEnterLinkOrLocalClause) &&
"Cannot be both!");
// Starting with OpenMP 5.2 the `to` clause has been replaced by the
@@ -1797,25 +1798,42 @@ void Parser::ParseOMPDeclareTargetClauses(
break;
}
+ // The 'local' clause is only available in OpenMP 6.0.
+ if (getLangOpts().OpenMP < 60 && ClauseName == "local") {
+ 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);
+ break;
+ }
+
if (!IsDeviceTypeClause && !IsIndirectClause &&
DTCI.Kind == OMPD_begin_declare_target) {
- Diag(Tok, diag::err_omp_declare_target_unexpected_clause)
+ Diag(Tok, getLangOpts().OpenMP >= 52
+ ? diag::err_omp_declare_target_unexpected_clause_52
+ : diag::err_omp_declare_target_unexpected_clause)
<< ClauseName << (getLangOpts().OpenMP >= 51 ? 3 : 0);
break;
}
- if (!IsDeviceTypeClause && !IsToEnterOrLinkClause && !IsIndirectClause) {
+
+ if (!IsDeviceTypeClause && !IsToEnterLinkOrLocalClause &&
+ !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 > 52 ? 5
+ : getLangOpts().OpenMP >= 51 ? 4
+ : getLangOpts().OpenMP >= 50 ? 2
+ : 1);
break;
}
- if (IsToEnterOrLinkClause || IsIndirectClause)
- HasToOrLinkOrIndirectClause = true;
+ if (IsToEnterLinkOrLocalClause || IsIndirectClause)
+ HasToLinkLocalOrIndirectClause = true;
if (IsIndirectClause) {
if (!ParseOpenMPIndirectClause(DTCI, /*ParseOnly*/ false))
@@ -1892,14 +1910,14 @@ void Parser::ParseOMPDeclareTargetClauses(
if (DTCI.Indirect && DTCI.DT != OMPDeclareTargetDeclAttr::DT_Any)
Diag(DeviceTypeLoc, diag::err_omp_declare_target_indirect_device_type);
- // For declare target require at least 'to' or 'link' to be present.
- if (DTCI.Kind == OMPD_declare_target && RequiresToOrLinkOrIndirectClause &&
- !HasToOrLinkOrIndirectClause)
- 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);
+ // declare target requires at least one clause.
+ if (DTCI.Kind == OMPD_declare_target && RequiresToLinkLocalOrIndirectClause &&
+ !HasToLinkLocalOrIndirectClause)
+ Diag(DTCI.Loc, diag::err_omp_declare_target_missing_required_clause)
+ << (getLangOpts().OpenMP >= 60 ? 3
+ : getLangOpts().OpenMP == 52 ? 2
+ : 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
index bbb4f939028ec..fe7199be4ead3 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -24453,6 +24453,14 @@ void SemaOpenMP::ActOnOpenMPDeclareTargetName(
if (getLangOpts().HIP)
Diag(Loc, diag::warn_hip_omp_target_directives);
+ // 'local' is incompatible with 'device_type(host)' because 'local'
+ // variables exist only on the device.
+ if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
+ DTCI.DT == OMPDeclareTargetDeclAttr::DT_Host) {
+ Diag(Loc, diag::err_omp_declare_target_local_host_only);
+ return;
+ }
+
// Explicit declare target lists have precedence.
const unsigned Level = -1;
@@ -24469,7 +24477,11 @@ void SemaOpenMP::ActOnOpenMPDeclareTargetName(
}
if (ActiveAttr && (*ActiveAttr)->getMapType() != MT &&
(*ActiveAttr)->getLevel() == Level) {
- Diag(Loc, diag::err_omp_declare_target_to_and_link) << ND;
+ Diag(Loc, diag::err_omp_declare_target_var_in_both_clauses)
+ << ND
+ << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(
+ (*ActiveAttr)->getMapType())
+ << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(MT);
return;
}
@@ -24483,6 +24495,11 @@ void SemaOpenMP::ActOnOpenMPDeclareTargetName(
if (!IndirectE)
IsIndirect = true;
}
+ // FIXME: 'local' clause is not yet implemented in CodeGen. For now, it is
+ // treated as 'enter'. For host compilation, 'local' is a no-op.
+ if (MT == OMPDeclareTargetDeclAttr::MT_Local &&
+ getLangOpts().OpenMPIsTargetDevice)
+ Diag(Loc, diag::warn_omp_declare_target_local_not_implemented);
auto *A = OMPDeclareTargetDeclAttr::CreateImplicit(
getASTContext(), MT, DTCI.DT, IndirectE, IsIndirect, Level,
SourceRange(Loc, Loc));
@@ -24508,7 +24525,8 @@ static void checkDeclInTargetContext(SourceLocation SL, SourceRange SR,
SemaRef.getCurBlock() || SemaRef.getCurCapturedRegion()) &&
VD->hasGlobalStorage()) {
if (!MapTy || (*MapTy != OMPDeclareTargetDeclAttr::MT_To &&
- *MapTy != OMPDeclareTargetDeclAttr::MT_Enter)) {
+ *MapTy != OMPDeclareTargetDeclAttr::MT_Enter &&
+ *MapTy != OMPDeclareTargetDeclAttr::MT_Local)) {
// 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
@@ -24559,8 +24577,11 @@ void SemaOpenMP::checkDeclIsAllowedInOpenMPTarget(Expr *E, Decl *D,
if (auto *FD = dyn_cast<FunctionDecl>(D)) {
std::optional<OMPDeclareTargetDeclAttr::MapTypeTy> Res =
OMPDeclareTargetDeclAttr::isDeclareTargetDeclaration(FD);
- if (IdLoc.isValid() && Res && *Res == OMPDeclareTargetDeclAttr::MT_Link) {
- Diag(IdLoc, diag::err_omp_function_in_link_clause);
+ if (IdLoc.isValid() && Res &&
+ (*Res == OMPDeclareTargetDeclAttr::MT_Link ||
+ *Res == OMPDeclareTargetDeclAttr::MT_Local)) {
+ Diag(IdLoc, diag::err_omp_function_in_target_clause_list)
+ << OMPDeclareTargetDeclAttr::ConvertMapTypeTyToStr(*Res);
Diag(FD->getLocation(), diag::note_defined_here) << FD;
return;
}
diff --git a/clang/test/AST/dump.cpp b/clang/test/AST/dump.cpp
ind...
[truncated]
``````````
</details>
https://github.com/llvm/llvm-project/pull/186281
More information about the cfe-commits
mailing list