mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-26 05:18:46 +00:00
[flang] Disambiguate F(X)=Y case where F is a function returning a pointer
F(X)=Y may be initially parsed as a statement function definition; an existing pass will detect statement functions that should be rewritten into assignment statemets with array element references as their left-hand side variables. However, F() may also be a reference to a function that returns a data pointer, and f18 did not handle this case correctly. The right fix is to rewrite the parse tree for F(X)=Y into an assignment to a function reference result. The cases that are actually assignments to array elements -- including all of the cases previously handled -- will have their left-hand sides converted to array element references later by another existing rewriting step. Differential Revision: https://reviews.llvm.org/D124299
This commit is contained in:
parent
ffe03ff75c
commit
149d3e4365
@ -203,28 +203,33 @@ Substring ArrayElement::ConvertToSubstring() {
|
||||
}
|
||||
|
||||
// R1544 stmt-function-stmt
|
||||
// Convert this stmt-function-stmt to an array element assignment statement.
|
||||
// Convert this stmt-function-stmt to an assignment to the result of a
|
||||
// pointer-valued function call -- which itself will be converted to a
|
||||
// much more likely array element assignment statement if it needs
|
||||
// to be.
|
||||
Statement<ActionStmt> StmtFunctionStmt::ConvertToAssignment() {
|
||||
auto &funcName{std::get<Name>(t)};
|
||||
auto &funcArgs{std::get<std::list<Name>>(t)};
|
||||
auto &funcExpr{std::get<Scalar<Expr>>(t).thing};
|
||||
CharBlock source{funcName.source};
|
||||
std::list<Expr> subscripts;
|
||||
for (Name &arg : funcArgs) {
|
||||
subscripts.push_back(WithSource(arg.source,
|
||||
Expr{common::Indirection{
|
||||
WithSource(arg.source, Designator{DataRef{Name{arg}}})}}));
|
||||
source.ExtendToCover(arg.source);
|
||||
}
|
||||
// extend source to include closing paren
|
||||
// Extend source to include closing parenthesis
|
||||
if (funcArgs.empty()) {
|
||||
CHECK(*source.end() == '(');
|
||||
source = CharBlock{source.begin(), source.end() + 1};
|
||||
}
|
||||
std::list<ActualArgSpec> actuals;
|
||||
for (const Name &arg : funcArgs) {
|
||||
actuals.emplace_back(std::optional<Keyword>{},
|
||||
ActualArg{Expr{WithSource(
|
||||
arg.source, Designator{DataRef{Name{arg.source, arg.symbol}}})}});
|
||||
source.ExtendToCover(arg.source);
|
||||
}
|
||||
CHECK(*source.end() == ')');
|
||||
source = CharBlock{source.begin(), source.end() + 1};
|
||||
auto variable{Variable{common::Indirection{WithSource(
|
||||
source, MakeArrayElementRef(funcName, std::move(subscripts)))}}};
|
||||
FunctionReference funcRef{WithSource(source,
|
||||
Call{ProcedureDesignator{Name{funcName.source, funcName.symbol}},
|
||||
std::move(actuals)})};
|
||||
auto variable{Variable{common::Indirection{std::move(funcRef)}}};
|
||||
return Statement{std::nullopt,
|
||||
ActionStmt{common::Indirection{
|
||||
AssignmentStmt{std::move(variable), std::move(funcExpr)}}}};
|
||||
|
@ -21,7 +21,8 @@ namespace Fortran::semantics {
|
||||
|
||||
using namespace parser::literals;
|
||||
|
||||
/// Convert misidentified statement functions to array element assignments.
|
||||
/// Convert misidentified statement functions to array element assignments
|
||||
/// or pointer-valued function result assignments.
|
||||
/// Convert misidentified format expressions to namelist group names.
|
||||
/// Convert misidentified character variables in I/O units to integer
|
||||
/// unit number expressions.
|
||||
@ -82,16 +83,23 @@ void RewriteMutator::Post(parser::Name &name) {
|
||||
void RewriteMutator::Post(parser::SpecificationPart &x) {
|
||||
auto &list{std::get<std::list<parser::DeclarationConstruct>>(x.t)};
|
||||
for (auto it{list.begin()}; it != list.end();) {
|
||||
if (auto stmt{std::get_if<stmtFuncType>(&it->u)}) {
|
||||
Symbol *symbol{std::get<parser::Name>(stmt->statement.value().t).symbol};
|
||||
if (symbol && symbol->has<ObjectEntityDetails>()) {
|
||||
// not a stmt func: remove it here and add to ones to convert
|
||||
stmtFuncsToConvert_.push_back(std::move(*stmt));
|
||||
it = list.erase(it);
|
||||
continue;
|
||||
bool isAssignment{false};
|
||||
if (auto *stmt{std::get_if<stmtFuncType>(&it->u)}) {
|
||||
if (const Symbol *
|
||||
symbol{std::get<parser::Name>(stmt->statement.value().t).symbol}) {
|
||||
const Symbol *funcRes{FindFunctionResult(*symbol)};
|
||||
isAssignment = symbol->has<ObjectEntityDetails>() ||
|
||||
(funcRes && IsPointer(*funcRes) && !IsProcedure(*funcRes));
|
||||
if (isAssignment) {
|
||||
stmtFuncsToConvert_.emplace_back(std::move(*stmt));
|
||||
}
|
||||
}
|
||||
}
|
||||
++it;
|
||||
if (isAssignment) {
|
||||
it = list.erase(it);
|
||||
} else {
|
||||
++it;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user