3737
3838#include " llvm/ADT/ArrayRef.h"
3939#include " llvm/ADT/STLExtras.h"
40+ #include " llvm/ADT/StringExtras.h"
4041#include " llvm/ADT/StringRef.h"
4142#include " llvm/Frontend/OpenMP/OMP.h"
4243
@@ -3398,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
33983399 }
33993400}
34003401
3401- void OmpStructureChecker::CheckAllowedMapTypes (
3402- const parser::OmpMapType::Value &type,
3403- const std::list<parser::OmpMapType::Value> &allowedMapTypeList) {
3404- if (!llvm::is_contained (allowedMapTypeList, type)) {
3405- std::string commaSeparatedMapTypes;
3406- llvm::interleave (
3407- allowedMapTypeList.begin (), allowedMapTypeList.end (),
3408- [&](const parser::OmpMapType::Value &mapType) {
3409- commaSeparatedMapTypes.append (parser::ToUpperCaseLetters (
3410- parser::OmpMapType::EnumToString (mapType)));
3411- },
3412- [&] { commaSeparatedMapTypes.append (" , " ); });
3413- context_.Say (GetContext ().clauseSource ,
3414- " Only the %s map types are permitted "
3415- " for MAP clauses on the %s directive" _err_en_US,
3416- commaSeparatedMapTypes, ContextDirectiveAsFortran ());
3402+ void OmpStructureChecker::CheckAllowedMapTypes (parser::OmpMapType::Value type,
3403+ llvm::ArrayRef<parser::OmpMapType::Value> allowed) {
3404+ if (llvm::is_contained (allowed, type)) {
3405+ return ;
34173406 }
3407+
3408+ llvm::SmallVector<std::string> names;
3409+ llvm::transform (
3410+ allowed, std::back_inserter (names), [](parser::OmpMapType::Value val) {
3411+ return parser::ToUpperCaseLetters (
3412+ parser::OmpMapType::EnumToString (val));
3413+ });
3414+ llvm::sort (names);
3415+ context_.Say (GetContext ().clauseSource ,
3416+ " Only the %s map types are permitted for MAP clauses on the %s directive" _err_en_US,
3417+ llvm::join (names, " , " ), ContextDirectiveAsFortran ());
34183418}
34193419
34203420void OmpStructureChecker::Enter (const parser::OmpClause::Map &x) {
@@ -3435,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
34353435 CheckIteratorModifier (*iter);
34363436 }
34373437 if (auto *type{OmpGetUniqueModifier<parser::OmpMapType>(modifiers)}) {
3438+ using Directive = llvm::omp::Directive;
34383439 using Value = parser::OmpMapType::Value;
3439- switch (GetContext ().directive ) {
3440- case llvm::omp::Directive::OMPD_target:
3441- case llvm::omp::Directive::OMPD_target_teams:
3442- case llvm::omp::Directive::OMPD_target_teams_distribute:
3443- case llvm::omp::Directive::OMPD_target_teams_distribute_simd:
3444- case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do:
3445- case llvm::omp::Directive::OMPD_target_teams_distribute_parallel_do_simd:
3446- case llvm::omp::Directive::OMPD_target_data:
3447- CheckAllowedMapTypes (
3448- type->v , {Value::To, Value::From, Value::Tofrom, Value::Alloc});
3449- break ;
3450- case llvm::omp::Directive::OMPD_target_enter_data:
3451- CheckAllowedMapTypes (type->v , {Value::To, Value::Alloc});
3452- break ;
3453- case llvm::omp::Directive::OMPD_target_exit_data:
3454- CheckAllowedMapTypes (
3455- type->v , {Value::From, Value::Release, Value::Delete});
3456- break ;
3457- default :
3458- break ;
3440+
3441+ static auto isValidForVersion{
3442+ [](parser::OmpMapType::Value t, unsigned version) {
3443+ switch (t) {
3444+ case parser::OmpMapType::Value::Alloc:
3445+ case parser::OmpMapType::Value::Delete:
3446+ case parser::OmpMapType::Value::Release:
3447+ return version < 60 ;
3448+ case parser::OmpMapType::Value::Storage:
3449+ return version >= 60 ;
3450+ default :
3451+ return true ;
3452+ }
3453+ }};
3454+
3455+ llvm::SmallVector<parser::OmpMapType::Value> mapEnteringTypes{[&]() {
3456+ llvm::SmallVector<parser::OmpMapType::Value> result;
3457+ for (size_t i{0 }; i != parser::OmpMapType::Value_enumSize; ++i) {
3458+ auto t{static_cast <parser::OmpMapType::Value>(i)};
3459+ if (isValidForVersion (t, version) && IsMapEnteringType (t)) {
3460+ result.push_back (t);
3461+ }
3462+ }
3463+ return result;
3464+ }()};
3465+ llvm::SmallVector<parser::OmpMapType::Value> mapExitingTypes{[&]() {
3466+ llvm::SmallVector<parser::OmpMapType::Value> result;
3467+ for (size_t i{0 }; i != parser::OmpMapType::Value_enumSize; ++i) {
3468+ auto t{static_cast <parser::OmpMapType::Value>(i)};
3469+ if (isValidForVersion (t, version) && IsMapExitingType (t)) {
3470+ result.push_back (t);
3471+ }
3472+ }
3473+ return result;
3474+ }()};
3475+
3476+ llvm::omp::Directive dir{GetContext ().directive };
3477+ llvm::ArrayRef<llvm::omp::Directive> leafs{
3478+ llvm::omp::getLeafConstructsOrSelf (dir)};
3479+
3480+ if (llvm::is_contained (leafs, Directive::OMPD_target) ||
3481+ llvm::is_contained (leafs, Directive::OMPD_target_data)) {
3482+ if (version >= 60 ) {
3483+ // Map types listed in the decay table. [6.0:276]
3484+ CheckAllowedMapTypes (
3485+ type->v , {Value::Storage, Value::From, Value::To, Value::Tofrom});
3486+ } else {
3487+ CheckAllowedMapTypes (
3488+ type->v , {Value::Alloc, Value::From, Value::To, Value::Tofrom});
3489+ }
3490+ } else if (llvm::is_contained (leafs, Directive::OMPD_target_enter_data)) {
3491+ CheckAllowedMapTypes (type->v , mapEnteringTypes);
3492+ } else if (llvm::is_contained (leafs, Directive::OMPD_target_exit_data)) {
3493+ CheckAllowedMapTypes (type->v , mapExitingTypes);
34593494 }
34603495 }
34613496
0 commit comments