Skip to content

Commit 1456802

Browse files
committed
Improve type checks, add testcases
1 parent 144170c commit 1456802

File tree

3 files changed

+86
-23
lines changed

3 files changed

+86
-23
lines changed

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

Lines changed: 55 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -2955,13 +2955,6 @@ struct VariableFinder : public evaluate::AnyTraverse<VariableFinder> {
29552955
};
29562956
} // namespace atomic
29572957

2958-
static bool IsAllocatable(const SomeExpr &expr) {
2959-
std::vector<SomeExpr> dsgs{atomic::DesignatorCollector{}(expr)};
2960-
assert(dsgs.size() == 1 && "Should have a single top-level designator");
2961-
evaluate::SymbolVector syms{evaluate::GetSymbolVector(dsgs.front())};
2962-
return !syms.empty() && IsAllocatable(syms.back()) && !IsArrayElement(expr);
2963-
}
2964-
29652958
static bool IsPointerAssignment(const evaluate::Assignment &x) {
29662959
return std::holds_alternative<evaluate::Assignment::BoundsSpec>(x.u) ||
29672960
std::holds_alternative<evaluate::Assignment::BoundsRemapping>(x.u);
@@ -3149,30 +3142,69 @@ void OmpStructureChecker::ErrorShouldBeVariable(
31493142
/// function references with scalar data pointer result of non-character
31503143
/// intrinsic type or variables that are non-polymorphic scalar pointers
31513144
/// and any length type parameter must be constant.
3152-
void OmpStructureChecker::CheckAtomicVariable(
3153-
const SomeExpr &atom, parser::CharBlock source) {
3154-
if (atom.Rank() != 0) {
3155-
context_.Say(source, "Atomic variable %s should be a scalar"_err_en_US,
3156-
atom.AsFortran());
3145+
void OmpStructureChecker::CheckAtomicType(SymbolRef sym,
3146+
parser::CharBlock source,
3147+
std::string_view name) {
3148+
const DeclTypeSpec *typeSpec{sym->GetType()};
3149+
if (!typeSpec) {
3150+
return;
31573151
}
31583152

3159-
if (std::optional<evaluate::DynamicType> dtype{atom.GetType()}) {
3160-
if (dtype->category() == TypeCategory::Character) {
3153+
if (!IsPointer(sym)) {
3154+
using Category = DeclTypeSpec::Category;
3155+
Category cat{typeSpec->category()};
3156+
if (cat == Category::Character) {
31613157
context_.Say(source,
3162-
"Atomic variable %s cannot have CHARACTER type"_err_en_US,
3163-
atom.AsFortran());
3164-
} else if (dtype->IsPolymorphic()) {
3158+
"Atomic variable %s cannot have CHARACTER type"_err_en_US,
3159+
name);
3160+
} else if (cat != Category::Numeric && cat != Category::Logical) {
31653161
context_.Say(source,
3166-
"Atomic variable %s cannot have a polymorphic type"_err_en_US,
3167-
atom.AsFortran());
3162+
"Atomic variable %s should have an intrinsic type"_err_en_US,
3163+
name);
31683164
}
3169-
// TODO: Check non-constant type parameters for non-character types.
3170-
// At the moment there don't seem to be any.
3165+
return;
3166+
}
3167+
3168+
// Variable is a pointer.
3169+
if (typeSpec->IsPolymorphic()) {
3170+
context_.Say(
3171+
source,
3172+
"Atomic variable %s cannot be a pointer to a polymorphic type"_err_en_US,
3173+
name);
3174+
return;
31713175
}
31723176

3173-
if (IsAllocatable(atom)) {
3177+
// Go over all length parameters, if any, and check if they are
3178+
// explicit.
3179+
if (const DerivedTypeSpec *derived{typeSpec->AsDerived()}) {
3180+
if (llvm::any_of(derived->parameters(), [](auto &&entry) {
3181+
// "entry" is a map entry
3182+
return entry.second.isLen() && !entry.second.isExplicit();
3183+
})) {
3184+
context_.Say(
3185+
source,
3186+
"Atomic variable %s is a pointer to a type with non-constant length parameter"_err_en_US,
3187+
name);
3188+
}
3189+
}
3190+
}
3191+
3192+
void OmpStructureChecker::CheckAtomicVariable(const SomeExpr &atom,
3193+
parser::CharBlock source) {
3194+
if (atom.Rank() != 0) {
3195+
context_.Say(source, "Atomic variable %s should be a scalar"_err_en_US,
3196+
atom.AsFortran());
3197+
}
3198+
3199+
std::vector<SomeExpr> dsgs{atomic::DesignatorCollector{}(atom)};
3200+
assert(dsgs.size() == 1 && "Should have a single top-level designator");
3201+
evaluate::SymbolVector syms{evaluate::GetSymbolVector(dsgs.front())};
3202+
3203+
CheckAtomicType(syms.back(), source, atom.AsFortran());
3204+
3205+
if (IsAllocatable(syms.back()) && !IsArrayElement(atom)) {
31743206
context_.Say(source, "Atomic variable %s cannot be ALLOCATABLE"_err_en_US,
3175-
atom.AsFortran());
3207+
atom.AsFortran());
31763208
}
31773209
}
31783210

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,8 @@ class OmpStructureChecker
259259
void CheckStorageOverlap(const evaluate::Expr<evaluate::SomeType> &,
260260
llvm::ArrayRef<evaluate::Expr<evaluate::SomeType>>, parser::CharBlock);
261261
void ErrorShouldBeVariable(const MaybeExpr &expr, parser::CharBlock source);
262+
void CheckAtomicType(
263+
SymbolRef sym, parser::CharBlock source, std::string_view name);
262264
void CheckAtomicVariable(
263265
const evaluate::Expr<evaluate::SomeType> &, parser::CharBlock);
264266
std::pair<const parser::ExecutionPartConstruct *,

flang/test/Semantics/OpenMP/atomic-read.f90

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,32 @@ subroutine f07
8787
v = x
8888
end
8989

90+
subroutine f08
91+
type :: struct
92+
integer :: m
93+
end type
94+
type(struct) :: x, v
95+
96+
!$omp atomic read
97+
!ERROR: Atomic variable x should have an intrinsic type
98+
v = x
99+
end
100+
101+
subroutine f09(x, v)
102+
class(*), pointer :: x, v
103+
104+
!$omp atomic read
105+
!ERROR: Atomic variable x cannot be a pointer to a polymorphic type
106+
v => x
107+
end
108+
109+
subroutine f10(x, v)
110+
type struct(length)
111+
integer, len :: length
112+
end type
113+
type(struct(*)), pointer :: x, v
114+
115+
!$omp atomic read
116+
!ERROR: Atomic variable x is a pointer to a type with non-constant length parameter
117+
v => x
118+
end

0 commit comments

Comments
 (0)