1 //===-- lib/Semantics/check-purity.cpp ------------------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 #include "check-purity.h"
10 #include "flang/Parser/parse-tree.h"
11 #include "flang/Semantics/tools.h"
13 namespace Fortran::semantics
{
14 void PurityChecker::Enter(const parser::ExecutableConstruct
&exec
) {
15 if (InPureSubprogram() && IsImageControlStmt(exec
)) {
16 context_
.Say(GetImageControlStmtLocation(exec
),
17 "An image control statement may not appear in a pure subprogram"_err_en_US
);
20 void PurityChecker::Enter(const parser::SubroutineSubprogram
&subr
) {
21 const auto &stmt
{std::get
<parser::Statement
<parser::SubroutineStmt
>>(subr
.t
)};
23 stmt
.source
, std::get
<std::list
<parser::PrefixSpec
>>(stmt
.statement
.t
));
26 void PurityChecker::Leave(const parser::SubroutineSubprogram
&) { Left(); }
28 void PurityChecker::Enter(const parser::FunctionSubprogram
&func
) {
29 const auto &stmt
{std::get
<parser::Statement
<parser::FunctionStmt
>>(func
.t
)};
31 stmt
.source
, std::get
<std::list
<parser::PrefixSpec
>>(stmt
.statement
.t
));
34 void PurityChecker::Leave(const parser::FunctionSubprogram
&) { Left(); }
36 bool PurityChecker::InPureSubprogram() const {
37 return pureDepth_
>= 0 && depth_
>= pureDepth_
;
40 bool PurityChecker::HasPurePrefix(
41 const std::list
<parser::PrefixSpec
> &prefixes
) const {
42 for (const parser::PrefixSpec
&prefix
: prefixes
) {
43 if (std::holds_alternative
<parser::PrefixSpec::Pure
>(prefix
.u
)) {
50 void PurityChecker::Entered(
51 parser::CharBlock source
, const std::list
<parser::PrefixSpec
> &prefixes
) {
53 context_
.messages().Say(source
,
54 "An internal subprogram may not contain an internal subprogram"_err_en_US
);
56 if (HasPurePrefix(prefixes
)) {
60 } else if (InPureSubprogram()) {
61 context_
.messages().Say(source
,
62 "An internal subprogram of a pure subprogram must also be pure"_err_en_US
);
67 void PurityChecker::Left() {
68 if (pureDepth_
== --depth_
) {
73 } // namespace Fortran::semantics