1717namespace Fortran ::semantics {
1818
1919void DeallocateChecker::Leave (const parser::DeallocateStmt &deallocateStmt) {
20+ bool gotStat{false }, gotMsg{false };
21+ const parser::Name *statVar{nullptr }, *msgVar{nullptr };
22+ for (const parser::StatOrErrmsg &deallocOpt :
23+ std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t )) {
24+ common::visit (
25+ common::visitors{
26+ [&](const parser::StatVariable &var) {
27+ if (gotStat) {
28+ context_.Say (
29+ " STAT may not be duplicated in a DEALLOCATE statement" _err_en_US);
30+ }
31+ if (const auto *designator{
32+ parser::Unwrap<parser::Designator>(var)}) {
33+ statVar = &parser::GetLastName (*designator);
34+ }
35+ gotStat = true ;
36+ },
37+ [&](const parser::MsgVariable &var) {
38+ WarnOnDeferredLengthCharacterScalar (context_,
39+ GetExpr (context_, var),
40+ parser::UnwrapRef<parser::Variable>(var).GetSource (),
41+ " ERRMSG=" );
42+ if (gotMsg) {
43+ context_.Say (
44+ " ERRMSG may not be duplicated in a DEALLOCATE statement" _err_en_US);
45+ }
46+ if (const auto *designator{
47+ parser::Unwrap<parser::Designator>(var)}) {
48+ msgVar = &parser::GetLastName (*designator);
49+ }
50+ gotMsg = true ;
51+ },
52+ },
53+ deallocOpt.u );
54+ }
2055 for (const parser::AllocateObject &allocateObject :
2156 std::get<std::list<parser::AllocateObject>>(deallocateStmt.t )) {
57+ const Symbol *ultimate{nullptr };
2258 common::visit (
2359 common::visitors{
2460 [&](const parser::Name &name) {
25- const Symbol * symbol{
26- name. symbol ? &name.symbol ->GetUltimate () : nullptr } ;
27- ;
28- if (context_.HasError (symbol )) {
61+ if (name. symbol ) {
62+ ultimate = &name.symbol ->GetUltimate ();
63+ }
64+ if (context_.HasError (ultimate )) {
2965 // already reported an error
30- } else if (!IsVariableName (*symbol )) {
66+ } else if (!IsVariableName (*ultimate )) {
3167 context_.Say (name.source ,
3268 " Name in DEALLOCATE statement must be a variable name" _err_en_US);
33- } else if (!IsAllocatableOrObjectPointer (symbol )) { // C936
69+ } else if (!IsAllocatableOrObjectPointer (ultimate )) { // C936
3470 context_.Say (name.source ,
3571 " Name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute" _err_en_US);
3672 } else if (auto whyNot{WhyNotDefinable (name.source ,
3773 context_.FindScope (name.source ),
3874 {DefinabilityFlag::PointerDefinition,
3975 DefinabilityFlag::AcceptAllocatable,
4076 DefinabilityFlag::PotentialDeallocation},
41- *symbol )}) {
77+ *ultimate )}) {
4278 // Catch problems with non-definability of the
4379 // pointer/allocatable
4480 context_
@@ -48,7 +84,7 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
4884 whyNot->set_severity (parser::Severity::Because)));
4985 } else if (auto whyNot{WhyNotDefinable (name.source ,
5086 context_.FindScope (name.source ),
51- DefinabilityFlags{}, *symbol )}) {
87+ DefinabilityFlags{}, *ultimate )}) {
5288 // Catch problems with non-definability of the dynamic object
5389 context_
5490 .Say (name.source ,
@@ -63,13 +99,11 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
6399 // Only perform structureComponent checks if it was successfully
64100 // analyzed by expression analysis.
65101 auto source{structureComponent.component .source };
102+ if (structureComponent.component .symbol ) {
103+ ultimate = &structureComponent.component .symbol ->GetUltimate ();
104+ }
66105 if (const auto *expr{GetExpr (context_, allocateObject)}) {
67- if (const Symbol *
68- symbol{structureComponent.component .symbol
69- ? &structureComponent.component .symbol
70- ->GetUltimate ()
71- : nullptr };
72- !IsAllocatableOrObjectPointer (symbol)) { // F'2023 C936
106+ if (!IsAllocatableOrObjectPointer (ultimate)) { // F'2023 C936
73107 context_.Say (source,
74108 " Component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute" _err_en_US);
75109 } else if (auto whyNot{WhyNotDefinable (source,
@@ -99,32 +133,22 @@ void DeallocateChecker::Leave(const parser::DeallocateStmt &deallocateStmt) {
99133 },
100134 },
101135 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 );
136+ if (ultimate) {
137+ if (gotStat && statVar) {
138+ if (const Symbol *symbol{statVar->symbol };
139+ symbol && *ultimate == symbol->GetUltimate ()) {
140+ context_.Say (statVar->source ,
141+ " STAT variable in DEALLOCATE must not be the variable being deallocated" _err_en_US);
142+ }
143+ }
144+ if (gotMsg && msgVar) {
145+ if (const Symbol *symbol{msgVar->symbol };
146+ symbol && *ultimate == symbol->GetUltimate ()) {
147+ context_.Say (msgVar->source ,
148+ " ERRMSG variable in DEALLOCATE must not be the variable being deallocated" _err_en_US);
149+ }
150+ }
151+ }
128152 }
129153}
130154
0 commit comments