| // { dg-do compile } | |
| /* { dg-additional-options "-Wno-deprecated-openmp" } */ | |
| #include <omp.h> | |
| /* | |
| typedef __UINTPTR_TYPE__ omp_uintptr_t; | |
| #if __cplusplus >= 201103L | |
| # define __GOMP_UINTPTR_T_ENUM : omp_uintptr_t | |
| #else | |
| # define __GOMP_UINTPTR_T_ENUM | |
| #endif | |
| typedef enum omp_memspace_handle_t __GOMP_UINTPTR_T_ENUM | |
| { | |
| omp_default_mem_space = 0, | |
| omp_large_cap_mem_space = 1, | |
| omp_const_mem_space = 2, | |
| omp_high_bw_mem_space = 3, | |
| omp_low_lat_mem_space = 4, | |
| ompx_gnu_managed_mem_space = 200, | |
| __omp_memspace_handle_t_max__ = __UINTPTR_MAX__ | |
| } omp_memspace_handle_t; | |
| typedef enum omp_allocator_handle_t __GOMP_UINTPTR_T_ENUM | |
| { | |
| omp_null_allocator = 0, | |
| omp_default_mem_alloc = 1, | |
| omp_large_cap_mem_alloc = 2, | |
| omp_const_mem_alloc = 3, | |
| omp_high_bw_mem_alloc = 4, | |
| omp_low_lat_mem_alloc = 5, | |
| omp_cgroup_mem_alloc = 6, | |
| omp_pteam_mem_alloc = 7, | |
| omp_thread_mem_alloc = 8, | |
| ompx_gnu_pinned_mem_alloc = 200, | |
| ompx_gnu_managed_mem_alloc = 201, | |
| __omp_allocator_handle_t_max__ = __UINTPTR_MAX__ | |
| } omp_allocator_handle_t; | |
| typedef struct omp_alloctrait_t | |
| { | |
| // omp_alloctrait_key_t key; | |
| // omp_uintptr_t value; | |
| } omp_alloctrait_t; | |
| */ | |
| template<typename TH, TH alloc> | |
| void f() | |
| { | |
| #pragma omp target uses_allocators(alloc) | |
| ; | |
| } | |
| template<typename TH, typename TT> | |
| void g(TT trait, TH alloc) | |
| { | |
| #pragma omp target uses_allocators(alloc) | |
| ; | |
| #pragma omp target uses_allocators(alloc(trait)) | |
| // { dg-error "traits array 'trait' must be defined in same scope as the construct on which the clause appears" "" { target *-*-* } .-1 } | |
| // { dg-error "traits array 'trait' must be of 'const omp_alloctrait_t \\\[\\\]' type" "" { target *-*-* } .-2 } | |
| ; | |
| } | |
| void use() | |
| { | |
| omp_allocator_handle_t my; | |
| static const omp_alloctrait_t t[] = {}; | |
| f<omp_allocator_handle_t, omp_null_allocator>(); // OK | |
| f<omp_allocator_handle_t, omp_default_mem_alloc>(); // OK | |
| g<omp_allocator_handle_t, const omp_alloctrait_t[]>(t, my); // 't'/traits not in the same scope | |
| } | |
| template<typename TH, TH alloc> | |
| void f2() | |
| { | |
| #pragma omp target uses_allocators(alloc) | |
| // { dg-error "allocator '\\(omp_allocator_handle_t\\)300' must be either a variable or a predefined allocator" "" { target *-*-* } .-1 } | |
| ; | |
| } | |
| template<typename TH, typename TT> | |
| void g2(TH alloc) | |
| { | |
| TT t = {}; | |
| #pragma omp target uses_allocators(alloc(t)) | |
| ; | |
| } | |
| void use2() | |
| { | |
| omp_allocator_handle_t my; | |
| const omp_allocator_handle_t wrong = (omp_allocator_handle_t) 300; | |
| f2<omp_allocator_handle_t, wrong>(); // 300 is not a predefined allocator | |
| g2<omp_allocator_handle_t, const omp_alloctrait_t[]>(my); // OK | |
| } |