]> granicus.if.org Git - clang/commitdiff
[OPENMP]Warn if the different allocator is used for the variable.
authorAlexey Bataev <a.bataev@hotmail.com>
Tue, 19 Mar 2019 20:33:44 +0000 (20:33 +0000)
committerAlexey Bataev <a.bataev@hotmail.com>
Tue, 19 Mar 2019 20:33:44 +0000 (20:33 +0000)
If the allocator was specified for the variable and next one is found
with the different allocator, the warning is emitted, and the allocator
is ignored.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@356513 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaOpenMP.cpp
test/OpenMP/allocate_allocator_ast_print.cpp
test/OpenMP/allocate_allocator_messages.cpp
test/OpenMP/allocate_codegen.cpp

index 1644ea97916fafc37e391e872f5714b72a2bc61f..c37dad11d1b85721bac8c59e5f5acfe9205cd337 100644 (file)
@@ -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 {
index 794ca2bee70659be452e5c80ff9561fd77c3917f..8b35371e0e33645b3b50b2c928642ad9840eca4e 100644 (file)
@@ -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;
index a9e838dc7c0ab49490c221081fd3d414abe583bd..02c669e1577f52fb9b5b984ee21c4a7805359e82 100644 (file)
@@ -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 {
index b5af2b5f71c455c11df1efedda625dd8ff1a0adf..db7d53d2f2cee44143f1b7e62b09479258a9d5b6 100644 (file)
@@ -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'}}
+
index eac2b9f38837e56aeb9dc69b1221daa55dbebdb8..6239ded455d35854e48ba8da4a32f10e45f3ed86 100644 (file)
@@ -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 {