@@ -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+
583615void 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.
0 commit comments