Skip to content

Commit 3bca850

Browse files
authored
[flang] Correct checking of PRESENT() (#78364)
The argument to the PRESENT() intrinsic function must be the name of a a whole OPTIONAL dummy argument. Fixes llvm-test-suite/Fortran/gfortran/regression/present_1.f90.
1 parent e9309b2 commit 3bca850

File tree

3 files changed

+47
-16
lines changed

3 files changed

+47
-16
lines changed

flang/lib/Evaluate/intrinsics.cpp

-16
Original file line numberDiff line numberDiff line change
@@ -2896,8 +2896,6 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
28962896
arg ? arg->sourceLocation() : context.messages().at(),
28972897
"Argument of ALLOCATED() must be an ALLOCATABLE object or component"_err_en_US);
28982898
}
2899-
} else if (name == "associated" || name == "reduce") {
2900-
// Now handled in Semantics/check-call.cpp
29012899
} else if (name == "atomic_and" || name == "atomic_or" ||
29022900
name == "atomic_xor") {
29032901
return CheckForCoindexedObject(
@@ -2939,20 +2937,6 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
29392937
arg ? arg->sourceLocation() : context.messages().at(),
29402938
"Argument of LOC() must be an object or procedure"_err_en_US);
29412939
}
2942-
} else if (name == "present") {
2943-
const auto &arg{call.arguments[0]};
2944-
if (arg) {
2945-
if (const auto *expr{arg->UnwrapExpr()}) {
2946-
if (const Symbol *symbol{UnwrapWholeSymbolDataRef(*expr)}) {
2947-
ok = symbol->attrs().test(semantics::Attr::OPTIONAL);
2948-
}
2949-
}
2950-
}
2951-
if (!ok) {
2952-
context.messages().Say(
2953-
arg ? arg->sourceLocation() : context.messages().at(),
2954-
"Argument of PRESENT() must be the name of an OPTIONAL dummy argument"_err_en_US);
2955-
}
29562940
} else if (name == "ucobound") {
29572941
return CheckDimAgainstCorank(call, context);
29582942
}

flang/lib/Semantics/check-call.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -1470,6 +1470,30 @@ static void CheckMove_Alloc(evaluate::ActualArguments &arguments,
14701470
}
14711471
}
14721472

1473+
// PRESENT (F'2023 16.9.163)
1474+
static void CheckPresent(evaluate::ActualArguments &arguments,
1475+
parser::ContextualMessages &messages) {
1476+
if (arguments.size() == 1) {
1477+
if (const auto &arg{arguments[0]}; arg) {
1478+
const Symbol *symbol{nullptr};
1479+
if (const auto *expr{arg->UnwrapExpr()}) {
1480+
if (const auto *proc{
1481+
std::get_if<evaluate::ProcedureDesignator>(&expr->u)}) {
1482+
symbol = proc->GetSymbol();
1483+
} else {
1484+
symbol = evaluate::UnwrapWholeSymbolDataRef(*expr);
1485+
}
1486+
} else {
1487+
symbol = arg->GetAssumedTypeDummy();
1488+
}
1489+
if (!symbol || !symbol->attrs().test(semantics::Attr::OPTIONAL)) {
1490+
messages.Say(arg ? arg->sourceLocation() : messages.at(),
1491+
"Argument of PRESENT() must be the name of a whole OPTIONAL dummy argument"_err_en_US);
1492+
}
1493+
}
1494+
}
1495+
}
1496+
14731497
// REDUCE (F'2023 16.9.173)
14741498
static void CheckReduce(
14751499
evaluate::ActualArguments &arguments, evaluate::FoldingContext &context) {
@@ -1680,6 +1704,8 @@ static void CheckSpecificIntrinsic(evaluate::ActualArguments &arguments,
16801704
CheckAssociated(arguments, context, scope);
16811705
} else if (intrinsic.name == "move_alloc") {
16821706
CheckMove_Alloc(arguments, context.foldingContext().messages());
1707+
} else if (intrinsic.name == "present") {
1708+
CheckPresent(arguments, context.foldingContext().messages());
16831709
} else if (intrinsic.name == "reduce") {
16841710
CheckReduce(arguments, context.foldingContext());
16851711
} else if (intrinsic.name == "transfer") {

flang/test/Semantics/present01.f90

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
module m
3+
type dt
4+
real a
5+
end type
6+
contains
7+
subroutine s(a,b,p,unl)
8+
type(dt), optional :: a(:), b
9+
procedure(sin), optional :: p
10+
type(*), optional :: unl
11+
print *, present(a) ! ok
12+
print *, present(p) ! ok
13+
print *, present(unl) ! ok
14+
!ERROR: Argument of PRESENT() must be the name of a whole OPTIONAL dummy argument
15+
print *, present(a(1))
16+
!ERROR: Argument of PRESENT() must be the name of a whole OPTIONAL dummy argument
17+
print *, present(b%a)
18+
!ERROR: Argument of PRESENT() must be the name of a whole OPTIONAL dummy argument
19+
print *, present(a(1)%a)
20+
end
21+
end

0 commit comments

Comments
 (0)