Skip to content

Commit 022dd65

Browse files
Krish GuptaKrish Gupta
authored andcommitted
[flang][OpenMP] Add diagnostic for ATOMIC WRITE with pointer to non-intrinsic type
Fixes #161932
1 parent 6b1604a commit 022dd65

File tree

3 files changed

+47
-5
lines changed

3 files changed

+47
-5
lines changed

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

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,38 @@ void OmpStructureChecker::CheckAtomicVariable(
580580
}
581581
}
582582

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+
583615
void OmpStructureChecker::CheckStorageOverlap(const SomeExpr &base,
584616
llvm::ArrayRef<evaluate::Expr<evaluate::SomeType>> exprs,
585617
parser::CharBlock source) {
@@ -789,7 +821,7 @@ void OmpStructureChecker::CheckAtomicCaptureAssignment(
789821
if (!IsVarOrFunctionRef(atom)) {
790822
ErrorShouldBeVariable(atom, rsrc);
791823
} else {
792-
CheckAtomicVariable(atom, rsrc);
824+
CheckAtomicVariable(atom, rsrc, capture);
793825
// This part should have been checked prior to calling this function.
794826
assert(*GetConvertInput(capture.rhs) == atom &&
795827
"This cannot be a capture assignment");
@@ -808,7 +840,7 @@ void OmpStructureChecker::CheckAtomicReadAssignment(
808840
if (!IsVarOrFunctionRef(atom)) {
809841
ErrorShouldBeVariable(atom, rsrc);
810842
} else {
811-
CheckAtomicVariable(atom, rsrc);
843+
CheckAtomicVariable(atom, rsrc, read);
812844
CheckStorageOverlap(atom, {read.lhs}, source);
813845
}
814846
} else {
@@ -829,7 +861,7 @@ void OmpStructureChecker::CheckAtomicWriteAssignment(
829861
if (!IsVarOrFunctionRef(atom)) {
830862
ErrorShouldBeVariable(atom, rsrc);
831863
} else {
832-
CheckAtomicVariable(atom, lsrc);
864+
CheckAtomicVariable(atom, lsrc, write);
833865
CheckStorageOverlap(atom, {write.rhs}, source);
834866
}
835867
}
@@ -854,7 +886,7 @@ OmpStructureChecker::CheckAtomicUpdateAssignment(
854886
return std::nullopt;
855887
}
856888

857-
CheckAtomicVariable(atom, lsrc);
889+
CheckAtomicVariable(atom, lsrc, update);
858890

859891
auto [hasErrors, tryReassoc]{CheckAtomicUpdateAssignmentRhs(
860892
atom, update.rhs, source, /*suppressDiagnostics=*/true)};
@@ -1017,7 +1049,7 @@ void OmpStructureChecker::CheckAtomicConditionalUpdateAssignment(
10171049
return;
10181050
}
10191051

1020-
CheckAtomicVariable(atom, alsrc);
1052+
CheckAtomicVariable(atom, alsrc, assign);
10211053

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

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,8 @@ class OmpStructureChecker
266266
SymbolRef sym, parser::CharBlock source, std::string_view name);
267267
void CheckAtomicVariable(
268268
const evaluate::Expr<evaluate::SomeType> &, parser::CharBlock);
269+
void CheckAtomicVariable(const evaluate::Expr<evaluate::SomeType> &,
270+
parser::CharBlock, const evaluate::Assignment &);
269271
std::pair<const parser::ExecutionPartConstruct *,
270272
const parser::ExecutionPartConstruct *>
271273
CheckUpdateCapture(const parser::ExecutionPartConstruct *ec1,
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
! RUN: not %flang_fc1 -fopenmp -fsyntax-only %s 2>&1 | FileCheck %s
2+
type t
3+
end type
4+
type(t), pointer :: a1, a2
5+
!$omp atomic write
6+
a1 = a2
7+
! CHECK: error: ATOMIC WRITE requires an intrinsic scalar variable; 'a1' has the POINTER attribute and derived type 't'
8+
end

0 commit comments

Comments
 (0)