Skip to content

Commit

Permalink
[flang] Add more support for alternate returns
Browse files Browse the repository at this point in the history
Add `hasAlternateReturns` to `evaluate::ProcedureRef`.

Add `HasAlternateReturns` to test subprogram symbols.

Fix `label01.F90` test: It was checking that "error: " didn't appear in
the output. But that was erroneously matching a warning that ends
"would be in error:". So change it to check for ": error: " instead.

Differential Revision: https://reviews.llvm.org/D83007
  • Loading branch information
tskeith committed Jul 2, 2020
1 parent c5b4f03 commit 05756e6
Show file tree
Hide file tree
Showing 5 changed files with 26 additions and 8 deletions.
8 changes: 6 additions & 2 deletions flang/include/flang/Evaluate/call.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,8 +190,10 @@ struct ProcedureDesignator {
class ProcedureRef {
public:
CLASS_BOILERPLATE(ProcedureRef)
ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a)
: proc_{std::move(p)}, arguments_(std::move(a)) {}
ProcedureRef(ProcedureDesignator &&p, ActualArguments &&a,
bool hasAlternateReturns = false)
: proc_{std::move(p)}, arguments_{std::move(a)},
hasAlternateReturns_{hasAlternateReturns} {}
~ProcedureRef();

ProcedureDesignator &proc() { return proc_; }
Expand All @@ -202,12 +204,14 @@ class ProcedureRef {
std::optional<Expr<SubscriptInteger>> LEN() const;
int Rank() const;
bool IsElemental() const { return proc_.IsElemental(); }
bool hasAlternateReturns() const { return hasAlternateReturns_; }
bool operator==(const ProcedureRef &) const;
llvm::raw_ostream &AsFortran(llvm::raw_ostream &) const;

protected:
ProcedureDesignator proc_;
ActualArguments arguments_;
bool hasAlternateReturns_;
};

template <typename A> class FunctionRef : public ProcedureRef {
Expand Down
1 change: 1 addition & 0 deletions flang/include/flang/Semantics/tools.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ bool IsInitialized(const Symbol &, bool ignoreDATAstatements = false);
bool HasIntrinsicTypeName(const Symbol &);
bool IsSeparateModuleProcedureInterface(const Symbol *);
bool IsAutomatic(const Symbol &);
bool HasAlternateReturns(const Symbol &);

// Return an ultimate component of type that matches predicate, or nullptr.
const Symbol *FindUltimateComponent(const DerivedTypeSpec &type,
Expand Down
13 changes: 9 additions & 4 deletions flang/lib/Semantics/expression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2006,7 +2006,8 @@ void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
const parser::Call &call{callStmt.v};
auto restorer{GetContextualMessages().SetLocation(call.source)};
ArgumentAnalyzer analyzer{*this, call.source, true /* allowAssumedType */};
for (const auto &arg : std::get<std::list<parser::ActualArgSpec>>(call.t)) {
const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)};
for (const auto &arg : actualArgList) {
analyzer.Analyze(arg, true /* is subroutine call */);
}
if (!analyzer.fatalErrors()) {
Expand All @@ -2016,8 +2017,10 @@ void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
ProcedureDesignator *proc{std::get_if<ProcedureDesignator>(&callee->u)};
CHECK(proc);
if (CheckCall(call.source, *proc, callee->arguments)) {
callStmt.typedCall.reset(
new ProcedureRef{std::move(*proc), std::move(callee->arguments)});
bool hasAlternateReturns{
analyzer.GetActuals().size() < actualArgList.size()};
callStmt.typedCall.reset(new ProcedureRef{std::move(*proc),
std::move(callee->arguments), hasAlternateReturns});
}
}
}
Expand Down Expand Up @@ -2678,6 +2681,7 @@ void ArgumentAnalyzer::Analyze(
// be detected and represented (they're not expressions).
// TODO: C1534: Don't allow a "restricted" specific intrinsic to be passed.
std::optional<ActualArgument> actual;
bool isAltReturn{false};
std::visit(common::visitors{
[&](const common::Indirection<parser::Expr> &x) {
// TODO: Distinguish & handle procedure name and
Expand All @@ -2690,6 +2694,7 @@ void ArgumentAnalyzer::Analyze(
"alternate return specification may not appear on"
" function reference"_err_en_US);
}
isAltReturn = true;
},
[&](const parser::ActualArg::PercentRef &) {
context_.Say("TODO: %REF() argument"_err_en_US);
Expand All @@ -2704,7 +2709,7 @@ void ArgumentAnalyzer::Analyze(
actual->set_keyword(argKW->v.source);
}
actuals_.emplace_back(std::move(*actual));
} else {
} else if (!isAltReturn) {
fatalErrors_ = true;
}
}
Expand Down
9 changes: 9 additions & 0 deletions flang/lib/Semantics/tools.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1292,4 +1292,13 @@ void LabelEnforce::SayWithConstruct(SemanticsContext &context,
.Attach(constructLocation, GetEnclosingConstructMsg());
}

bool HasAlternateReturns(const Symbol &subprogram) {
for (const auto *dummyArg : subprogram.get<SubprogramDetails>().dummyArgs()) {
if (!dummyArg) {
return true;
}
}
return false;
}

} // namespace Fortran::semantics
3 changes: 1 addition & 2 deletions flang/test/Semantics/label01.F90
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
! RUN: %f18 -funparse-with-symbols -DSTRICT_F18 -Mstandard %s 2>&1 | FileCheck %s
! RUN: %f18 -funparse-with-symbols -DARCHAIC_FORTRAN %s 2>&1 | FileCheck %s
! CHECK-NOT: error:{{[[:space:]]}}
! CHECK-NOT: :{{[[:space:]]}}error:{{[[:space:]]}}
! FIXME: the above check line does not work because diags are not emitted with error: in them.

! these are the conformance tests
! define STRICT_F18 to eliminate tests of features not in F18
! define ARCHAIC_FORTRAN to add test of feature found in Fortran before F95


subroutine sub00(a,b,n,m)
integer :: n, m
real a(n)
Expand Down

0 comments on commit 05756e6

Please sign in to comment.