llvm-project
77 строк · 2.5 Кб
1//===-- lib/Semantics/check-purity.cpp ------------------------------------===//
2//
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
6//
7//===----------------------------------------------------------------------===//
8
9#include "check-purity.h"
10#include "flang/Parser/parse-tree.h"
11#include "flang/Semantics/tools.h"
12
13namespace Fortran::semantics {
14void PurityChecker::Enter(const parser::ExecutableConstruct &exec) {
15if (InPureSubprogram() && IsImageControlStmt(exec)) {
16context_.Say(GetImageControlStmtLocation(exec),
17"An image control statement may not appear in a pure subprogram"_err_en_US);
18}
19}
20void PurityChecker::Enter(const parser::SubroutineSubprogram &subr) {
21const auto &stmt{std::get<parser::Statement<parser::SubroutineStmt>>(subr.t)};
22Entered(
23stmt.source, std::get<std::list<parser::PrefixSpec>>(stmt.statement.t));
24}
25
26void PurityChecker::Leave(const parser::SubroutineSubprogram &) { Left(); }
27
28void PurityChecker::Enter(const parser::FunctionSubprogram &func) {
29const auto &stmt{std::get<parser::Statement<parser::FunctionStmt>>(func.t)};
30Entered(
31stmt.source, std::get<std::list<parser::PrefixSpec>>(stmt.statement.t));
32}
33
34void PurityChecker::Leave(const parser::FunctionSubprogram &) { Left(); }
35
36bool PurityChecker::InPureSubprogram() const {
37return pureDepth_ >= 0 && depth_ >= pureDepth_;
38}
39
40bool PurityChecker::HasPurePrefix(
41const std::list<parser::PrefixSpec> &prefixes) const {
42bool result{false};
43for (const parser::PrefixSpec &prefix : prefixes) {
44if (std::holds_alternative<parser::PrefixSpec::Impure>(prefix.u)) {
45return false;
46} else if (std::holds_alternative<parser::PrefixSpec::Pure>(prefix.u) ||
47std::holds_alternative<parser::PrefixSpec::Elemental>(prefix.u)) {
48result = true;
49}
50}
51return result;
52}
53
54void PurityChecker::Entered(
55parser::CharBlock source, const std::list<parser::PrefixSpec> &prefixes) {
56if (depth_ == 2) {
57context_.messages().Say(source,
58"An internal subprogram may not contain an internal subprogram"_err_en_US);
59}
60if (HasPurePrefix(prefixes)) {
61if (pureDepth_ < 0) {
62pureDepth_ = depth_;
63}
64} else if (InPureSubprogram()) {
65context_.messages().Say(source,
66"An internal subprogram of a pure subprogram must also be pure"_err_en_US);
67}
68++depth_;
69}
70
71void PurityChecker::Left() {
72if (pureDepth_ == --depth_) {
73pureDepth_ = -1;
74}
75}
76
77} // namespace Fortran::semantics
78