brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.9 KiB · e6ce1b3 Raw
151 lines · cpp
1//===-- lib/Semantics/check-deallocate.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "check-deallocate.h"10#include "check-allocate.h"11#include "definable.h"12#include "flang/Evaluate/type.h"13#include "flang/Parser/message.h"14#include "flang/Parser/parse-tree.h"15#include "flang/Semantics/expression.h"16#include "flang/Semantics/tools.h"17#include <optional>18 19namespace Fortran::semantics {20 21void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {22  bool gotStat{false}, gotMsg{false};23  const SomeExpr *statVar{nullptr}, *msgVar{nullptr};24  std::optional<parser::CharBlock> statSource;25  std::optional<parser::CharBlock> msgSource;26  for (const parser::StatOrErrmsg &deallocOpt :27      std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {28    common::visit(29        common::visitors{30            [&](const parser::StatVariable &var) {31              if (gotStat) {32                context_.Say(33                    "STAT may not be duplicated in a DEALLOCATE statement"_err_en_US);34              }35              gotStat = true;36              statVar = GetExpr(context_, var);37              statSource = parser::Unwrap<parser::Variable>(var)->GetSource();38            },39            [&](const parser::MsgVariable &var) {40              WarnOnDeferredLengthCharacterScalar(context_,41                  GetExpr(context_, var),42                  parser::UnwrapRef<parser::Variable>(var).GetSource(),43                  "ERRMSG=");44              if (gotMsg) {45                context_.Say(46                    "ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US);47              }48              gotMsg = true;49              msgVar = GetExpr(context_, var);50              msgSource = parser::Unwrap<parser::Variable>(var)->GetSource();51            },52        },53        deallocOpt.u);54  }55  for (const parser::AllocateObject &allocateObject :56      std::get<std::list<parser::AllocateObject>>(deallocateStmt.t)) {57    parser::CharBlock source;58    common::visit(59        common::visitors{60            [&](const parser::Name &name) {61              const Symbol *symbol{62                  name.symbol ? &name.symbol->GetUltimate() : nullptr};63              source = name.source;64              if (context_.HasError(symbol)) {65                // already reported an error66              } else if (!IsVariableName(*symbol)) {67                context_.Say(source,68                    "Name in DEALLOCATE statement must be a variable name"_err_en_US);69              } else if (!IsAllocatableOrObjectPointer(symbol)) { // C93670                context_.Say(source,71                    "Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);72              } else if (auto whyNot{73                             WhyNotDefinable(source, context_.FindScope(source),74                                 {DefinabilityFlag::PointerDefinition,75                                     DefinabilityFlag::AcceptAllocatable,76                                     DefinabilityFlag::PotentialDeallocation},77                                 *symbol)}) {78                // Catch problems with non-definability of the79                // pointer/allocatable80                context_81                    .Say(source,82                        "Name in DEALLOCATE statement is not definable"_err_en_US)83                    .Attach(std::move(84                        whyNot->set_severity(parser::Severity::Because)));85              } else if (auto whyNot{86                             WhyNotDefinable(source, context_.FindScope(source),87                                 DefinabilityFlags{}, *symbol)}) {88                // Catch problems with non-definability of the dynamic object89                context_90                    .Say(source,91                        "Object in DEALLOCATE statement is not deallocatable"_err_en_US)92                    .Attach(std::move(93                        whyNot->set_severity(parser::Severity::Because)));94              } else {95                context_.CheckIndexVarRedefine(name);96              }97            },98            [&](const parser::StructureComponent &structureComponent) {99              // Only perform structureComponent checks if it was successfully100              // analyzed by expression analysis.101              source = structureComponent.component.source;102              if (const auto *expr{GetExpr(context_, allocateObject)}) {103                if (const Symbol *symbol{structureComponent.component.symbol104                            ? &structureComponent.component.symbol105                                  ->GetUltimate()106                            : nullptr};107                    !IsAllocatableOrObjectPointer(symbol)) { // F'2023 C936108                  context_.Say(source,109                      "Component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);110                } else if (auto whyNot{WhyNotDefinable(source,111                               context_.FindScope(source),112                               {DefinabilityFlag::PointerDefinition,113                                   DefinabilityFlag::AcceptAllocatable,114                                   DefinabilityFlag::PotentialDeallocation},115                               *expr)}) {116                  context_117                      .Say(source,118                          "Name in DEALLOCATE statement is not definable"_err_en_US)119                      .Attach(std::move(120                          whyNot->set_severity(parser::Severity::Because)));121                } else if (auto whyNot{WhyNotDefinable(source,122                               context_.FindScope(source), DefinabilityFlags{},123                               *expr)}) {124                  context_125                      .Say(source,126                          "Object in DEALLOCATE statement is not deallocatable"_err_en_US)127                      .Attach(std::move(128                          whyNot->set_severity(parser::Severity::Because)));129                } else if (evaluate::ExtractCoarrayRef(*expr)) { // F'2023 C955130                  context_.Say(source,131                      "Component in DEALLOCATE statement may not be coindexed"_err_en_US);132                }133              }134            },135        },136        allocateObject.u);137    if (const SomeExpr *allocObj{GetExpr(context_, allocateObject)}) {138      if (AreSameAllocation(allocObj, statVar)) {139        context_.Say(statSource.value_or(source),140            "STAT variable in DEALLOCATE must not be the variable being deallocated"_err_en_US);141      }142      if (AreSameAllocation(allocObj, msgVar)) {143        context_.Say(msgSource.value_or(source),144            "ERRMSG variable in DEALLOCATE must not be the variable being deallocated"_err_en_US);145      }146    }147  }148}149 150} // namespace Fortran::semantics151