forked from OSchip/llvm-project
[flang] Implement semantic checks for DEALLOCATE statements.
The parser checks for duplicate dealloc-opts and expr analysis checks that dealloc-opts are the right type. Original-commit: flang-compiler/f18@1ade7f6617 Reviewed-on: https://github.com/flang-compiler/f18/pull/401 Tree-same-pre-rewrite: false
This commit is contained in:
parent
28329e92b6
commit
70285af0ad
|
@ -18,6 +18,7 @@ add_library(FortranSemantics
|
|||
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
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
// 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
|
|
@ -0,0 +1,34 @@
|
|||
// 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_
|
|
@ -17,6 +17,7 @@
|
|||
#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"
|
||||
|
@ -78,8 +79,8 @@ private:
|
|||
|
||||
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,
|
||||
|
|
|
@ -123,10 +123,18 @@ bool IsPointer(const Symbol &symbol) {
|
|||
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);
|
||||
}
|
||||
|
|
|
@ -49,6 +49,8 @@ bool IsPureFunction(const Symbol &);
|
|||
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
|
||||
|
|
|
@ -91,6 +91,8 @@ set(ERROR_TESTS
|
|||
computed-goto02.f90
|
||||
nullify01.f90
|
||||
nullify02.f90
|
||||
deallocate01.f90
|
||||
deallocate04.f90
|
||||
)
|
||||
|
||||
# These test files have expected symbols in the source
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
! 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
|
|
@ -0,0 +1,69 @@
|
|||
! 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
|
Loading…
Reference in New Issue