[flang][OpenMP] Sema checks, lowering with new format of MAP modifiers (#149137)

OpenMP 6.0 has changed the modifiers on the MAP clause. Previous patch
has introduced parsing support for them. This patch introduces
processing of the new forms in semantic checks and in lowering. This
only applies to existing modifiers, which were updated in the 6.0 spec.
Any of the newly introduced modifiers (SELF and REF) are ignored.
This commit is contained in:
Krzysztof Parzyszek 2025-07-22 07:37:47 -05:00 committed by GitHub
parent b692b239f0
commit 2914a488c7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 297 additions and 131 deletions

View File

@ -812,9 +812,8 @@ public:
// OpenMP data-sharing attribute
OmpShared, OmpPrivate, OmpLinear, OmpFirstPrivate, OmpLastPrivate,
// OpenMP data-mapping attribute
OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapAlloc, OmpMapRelease,
OmpMapDelete, OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr,
OmpHasDeviceAddr,
OmpMapTo, OmpMapFrom, OmpMapToFrom, OmpMapStorage, OmpMapDelete,
OmpUseDevicePtr, OmpUseDeviceAddr, OmpIsDevicePtr, OmpHasDeviceAddr,
// OpenMP data-copying attribute
OmpCopyIn, OmpCopyPrivate,
// OpenMP miscellaneous flags

View File

@ -1315,7 +1315,8 @@ bool ClauseProcessor::processMap(
const parser::CharBlock &source) {
using Map = omp::clause::Map;
mlir::Location clauseLocation = converter.genLocation(source);
const auto &[mapType, typeMods, mappers, iterator, objects] = clause.t;
const auto &[mapType, typeMods, refMod, mappers, iterator, objects] =
clause.t;
llvm::omp::OpenMPOffloadMappingFlags mapTypeBits =
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_NONE;
std::string mapperIdName = "__implicit_mapper";
@ -1342,16 +1343,13 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_TO |
llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_FROM;
break;
case Map::MapType::Alloc:
case Map::MapType::Release:
case Map::MapType::Storage:
// alloc and release is the default map_type for the Target Data
// Ops, i.e. if no bits for map_type is supplied then alloc/release
// is implicitly assumed based on the target directive. Default
// value for Target Data and Enter Data is alloc and for Exit Data
// it is release.
// (aka storage in 6.0+) is implicitly assumed based on the target
// directive. Default value for Target Data and Enter Data is alloc
// and for Exit Data it is release.
break;
case Map::MapType::Delete:
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
}
if (typeMods) {
@ -1362,6 +1360,8 @@ bool ClauseProcessor::processMap(
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_PRESENT;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Close))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_CLOSE;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::Delete))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_DELETE;
if (llvm::is_contained(*typeMods, Map::MapTypeModifier::OmpxHold))
mapTypeBits |= llvm::omp::OpenMPOffloadMappingFlags::OMP_MAP_OMPX_HOLD;
}

View File

@ -1001,19 +1001,21 @@ Map make(const parser::OmpClause::Map &inp,
semantics::SemanticsContext &semaCtx) {
// inp.v -> parser::OmpMapClause
CLAUSET_ENUM_CONVERT( //
convert1, parser::OmpMapType::Value, Map::MapType,
convertMapType, parser::OmpMapType::Value, Map::MapType,
// clang-format off
MS(Alloc, Alloc)
MS(Delete, Delete)
MS(From, From)
MS(Release, Release)
MS(To, To)
MS(Tofrom, Tofrom)
MS(Alloc, Storage)
MS(Delete, Storage)
MS(Release, Storage)
MS(Storage, Storage)
MS(From, From)
MS(To, To)
MS(Tofrom, Tofrom)
// clang-format on
);
CLAUSET_ENUM_CONVERT( //
convert2, parser::OmpMapTypeModifier::Value, Map::MapTypeModifier,
convertMapTypeMod, parser::OmpMapTypeModifier::Value,
Map::MapTypeModifier,
// clang-format off
MS(Always, Always)
MS(Close, Close)
@ -1022,43 +1024,76 @@ Map make(const parser::OmpClause::Map &inp,
// clang-format on
);
CLAUSET_ENUM_CONVERT( //
convertRefMod, parser::OmpRefModifier::Value, Map::RefModifier,
// clang-format off
MS(Ref_Ptee, RefPtee)
MS(Ref_Ptr, RefPtr)
MS(Ref_Ptr_Ptee, RefPtrPtee)
// clang-format on
);
// Treat always, close, present, self, delete modifiers as map-type-
// modifiers.
auto &mods = semantics::OmpGetModifiers(inp.v);
auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods);
auto *t2 = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods);
auto *t3 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
auto &t4 = std::get<parser::OmpObjectList>(inp.v.t);
auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpMapType>(mods);
auto &t2 = std::get<parser::OmpObjectList>(inp.v.t);
auto type = [&]() -> std::optional<Map::MapType> {
if (t1)
return convertMapType(t1->v);
return std::nullopt;
}();
llvm::DenseSet<Map::MapTypeModifier> modSet;
if (t1 && t1->v == parser::OmpMapType::Value::Delete)
modSet.insert(Map::MapTypeModifier::Delete);
for (auto *typeMod :
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
modSet.insert(convertMapTypeMod(typeMod->v));
}
if (semantics::OmpGetUniqueModifier<parser::OmpAlwaysModifier>(mods))
modSet.insert(Map::MapTypeModifier::Always);
if (semantics::OmpGetUniqueModifier<parser::OmpCloseModifier>(mods))
modSet.insert(Map::MapTypeModifier::Close);
if (semantics::OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods))
modSet.insert(Map::MapTypeModifier::Delete);
if (semantics::OmpGetUniqueModifier<parser::OmpPresentModifier>(mods))
modSet.insert(Map::MapTypeModifier::Present);
if (semantics::OmpGetUniqueModifier<parser::OmpSelfModifier>(mods))
modSet.insert(Map::MapTypeModifier::Self);
if (semantics::OmpGetUniqueModifier<parser::OmpxHoldModifier>(mods))
modSet.insert(Map::MapTypeModifier::OmpxHold);
std::optional<Map::MapTypeModifiers> maybeTypeMods{};
if (!modSet.empty())
maybeTypeMods = Map::MapTypeModifiers(modSet.begin(), modSet.end());
auto refMod = [&]() -> std::optional<Map::RefModifier> {
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpRefModifier>(mods))
return convertRefMod(t->v);
return std::nullopt;
}();
auto mappers = [&]() -> std::optional<List<Mapper>> {
if (t1)
return List<Mapper>{Mapper{makeObject(t1->v, semaCtx)}};
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpMapper>(mods))
return List<Mapper>{Mapper{makeObject(t->v, semaCtx)}};
return std::nullopt;
}();
auto iterator = [&]() -> std::optional<Iterator> {
if (t2)
return makeIterator(*t2, semaCtx);
if (auto *t = semantics::OmpGetUniqueModifier<parser::OmpIterator>(mods))
return makeIterator(*t, semaCtx);
return std::nullopt;
}();
auto type = [&]() -> std::optional<Map::MapType> {
if (t3)
return convert1(t3->v);
return std::nullopt;
}();
Map::MapTypeModifiers typeMods;
for (auto *typeMod :
semantics::OmpGetRepeatableModifier<parser::OmpMapTypeModifier>(mods)) {
typeMods.push_back(convert2(typeMod->v));
}
std::optional<Map::MapTypeModifiers> maybeTypeMods{};
if (!typeMods.empty())
maybeTypeMods = std::move(typeMods);
return Map{{/*MapType=*/std::move(type),
/*MapTypeModifiers=*/std::move(maybeTypeMods),
/*Mapper=*/std::move(mappers), /*Iterator=*/std::move(iterator),
/*LocatorList=*/makeObjects(t4, semaCtx)}};
/*RefModifier=*/std::move(refMod), /*Mapper=*/std::move(mappers),
/*Iterator=*/std::move(iterator),
/*LocatorList=*/makeObjects(t2, semaCtx)}};
}
Match make(const parser::OmpClause::Match &inp,

View File

@ -27,7 +27,8 @@ class CanonicalizationOfOmp {
public:
template <typename T> bool Pre(T &) { return true; }
template <typename T> void Post(T &) {}
CanonicalizationOfOmp(parser::Messages &messages) : messages_{messages} {}
CanonicalizationOfOmp(SemanticsContext &context)
: context_{context}, messages_{context.messages()} {}
void Post(parser::Block &block) {
for (auto it{block.begin()}; it != block.end(); ++it) {
@ -401,6 +402,11 @@ private:
// if the specified OpenMP version is less than 6.0, rewrite the affected
// modifiers back into the pre-6.0 forms.
void CanonicalizeMapModifiers(parser::OmpMapClause &map) {
unsigned version{context_.langOptions().OpenMPVersion};
if (version >= 60) {
return;
}
// Omp{Always, Close, Present, xHold}Modifier -> OmpMapTypeModifier
// OmpDeleteModifier -> OmpMapType
using Modifier = parser::OmpMapClause::Modifier;
@ -432,12 +438,13 @@ private:
// same construct. This is for converting utility constructs to executable
// constructs.
std::map<parser::SpecificationPart *, parser::Block *> blockForSpec_;
SemanticsContext &context_;
parser::Messages &messages_;
};
bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program) {
CanonicalizationOfOmp omp{messages};
bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program) {
CanonicalizationOfOmp omp{context};
Walk(program, omp);
return !messages.AnyFatalError();
return !context.messages().AnyFatalError();
}
} // namespace Fortran::semantics

View File

@ -11,13 +11,12 @@
namespace Fortran::parser {
struct Program;
class Messages;
} // namespace Fortran::parser
}
namespace Fortran::semantics {
class SemanticsContext;
bool CanonicalizeOmp(parser::Messages &messages, parser::Program &program);
bool CanonicalizeOmp(SemanticsContext &context, parser::Program &program);
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CANONICALIZE_OMP_H_

View File

@ -37,6 +37,7 @@
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Frontend/OpenMP/OMP.h"
@ -3398,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
}
}
void OmpStructureChecker::CheckAllowedMapTypes(
const parser::OmpMapType::Value &type,
const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
if (!llvm::is_contained(allowedMapTypeList, type)) {
std::string commaSeparatedMapTypes;
llvm::interleave(
allowedMapTypeList.begin(), allowedMapTypeList.end(),
[&](const parser::OmpMapType::Value &mapType) {
commaSeparatedMapTypes.append(parser::ToUpperCaseLetters(
parser::OmpMapType::EnumToString(mapType)));
},
[&] { commaSeparatedMapTypes.append(", "); });
context_.Say(GetContext().clauseSource,
"Only the %s map types are permitted "
"for MAP clauses on the %s directive"_err_en_US,
commaSeparatedMapTypes, ContextDirectiveAsFortran());
void OmpStructureChecker::CheckAllowedMapTypes(parser::OmpMapType::Value type,
llvm::ArrayRef<parser::OmpMapType::Value> allowed) {
if (llvm::is_contained(allowed, type)) {
return;
}
llvm::SmallVector<std::string> names;
llvm::transform(
allowed, std::back_inserter(names), [](parser::OmpMapType::Value val) {
return parser::ToUpperCaseLetters(
parser::OmpMapType::EnumToString(val));
});
llvm::sort(names);
context_.Say(GetContext().clauseSource,
"Only the %s map types are permitted for MAP clauses on the %s directive"_err_en_US,
llvm::join(names, ", "), ContextDirectiveAsFortran());
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
@ -3435,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
CheckIteratorModifier(*iter);
}
if (auto *type{OmpGetUniqueModifier<parser::OmpMapType>(modifiers)}) {
using Directive = llvm::omp::Directive;
using Value = parser::OmpMapType::Value;
switch (GetContext().directive) {
case llvm::omp::Directive::OMPD_target:
case llvm::omp::Directive::OMPD_target_teams:
case llvm::omp::Directive::OMPD_target_teams_distribute:
case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
case llvm::omp::Directive::OMPD_target_data:
CheckAllowedMapTypes(
type->v, {Value::To, Value::From, Value::Tofrom, Value::Alloc});
break;
case llvm::omp::Directive::OMPD_target_enter_data:
CheckAllowedMapTypes(type->v, {Value::To, Value::Alloc});
break;
case llvm::omp::Directive::OMPD_target_exit_data:
CheckAllowedMapTypes(
type->v, {Value::From, Value::Release, Value::Delete});
break;
default:
break;
static auto isValidForVersion{
[](parser::OmpMapType::Value t, unsigned version) {
switch (t) {
case parser::OmpMapType::Value::Alloc:
case parser::OmpMapType::Value::Delete:
case parser::OmpMapType::Value::Release:
return version < 60;
case parser::OmpMapType::Value::Storage:
return version >= 60;
default:
return true;
}
}};
llvm::SmallVector<parser::OmpMapType::Value> mapEnteringTypes{[&]() {
llvm::SmallVector<parser::OmpMapType::Value> result;
for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
auto t{static_cast<parser::OmpMapType::Value>(i)};
if (isValidForVersion(t, version) && IsMapEnteringType(t)) {
result.push_back(t);
}
}
return result;
}()};
llvm::SmallVector<parser::OmpMapType::Value> mapExitingTypes{[&]() {
llvm::SmallVector<parser::OmpMapType::Value> result;
for (size_t i{0}; i != parser::OmpMapType::Value_enumSize; ++i) {
auto t{static_cast<parser::OmpMapType::Value>(i)};
if (isValidForVersion(t, version) && IsMapExitingType(t)) {
result.push_back(t);
}
}
return result;
}()};
llvm::omp::Directive dir{GetContext().directive};
llvm::ArrayRef<llvm::omp::Directive> leafs{
llvm::omp::getLeafConstructsOrSelf(dir)};
if (llvm::is_contained(leafs, Directive::OMPD_target) ||
llvm::is_contained(leafs, Directive::OMPD_target_data)) {
if (version >= 60) {
// Map types listed in the decay table. [6.0:276]
CheckAllowedMapTypes(
type->v, {Value::Storage, Value::From, Value::To, Value::Tofrom});
} else {
CheckAllowedMapTypes(
type->v, {Value::Alloc, Value::From, Value::To, Value::Tofrom});
}
} else if (llvm::is_contained(leafs, Directive::OMPD_target_enter_data)) {
CheckAllowedMapTypes(type->v, mapEnteringTypes);
} else if (llvm::is_contained(leafs, Directive::OMPD_target_exit_data)) {
CheckAllowedMapTypes(type->v, mapExitingTypes);
}
}

View File

@ -179,8 +179,8 @@ private:
void HasInvalidDistributeNesting(const parser::OpenMPLoopConstruct &x);
void HasInvalidLoopBinding(const parser::OpenMPLoopConstruct &x);
// specific clause related
void CheckAllowedMapTypes(const parser::OmpMapType::Value &,
const std::list<parser::OmpMapType::Value> &);
void CheckAllowedMapTypes(
parser::OmpMapType::Value, llvm::ArrayRef<parser::OmpMapType::Value>);
const std::list<parser::OmpTraitProperty> &GetTraitPropertyList(
const parser::OmpTraitSelector &);

View File

@ -143,6 +143,31 @@ bool IsVarOrFunctionRef(const MaybeExpr &expr) {
}
}
bool IsMapEnteringType(parser::OmpMapType::Value type) {
switch (type) {
case parser::OmpMapType::Value::Alloc:
case parser::OmpMapType::Value::Storage:
case parser::OmpMapType::Value::To:
case parser::OmpMapType::Value::Tofrom:
return true;
default:
return false;
}
}
bool IsMapExitingType(parser::OmpMapType::Value type) {
switch (type) {
case parser::OmpMapType::Value::Delete:
case parser::OmpMapType::Value::From:
case parser::OmpMapType::Value::Release:
case parser::OmpMapType::Value::Storage:
case parser::OmpMapType::Value::Tofrom:
return true;
default:
return false;
}
}
std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr) {
const parser::TypedExpr &typedExpr{parserExpr.typedExpr};
// ForwardOwningPointer typedExpr

View File

@ -59,6 +59,9 @@ bool IsExtendedListItem(const Symbol &sym);
bool IsVariableListItem(const Symbol &sym);
bool IsVarOrFunctionRef(const MaybeExpr &expr);
bool IsMapEnteringType(parser::OmpMapType::Value type);
bool IsMapExitingType(parser::OmpMapType::Value type);
std::optional<SomeExpr> GetEvaluateExpr(const parser::Expr &parserExpr);
std::optional<evaluate::DynamicType> GetDynamicType(
const parser::Expr &parserExpr);

View File

@ -727,7 +727,9 @@ public:
void Post(const parser::EorLabel &eorLabel) { CheckSourceLabel(eorLabel.v); }
void Post(const parser::OmpMapClause &x) {
Symbol::Flag ompFlag = Symbol::Flag::OmpMapToFrom;
unsigned version{context_.langOptions().OpenMPVersion};
std::optional<Symbol::Flag> ompFlag;
auto &mods{OmpGetModifiers(x)};
if (auto *mapType{OmpGetUniqueModifier<parser::OmpMapType>(mods)}) {
switch (mapType->v) {
@ -741,10 +743,9 @@ public:
ompFlag = Symbol::Flag::OmpMapToFrom;
break;
case parser::OmpMapType::Value::Alloc:
ompFlag = Symbol::Flag::OmpMapAlloc;
break;
case parser::OmpMapType::Value::Release:
ompFlag = Symbol::Flag::OmpMapRelease;
case parser::OmpMapType::Value::Storage:
ompFlag = Symbol::Flag::OmpMapStorage;
break;
case parser::OmpMapType::Value::Delete:
ompFlag = Symbol::Flag::OmpMapDelete;
@ -753,6 +754,24 @@ public:
break;
}
}
if (!ompFlag) {
if (version >= 60) {
// [6.0:275:12-15]
// When a map-type is not specified for a clause on which it may be
// specified, the map-type defaults to storage if the delete-modifier
// is present on the clause or if the list item for which the map-type
// is not specified is an assumed-size array.
if (OmpGetUniqueModifier<parser::OmpDeleteModifier>(mods)) {
ompFlag = Symbol::Flag::OmpMapStorage;
}
// Otherwise, if delete-modifier is absent, leave ompFlag unset.
} else {
// [5.2:151:10]
// If a map-type is not specified, the map-type defaults to tofrom.
ompFlag = Symbol::Flag::OmpMapToFrom;
}
}
const auto &ompObjList{std::get<parser::OmpObjectList>(x.t)};
for (const auto &ompObj : ompObjList.v) {
common::visit(
@ -761,15 +780,15 @@ public:
if (const auto *name{
semantics::getDesignatorNameIfDataRef(designator)}) {
if (name->symbol) {
name->symbol->set(ompFlag);
AddToContextObjectWithDSA(*name->symbol, ompFlag);
}
if (name->symbol &&
semantics::IsAssumedSizeArray(*name->symbol)) {
context_.Say(designator.source,
"Assumed-size whole arrays may not appear on the %s "
"clause"_err_en_US,
"MAP");
name->symbol->set(
ompFlag.value_or(Symbol::Flag::OmpMapStorage));
AddToContextObjectWithDSA(*name->symbol, *ompFlag);
if (semantics::IsAssumedSizeArray(*name->symbol)) {
context_.Say(designator.source,
"Assumed-size whole arrays may not appear on the %s "
"clause"_err_en_US,
"MAP");
}
}
}
},
@ -777,7 +796,7 @@ public:
},
ompObj.u);
ResolveOmpObject(ompObj, ompFlag);
ResolveOmpObject(ompObj, ompFlag.value_or(Symbol::Flag::OmpMapStorage));
}
}
@ -2776,9 +2795,8 @@ void OmpAttributeVisitor::ResolveOmpObject(
}
Symbol::Flag dataMappingAttributeFlags[] = {
Symbol::Flag::OmpMapTo, Symbol::Flag::OmpMapFrom,
Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapAlloc,
Symbol::Flag::OmpMapRelease, Symbol::Flag::OmpMapDelete,
Symbol::Flag::OmpIsDevicePtr,
Symbol::Flag::OmpMapToFrom, Symbol::Flag::OmpMapStorage,
Symbol::Flag::OmpMapDelete, Symbol::Flag::OmpIsDevicePtr,
Symbol::Flag::OmpHasDeviceAddr};
Symbol::Flag dataSharingAttributeFlags[] = {

View File

@ -642,8 +642,7 @@ bool Semantics::Perform() {
return ValidateLabels(context_, program_) &&
parser::CanonicalizeDo(program_) && // force line break
CanonicalizeAcc(context_.messages(), program_) &&
CanonicalizeOmp(context_.messages(), program_) &&
CanonicalizeCUDA(program_) &&
CanonicalizeOmp(context_, program_) && CanonicalizeCUDA(program_) &&
PerformStatementSemantics(context_, program_) &&
CanonicalizeDirectives(context_.messages(), program_) &&
ModFileWriter{context_}

View File

@ -861,8 +861,7 @@ std::string Symbol::OmpFlagToClauseName(Symbol::Flag ompFlag) {
case Symbol::Flag::OmpMapTo:
case Symbol::Flag::OmpMapFrom:
case Symbol::Flag::OmpMapToFrom:
case Symbol::Flag::OmpMapAlloc:
case Symbol::Flag::OmpMapRelease:
case Symbol::Flag::OmpMapStorage:
case Symbol::Flag::OmpMapDelete:
clauseName = "MAP";
break;

View File

@ -1,4 +1,6 @@
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=51 %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
! RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=60 %s -o - | FileCheck %s
subroutine map_present_target_data
integer :: x
@ -15,6 +17,14 @@ subroutine map_present_update
!$omp target update to(present: x)
end subroutine
subroutine map_always
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(always, tofrom) {{.*}} {name = "x"}
!CHECK: omp.target_data map_entries(%[[MAP]] : {{.*}}) {
!$omp target data map(always, tofrom: x)
!$omp end target data
end subroutine
subroutine map_close
integer :: x
!CHECK: %[[MAP:.*]] = omp.map.info {{.*}} map_clauses(close, tofrom) {{.*}} {name = "x"}

View File

@ -207,7 +207,7 @@ program main
enddo
!$omp end target teams
!ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS directive
!ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS directive
!$omp target teams map(delete:a)
do i = 1, N
a(i) = 3.14
@ -307,7 +307,7 @@ program main
enddo
!$omp end target teams distribute
!ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive
!ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE directive
!$omp target teams distribute map(delete:a)
do i = 1, N
a(i) = 3.14
@ -400,7 +400,7 @@ program main
enddo
!$omp end target teams distribute parallel do
!ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
!ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO directive
!$omp target teams distribute parallel do map(delete:a)
do i = 1, N
a(i) = 3.14
@ -500,7 +500,7 @@ program main
enddo
!$omp end target teams distribute parallel do simd
!ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
!ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET TEAMS DISTRIBUTE PARALLEL DO SIMD directive
!$omp target teams distribute parallel do simd map(delete:a)
do i = 1, N
a(i) = 3.14

View File

@ -123,7 +123,7 @@ program main
enddo
!$omp end target
!ERROR: Only the TO, FROM, TOFROM, ALLOC map types are permitted for MAP clauses on the TARGET directive
!ERROR: Only the ALLOC, FROM, TO, TOFROM map types are permitted for MAP clauses on the TARGET directive
!$omp target map(delete:a)
do i = 1, N
a = 3.14
@ -160,7 +160,7 @@ program main
!ERROR: At most one IF clause can appear on the TARGET ENTER DATA directive
!$omp target enter data map(to:a) if(.true.) if(.false.)
!ERROR: Only the TO, ALLOC map types are permitted for MAP clauses on the TARGET ENTER DATA directive
!ERROR: Only the ALLOC, TO, TOFROM map types are permitted for MAP clauses on the TARGET ENTER DATA directive
!$omp target enter data map(from:a)
!$omp target exit data map(delete:a)
@ -168,7 +168,7 @@ program main
!ERROR: At most one DEVICE clause can appear on the TARGET EXIT DATA directive
!$omp target exit data map(from:a) device(0) device(1)
!ERROR: Only the FROM, RELEASE, DELETE map types are permitted for MAP clauses on the TARGET EXIT DATA directive
!ERROR: Only the DELETE, FROM, RELEASE, TOFROM map types are permitted for MAP clauses on the TARGET EXIT DATA directive
!$omp target exit data map(to:a)
!$omp target update if(.true.) device(1) to(a) from(b) depend(inout:c) nowait

View File

@ -0,0 +1,35 @@
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=52 -Werror
subroutine f00(x)
integer :: x
!WARNING: 'self-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
!$omp target map(self: x)
x = x + 1
!$omp end target
end
subroutine f01(x)
integer, pointer :: x
!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
!$omp target map(ref_ptr: x)
x = x + 1
!$omp end target
end
subroutine f02(x)
integer, pointer :: x
!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
!$omp target map(ref_ptee: x)
x = x + 1
!$omp end target
end
subroutine f03(x)
integer, pointer :: x
!WARNING: 'ref-modifier' modifier is not supported in OpenMP v5.2, try -fopenmp-version=60
!$omp target map(ref_ptr_ptee: x)
x = x + 1
!$omp end target
end

View File

@ -779,16 +779,17 @@ struct LinkT {
template <typename T, typename I, typename E> //
struct MapT {
using LocatorList = ObjectListT<I, E>;
ENUM(MapType, To, From, Tofrom, Alloc, Release, Delete);
ENUM(MapTypeModifier, Always, Close, Present, OmpxHold);
ENUM(MapType, To, From, Tofrom, Storage);
ENUM(MapTypeModifier, Always, Close, Delete, Present, Self, OmpxHold);
ENUM(RefModifier, RefPtee, RefPtr, RefPtrPtee);
// See note at the definition of the MapperT type.
using Mappers = ListT<type::MapperT<I, E>>; // Not a spec name
using Iterator = type::IteratorT<T, I, E>;
using MapTypeModifiers = ListT<MapTypeModifier>; // Not a spec name
using TupleTrait = std::true_type;
std::tuple<OPT(MapType), OPT(MapTypeModifiers), OPT(Mappers), OPT(Iterator),
LocatorList>
std::tuple<OPT(MapType), OPT(MapTypeModifiers), OPT(RefModifier),
OPT(Mappers), OPT(Iterator), LocatorList>
t;
};

View File

@ -708,6 +708,7 @@ bool ConstructDecompositionT<C, H>::applyClause(
tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
{/*MapType=*/MapType::Tofrom,
/*MapTypeModifier=*/std::nullopt,
/*RefModifier=*/std::nullopt,
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
/*LocatorList=*/std::move(tofrom)}});
dirTarget->clauses.push_back(map);
@ -969,8 +970,8 @@ bool ConstructDecompositionT<C, H>::applyClause(
llvm::omp::Clause::OMPC_map,
tomp::clause::MapT<TypeTy, IdTy, ExprTy>{
{/*MapType=*/MapType::Tofrom, /*MapTypeModifier=*/std::nullopt,
/*Mapper=*/std::nullopt, /*Iterator=*/std::nullopt,
/*LocatorList=*/std::move(tofrom)}});
/*RefModifier=*/std::nullopt, /*Mapper=*/std::nullopt,
/*Iterator=*/std::nullopt, /*LocatorList=*/std::move(tofrom)}});
dirTarget->clauses.push_back(map);
applied = true;

View File

@ -431,8 +431,8 @@ TEST_F(OpenMPDecompositionTest, Firstprivate3) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (12), (27)
ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17)
ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (12), (27)
ASSERT_EQ(Dir1, "teams shared(x)"); // (6), (17)
ASSERT_EQ(Dir2, "distribute firstprivate(x) lastprivate(, (x))"); // (5), (21)
}
@ -574,9 +574,9 @@ TEST_F(OpenMPDecompositionTest, Lastprivate3) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (21), (27)
ASSERT_EQ(Dir1, "parallel shared(x)"); // (22)
ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21)
ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (21), (27)
ASSERT_EQ(Dir1, "parallel shared(x)"); // (22)
ASSERT_EQ(Dir2, "do lastprivate(, (x))"); // (21)
}
// SHARED
@ -984,9 +984,9 @@ TEST_F(OpenMPDecompositionTest, Reduction7) {
std::string Dir0 = stringify(Dec.output[0]);
std::string Dir1 = stringify(Dec.output[1]);
std::string Dir2 = stringify(Dec.output[2]);
ASSERT_EQ(Dir0, "target map(2, , , , (x))"); // (36), (10)
ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4)
ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36)
ASSERT_EQ(Dir0, "target map(2, , , , , (x))"); // (36), (10)
ASSERT_EQ(Dir1, "parallel shared(x)"); // (36), (1), (4)
ASSERT_EQ(Dir2, "do reduction(, (3), (x))"); // (36)
}
// IF