diff options
| -rw-r--r-- | clang/include/clang/Basic/DiagnosticSemaKinds.td | 6 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 71 | ||||
| -rw-r--r-- | clang/test/OpenMP/allocate_allocator_ast_print.cpp | 11 | ||||
| -rw-r--r-- | clang/test/OpenMP/allocate_allocator_messages.cpp | 17 | ||||
| -rw-r--r-- | clang/test/OpenMP/allocate_codegen.cpp | 6 |
5 files changed, 95 insertions, 16 deletions
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 1644ea97916..c37dad11d1b 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -9146,6 +9146,12 @@ def err_omp_expected_predefined_allocator : Error< "storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', " "'omp_const_mem_alloc', 'omp_high_bw_mem_alloc', 'omp_low_lat_mem_alloc', " "'omp_cgroup_mem_alloc', 'omp_pteam_mem_alloc' or 'omp_thread_mem_alloc'">; +def warn_omp_used_different_allocator : Warning< + "allocate directive specifies %select{default|'%1'}0 allocator while " + "previously used %select{default|'%3'}2">, + InGroup<OpenMPClauses>; +def note_omp_previous_allocator : Note< + "previous allocator is specified here">; } // end of OpenMP category let CategoryName = "Related Result Type Issue" in { diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index 794ca2bee70..8b35371e0e3 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -2216,6 +2216,61 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective( if (isa<ParmVarDecl>(VD)) continue; + // If the used several times in the allocate directive, the same allocator + // must be used. + if (VD->hasAttr<OMPAllocateDeclAttr>()) { + const auto *A = VD->getAttr<OMPAllocateDeclAttr>(); + const Expr *PrevAllocator = A->getAllocator(); + bool AllocatorsMatch = false; + if (Allocator && PrevAllocator) { + const Expr *AE = Allocator->IgnoreParenImpCasts(); + const Expr *PAE = PrevAllocator->IgnoreParenImpCasts(); + llvm::FoldingSetNodeID AEId, PAEId; + AE->Profile(AEId, Context, /*Canonical=*/true); + PAE->Profile(PAEId, Context, /*Canonical=*/true); + AllocatorsMatch = AEId == PAEId; + } else if (!Allocator && !PrevAllocator) { + AllocatorsMatch = true; + } else { + const Expr *AE = Allocator ? Allocator : PrevAllocator; + // In this case the specified allocator must be the default one. + AE = AE->IgnoreParenImpCasts(); + if (const auto *DRE = dyn_cast<DeclRefExpr>(AE)) { + DeclarationName DN = DRE->getDecl()->getDeclName(); + AllocatorsMatch = + DN.isIdentifier() && + DN.getAsIdentifierInfo()->isStr("omp_default_mem_alloc"); + } + } + if (!AllocatorsMatch) { + SmallString<256> AllocatorBuffer; + llvm::raw_svector_ostream AllocatorStream(AllocatorBuffer); + if (Allocator) + Allocator->printPretty(AllocatorStream, nullptr, getPrintingPolicy()); + SmallString<256> PrevAllocatorBuffer; + llvm::raw_svector_ostream PrevAllocatorStream(PrevAllocatorBuffer); + if (PrevAllocator) + PrevAllocator->printPretty(PrevAllocatorStream, nullptr, + getPrintingPolicy()); + + SourceLocation AllocatorLoc = + Allocator ? Allocator->getExprLoc() : RefExpr->getExprLoc(); + SourceRange AllocatorRange = + Allocator ? Allocator->getSourceRange() : RefExpr->getSourceRange(); + SourceLocation PrevAllocatorLoc = + PrevAllocator ? PrevAllocator->getExprLoc() : A->getLocation(); + SourceRange PrevAllocatorRange = + PrevAllocator ? PrevAllocator->getSourceRange() : A->getRange(); + Diag(AllocatorLoc, diag::warn_omp_used_different_allocator) + << (Allocator ? 1 : 0) << AllocatorStream.str() + << (PrevAllocator ? 1 : 0) << PrevAllocatorStream.str() + << AllocatorRange; + Diag(PrevAllocatorLoc, diag::note_omp_previous_allocator) + << PrevAllocatorRange; + continue; + } + } + // OpenMP, 2.11.3 allocate Directive, Restrictions, C / C++ // If a list item has a static storage type, the allocator expression in the // allocator clause must be a constant expression that evaluates to one of @@ -2254,11 +2309,17 @@ Sema::DeclGroupPtrTy Sema::ActOnOpenMPAllocateDirective( } Vars.push_back(RefExpr); - Attr *A = OMPAllocateDeclAttr::CreateImplicit(Context, Allocator, - DE->getSourceRange()); - VD->addAttr(A); - if (ASTMutationListener *ML = Context.getASTMutationListener()) - ML->DeclarationMarkedOpenMPAllocate(VD, A); + if ((!Allocator || (Allocator && !Allocator->isTypeDependent() && + !Allocator->isValueDependent() && + !Allocator->isInstantiationDependent() && + !Allocator->containsUnexpandedParameterPack())) && + !VD->hasAttr<OMPAllocateDeclAttr>()) { + Attr *A = OMPAllocateDeclAttr::CreateImplicit(Context, Allocator, + DE->getSourceRange()); + VD->addAttr(A); + if (ASTMutationListener *ML = Context.getASTMutationListener()) + ML->DeclarationMarkedOpenMPAllocate(VD, A); + } } if (Vars.empty()) return nullptr; diff --git a/clang/test/OpenMP/allocate_allocator_ast_print.cpp b/clang/test/OpenMP/allocate_allocator_ast_print.cpp index a9e838dc7c0..02c669e1577 100644 --- a/clang/test/OpenMP/allocate_allocator_ast_print.cpp +++ b/clang/test/OpenMP/allocate_allocator_ast_print.cpp @@ -38,15 +38,16 @@ struct St1{ // CHECK-NEXT: #pragma omp allocate(St1::b) allocator(omp_default_mem_alloc){{$}} } d; -int a, b; +int a, b, c; // CHECK: int a; // CHECK: int b; +// CHECK: int c; #pragma omp allocate(a) allocator(omp_large_cap_mem_alloc) -#pragma omp allocate(a) allocator(omp_const_mem_alloc) +#pragma omp allocate(b) allocator(omp_const_mem_alloc) // CHECK-NEXT: #pragma omp allocate(a) allocator(omp_large_cap_mem_alloc) -// CHECK-NEXT: #pragma omp allocate(a) allocator(omp_const_mem_alloc) -#pragma omp allocate(d, b) allocator(omp_high_bw_mem_alloc) -// CHECK-NEXT: #pragma omp allocate(d,b) allocator(omp_high_bw_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(b) allocator(omp_const_mem_alloc) +#pragma omp allocate(c, d) allocator(omp_high_bw_mem_alloc) +// CHECK-NEXT: #pragma omp allocate(c,d) allocator(omp_high_bw_mem_alloc) template <class T> struct ST { diff --git a/clang/test/OpenMP/allocate_allocator_messages.cpp b/clang/test/OpenMP/allocate_allocator_messages.cpp index b5af2b5f71c..db7d53d2f2c 100644 --- a/clang/test/OpenMP/allocate_allocator_messages.cpp +++ b/clang/test/OpenMP/allocate_allocator_messages.cpp @@ -14,16 +14,27 @@ int sss; #pragma omp allocate(sss) allocator(0,sss) // expected-error {{expected ')'}} expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} expected-note {{to match this '('}} #pragma omp allocate(sss) allocator(sss) // expected-error {{omp_allocator_handle_t type not found; include <omp.h>}} -typedef void *omp_allocator_handle_t; +typedef void **omp_allocator_handle_t; +extern const omp_allocator_handle_t omp_thread_mem_alloc; +extern const omp_allocator_handle_t omp_high_bw_mem_alloc; struct St1{ int a; static int b; -#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'omp_allocator_handle_t' (aka 'void *') with an expression of incompatible type 'int'}} +#pragma omp allocate(b) allocator(sss) // expected-error {{initializing 'omp_allocator_handle_t' (aka 'void **') with an expression of incompatible type 'int'}} expected-note {{previous allocator is specified here}} +#pragma omp allocate(b) +#pragma omp allocate(b) allocator(omp_thread_mem_alloc) // expected-warning {{allocate directive specifies 'omp_thread_mem_alloc' allocator while previously used default}} } d; // expected-note 2 {{'d' defined here}} // expected-error@+1 {{expected one of the predefined allocators for the variables with the static storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', 'omp_const_mem_alloc', 'omp_high_bw_mem_alloc', 'omp_low_lat_mem_alloc', 'omp_cgroup_mem_alloc', 'omp_pteam_mem_alloc' or 'omp_thread_mem_alloc'}} #pragma omp allocate(d) allocator(nullptr) -extern void *allocator; +extern void **allocator; // expected-error@+1 {{expected one of the predefined allocators for the variables with the static storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', 'omp_const_mem_alloc', 'omp_high_bw_mem_alloc', 'omp_low_lat_mem_alloc', 'omp_cgroup_mem_alloc', 'omp_pteam_mem_alloc' or 'omp_thread_mem_alloc'}} #pragma omp allocate(d) allocator(allocator) +#pragma omp allocate(d) allocator(omp_thread_mem_alloc) // expected-note {{previous allocator is specified here}} +#pragma omp allocate(d) // expected-warning {{allocate directive specifies default allocator while previously used 'omp_thread_mem_alloc'}} + +int c; +#pragma omp allocate(c) allocator(omp_thread_mem_alloc) // expected-note {{previous allocator is specified here}} +#pragma omp allocate(c) allocator(omp_high_bw_mem_alloc) // expected-warning {{allocate directive specifies 'omp_high_bw_mem_alloc' allocator while previously used 'omp_thread_mem_alloc'}} + diff --git a/clang/test/OpenMP/allocate_codegen.cpp b/clang/test/OpenMP/allocate_codegen.cpp index eac2b9f3883..6239ded455d 100644 --- a/clang/test/OpenMP/allocate_codegen.cpp +++ b/clang/test/OpenMP/allocate_codegen.cpp @@ -37,10 +37,10 @@ struct St1{ #pragma omp allocate(b) allocator(omp_default_mem_alloc) } d; -int a, b; +int a, b, c; #pragma omp allocate(a) allocator(omp_large_cap_mem_alloc) -#pragma omp allocate(a) allocator(omp_const_mem_alloc) -#pragma omp allocate(d, b) allocator(omp_high_bw_mem_alloc) +#pragma omp allocate(b) allocator(omp_const_mem_alloc) +#pragma omp allocate(d, c) allocator(omp_high_bw_mem_alloc) template <class T> struct ST { |

