77// ===----------------------------------------------------------------------===//
88
99#include " check-deallocate.h"
10+ #include " check-allocate.h"
1011#include " definable.h"
1112#include " flang/Evaluate/type.h"
1213#include " flang/Parser/message.h"
1314#include " flang/Parser/parse-tree.h"
1415#include " flang/Semantics/expression.h"
1516#include " flang/Semantics/tools.h"
17+ #include < optional>
1618
1719namespace Fortran ::semantics {
1820
1921void 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+ }
2055 for (const parser::AllocateObject &allocateObject :
2156 std::get<std::list<parser::AllocateObject>>(deallocateStmt.t )) {
57+ parser::CharBlock source;
2258 common::visit (
2359 common::visitors{
2460 [&](const parser::Name &name) {
2561 const Symbol *symbol{
2662 name.symbol ? &name.symbol ->GetUltimate () : nullptr };
27- ;
63+ source = name. source ;
2864 if (context_.HasError (symbol)) {
2965 // already reported an error
3066 } else if (!IsVariableName (*symbol)) {
31- context_.Say (name. source ,
67+ context_.Say (source,
3268 " Name in DEALLOCATE statement must be a variable name" _err_en_US);
3369 } else if (!IsAllocatableOrObjectPointer (symbol)) { // C936
34- context_.Say (name. source ,
70+ context_.Say (source,
3571 " Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute" _err_en_US);
36- } else if (auto whyNot{WhyNotDefinable (name. source ,
37- context_.FindScope (name. source ),
38- {DefinabilityFlag::PointerDefinition,
39- DefinabilityFlag::AcceptAllocatable,
40- DefinabilityFlag::PotentialDeallocation},
41- *symbol)}) {
72+ } else if (auto whyNot{
73+ WhyNotDefinable (source, context_.FindScope (source),
74+ {DefinabilityFlag::PointerDefinition,
75+ DefinabilityFlag::AcceptAllocatable,
76+ DefinabilityFlag::PotentialDeallocation},
77+ *symbol)}) {
4278 // Catch problems with non-definability of the
4379 // pointer/allocatable
4480 context_
45- .Say (name. source ,
81+ .Say (source,
4682 " Name in DEALLOCATE statement is not definable" _err_en_US)
4783 .Attach (std::move (
4884 whyNot->set_severity (parser::Severity::Because)));
49- } else if (auto whyNot{WhyNotDefinable (name. source ,
50- context_.FindScope (name. source ),
51- DefinabilityFlags{}, *symbol)}) {
85+ } else if (auto whyNot{
86+ WhyNotDefinable (source, context_.FindScope (source),
87+ DefinabilityFlags{}, *symbol)}) {
5288 // Catch problems with non-definability of the dynamic object
5389 context_
54- .Say (name. source ,
90+ .Say (source,
5591 " Object in DEALLOCATE statement is not deallocatable" _err_en_US)
5692 .Attach (std::move (
5793 whyNot->set_severity (parser::Severity::Because)));
@@ -62,13 +98,12 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
6298 [&](const parser::StructureComponent &structureComponent) {
6399 // Only perform structureComponent checks if it was successfully
64100 // analyzed by expression analysis.
65- auto source{ structureComponent.component .source } ;
101+ source = structureComponent.component .source ;
66102 if (const auto *expr{GetExpr (context_, allocateObject)}) {
67- if (const Symbol *
68- symbol{structureComponent.component .symbol
69- ? &structureComponent.component .symbol
70- ->GetUltimate ()
71- : nullptr };
103+ if (const Symbol *symbol{structureComponent.component .symbol
104+ ? &structureComponent.component .symbol
105+ ->GetUltimate ()
106+ : nullptr };
72107 !IsAllocatableOrObjectPointer (symbol)) { // F'2023 C936
73108 context_.Say (source,
74109 " Component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute" _err_en_US);
@@ -99,32 +134,16 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
99134 },
100135 },
101136 allocateObject.u );
102- }
103- bool gotStat{false }, gotMsg{false };
104- for (const parser::StatOrErrmsg &deallocOpt :
105- std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t )) {
106- common::visit (
107- common::visitors{
108- [&](const parser::StatVariable &) {
109- if (gotStat) {
110- context_.Say (
111- " STAT may not be duplicated in a DEALLOCATE statement" _err_en_US);
112- }
113- gotStat = true ;
114- },
115- [&](const parser::MsgVariable &var) {
116- WarnOnDeferredLengthCharacterScalar (context_,
117- GetExpr (context_, var),
118- parser::UnwrapRef<parser::Variable>(var).GetSource (),
119- " ERRMSG=" );
120- if (gotMsg) {
121- context_.Say (
122- " ERRMSG may not be duplicated in a DEALLOCATE statement" _err_en_US);
123- }
124- gotMsg = true ;
125- },
126- },
127- deallocOpt.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+ }
128147 }
129148}
130149
0 commit comments