canonicalize-do.cc
check-arithmeticif.cc
check-computed-goto.cc
+ check-deallocate.cc
check-do-concurrent.cc
check-if-construct.cc
check-if-stmt.cc
--- /dev/null
+// 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<std::list<parser::AllocateObject>>(deallocateStmt.t)) {
+ std::visit(
+ common::visitors{
+ [&](const parser::Name &name) {
+ auto const *symbol{name.symbol};
+ if (!IsVariableName(*symbol)) {
+ context_.messages().Say(name.source,
+ "name in DEALLOCATE statement must be a variable name"_err_en_US);
+ } else if (!IsAllocatableOrPointer(*symbol)) { // C951
+ context_.messages().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)) { // C951
+ context_.messages().Say(structureComponent.component.source,
+ "component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute"_err_en_US);
+ }
+ }
+ },
+ },
+ allocateObject.u);
+ }
+ // The parser is catchng dups too
+ bool gotStat{false}, gotMsg{false};
+ for (const parser::StatOrErrmsg &deallocOpt :
+ std::get<std::list<parser::StatOrErrmsg>>(deallocateStmt.t)) {
+ std::visit(
+ common::visitors{
+ [&](const parser::StatVariable &statVariable) {
+ // ExpressionAnalyzer emits error messages
+ evaluate::ExpressionAnalyzer analyzer{context_};
+ (void)analyzer.Analyze(statVariable.v);
+ if(gotStat) {
+ context_.Say("STAT may not be duplicated in a DEALLOCATE statement"_err_en_US);
+ }
+ gotStat = true;
+ },
+ [&](const parser::MsgVariable &msgVariable) {
+ // ExpressionAnalyzer emits error messages
+ evaluate::ExpressionAnalyzer analyzer{context_};
+ (void)analyzer.Analyze(msgVariable.v);
+ if(gotMsg) {
+ context_.Say("ERRMSG may not be duplicated in a DEALLOCATE statement"_err_en_US);
+ }
+ gotMsg = true;
+ },
+ },
+ deallocOpt.u);
+ }
+}
+} // namespace Fortran::semantics
--- /dev/null
+// 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.
+
+#ifndef FORTRAN_SEMANTICS_CHECK_DEALLOCATE_H_
+#define FORTRAN_SEMANTICS_CHECK_DEALLOCATE_H_
+
+#include "semantics.h"
+
+namespace Fortran::parser {
+struct DeallocateStmt;
+}
+
+namespace Fortran::semantics {
+class DeallocateChecker : public virtual BaseChecker {
+public:
+ inline DeallocateChecker(SemanticsContext &context) : context_{context} {}
+ void Leave(const parser::DeallocateStmt &);
+
+private:
+ SemanticsContext &context_;
+};
+}
+#endif // FORTRAN_SEMANTICS_CHECK_DEALLOCATE_H_
#include "canonicalize-do.h"
#include "check-arithmeticif.h"
#include "check-computed-goto.h"
+#include "check-deallocate.h"
#include "check-do-concurrent.h"
#include "check-if-construct.h"
#include "check-if-stmt.h"
using StatementSemanticsPass1 = SemanticsVisitor<ExprChecker>;
using StatementSemanticsPass2 = SemanticsVisitor<ArithmeticIfStmtChecker,
- AssignmentChecker, ComputedGotoStmtChecker, DoConcurrentChecker,
- IfConstructChecker, IfStmtChecker, NullifyChecker>;
+ AssignmentChecker, ComputedGotoStmtChecker, DeallocateChecker,
+ DoConcurrentChecker, IfConstructChecker, IfStmtChecker, NullifyChecker>;
SemanticsContext::SemanticsContext(
const common::IntrinsicTypeDefaultKinds &defaultKinds,
return symbol.attrs().test(Attr::POINTER);
}
+bool IsAllocatable(const Symbol &symbol) {
+ return symbol.attrs().test(Attr::ALLOCATABLE);
+}
+
bool IsPointerDummy(const Symbol &symbol) {
return IsPointer(symbol) && IsDummy(symbol);
}
+bool IsAllocatableOrPointer(const Symbol &symbol) {
+ return IsPointer(symbol) || IsAllocatable(symbol);
+}
+
bool IsParameter(const Symbol &symbol) {
return symbol.attrs().test(Attr::PARAMETER);
}
bool IsPureFunction(const Scope &);
bool IsProcName(const Symbol &symbol); // proc-name
bool IsVariableName(const Symbol &symbol); // variable-name
+bool IsAllocatable(const Symbol &);
+bool IsAllocatableOrPointer(const Symbol &);
// Determines whether an object might be visible outside a
// PURE function (C1594); returns a non-null Symbol pointer for
computed-goto02.f90
nullify01.f90
nullify02.f90
+ deallocate01.f90
+ deallocate04.f90
)
# These test files have expected symbols in the source
--- /dev/null
+! 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.
+
+! Test that DEALLOCATE works
+
+INTEGER, PARAMETER :: maxvalue=1024
+
+Type dt
+ Integer :: l = 3
+End Type
+Type t
+ Type(dt),Pointer :: p
+End Type
+
+Type(t),Allocatable :: x(:)
+Type(t),Pointer :: y(:)
+Type(t),Pointer :: z
+Integer :: s
+CHARACTER(256) :: e
+
+Integer, Pointer :: pi
+
+Allocate(p)
+Allocate(x(3))
+
+Deallocate(x(2)%p)
+
+Deallocate(y(2)%p)
+
+Deallocate(pi)
+
+Deallocate(z%p)
+
+Deallocate(x%p, stat=s, errmsg=e)
+Deallocate(x%p, errmsg=e)
+Deallocate(x%p, stat=s)
+
+Deallocate(y%p, stat=s, errmsg=e)
+Deallocate(y%p, errmsg=e)
+Deallocate(y%p, stat=s)
+
+Deallocate(z, stat=s, errmsg=e)
+Deallocate(z, errmsg=e)
+Deallocate(z, stat=s)
+
+Deallocate(z, y%p, stat=s, errmsg=e)
+Deallocate(z, y%p, errmsg=e)
+Deallocate(z, y%p, stat=s)
+
+End Program
--- /dev/null
+! 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.
+
+! Check for semantic errors in DEALLOCATE statements
+
+INTEGER, PARAMETER :: maxvalue=1024
+
+Type dt
+ Integer :: l = 3
+End Type
+Type t
+ Type(dt) :: p
+End Type
+
+Type(t),Allocatable :: x(:)
+
+Real :: r
+Integer :: s
+Integer :: e
+Integer :: pi
+Character(256) :: ee
+Procedure(Real) :: prp
+
+Allocate(x(3))
+
+!ERROR: component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+Deallocate(x(2)%p)
+
+!ERROR: name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+Deallocate(pi)
+
+!ERROR: component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+!ERROR: name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+Deallocate(x(2)%p, pi)
+
+!ERROR: name in DEALLOCATE statement must be a variable name
+Deallocate(prp)
+
+!ERROR: name in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+!ERROR: name in DEALLOCATE statement must be a variable name
+Deallocate(pi, prp)
+
+!ERROR: name in DEALLOCATE statement must be a variable name
+Deallocate(maxvalue)
+
+!ERROR: component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+Deallocate(x%p)
+
+!ERROR: component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+!ERROR: Must have default CHARACTER type
+Deallocate(x%p, stat=s, errmsg=e)
+
+!ERROR: component in DEALLOCATE statement must have the ALLOCATABLE or POINTER attribute
+!ERROR: Must have INTEGER type
+!ERROR: Must have default CHARACTER type
+Deallocate(x%p, stat=r, errmsg=e)
+
+End Program