Skip to content

Commit c759334

Browse files
authored
[flang] Better error message for RANK(NULL()) (#93577)
We currently complain that the argument may not be a procedure, which is confusing. Distinguish the NULL() case from other error cases (which are indeed procedures). And clean up the utility predicates used for these tests -- the current IsProcedure() is really just a test for a procedure designator.
1 parent 13f6797 commit c759334

File tree

7 files changed

+29
-10
lines changed

7 files changed

+29
-10
lines changed

flang/include/flang/Evaluate/tools.h

+3-2
Original file line numberDiff line numberDiff line change
@@ -1017,10 +1017,11 @@ bool IsAllocatableOrPointerObject(const Expr<SomeType> &);
10171017
bool IsAllocatableDesignator(const Expr<SomeType> &);
10181018

10191019
// Procedure and pointer detection predicates
1020-
bool IsProcedure(const Expr<SomeType> &);
1021-
bool IsFunction(const Expr<SomeType> &);
1020+
bool IsProcedureDesignator(const Expr<SomeType> &);
1021+
bool IsFunctionDesignator(const Expr<SomeType> &);
10221022
bool IsPointer(const Expr<SomeType> &);
10231023
bool IsProcedurePointer(const Expr<SomeType> &);
1024+
bool IsProcedure(const Expr<SomeType> &);
10241025
bool IsProcedurePointerTarget(const Expr<SomeType> &);
10251026
bool IsBareNullPointer(const Expr<SomeType> *); // NULL() w/o MOLD= or type
10261027
bool IsNullObjectPointer(const Expr<SomeType> &);

flang/lib/Evaluate/intrinsics.cpp

+5
Original file line numberDiff line numberDiff line change
@@ -1808,7 +1808,12 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18081808
continue;
18091809
} else if (d.typePattern.kindCode == KindCode::nullPointerType) {
18101810
continue;
1811+
} else if (IsNullPointer(expr)) {
1812+
messages.Say(arg->sourceLocation(),
1813+
"Actual argument for '%s=' may not be NULL()"_err_en_US,
1814+
d.keyword);
18111815
} else {
1816+
CHECK(IsProcedure(expr));
18121817
messages.Say(arg->sourceLocation(),
18131818
"Actual argument for '%s=' may not be a procedure"_err_en_US,
18141819
d.keyword);

flang/lib/Evaluate/tools.cpp

+6-2
Original file line numberDiff line numberDiff line change
@@ -818,10 +818,10 @@ bool IsCoarray(const Symbol &symbol) {
818818
return GetAssociationRoot(symbol).Corank() > 0;
819819
}
820820

821-
bool IsProcedure(const Expr<SomeType> &expr) {
821+
bool IsProcedureDesignator(const Expr<SomeType> &expr) {
822822
return std::holds_alternative<ProcedureDesignator>(expr.u);
823823
}
824-
bool IsFunction(const Expr<SomeType> &expr) {
824+
bool IsFunctionDesignator(const Expr<SomeType> &expr) {
825825
const auto *designator{std::get_if<ProcedureDesignator>(&expr.u)};
826826
return designator && designator->GetType().has_value();
827827
}
@@ -847,6 +847,10 @@ bool IsProcedurePointer(const Expr<SomeType> &expr) {
847847
}
848848
}
849849

850+
bool IsProcedure(const Expr<SomeType> &expr) {
851+
return IsProcedureDesignator(expr) || IsProcedurePointer(expr);
852+
}
853+
850854
bool IsProcedurePointerTarget(const Expr<SomeType> &expr) {
851855
return common::visit(common::visitors{
852856
[](const NullPointer &) { return true; },

flang/lib/Lower/Bridge.cpp

+2-1
Original file line numberDiff line numberDiff line change
@@ -3761,7 +3761,8 @@ class FirConverter : public Fortran::lower::AbstractConverter {
37613761
const Fortran::evaluate::Assignment::BoundsSpec &lbExprs) {
37623762
Fortran::lower::StatementContext stmtCtx;
37633763

3764-
if (!lowerToHighLevelFIR() && Fortran::evaluate::IsProcedure(assign.rhs))
3764+
if (!lowerToHighLevelFIR() &&
3765+
Fortran::evaluate::IsProcedureDesignator(assign.rhs))
37653766
TODO(loc, "procedure pointer assignment");
37663767
if (Fortran::evaluate::IsProcedurePointer(assign.lhs)) {
37673768
hlfir::Entity lhs = Fortran::lower::convertExprToHLFIR(

flang/lib/Semantics/data-to-inits.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ bool DataInitializationCompiler<DSV>::InitElement(
387387
// nothing to do; rely on zero initialization
388388
return true;
389389
} else if (isProcPointer) {
390-
if (evaluate::IsProcedure(*expr)) {
390+
if (evaluate::IsProcedureDesignator(*expr)) {
391391
if (CheckPointerAssignment(exprAnalyzer_.context(), designator, *expr,
392392
scope,
393393
/*isBoundsRemapping=*/false, /*isAssumedRank=*/false)) {
@@ -419,7 +419,7 @@ bool DataInitializationCompiler<DSV>::InitElement(
419419
} else if (evaluate::IsNullPointer(*expr)) {
420420
exprAnalyzer_.Say("Initializer for '%s' must not be a pointer"_err_en_US,
421421
DescribeElement());
422-
} else if (evaluate::IsProcedure(*expr)) {
422+
} else if (evaluate::IsProcedureDesignator(*expr)) {
423423
exprAnalyzer_.Say("Initializer for '%s' must not be a procedure"_err_en_US,
424424
DescribeElement());
425425
} else if (auto designatorType{designator.GetType()}) {

flang/lib/Semantics/expression.cpp

+4-3
Original file line numberDiff line numberDiff line change
@@ -4608,14 +4608,15 @@ std::optional<ActualArgument> ArgumentAnalyzer::AnalyzeExpr(
46084608
context_.SayAt(expr.source,
46094609
"TYPE(*) dummy argument may only be used as an actual argument"_err_en_US);
46104610
} else if (MaybeExpr argExpr{AnalyzeExprOrWholeAssumedSizeArray(expr)}) {
4611-
if (isProcedureCall_ || !IsProcedure(*argExpr)) {
4611+
if (isProcedureCall_ || !IsProcedureDesignator(*argExpr)) {
46124612
ActualArgument arg{std::move(*argExpr)};
46134613
SetArgSourceLocation(arg, expr.source);
46144614
return std::move(arg);
46154615
}
46164616
context_.SayAt(expr.source,
4617-
IsFunction(*argExpr) ? "Function call must have argument list"_err_en_US
4618-
: "Subroutine name is not allowed here"_err_en_US);
4617+
IsFunctionDesignator(*argExpr)
4618+
? "Function call must have argument list"_err_en_US
4619+
: "Subroutine name is not allowed here"_err_en_US);
46194620
}
46204621
return std::nullopt;
46214622
}

flang/test/Semantics/resolve09.f90

+7
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,10 @@ subroutine s10
153153
!ERROR: Actual argument for 'a=' may not be a procedure
154154
print *, abs(a10)
155155
end
156+
157+
subroutine s11
158+
real, pointer :: p(:)
159+
!ERROR: Actual argument for 'a=' may not be NULL()
160+
print *, rank(null())
161+
print *, rank(null(mold=p)) ! ok
162+
end

0 commit comments

Comments
 (0)