Files
llvm/flang/lib/Semantics/check-return.cpp
Tim Keith 1f525ece4a [flang][NFC] Add GetTopLevelUnitContaining functions
`GetTopLevelUnitContaining` returns the Scope nested in the global scope
that contains the given Scope or Symbol.

Use "Get" rather than "Find" in the name because "Find" implies it might
not be found, which can't happen. Following that logic, rename
`FindProgramUnitContaining` to `GetProgramUnitContaining` and have it
also return a reference rather that a pointer.

Note that the use of "ProgramUnit" is slightly confusing. In the Fortran
standard, "program-unit" refers to what is called a "TopLevelUnit" here.
What we are calling a "ProgramUnit" (here and in `ProgramTree`) includes
internal subprograms while "TopLevelUnit" does not.

Differential Revision: https://reviews.llvm.org/D92491
2020-12-02 10:28:49 -08:00

46 lines
1.8 KiB
C++

//===-- lib/Semantics/check-return.cpp ------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include "check-return.h"
#include "flang/Common/Fortran-features.h"
#include "flang/Parser/message.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Semantics/semantics.h"
#include "flang/Semantics/tools.h"
namespace Fortran::semantics {
static const Scope *FindContainingSubprogram(const Scope &start) {
const Scope &scope{GetProgramUnitContaining(start)};
return scope.kind() == Scope::Kind::MainProgram ||
scope.kind() == Scope::Kind::Subprogram
? &scope
: nullptr;
}
void ReturnStmtChecker::Leave(const parser::ReturnStmt &returnStmt) {
// R1542 Expression analysis validates the scalar-int-expr
// C1574 The return-stmt shall be in the inclusive scope of a function or
// subroutine subprogram.
// C1575 The scalar-int-expr is allowed only in the inclusive scope of a
// subroutine subprogram.
const auto &scope{context_.FindScope(context_.location().value())};
if (const auto *subprogramScope{FindContainingSubprogram(scope)}) {
if (returnStmt.v &&
(subprogramScope->kind() == Scope::Kind::MainProgram ||
IsFunction(*subprogramScope->GetSymbol()))) {
context_.Say(
"RETURN with expression is only allowed in SUBROUTINE subprogram"_err_en_US);
} else if (context_.ShouldWarn(common::LanguageFeature::ProgramReturn)) {
context_.Say("RETURN should not appear in a main program"_en_US);
}
}
}
} // namespace Fortran::semantics