Skip to content

Commit 65472a5

Browse files
Krish GuptaKrish Gupta
authored andcommitted
[flang][OpenMP] Centralize pointer-to-non-intrinsic check via bool flag
1 parent 022dd65 commit 65472a5

File tree

3 files changed

+34
-47
lines changed

3 files changed

+34
-47
lines changed

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

Lines changed: 30 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -519,8 +519,8 @@ struct AtomicAnalysis {
519519
/// function references with scalar data pointer result of non-character
520520
/// intrinsic type or variables that are non-polymorphic scalar pointers
521521
/// and any length type parameter must be constant.
522-
void OmpStructureChecker::CheckAtomicType(
523-
SymbolRef sym, parser::CharBlock source, std::string_view name) {
522+
void OmpStructureChecker::CheckAtomicType(SymbolRef sym,
523+
parser::CharBlock source, std::string_view name, bool checkTypeOnPointer) {
524524
const DeclTypeSpec *typeSpec{sym->GetType()};
525525
if (!typeSpec) {
526526
return;
@@ -547,6 +547,22 @@ void OmpStructureChecker::CheckAtomicType(
547547
return;
548548
}
549549

550+
// Apply pointer-to-non-intrinsic rule only for intrinsic-assignment paths.
551+
if (checkTypeOnPointer) {
552+
using Category = DeclTypeSpec::Category;
553+
Category cat{typeSpec->category()};
554+
if (cat != Category::Numeric && cat != Category::Logical) {
555+
std::string details = " has the POINTER attribute";
556+
if (const auto *derived{typeSpec->AsDerived()}) {
557+
details += " and derived type '"s + derived->name().ToString() + "'";
558+
}
559+
context_.Say(source,
560+
"ATOMIC operation requires an intrinsic scalar variable; '%s'%s"_err_en_US,
561+
sym->name(), details);
562+
return;
563+
}
564+
}
565+
550566
// Go over all length parameters, if any, and check if they are
551567
// explicit.
552568
if (const DerivedTypeSpec *derived{typeSpec->AsDerived()}) {
@@ -562,7 +578,7 @@ void OmpStructureChecker::CheckAtomicType(
562578
}
563579

564580
void OmpStructureChecker::CheckAtomicVariable(
565-
const SomeExpr &atom, parser::CharBlock source) {
581+
const SomeExpr &atom, parser::CharBlock source, bool checkTypeOnPointer) {
566582
if (atom.Rank() != 0) {
567583
context_.Say(source, "Atomic variable %s should be a scalar"_err_en_US,
568584
atom.AsFortran());
@@ -572,46 +588,14 @@ void OmpStructureChecker::CheckAtomicVariable(
572588
assert(dsgs.size() == 1 && "Should have a single top-level designator");
573589
evaluate::SymbolVector syms{evaluate::GetSymbolVector(dsgs.front())};
574590

575-
CheckAtomicType(syms.back(), source, atom.AsFortran());
591+
CheckAtomicType(syms.back(), source, atom.AsFortran(), checkTypeOnPointer);
576592

577593
if (IsAllocatable(syms.back()) && !IsArrayElement(atom)) {
578594
context_.Say(source, "Atomic variable %s cannot be ALLOCATABLE"_err_en_US,
579595
atom.AsFortran());
580596
}
581597
}
582598

583-
void OmpStructureChecker::CheckAtomicVariable(const SomeExpr &atom,
584-
parser::CharBlock source, const evaluate::Assignment &assign) {
585-
// First do all the standard checks
586-
CheckAtomicVariable(atom, source);
587-
588-
// For intrinsic assignment, check if the variable is a pointer
589-
// to a non-intrinsic type, which is not allowed in atomic operations
590-
if (!IsPointerAssignment(assign)) {
591-
std::vector<SomeExpr> dsgs{GetAllDesignators(atom)};
592-
if (!dsgs.empty()) {
593-
evaluate::SymbolVector syms{evaluate::GetSymbolVector(dsgs.front())};
594-
if (!syms.empty() && IsPointer(syms.back())) {
595-
SymbolRef sym = syms.back();
596-
if (const DeclTypeSpec *typeSpec{sym->GetType()}) {
597-
using Category = DeclTypeSpec::Category;
598-
Category cat{typeSpec->category()};
599-
if (cat != Category::Numeric && cat != Category::Logical) {
600-
std::string details = " has the POINTER attribute";
601-
if (const auto *derived{typeSpec->AsDerived()}) {
602-
details +=
603-
" and derived type '"s + derived->name().ToString() + "'";
604-
}
605-
context_.Say(source,
606-
"ATOMIC operation requires an intrinsic scalar variable; '%s'%s"_err_en_US,
607-
sym->name(), details);
608-
}
609-
}
610-
}
611-
}
612-
}
613-
}
614-
615599
void OmpStructureChecker::CheckStorageOverlap(const SomeExpr &base,
616600
llvm::ArrayRef<evaluate::Expr<evaluate::SomeType>> exprs,
617601
parser::CharBlock source) {
@@ -821,7 +805,8 @@ void OmpStructureChecker::CheckAtomicCaptureAssignment(
821805
if (!IsVarOrFunctionRef(atom)) {
822806
ErrorShouldBeVariable(atom, rsrc);
823807
} else {
824-
CheckAtomicVariable(atom, rsrc, capture);
808+
CheckAtomicVariable(
809+
atom, rsrc, /*checkTypeOnPointer=*/!IsPointerAssignment(capture));
825810
// This part should have been checked prior to calling this function.
826811
assert(*GetConvertInput(capture.rhs) == atom &&
827812
"This cannot be a capture assignment");
@@ -840,7 +825,8 @@ void OmpStructureChecker::CheckAtomicReadAssignment(
840825
if (!IsVarOrFunctionRef(atom)) {
841826
ErrorShouldBeVariable(atom, rsrc);
842827
} else {
843-
CheckAtomicVariable(atom, rsrc, read);
828+
CheckAtomicVariable(
829+
atom, rsrc, /*checkTypeOnPointer=*/!IsPointerAssignment(read));
844830
CheckStorageOverlap(atom, {read.lhs}, source);
845831
}
846832
} else {
@@ -861,7 +847,8 @@ void OmpStructureChecker::CheckAtomicWriteAssignment(
861847
if (!IsVarOrFunctionRef(atom)) {
862848
ErrorShouldBeVariable(atom, rsrc);
863849
} else {
864-
CheckAtomicVariable(atom, lsrc, write);
850+
CheckAtomicVariable(
851+
atom, lsrc, /*checkTypeOnPointer=*/!IsPointerAssignment(write));
865852
CheckStorageOverlap(atom, {write.rhs}, source);
866853
}
867854
}
@@ -886,7 +873,8 @@ OmpStructureChecker::CheckAtomicUpdateAssignment(
886873
return std::nullopt;
887874
}
888875

889-
CheckAtomicVariable(atom, lsrc, update);
876+
CheckAtomicVariable(
877+
atom, lsrc, /*checkTypeOnPointer=*/!IsPointerAssignment(update));
890878

891879
auto [hasErrors, tryReassoc]{CheckAtomicUpdateAssignmentRhs(
892880
atom, update.rhs, source, /*suppressDiagnostics=*/true)};
@@ -1049,7 +1037,8 @@ void OmpStructureChecker::CheckAtomicConditionalUpdateAssignment(
10491037
return;
10501038
}
10511039

1052-
CheckAtomicVariable(atom, alsrc, assign);
1040+
CheckAtomicVariable(
1041+
atom, alsrc, /*checkTypeOnPointer=*/!IsPointerAssignment(assign));
10531042

10541043
auto top{GetTopLevelOperationIgnoreResizing(cond)};
10551044
// Missing arguments to operations would have been diagnosed by now.

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

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -262,12 +262,10 @@ class OmpStructureChecker
262262
void CheckStorageOverlap(const evaluate::Expr<evaluate::SomeType> &,
263263
llvm::ArrayRef<evaluate::Expr<evaluate::SomeType>>, parser::CharBlock);
264264
void ErrorShouldBeVariable(const MaybeExpr &expr, parser::CharBlock source);
265-
void CheckAtomicType(
266-
SymbolRef sym, parser::CharBlock source, std::string_view name);
267-
void CheckAtomicVariable(
268-
const evaluate::Expr<evaluate::SomeType> &, parser::CharBlock);
265+
void CheckAtomicType(SymbolRef sym, parser::CharBlock source,
266+
std::string_view name, bool checkTypeOnPointer = true);
269267
void CheckAtomicVariable(const evaluate::Expr<evaluate::SomeType> &,
270-
parser::CharBlock, const evaluate::Assignment &);
268+
parser::CharBlock, bool checkTypeOnPointer = true);
271269
std::pair<const parser::ExecutionPartConstruct *,
272270
const parser::ExecutionPartConstruct *>
273271
CheckUpdateCapture(const parser::ExecutionPartConstruct *ec1,

flang/test/Semantics/OpenMP/omp-atomic-write-pointer-derived.f90

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,5 @@
44
type(t), pointer :: a1, a2
55
!$omp atomic write
66
a1 = a2
7-
! CHECK: error: ATOMIC WRITE requires an intrinsic scalar variable; 'a1' has the POINTER attribute and derived type 't'
7+
! CHECK: error: ATOMIC operation requires an intrinsic scalar variable; 'a1' has the POINTER attribute and derived type 't'
88
end

0 commit comments

Comments
 (0)