[flang-commits] [flang] a567961 - [flang] Better messages for function vs. array errors
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Tue Jan 18 15:42:16 PST 2022
Author: Peter Klausler
Date: 2022-01-18T15:42:08-08:00
New Revision: a56796157498a2642e5bec84f5247a3460f8222d
URL: https://github.com/llvm/llvm-project/commit/a56796157498a2642e5bec84f5247a3460f8222d
DIFF: https://github.com/llvm/llvm-project/commit/a56796157498a2642e5bec84f5247a3460f8222d.diff
LOG: [flang] Better messages for function vs. array errors
When a scalar-valued function with no distinct RESULT
is being called recursively in its own executable part,
emit a better message about the error. Clean up the
code that resolves function vs. array ambiguities in
expression semantics.
Update to address review comment
Differential Revision: https://reviews.llvm.org/D117577
Added:
Modified:
flang/include/flang/Semantics/tools.h
flang/lib/Semantics/expression.cpp
flang/lib/Semantics/tools.cpp
flang/test/Semantics/resolve59.f90
flang/test/Semantics/resolve93.f90
Removed:
################################################################################
diff --git a/flang/include/flang/Semantics/tools.h b/flang/include/flang/Semantics/tools.h
index 6047eeae9dfc4..c52ee29c82c43 100644
--- a/flang/include/flang/Semantics/tools.h
+++ b/flang/include/flang/Semantics/tools.h
@@ -96,7 +96,8 @@ bool IsPointerDummy(const Symbol &);
bool IsBindCProcedure(const Symbol &);
bool IsBindCProcedure(const Scope &);
bool IsProcName(const Symbol &); // proc-name
-bool IsFunctionResultWithSameNameAsFunction(const Symbol &);
+// Returns a pointer to the function's symbol when true, else null
+const Symbol *IsFunctionResultWithSameNameAsFunction(const Symbol &);
bool IsOrContainsEventOrLockComponent(const Symbol &);
bool CanBeTypeBoundProc(const Symbol *);
// Does a non-PARAMETER symbol have explicit initialization with =value or
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index cf4b5485362b4..56d3b82a657e7 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -2781,33 +2781,43 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::Expr::DefinedBinary &x) {
"No operator %s defined for %s and %s"_err_en_US, nullptr, true);
}
-static void CheckFuncRefToArrayElementRefHasSubscripts(
- semantics::SemanticsContext &context,
+// Returns true if a parsed function reference should be converted
+// into an array element reference.
+static bool CheckFuncRefToArrayElement(semantics::SemanticsContext &context,
const parser::FunctionReference &funcRef) {
// Emit message if the function reference fix will end up an array element
- // reference with no subscripts because it will not be possible to later tell
- // the
diff erence in expressions between empty subscript list due to bad
- // subscripts error recovery or because the user did not put any.
- if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
- auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
- const auto *name{std::get_if<parser::Name>(&proc.u)};
- if (!name) {
- name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
- }
- auto &msg{context.Say(funcRef.v.source,
- name->symbol && name->symbol->Rank() == 0
- ? "'%s' is not a function"_err_en_US
- : "Reference to array '%s' with empty subscript list"_err_en_US,
- name->source)};
- if (name->symbol) {
- if (semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)) {
- msg.Attach(name->source,
- "A result variable must be declared with RESULT to allow recursive "
- "function calls"_en_US);
- } else {
+ // reference with no subscripts, or subscripts on a scalar, because it will
+ // not be possible to later distinguish in expressions between an empty
+ // subscript list due to bad subscripts error recovery or because the
+ // user did not put any.
+ auto &proc{std::get<parser::ProcedureDesignator>(funcRef.v.t)};
+ const auto *name{std::get_if<parser::Name>(&proc.u)};
+ if (!name) {
+ name = &std::get<parser::ProcComponentRef>(proc.u).v.thing.component;
+ }
+ if (!name->symbol) {
+ return false;
+ } else if (name->symbol->Rank() == 0) {
+ if (const Symbol *
+ function{
+ semantics::IsFunctionResultWithSameNameAsFunction(*name->symbol)}) {
+ auto &msg{context.Say(funcRef.v.source,
+ "Recursive call to '%s' requires a distinct RESULT in its declaration"_err_en_US,
+ name->source)};
+ AttachDeclaration(&msg, *function);
+ name->symbol = const_cast<Symbol *>(function);
+ }
+ return false;
+ } else {
+ if (std::get<std::list<parser::ActualArgSpec>>(funcRef.v.t).empty()) {
+ auto &msg{context.Say(funcRef.v.source,
+ "Reference to array '%s' with empty subscript list"_err_en_US,
+ name->source)};
+ if (name->symbol) {
AttachDeclaration(&msg, *name->symbol);
}
}
+ return true;
}
}
@@ -2841,8 +2851,9 @@ static void FixMisparsedFunctionReference(
// pointer as per C1105 so this cannot be a function reference.
if constexpr (common::HasMember<common::Indirection<parser::Designator>,
uType>) {
- CheckFuncRefToArrayElementRefHasSubscripts(context, funcRef);
- u = common::Indirection{funcRef.ConvertToArrayElementRef()};
+ if (CheckFuncRefToArrayElement(context, funcRef)) {
+ u = common::Indirection{funcRef.ConvertToArrayElementRef()};
+ }
} else {
DIE("can't fix misparsed function as array reference");
}
diff --git a/flang/lib/Semantics/tools.cpp b/flang/lib/Semantics/tools.cpp
index e4d1e2f09d67e..72816b7a6d897 100644
--- a/flang/lib/Semantics/tools.cpp
+++ b/flang/lib/Semantics/tools.cpp
@@ -1345,13 +1345,15 @@ const Symbol *FindImmediateComponent(const DerivedTypeSpec &type,
return nullptr;
}
-bool IsFunctionResultWithSameNameAsFunction(const Symbol &symbol) {
+const Symbol *IsFunctionResultWithSameNameAsFunction(const Symbol &symbol) {
if (IsFunctionResult(symbol)) {
if (const Symbol * function{symbol.owner().symbol()}) {
- return symbol.name() == function->name();
+ if (symbol.name() == function->name()) {
+ return function;
+ }
}
}
- return false;
+ return nullptr;
}
void LabelEnforce::Post(const parser::GotoStmt &gotoStmt) {
diff --git a/flang/test/Semantics/resolve59.f90 b/flang/test/Semantics/resolve59.f90
index 0eeb1170fb3d7..6f9324e36ec03 100644
--- a/flang/test/Semantics/resolve59.f90
+++ b/flang/test/Semantics/resolve59.f90
@@ -10,7 +10,7 @@ module m_no_result
! testing with data object results
function f1()
real :: x, f1
- !ERROR: 'f1' is not a function
+ !ERROR: Recursive call to 'f1' requires a distinct RESULT in its declaration
x = acos(f1())
f1 = x
x = acos(f1) !OK
@@ -18,7 +18,7 @@ function f1()
function f2(i)
integer i
real :: x, f2
- !ERROR: 'f2' is not an array
+ !ERROR: Recursive call to 'f2' requires a distinct RESULT in its declaration
x = acos(f2(i+1))
f2 = x
x = acos(f2) !OK
@@ -63,7 +63,7 @@ function f6() result(f6) !OKI (warning)
end function
function f7() result(f7) !OKI (warning)
real :: x, f7
- !ERROR: 'f7' is not a function
+ !ERROR: Recursive call to 'f7' requires a distinct RESULT in its declaration
x = acos(f7())
f7 = x
x = acos(f7) !OK
@@ -124,7 +124,7 @@ function f5(x) result(r)
! testing that calling the result is also caught
function f6() result(r)
real :: x, r
- !ERROR: 'r' is not a function
+ !ERROR: 'r' is not a callable procedure
x = r()
end function
end module
diff --git a/flang/test/Semantics/resolve93.f90 b/flang/test/Semantics/resolve93.f90
index 71e0e40a2a230..a54c753657641 100644
--- a/flang/test/Semantics/resolve93.f90
+++ b/flang/test/Semantics/resolve93.f90
@@ -9,8 +9,9 @@ subroutine s1()
character(10) str3
!ERROR: Cannot reference function 'str1' as data
print *, str1(1:9), str1(7)
- !ERROR: 'str2' is not an array
- print *, str2(1:9), str2(7)
+ print *, str2(1:9) ! substring is ok
+ !ERROR: 'str2' is not a callable procedure
+ print *, str2(7)
!ERROR: Cannot reference function 'str3' as data
print *, str3(7), str3(1:9)
end block
More information about the flang-commits
mailing list