@@ -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
564580void 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,7 +588,7 @@ 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,
@@ -789,7 +805,8 @@ void OmpStructureChecker::CheckAtomicCaptureAssignment(
789805 if (!IsVarOrFunctionRef (atom)) {
790806 ErrorShouldBeVariable (atom, rsrc);
791807 } else {
792- CheckAtomicVariable (atom, rsrc);
808+ CheckAtomicVariable (
809+ atom, rsrc, /* checkTypeOnPointer=*/ !IsPointerAssignment (capture));
793810 // This part should have been checked prior to calling this function.
794811 assert (*GetConvertInput (capture.rhs ) == atom &&
795812 " This cannot be a capture assignment" );
@@ -808,7 +825,8 @@ void OmpStructureChecker::CheckAtomicReadAssignment(
808825 if (!IsVarOrFunctionRef (atom)) {
809826 ErrorShouldBeVariable (atom, rsrc);
810827 } else {
811- CheckAtomicVariable (atom, rsrc);
828+ CheckAtomicVariable (
829+ atom, rsrc, /* checkTypeOnPointer=*/ !IsPointerAssignment (read));
812830 CheckStorageOverlap (atom, {read.lhs }, source);
813831 }
814832 } else {
@@ -829,7 +847,8 @@ void OmpStructureChecker::CheckAtomicWriteAssignment(
829847 if (!IsVarOrFunctionRef (atom)) {
830848 ErrorShouldBeVariable (atom, rsrc);
831849 } else {
832- CheckAtomicVariable (atom, lsrc);
850+ CheckAtomicVariable (
851+ atom, lsrc, /* checkTypeOnPointer=*/ !IsPointerAssignment (write));
833852 CheckStorageOverlap (atom, {write.rhs }, source);
834853 }
835854}
@@ -854,7 +873,8 @@ OmpStructureChecker::CheckAtomicUpdateAssignment(
854873 return std::nullopt ;
855874 }
856875
857- CheckAtomicVariable (atom, lsrc);
876+ CheckAtomicVariable (
877+ atom, lsrc, /* checkTypeOnPointer=*/ !IsPointerAssignment (update));
858878
859879 auto [hasErrors, tryReassoc]{CheckAtomicUpdateAssignmentRhs (
860880 atom, update.rhs , source, /* suppressDiagnostics=*/ true )};
@@ -1017,7 +1037,8 @@ void OmpStructureChecker::CheckAtomicConditionalUpdateAssignment(
10171037 return ;
10181038 }
10191039
1020- CheckAtomicVariable (atom, alsrc);
1040+ CheckAtomicVariable (
1041+ atom, alsrc, /* checkTypeOnPointer=*/ !IsPointerAssignment (assign));
10211042
10221043 auto top{GetTopLevelOperationIgnoreResizing (cond)};
10231044 // Missing arguments to operations would have been diagnosed by now.
0 commit comments