[flang-commits] [flang] 80ea006 - [flang] [openmp] Add Fortran specific semantic check 4 for OpenMP Allocate directive.
Isaac Perry via flang-commits
flang-commits at lists.llvm.org
Tue Jun 15 08:04:27 PDT 2021
Author: Isaac Perry
Date: 2021-06-15T16:04:04+01:00
New Revision: 80ea006ef9e08364854394b633b904fa85e38e4e
URL: https://github.com/llvm/llvm-project/commit/80ea006ef9e08364854394b633b904fa85e38e4e
DIFF: https://github.com/llvm/llvm-project/commit/80ea006ef9e08364854394b633b904fa85e38e4e.diff
LOG: [flang] [openmp] Add Fortran specific semantic check 4 for OpenMP Allocate directive.
This patch adds the 4th Fortran specific semantic check for the OpenMP
allocate directive: "If a list item has the SAVE attribute, is a common
block name, or is declared in the scope of a module, then only predefined
memory allocator parameters can be used in the allocator clause".
Code in this patch was based on code from https://reviews.llvm.org/D93549/new/.
Differential Revision: https://reviews.llvm.org/D102400
Added:
flang/test/Semantics/omp-allocate08.f90
Modified:
flang/include/flang/Semantics/tools.h
flang/lib/Semantics/check-omp-structure.cpp
flang/lib/Semantics/check-omp-structure.h
Removed:
################################################################################
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index bb7d0b6009ddb..aa48c7456aeb6 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -140,6 +140,9 @@ inline bool IsAllocatable(const Symbol &symbol) {
inline bool IsAllocatableOrPointer(const Symbol &symbol) {
return IsPointer(symbol) || IsAllocatable(symbol);
}
+inline bool IsSave(const Symbol &symbol) {
+ return symbol.attrs().test(Attr::SAVE);
+}
inline bool IsNamedConstant(const Symbol &symbol) {
return symbol.attrs().test(Attr::PARAMETER);
}
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index cfce1d0915d7d..07ca47d5c43b9 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -237,6 +237,47 @@ void OmpStructureChecker::HasInvalidTeamsNesting(
}
}
+void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
+ const parser::CharBlock &source, const parser::Name &name) {
+ if (const auto *symbol{name.symbol}) {
+ const auto *commonBlock{FindCommonBlockContaining(*symbol)};
+ const auto &scope{context_.FindScope(symbol->name())};
+ const Scope &containingScope{GetProgramUnitContaining(scope)};
+ if (!isPredefinedAllocator &&
+ (IsSave(*symbol) || commonBlock ||
+ containingScope.kind() == Scope::Kind::Module)) {
+ context_.Say(source,
+ "If list items within the ALLOCATE directive have the "
+ "SAVE attribute, are a common block name, or are "
+ "declared in the scope of a module, then only "
+ "predefined memory allocator parameters can be used "
+ "in the allocator clause"_err_en_US);
+ }
+ }
+}
+
+void OmpStructureChecker::CheckPredefinedAllocatorRestriction(
+ const parser::CharBlock &source,
+ const parser::OmpObjectList &ompObjectList) {
+ for (const auto &ompObject : ompObjectList.v) {
+ std::visit(
+ common::visitors{
+ [&](const parser::Designator &designator) {
+ if (const auto *dataRef{
+ std::get_if<parser::DataRef>(&designator.u)}) {
+ if (const auto *name{std::get_if<parser::Name>(&dataRef->u)}) {
+ CheckPredefinedAllocatorRestriction(source, *name);
+ }
+ }
+ },
+ [&](const parser::Name &name) {
+ CheckPredefinedAllocatorRestriction(source, name);
+ },
+ },
+ ompObject.u);
+ }
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
// Simd Construct with Ordered Construct Nesting check
// We cannot use CurrentDirectiveIsNested() here because
@@ -700,6 +741,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareSimdConstruct &) {
}
void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) {
+ isPredefinedAllocator = true;
const auto &dir{std::get<parser::Verbatim>(x.t)};
const auto &objectList{std::get<parser::OmpObjectList>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate);
@@ -707,9 +749,21 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAllocate &x) {
}
void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ const auto &objectList{std::get<parser::OmpObjectList>(x.t)};
+ CheckPredefinedAllocatorRestriction(dir.source, objectList);
dirContext_.pop_back();
}
+void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
+ CheckAllowed(llvm::omp::Clause::OMPC_allocator);
+ // Note: Predefined allocators are stored in ScalarExpr as numbers
+ // whereas custom allocators are stored as strings, so if the ScalarExpr
+ // actually has an int value, then it must be a predefined allocator
+ isPredefinedAllocator = GetIntValue(x.v).has_value();
+ RequiresPositiveParameter(llvm::omp::Clause::OMPC_allocator, x.v);
+}
+
void OmpStructureChecker::Enter(const parser::OpenMPDeclareTargetConstruct &x) {
const auto &dir{std::get<parser::Verbatim>(x.t)};
PushContext(dir.source, llvm::omp::Directive::OMPD_declare_target);
@@ -724,6 +778,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareTargetConstruct &) {
}
void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) {
+ isPredefinedAllocator = true;
const auto &dir{std::get<parser::Verbatim>(x.t)};
const auto &objectList{std::get<std::optional<parser::OmpObjectList>>(x.t)};
PushContextAndClauseSets(dir.source, llvm::omp::Directive::OMPD_allocate);
@@ -731,7 +786,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPExecutableAllocate &x) {
CheckIsVarPartOfAnotherVar(dir.source, *objectList);
}
-void OmpStructureChecker::Leave(const parser::OpenMPExecutableAllocate &) {
+void OmpStructureChecker::Leave(const parser::OpenMPExecutableAllocate &x) {
+ const auto &dir{std::get<parser::Verbatim>(x.t)};
+ const auto &objectList{std::get<std::optional<parser::OmpObjectList>>(x.t)};
+ if (objectList)
+ CheckPredefinedAllocatorRestriction(dir.source, *objectList);
dirContext_.pop_back();
}
@@ -1019,7 +1078,6 @@ CHECK_SIMPLE_CLAUSE(Novariants, OMPC_novariants)
CHECK_SIMPLE_CLAUSE(Nocontext, OMPC_nocontext)
CHECK_SIMPLE_CLAUSE(Filter, OMPC_filter)
-CHECK_REQ_SCALAR_INT_CLAUSE(Allocator, OMPC_allocator)
CHECK_REQ_SCALAR_INT_CLAUSE(Grainsize, OMPC_grainsize)
CHECK_REQ_SCALAR_INT_CLAUSE(NumTasks, OMPC_num_tasks)
CHECK_REQ_SCALAR_INT_CLAUSE(NumTeams, OMPC_num_teams)
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 9ca69eb14c33e..be9de114ef21e 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -236,6 +236,11 @@ class OmpStructureChecker
void CheckMultipleAppearanceAcrossContext(
const parser::OmpObjectList &ompObjectList);
const parser::OmpObjectList *GetOmpObjectList(const parser::OmpClause &);
+ void CheckPredefinedAllocatorRestriction(const parser::CharBlock &source,
+ const parser::OmpObjectList &ompObjectList);
+ void CheckPredefinedAllocatorRestriction(
+ const parser::CharBlock &source, const parser::Name &name);
+ bool isPredefinedAllocator{false};
};
} // namespace Fortran::semantics
#endif // FORTRAN_SEMANTICS_CHECK_OMP_STRUCTURE_H_
diff --git a/flang/test/Semantics/omp-allocate08.f90 b/flang/test/Semantics/omp-allocate08.f90
new file mode 100644
index 0000000000000..42caef9505e2f
--- /dev/null
+++ b/flang/test/Semantics/omp-allocate08.f90
@@ -0,0 +1,42 @@
+! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp
+! OpenMP Version 5.0
+! 2.11.3 allocate Directive
+! If list items within the ALLOCATE directive have the SAVE attribute, are a common block name, or are declared in the scope of a
+! module, then only predefined memory allocator parameters can be used in the allocator clause
+
+module AllocateModule
+ INTEGER :: z
+end module
+
+subroutine allocate()
+use omp_lib
+use AllocateModule
+ integer, SAVE :: x
+ integer :: w
+ COMMON /CommonName/ y
+
+ integer(kind=omp_allocator_handle_kind) :: custom_allocator
+ integer(kind=omp_memspace_handle_kind) :: memspace
+ type(omp_alloctrait), dimension(1) :: trait
+ memspace = omp_default_mem_space
+ trait(1)%key = fallback
+ trait(1)%value = default_mem_fb
+ custom_allocator = omp_init_allocator(memspace, 1, trait)
+
+ !$omp allocate(x) allocator(omp_default_mem_alloc)
+ !$omp allocate(y) allocator(omp_default_mem_alloc)
+ !$omp allocate(z) allocator(omp_default_mem_alloc)
+
+ !$omp allocate(x)
+ !$omp allocate(y)
+ !$omp allocate(z)
+
+ !$omp allocate(w) allocator(custom_allocator)
+
+ !ERROR: If list items within the ALLOCATE directive have the SAVE attribute, are a common block name, or are declared in the scope of a module, then only predefined memory allocator parameters can be used in the allocator clause
+ !$omp allocate(x) allocator(custom_allocator)
+ !ERROR: If list items within the ALLOCATE directive have the SAVE attribute, are a common block name, or are declared in the scope of a module, then only predefined memory allocator parameters can be used in the allocator clause
+ !$omp allocate(y) allocator(custom_allocator)
+ !ERROR: If list items within the ALLOCATE directive have the SAVE attribute, are a common block name, or are declared in the scope of a module, then only predefined memory allocator parameters can be used in the allocator clause
+ !$omp allocate(z) allocator(custom_allocator)
+end subroutine allocate
More information about the flang-commits
mailing list