// Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "check-deallocate.h" #include "expression.h" #include "tools.h" #include "../parser/message.h" #include "../parser/parse-tree.h" namespace Fortran::semantics { void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) { for (const parser::AllocateObject &allocateObject : std::get>(deallocateStmt.t)) { std::visit( common::visitors{ [&](const parser::Name &name) { auto const *symbol{name.symbol}; if (context_.HasError(symbol)) { // already reported an error } else if (!IsVariableName(*symbol)) { context_.Say(name.source, "name in DEALLOCATE statement must be a variable name"_err_en_US); } else if (!IsAllocatableOrPointer(*symbol)) { // C932 context_.Say(name.source, "name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US); } }, [&](const parser::StructureComponent &structureComponent) { evaluate::ExpressionAnalyzer analyzer{context_}; if (MaybeExpr checked{analyzer.Analyze(structureComponent)}) { if (!IsAllocatableOrPointer( *structureComponent.component.symbol)) { // C932 context_.Say(structureComponent.component.source, "component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US); } } }, }, allocateObject.u); } bool gotStat{false}, gotMsg{false}; for (const parser::StatOrErrmsg &deallocOpt : std::get>(deallocateStmt.t)) { std::visit( common::visitors{ [&](const parser::StatVariable &statVariable) { if (gotStat) { context_.Say( "STAT may not be duplicated in a DEALLOCATE statement"_err_en_US); } gotStat = true; }, [&](const parser::MsgVariable &msgVariable) { if (gotMsg) { context_.Say( "ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US); } gotMsg = true; }, }, deallocOpt.u); } } } // namespace Fortran::semantics