[flang] Refine pointer/target test for ASSOCIATED intrinsic
The second argument to the ASSOCIATED intrinsic must be a valid pointer or target. The test for this property only checked the last symbol in a data-reference, but any symbol in the reference with the POINTER or TARGET attribute will do. Differential Revision: https://reviews.llvm.org/D119450
This commit is contained in:
parent
100ec80ab5
commit
82dbe82585
|
|
@ -2260,22 +2260,18 @@ static bool CheckAssociated(SpecificCall &call, FoldingContext &context) {
|
||||||
"procedure designator"_err_en_US,
|
"procedure designator"_err_en_US,
|
||||||
pointerSymbol->name(), targetName),
|
pointerSymbol->name(), targetName),
|
||||||
*pointerSymbol);
|
*pointerSymbol);
|
||||||
} else {
|
} else if (targetSymbol) {
|
||||||
// object pointer and target
|
// object pointer and target
|
||||||
if (const Symbol * targetSymbol{GetLastSymbol(*targetExpr)}) {
|
SymbolVector symbols{GetSymbolVector(*targetExpr)};
|
||||||
if (!(targetSymbol->attrs().test(semantics::Attr::POINTER) ||
|
CHECK(!symbols.empty());
|
||||||
targetSymbol->attrs().test(
|
if (!GetLastTarget(symbols)) {
|
||||||
semantics::Attr::TARGET))) {
|
parser::Message *msg{context.messages().Say(
|
||||||
AttachDeclaration(
|
"TARGET= argument '%s' must have either the POINTER or the TARGET attribute"_err_en_US,
|
||||||
context.messages().Say(
|
targetExpr->AsFortran())};
|
||||||
"TARGET= argument '%s' must have either "
|
for (SymbolRef ref : symbols) {
|
||||||
"the POINTER or the TARGET "
|
msg = AttachDeclaration(msg, *ref);
|
||||||
"attribute"_err_en_US,
|
|
||||||
targetName),
|
|
||||||
*targetSymbol);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (const auto pointerType{pointerArg->GetType()}) {
|
if (const auto pointerType{pointerArg->GetType()}) {
|
||||||
if (const auto targetType{targetArg->GetType()}) {
|
if (const auto targetType{targetArg->GetType()}) {
|
||||||
ok = pointerType->IsTkCompatibleWith(*targetType);
|
ok = pointerType->IsTkCompatibleWith(*targetType);
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,14 @@ subroutine assoc()
|
||||||
end function
|
end function
|
||||||
end interface
|
end interface
|
||||||
|
|
||||||
|
type :: t1
|
||||||
|
integer :: n
|
||||||
|
end type t1
|
||||||
|
type :: t2
|
||||||
|
type(t1) :: t1arr(2)
|
||||||
|
type(t1), pointer :: t1ptr(:)
|
||||||
|
end type t2
|
||||||
|
|
||||||
contains
|
contains
|
||||||
integer function intFunc(x)
|
integer function intFunc(x)
|
||||||
integer, intent(in) :: x
|
integer, intent(in) :: x
|
||||||
|
|
@ -60,6 +68,10 @@ subroutine assoc()
|
||||||
procedure(subrInt), pointer :: subProcPointer
|
procedure(subrInt), pointer :: subProcPointer
|
||||||
procedure(), pointer :: implicitProcPointer
|
procedure(), pointer :: implicitProcPointer
|
||||||
logical :: lVar
|
logical :: lVar
|
||||||
|
type(t1) :: t1x
|
||||||
|
type(t1), target :: t1xtarget
|
||||||
|
type(t2) :: t2x
|
||||||
|
type(t2), target :: t2xtarget
|
||||||
|
|
||||||
!ERROR: missing mandatory 'pointer=' argument
|
!ERROR: missing mandatory 'pointer=' argument
|
||||||
lVar = associated()
|
lVar = associated()
|
||||||
|
|
@ -91,6 +103,15 @@ subroutine assoc()
|
||||||
!ERROR: TARGET= argument 'intvar' must have either the POINTER or the TARGET attribute
|
!ERROR: TARGET= argument 'intvar' must have either the POINTER or the TARGET attribute
|
||||||
lVar = associated(intPointerVar1, intVar)
|
lVar = associated(intPointerVar1, intVar)
|
||||||
|
|
||||||
|
!ERROR: TARGET= argument 't1x%n' must have either the POINTER or the TARGET attribute
|
||||||
|
lVar = associated(intPointerVar1, t1x%n)
|
||||||
|
lVar = associated(intPointerVar1, t1xtarget%n) ! ok
|
||||||
|
!ERROR: TARGET= argument 't2x%t1arr(1_8)%n' must have either the POINTER or the TARGET attribute
|
||||||
|
lVar = associated(intPointerVar1, t2x%t1arr(1)%n)
|
||||||
|
lVar = associated(intPointerVar1, t2x%t1ptr(1)%n) ! ok
|
||||||
|
lVar = associated(intPointerVar1, t2xtarget%t1arr(1)%n) ! ok
|
||||||
|
lVar = associated(intPointerVar1, t2xtarget%t1ptr(1)%n) ! ok
|
||||||
|
|
||||||
! Procedure pointer tests
|
! Procedure pointer tests
|
||||||
intprocPointer1 => intProc !OK
|
intprocPointer1 => intProc !OK
|
||||||
lVar = associated(intprocPointer1, intProc) !OK
|
lVar = associated(intprocPointer1, intProc) !OK
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue