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-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "check-deallocate.h" 10 #include "flang/Parser/message.h" 11 #include "flang/Parser/parse-tree.h" 12 #include "flang/Semantics/expression.h" 13 #include "flang/Semantics/tools.h" 14 15 namespace Fortran::semantics { 16 17 void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) { 18 for (const parser::AllocateObject &allocateObject : 19 std::get<std::list<parser::AllocateObject>>(deallocateStmt.t)) { 20 std::visit( 21 common::visitors{ 22 [&](const parser::Name &name) { 23 auto const *symbol{name.symbol}; 24 if (context_.HasError(symbol)) { 25 // already reported an error 26 } else if (!IsVariableName(*symbol)) { 27 context_.Say(name.source, 28 "name in DEALLOCATE statement must be a variable name"_err_en_US); 29 } else if (!IsAllocatableOrPointer(*symbol)) { // C932 30 context_.Say(name.source, 31 "name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US); 32 } else { 33 context_.CheckIndexVarRedefine(name); 34 } 35 }, 36 [&](const parser::StructureComponent &structureComponent) { 37 evaluate::ExpressionAnalyzer analyzer{context_}; 38 if (MaybeExpr checked{analyzer.Analyze(structureComponent)}) { 39 if (!IsAllocatableOrPointer( 40 *structureComponent.component.symbol)) { // C932 41 context_.Say(structureComponent.component.source, 42 "component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US); 43 } 44 } 45 }, 46 }, 47 allocateObject.u); 48 } 49 bool gotStat{false}, gotMsg{false}; 50 for (const parser::StatOrErrmsg &deallocOpt : 51 std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) { 52 std::visit( 53 common::visitors{ 54 [&](const parser::StatVariable &) { 55 if (gotStat) { 56 context_.Say( 57 "STAT may not be duplicated in a DEALLOCATE statement"_err_en_US); 58 } 59 gotStat = true; 60 }, 61 [&](const parser::MsgVariable &) { 62 if (gotMsg) { 63 context_.Say( 64 "ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US); 65 } 66 gotMsg = true; 67 }, 68 }, 69 deallocOpt.u); 70 } 71 } 72 } // namespace Fortran::semantics 73