Skip to content

Commit 6308531

Browse files
authored
[flang][OpenMP] Analyze objects in OmpObjectList on clauses (#155424)
This is intended to diagnose errors such as incorrect uses of assumed-size arrays, for example. Fixes #151990
1 parent a74a801 commit 6308531

File tree

7 files changed

+77
-7
lines changed

7 files changed

+77
-7
lines changed

flang/lib/Semantics/check-omp-structure.cpp

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,43 @@ bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
268268
return CheckAllowed(clause);
269269
}
270270

271+
void OmpStructureChecker::AnalyzeObject(
272+
const parser::OmpObject &object, bool allowAssumedSizeArrays) {
273+
if (std::holds_alternative<parser::Name>(object.u)) {
274+
// Do not analyze common block names. The analyzer will flag an error
275+
// on those.
276+
return;
277+
}
278+
if (auto *symbol{GetObjectSymbol(object)}) {
279+
// Eliminate certain kinds of symbols before running the analyzer to
280+
// avoid confusing error messages. The analyzer assumes that the context
281+
// of the object use is an expression, and some diagnostics are tailored
282+
// to that.
283+
if (symbol->has<DerivedTypeDetails>() || symbol->has<MiscDetails>()) {
284+
// Type names, construct names, etc.
285+
return;
286+
}
287+
if (auto *typeSpec{symbol->GetType()}) {
288+
if (typeSpec->category() == DeclTypeSpec::Category::Character) {
289+
// Don't pass character objects to the analyzer, it can emit somewhat
290+
// cryptic errors (e.g. "'obj' is not an array"). Substrings are
291+
// checked elsewhere in OmpStructureChecker.
292+
return;
293+
}
294+
}
295+
}
296+
evaluate::ExpressionAnalyzer ea{context_};
297+
auto restore{ea.AllowWholeAssumedSizeArray(allowAssumedSizeArrays)};
298+
common::visit([&](auto &&s) { ea.Analyze(s); }, object.u);
299+
}
300+
301+
void OmpStructureChecker::AnalyzeObjects(
302+
const parser::OmpObjectList &objects, bool allowAssumedSizeArrays) {
303+
for (const parser::OmpObject &object : objects.v) {
304+
AnalyzeObject(object, allowAssumedSizeArrays);
305+
}
306+
}
307+
271308
bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
272309
// Definition of close nesting:
273310
//
@@ -2697,8 +2734,9 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &) {
26972734
void OmpStructureChecker::Enter(const parser::OmpClause &x) {
26982735
SetContextClause(x);
26992736

2737+
llvm::omp::Clause id{x.Id()};
27002738
// The visitors for these clauses do their own checks.
2701-
switch (x.Id()) {
2739+
switch (id) {
27022740
case llvm::omp::Clause::OMPC_copyprivate:
27032741
case llvm::omp::Clause::OMPC_enter:
27042742
case llvm::omp::Clause::OMPC_lastprivate:
@@ -2712,7 +2750,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
27122750
// Named constants are OK to be used within 'shared' and 'firstprivate'
27132751
// clauses. The check for this happens a few lines below.
27142752
bool SharedOrFirstprivate = false;
2715-
switch (x.Id()) {
2753+
switch (id) {
27162754
case llvm::omp::Clause::OMPC_shared:
27172755
case llvm::omp::Clause::OMPC_firstprivate:
27182756
SharedOrFirstprivate = true;
@@ -2721,7 +2759,20 @@ void OmpStructureChecker::Enter(const parser::OmpClause &x) {
27212759
break;
27222760
}
27232761

2762+
auto allowsAssumedSizeArrays{[](llvm::omp::Clause c) {
2763+
// These clauses allow assumed-size-arrays as list items.
2764+
switch (c) {
2765+
case llvm::omp::Clause::OMPC_map:
2766+
case llvm::omp::Clause::OMPC_shared:
2767+
case llvm::omp::Clause::OMPC_use_device_addr:
2768+
return true;
2769+
default:
2770+
return false;
2771+
}
2772+
}};
2773+
27242774
if (const parser::OmpObjectList *objList{GetOmpObjectList(x)}) {
2775+
AnalyzeObjects(*objList, allowsAssumedSizeArrays(id));
27252776
SymbolSourceMap symbols;
27262777
GetSymbolsInObjectList(*objList, symbols);
27272778
for (const auto &[symbol, source] : symbols) {

flang/lib/Semantics/check-omp-structure.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ class OmpStructureChecker
167167
void CheckVariableListItem(const SymbolSourceMap &symbols);
168168
void CheckDirectiveSpelling(
169169
parser::CharBlock spelling, llvm::omp::Directive id);
170+
void AnalyzeObject(
171+
const parser::OmpObject &object, bool allowAssumedSizeArrays = false);
172+
void AnalyzeObjects(const parser::OmpObjectList &objects,
173+
bool allowAssumedSizeArrays = false);
170174
void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
171175
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
172176
const std::string &clauseName);

flang/test/Lower/OpenMP/Todo/omp-do-simd-linear.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
! RUN: %not_todo_cmd bbc -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
44
! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -o - %s 2>&1 | FileCheck %s
55
subroutine testDoSimdLinear(int_array)
6-
integer :: int_array(*)
6+
integer :: int_array(:)
77
!CHECK: not yet implemented: Unhandled clause LINEAR in SIMD construct
88
!$omp do simd linear(int_array)
99
do index_ = 1, 10

flang/test/Semantics/OpenMP/cray-pointer-usage.f90

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ subroutine test_cray_pointer_usage
44
integer :: i
55
real(8) :: var(*), pointee(2)
66
pointer(ivar, var)
7+
real(8) :: var2(10)
8+
pointer(ivar2, var2)
9+
! ERROR: Whole assumed-size array 'var' may not appear here without subscripts
710
! ERROR: Cray Pointee 'var' may not appear in LINEAR clause
811
! ERROR: The list item 'var' specified without the REF 'linear-modifier' must be of INTEGER type
912
! ERROR: The list item `var` must be a dummy argument
@@ -17,9 +20,9 @@ subroutine test_cray_pointer_usage
1720
print *, var(1)
1821
!$omp end parallel
1922

20-
! ERROR: Cray Pointee 'var' may not appear in PRIVATE clause, use Cray Pointer 'ivar' instead
21-
!$omp parallel num_threads(2) default(none) private(var)
22-
print *, var(1)
23+
! ERROR: Cray Pointee 'var2' may not appear in PRIVATE clause, use Cray Pointer 'ivar2' instead
24+
!$omp parallel num_threads(2) default(none) private(var2)
25+
print *, var2(1)
2326
!$omp end parallel
2427

2528
! ERROR: Cray Pointee 'var' may not appear in SHARED clause, use Cray Pointer 'ivar' instead

flang/test/Semantics/OpenMP/declare-mapper02.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,5 +6,6 @@
66
end type t1
77

88
!ERROR: ABSTRACT derived type may not be used here
9+
!ERROR: Reference to object with abstract derived type 't1' must be polymorphic
910
!$omp declare mapper(mm : t1::x) map(x, x%y)
1011
end

flang/test/Semantics/OpenMP/depend01.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ program omp_depend
2020
!ERROR: 'a' in DEPEND clause must have a positive stride
2121
!ERROR: 'b' in DEPEND clause must have a positive stride
2222
!ERROR: 'b' in DEPEND clause is a zero size array section
23-
!$omp task shared(x) depend(in: a(10:5:-1)) depend(in: b(5:10:-1))
23+
!$omp task shared(x) depend(in: a(10:5:-1)) depend(in: b(5:10:-1, 2))
2424
print *, a(5:10), b
2525
!$omp end task
2626

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
!RUN: %python %S/../test_errors.py %s %flang -fopenmp -fopenmp-version=45
2+
3+
subroutine foo(x)
4+
integer :: x(3, *)
5+
!$omp task depend(in:x(:,5))
6+
!$omp end task
7+
!ERROR: Assumed-size array 'x' must have explicit final subscript upper bound value
8+
!$omp task depend(in:x(5,:))
9+
!$omp end task
10+
end
11+

0 commit comments

Comments
 (0)