Index: flang/lib/Semantics/check-call.cpp =================================================================== --- flang/lib/Semantics/check-call.cpp +++ flang/lib/Semantics/check-call.cpp @@ -441,7 +441,8 @@ // technically legal but worth emitting a warning // llvm-project issue #58973: constant actual argument passed in where dummy // argument is marked volatile - if (dummyIsVolatile && !IsVariable(actual)) { + bool actualIsVariable{evaluate::IsVariable(actual)}; + if (dummyIsVolatile && !actualIsVariable) { messages.Say( "actual argument associated with VOLATILE %s is not a variable"_warn_en_US, dummyName); @@ -599,6 +600,24 @@ "Actual argument associated with %s may not be null pointer %s"_err_en_US, dummyName, actual.AsFortran()); } + + // Warn about dubious actual argument association with a TARGET dummy argument + if (dummy.attrs.test(characteristics::DummyDataObject::Attr::Target)) { + bool actualIsTemp{!actualIsVariable || HasVectorSubscript(actual) || + evaluate::ExtractCoarrayRef(actual)}; + if (actualIsTemp) { + messages.Say( + "Any pointer associated with TARGET %s during this call will not be associated with the value of '%s' afterwards"_warn_en_US, + dummyName, actual.AsFortran()); + } else { + auto actualSymbolVector{GetSymbolVector(actual)}; + if (!evaluate::GetLastTarget(actualSymbolVector)) { + messages.Say( + "Any pointer associated with TARGET %s during this call must not be used afterwards, as '%s' is not a target"_warn_en_US, + dummyName, actual.AsFortran()); + } + } + } } static void CheckProcedureArg(evaluate::ActualArgument &arg, Index: flang/test/Semantics/call34.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/call34.f90 @@ -0,0 +1,22 @@ +! RUN: %python %S/test_errors.py %s %flang_fc1 -Werror +module m + contains + subroutine foo(a) + real, intent(in), target :: a(:) + end subroutine +end module + +program test + use m + real, target :: a(1) + real :: b(1) + call foo(a) ! ok + !WARNING: Any pointer associated with TARGET dummy argument 'a=' during this call must not be used afterwards, as 'b' is not a target + call foo(b) + !WARNING: Any pointer associated with TARGET dummy argument 'a=' during this call will not be associated with the value of '(a)' afterwards + call foo((a)) + !WARNING: Any pointer associated with TARGET dummy argument 'a=' during this call will not be associated with the value of 'a([INTEGER(8)::1_8])' afterwards + call foo(a([1])) + !ERROR: Scalar actual argument may not be associated with assumed-shape dummy argument 'a=' + call foo(a(1)) +end