summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Basic/DiagnosticSemaKinds.td6
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp71
-rw-r--r--clang/test/OpenMP/allocate_allocator_ast_print.cpp11
-rw-r--r--clang/test/OpenMP/allocate_allocator_messages.cpp17
-rw-r--r--clang/test/OpenMP/allocate_codegen.cpp6
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 {
OpenPOWER on IntegriCloud