diff --git a/flang/lib/Semantics/pointer-assignment.cpp b/flang/lib/Semantics/pointer-assignment.cpp index 36c9c5b845706..c17eb0aa941ec 100644 --- a/flang/lib/Semantics/pointer-assignment.cpp +++ b/flang/lib/Semantics/pointer-assignment.cpp @@ -329,7 +329,6 @@ bool PointerAssignmentChecker::Check(const evaluate::Designator &d) { " shape"_err_en_US; } else if (rhsType->corank() > 0 && (isVolatile_ != last->attrs().test(Attr::VOLATILE))) { // C1020 - // TODO: what if A is VOLATILE in A%B%C? need a better test here if (isVolatile_) { msg = "Pointer may not be VOLATILE when target is a" " non-VOLATILE coarray"_err_en_US; @@ -569,6 +568,12 @@ bool CheckPointerAssignment(SemanticsContext &context, const SomeExpr &lhs, return false; // error was reported } PointerAssignmentChecker checker{context, scope, *pointer}; + const Symbol *base{GetFirstSymbol(lhs)}; + if (base) { + // 8.5.20(4) If an object has the VOLATILE attribute, then all of its + // subobjects also have the VOLATILE attribute. + checker.set_isVolatile(base->attrs().test(Attr::VOLATILE)); + } checker.set_isBoundsRemapping(isBoundsRemapping); checker.set_isAssumedRank(isAssumedRank); bool lhsOk{checker.CheckLeftHandSide(lhs)}; diff --git a/flang/test/Semantics/assign02.f90 b/flang/test/Semantics/assign02.f90 index d83d126e2734c..9fa672025bfe7 100644 --- a/flang/test/Semantics/assign02.f90 +++ b/flang/test/Semantics/assign02.f90 @@ -8,9 +8,11 @@ module m1 type t2 sequence real :: t2Field + real, pointer :: t2FieldPtr end type type t3 type(t2) :: t3Field + type(t2), pointer :: t3FieldPtr end type contains @@ -198,6 +200,14 @@ subroutine s13 q2 => y%t3Field !OK: q3 => y + !ERROR: VOLATILE target associated with non-VOLATILE pointer + p3%t3FieldPtr => y%t3Field + !ERROR: VOLATILE target associated with non-VOLATILE pointer + p3%t3FieldPtr%t2FieldPtr => y%t3Field%t2Field + !OK + q3%t3FieldPtr => y%t3Field + !OK + q3%t3FieldPtr%t2FieldPtr => y%t3Field%t2Field end end