37
37
38
38
#include " llvm/ADT/ArrayRef.h"
39
39
#include " llvm/ADT/STLExtras.h"
40
+ #include " llvm/ADT/StringExtras.h"
40
41
#include " llvm/ADT/StringRef.h"
41
42
#include " llvm/Frontend/OpenMP/OMP.h"
42
43
@@ -3398,23 +3399,22 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
3398
3399
}
3399
3400
}
3400
3401
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 ;
3417
3406
}
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 ());
3418
3418
}
3419
3419
3420
3420
void OmpStructureChecker::Enter (const parser::OmpClause::Map &x) {
@@ -3435,27 +3435,62 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
3435
3435
CheckIteratorModifier (*iter);
3436
3436
}
3437
3437
if (auto *type{OmpGetUniqueModifier<parser::OmpMapType>(modifiers)}) {
3438
+ using Directive = llvm::omp::Directive;
3438
3439
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);
3459
3494
}
3460
3495
}
3461
3496
0 commit comments