2020-02-25 23:11:52 +08:00
|
|
|
//===-- lib/Evaluate/check-expression.cpp ---------------------------------===//
|
2019-09-19 06:43:12 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-09-19 06:43:12 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-09-19 06:43:12 +08:00
|
|
|
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Evaluate/check-expression.h"
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
#include "flang/Evaluate/intrinsics.h"
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Evaluate/traverse.h"
|
|
|
|
#include "flang/Evaluate/type.h"
|
|
|
|
#include "flang/Semantics/symbol.h"
|
|
|
|
#include "flang/Semantics/tools.h"
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
#include <set>
|
|
|
|
#include <string>
|
2019-09-19 06:43:12 +08:00
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
|
|
|
|
|
|
|
// Constant expression predicate IsConstantExpr().
|
|
|
|
// This code determines whether an expression is a "constant expression"
|
|
|
|
// in the sense of section 10.1.12. This is not the same thing as being
|
|
|
|
// able to fold it (yet) into a known constant value; specifically,
|
|
|
|
// the expression may reference derived type kind parameters whose values
|
|
|
|
// are not yet known.
|
2019-10-23 01:34:05 +08:00
|
|
|
class IsConstantExprHelper : public AllTraverse<IsConstantExprHelper, true> {
|
2019-09-19 06:43:12 +08:00
|
|
|
public:
|
2019-10-23 01:34:05 +08:00
|
|
|
using Base = AllTraverse<IsConstantExprHelper, true>;
|
2019-09-20 06:49:13 +08:00
|
|
|
IsConstantExprHelper() : Base{*this} {}
|
|
|
|
using Base::operator();
|
2019-09-19 06:43:12 +08:00
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <int KIND> bool operator()(const TypeParamInquiry<KIND> &inq) const {
|
2019-09-17 07:58:13 +08:00
|
|
|
return IsKindTypeParameter(inq.parameter());
|
2019-09-20 06:49:13 +08:00
|
|
|
}
|
|
|
|
bool operator()(const semantics::Symbol &symbol) const {
|
2020-06-19 08:17:04 +08:00
|
|
|
const auto &ultimate{symbol.GetUltimate()};
|
|
|
|
return IsNamedConstant(ultimate) || IsImpliedDoIndex(ultimate) ||
|
|
|
|
IsInitialProcedureTarget(ultimate);
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2019-09-20 06:49:13 +08:00
|
|
|
bool operator()(const CoarrayRef &) const { return false; }
|
|
|
|
bool operator()(const semantics::ParamValue ¶m) const {
|
|
|
|
return param.isExplicit() && (*this)(param.GetExplicit());
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> bool operator()(const FunctionRef<T> &call) const {
|
2019-09-19 06:43:12 +08:00
|
|
|
if (const auto *intrinsic{std::get_if<SpecificIntrinsic>(&call.proc().u)}) {
|
2019-09-20 06:49:13 +08:00
|
|
|
return intrinsic->name == "kind";
|
2019-09-21 00:46:00 +08:00
|
|
|
// TODO: other inquiry intrinsics
|
2019-09-19 06:43:12 +08:00
|
|
|
} else {
|
2019-09-20 06:49:13 +08:00
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
}
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
bool operator()(const StructureConstructor &constructor) const {
|
|
|
|
for (const auto &[symRef, expr] : constructor) {
|
2020-06-19 08:17:04 +08:00
|
|
|
if (!IsConstantStructureConstructorComponent(*symRef, expr.value())) {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2020-06-03 12:56:10 +08:00
|
|
|
bool operator()(const Component &component) const {
|
|
|
|
return (*this)(component.base());
|
|
|
|
}
|
2019-09-19 06:43:12 +08:00
|
|
|
// Forbid integer division by zero in constants.
|
2020-03-29 12:00:16 +08:00
|
|
|
template <int KIND>
|
2019-09-20 06:49:13 +08:00
|
|
|
bool operator()(
|
|
|
|
const Divide<Type<TypeCategory::Integer, KIND>> &division) const {
|
2019-09-19 06:43:12 +08:00
|
|
|
using T = Type<TypeCategory::Integer, KIND>;
|
|
|
|
if (const auto divisor{GetScalarConstantValue<T>(division.right())}) {
|
2020-06-04 15:41:28 +08:00
|
|
|
return !divisor->IsZero() && (*this)(division.left());
|
2019-09-20 06:49:13 +08:00
|
|
|
} else {
|
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
|
|
|
|
bool operator()(const Constant<SomeDerived> &) const { return true; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
bool IsConstantStructureConstructorComponent(
|
|
|
|
const Symbol &component, const Expr<SomeType> &expr) const {
|
|
|
|
if (IsAllocatable(component)) {
|
|
|
|
return IsNullPointer(expr);
|
|
|
|
} else if (IsPointer(component)) {
|
|
|
|
return IsNullPointer(expr) || IsInitialDataTarget(expr) ||
|
|
|
|
IsInitialProcedureTarget(expr);
|
|
|
|
} else {
|
|
|
|
return (*this)(expr);
|
|
|
|
}
|
|
|
|
}
|
2019-09-19 06:43:12 +08:00
|
|
|
};
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename A> bool IsConstantExpr(const A &x) {
|
2019-09-20 06:49:13 +08:00
|
|
|
return IsConstantExprHelper{}(x);
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2019-09-20 06:49:13 +08:00
|
|
|
template bool IsConstantExpr(const Expr<SomeType> &);
|
2019-09-17 07:58:13 +08:00
|
|
|
template bool IsConstantExpr(const Expr<SomeInteger> &);
|
2020-03-14 03:19:44 +08:00
|
|
|
template bool IsConstantExpr(const Expr<SubscriptInteger> &);
|
2020-06-19 08:17:04 +08:00
|
|
|
template bool IsConstantExpr(const StructureConstructor &);
|
2019-09-19 06:43:12 +08:00
|
|
|
|
|
|
|
// Object pointer initialization checking predicate IsInitialDataTarget().
|
|
|
|
// This code determines whether an expression is allowable as the static
|
|
|
|
// data address used to initialize a pointer with "=> x". See C765.
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
class IsInitialDataTargetHelper
|
2020-03-29 12:00:16 +08:00
|
|
|
: public AllTraverse<IsInitialDataTargetHelper, true> {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
public:
|
2019-10-23 01:34:05 +08:00
|
|
|
using Base = AllTraverse<IsInitialDataTargetHelper, true>;
|
2019-09-19 07:47:25 +08:00
|
|
|
using Base::operator();
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
explicit IsInitialDataTargetHelper(parser::ContextualMessages *m)
|
2020-03-29 12:00:16 +08:00
|
|
|
: Base{*this}, messages_{m} {}
|
2019-09-19 07:47:25 +08:00
|
|
|
|
2020-06-19 08:17:04 +08:00
|
|
|
bool emittedMessage() const { return emittedMessage_; }
|
|
|
|
|
2019-09-19 07:47:25 +08:00
|
|
|
bool operator()(const BOZLiteralConstant &) const { return false; }
|
|
|
|
bool operator()(const NullPointer &) const { return true; }
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> bool operator()(const Constant<T> &) const {
|
2019-09-19 07:47:25 +08:00
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
bool operator()(const semantics::Symbol &symbol) {
|
2019-09-17 07:58:13 +08:00
|
|
|
const Symbol &ultimate{symbol.GetUltimate()};
|
|
|
|
if (IsAllocatable(ultimate)) {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
if (messages_) {
|
|
|
|
messages_->Say(
|
|
|
|
"An initial data target may not be a reference to an ALLOCATABLE '%s'"_err_en_US,
|
|
|
|
ultimate.name());
|
2020-06-19 08:17:04 +08:00
|
|
|
emittedMessage_ = true;
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
return false;
|
2019-09-17 07:58:13 +08:00
|
|
|
} else if (ultimate.Corank() > 0) {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
if (messages_) {
|
|
|
|
messages_->Say(
|
|
|
|
"An initial data target may not be a reference to a coarray '%s'"_err_en_US,
|
|
|
|
ultimate.name());
|
2020-06-19 08:17:04 +08:00
|
|
|
emittedMessage_ = true;
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
return false;
|
2019-09-17 07:58:13 +08:00
|
|
|
} else if (!ultimate.attrs().test(semantics::Attr::TARGET)) {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
if (messages_) {
|
|
|
|
messages_->Say(
|
|
|
|
"An initial data target may not be a reference to an object '%s' that lacks the TARGET attribute"_err_en_US,
|
|
|
|
ultimate.name());
|
2020-06-19 08:17:04 +08:00
|
|
|
emittedMessage_ = true;
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
return false;
|
2019-09-17 07:58:13 +08:00
|
|
|
} else if (!IsSaved(ultimate)) {
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
if (messages_) {
|
|
|
|
messages_->Say(
|
|
|
|
"An initial data target may not be a reference to an object '%s' that lacks the SAVE attribute"_err_en_US,
|
|
|
|
ultimate.name());
|
2020-06-19 08:17:04 +08:00
|
|
|
emittedMessage_ = true;
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
return false;
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
2019-09-19 07:47:25 +08:00
|
|
|
bool operator()(const StaticDataObject &) const { return false; }
|
2020-03-29 12:00:16 +08:00
|
|
|
template <int KIND> bool operator()(const TypeParamInquiry<KIND> &) const {
|
2019-09-19 07:47:25 +08:00
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2019-09-19 07:47:25 +08:00
|
|
|
bool operator()(const Triplet &x) const {
|
|
|
|
return IsConstantExpr(x.lower()) && IsConstantExpr(x.upper()) &&
|
|
|
|
IsConstantExpr(x.stride());
|
|
|
|
}
|
|
|
|
bool operator()(const Subscript &x) const {
|
2020-03-29 12:00:16 +08:00
|
|
|
return std::visit(common::visitors{
|
|
|
|
[&](const Triplet &t) { return (*this)(t); },
|
|
|
|
[&](const auto &y) {
|
|
|
|
return y.value().Rank() == 0 &&
|
|
|
|
IsConstantExpr(y.value());
|
|
|
|
},
|
|
|
|
},
|
2019-09-19 07:47:25 +08:00
|
|
|
x.u);
|
|
|
|
}
|
|
|
|
bool operator()(const CoarrayRef &) const { return false; }
|
|
|
|
bool operator()(const Substring &x) const {
|
|
|
|
return IsConstantExpr(x.lower()) && IsConstantExpr(x.upper()) &&
|
|
|
|
(*this)(x.parent());
|
|
|
|
}
|
|
|
|
bool operator()(const DescriptorInquiry &) const { return false; }
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> bool operator()(const ArrayConstructor<T> &) const {
|
2019-09-19 07:47:25 +08:00
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2019-09-19 07:47:25 +08:00
|
|
|
bool operator()(const StructureConstructor &) const { return false; }
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> bool operator()(const FunctionRef<T> &) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
template <typename D, typename R, typename... O>
|
2019-09-19 07:47:25 +08:00
|
|
|
bool operator()(const Operation<D, R, O...> &) const {
|
|
|
|
return false;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> bool operator()(const Parentheses<T> &x) const {
|
2019-09-19 07:47:25 +08:00
|
|
|
return (*this)(x.left());
|
|
|
|
}
|
|
|
|
bool operator()(const Relational<SomeType> &) const { return false; }
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
|
2019-09-17 07:58:13 +08:00
|
|
|
private:
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
parser::ContextualMessages *messages_;
|
2020-06-19 08:17:04 +08:00
|
|
|
bool emittedMessage_{false};
|
2019-09-19 07:47:25 +08:00
|
|
|
};
|
2019-09-19 06:43:12 +08:00
|
|
|
|
2019-09-17 07:58:13 +08:00
|
|
|
bool IsInitialDataTarget(
|
Rework DATA statement semantics to use typed expressions
Summary:
Updates recent work on DATA statement semantic checking in
flang/lib/Semantics/check-data.{h,cpp} to use the compiler's
internal representation for typed expressions rather than working
on the raw parse tree. Saves the analyzed expressions for DATA
statement values as parse tree decorations because they'll soon be
needed in lowering. Corrects wording of some error messages.
Fixes a bug in constant expression checking: structure constructors
are not constant expressions if they set an allocatable component
to anything other than NULL.
Includes infrastructure changes to make this work, some renaming
to reflect the fact that the implied DO loop indices tracked by
expression analysis are not (just) from array constructors, remove
some dead code, and improve some comments.
Reviewers: tskeith, sscalpone, jdoerfert, DavidTruby, anchu-rajendran, schweitz
Reviewed By: tskeith, anchu-rajendran, schweitz
Subscribers: llvm-commits, flang-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78834
2020-04-25 04:54:11 +08:00
|
|
|
const Expr<SomeType> &x, parser::ContextualMessages *messages) {
|
2020-06-19 08:17:04 +08:00
|
|
|
IsInitialDataTargetHelper helper{messages};
|
|
|
|
bool result{helper(x)};
|
|
|
|
if (!result && messages && !helper.emittedMessage()) {
|
|
|
|
messages->Say(
|
|
|
|
"An initial data target must be a designator with constant subscripts"_err_en_US);
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInitialProcedureTarget(const semantics::Symbol &symbol) {
|
|
|
|
const auto &ultimate{symbol.GetUltimate()};
|
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
|
|
|
[](const semantics::SubprogramDetails &) { return true; },
|
|
|
|
[](const semantics::SubprogramNameDetails &) { return true; },
|
|
|
|
[&](const semantics::ProcEntityDetails &proc) {
|
|
|
|
return !semantics::IsPointer(ultimate) && !proc.isDummy();
|
|
|
|
},
|
|
|
|
[](const auto &) { return false; },
|
|
|
|
},
|
|
|
|
ultimate.details());
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInitialProcedureTarget(const ProcedureDesignator &proc) {
|
|
|
|
if (const auto *intrin{proc.GetSpecificIntrinsic()}) {
|
|
|
|
return !intrin->isRestrictedSpecific;
|
|
|
|
} else if (proc.GetComponent()) {
|
|
|
|
return false;
|
|
|
|
} else {
|
|
|
|
return IsInitialProcedureTarget(DEREF(proc.GetSymbol()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
bool IsInitialProcedureTarget(const Expr<SomeType> &expr) {
|
|
|
|
if (const auto *proc{std::get_if<ProcedureDesignator>(&expr.u)}) {
|
|
|
|
return IsInitialProcedureTarget(*proc);
|
|
|
|
} else {
|
|
|
|
return IsNullPointer(expr);
|
|
|
|
}
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Specification expression validation (10.1.11(2), C1010)
|
2019-09-21 05:28:15 +08:00
|
|
|
class CheckSpecificationExprHelper
|
2020-03-29 12:00:16 +08:00
|
|
|
: public AnyTraverse<CheckSpecificationExprHelper,
|
|
|
|
std::optional<std::string>> {
|
2019-09-21 05:28:15 +08:00
|
|
|
public:
|
2019-09-21 00:46:00 +08:00
|
|
|
using Result = std::optional<std::string>;
|
|
|
|
using Base = AnyTraverse<CheckSpecificationExprHelper, Result>;
|
2020-05-13 00:53:58 +08:00
|
|
|
explicit CheckSpecificationExprHelper(
|
|
|
|
const semantics::Scope &s, const IntrinsicProcTable &table)
|
|
|
|
: Base{*this}, scope_{s}, table_{table} {}
|
2019-09-19 06:43:12 +08:00
|
|
|
using Base::operator();
|
|
|
|
|
2019-09-21 00:46:00 +08:00
|
|
|
Result operator()(const ProcedureDesignator &) const {
|
|
|
|
return "dummy procedure argument";
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
2019-09-21 00:46:00 +08:00
|
|
|
Result operator()(const CoarrayRef &) const { return "coindexed reference"; }
|
2019-09-19 06:43:12 +08:00
|
|
|
|
2019-09-21 00:46:00 +08:00
|
|
|
Result operator()(const semantics::Symbol &symbol) const {
|
2019-09-19 06:43:12 +08:00
|
|
|
if (semantics::IsNamedConstant(symbol)) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return std::nullopt;
|
2020-05-13 00:53:58 +08:00
|
|
|
} else if (scope_.IsDerivedType() && IsVariableName(symbol)) { // C750, C754
|
|
|
|
return "derived type component or type parameter value not allowed to "
|
|
|
|
"reference variable '"s +
|
2020-05-07 03:23:05 +08:00
|
|
|
symbol.name().ToString() + "'";
|
[flang][NFC] Remove link-time dependency of Evaluate on Semantics
Summary:
Some Symbol-related functions used in Evaluate were moved to
Evaluate/tools.h. This includes changing some member functions that were
replaced by non-member functions `IsDummy`, `GetUsedModule`, and
`CountLenParameters`.
Some member functions were made inline in `Scope`, `Symbol`,
`ArraySpec`, and `DeclTypeSpec`. The definitions were preceded by a
comment explaining why they are inline.
`IsConstantShape` was expanded inline in `IsDescriptor` because it isn't
used anywhere else
After this change, at least when compiling with clang on macos,
`libFortranEvaluate.a` has no undefined symbols that are satisfied by
`libFortranSemantics.a`.
Reviewers: klausler, PeteSteinfeld, sscalpone, jdoerfert, DavidTruby
Reviewed By: PeteSteinfeld
Subscribers: llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D80762
2020-05-30 07:39:13 +08:00
|
|
|
} else if (IsDummy(symbol)) {
|
2019-09-19 06:43:12 +08:00
|
|
|
if (symbol.attrs().test(semantics::Attr::OPTIONAL)) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return "reference to OPTIONAL dummy argument '"s +
|
|
|
|
symbol.name().ToString() + "'";
|
2019-09-19 06:43:12 +08:00
|
|
|
} else if (symbol.attrs().test(semantics::Attr::INTENT_OUT)) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return "reference to INTENT(OUT) dummy argument '"s +
|
|
|
|
symbol.name().ToString() + "'";
|
2019-09-19 06:43:12 +08:00
|
|
|
} else if (symbol.has<semantics::ObjectEntityDetails>()) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return std::nullopt;
|
2019-09-19 06:43:12 +08:00
|
|
|
} else {
|
2019-09-21 00:46:00 +08:00
|
|
|
return "dummy procedure argument";
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
} else if (symbol.has<semantics::UseDetails>() ||
|
|
|
|
symbol.has<semantics::HostAssocDetails>() ||
|
|
|
|
symbol.owner().kind() == semantics::Scope::Kind::Module) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return std::nullopt;
|
2019-09-19 06:43:12 +08:00
|
|
|
} else if (const auto *object{
|
|
|
|
symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
|
|
|
// TODO: what about EQUIVALENCE with data in COMMON?
|
|
|
|
// TODO: does this work for blank COMMON?
|
2019-11-10 01:29:31 +08:00
|
|
|
if (object->commonBlock()) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return std::nullopt;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
}
|
2019-09-21 05:28:15 +08:00
|
|
|
for (const semantics::Scope *s{&scope_}; !s->IsGlobal();) {
|
|
|
|
s = &s->parent();
|
|
|
|
if (s == &symbol.owner()) {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
2019-09-21 00:46:00 +08:00
|
|
|
return "reference to local entity '"s + symbol.name().ToString() + "'";
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
|
2019-09-21 00:46:00 +08:00
|
|
|
Result operator()(const Component &x) const {
|
2019-09-19 06:43:12 +08:00
|
|
|
// Don't look at the component symbol.
|
|
|
|
return (*this)(x.base());
|
|
|
|
}
|
2019-09-21 05:28:15 +08:00
|
|
|
Result operator()(const DescriptorInquiry &) const {
|
|
|
|
// Subtle: Uses of SIZE(), LBOUND(), &c. that are valid in specification
|
|
|
|
// expressions will have been converted to expressions over descriptor
|
|
|
|
// inquiries by Fold().
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
2019-09-19 06:43:12 +08:00
|
|
|
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
template <int KIND>
|
|
|
|
Result operator()(const TypeParamInquiry<KIND> &inq) const {
|
|
|
|
if (scope_.IsDerivedType() && !IsConstantExpr(inq) &&
|
2020-05-13 00:53:58 +08:00
|
|
|
inq.parameter().owner() != scope_) { // C750, C754
|
|
|
|
return "non-constant reference to a type parameter inquiry not "
|
|
|
|
"allowed for derived type components or type parameter values";
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> Result operator()(const FunctionRef<T> &x) const {
|
2019-09-19 06:43:12 +08:00
|
|
|
if (const auto *symbol{x.proc().GetSymbol()}) {
|
2019-12-04 00:43:05 +08:00
|
|
|
if (!semantics::IsPureProcedure(*symbol)) {
|
2019-09-21 00:46:00 +08:00
|
|
|
return "reference to impure function '"s + symbol->name().ToString() +
|
|
|
|
"'";
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
if (semantics::IsStmtFunction(*symbol)) {
|
|
|
|
return "reference to statement function '"s +
|
|
|
|
symbol->name().ToString() + "'";
|
|
|
|
}
|
2020-05-13 00:53:58 +08:00
|
|
|
if (scope_.IsDerivedType()) { // C750, C754
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
return "reference to function '"s + symbol->name().ToString() +
|
2020-05-13 00:53:58 +08:00
|
|
|
"' not allowed for derived type components or type parameter"
|
|
|
|
" values";
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
}
|
2019-09-19 06:43:12 +08:00
|
|
|
// TODO: other checks for standard module procedures
|
|
|
|
} else {
|
|
|
|
const SpecificIntrinsic &intrin{DEREF(x.proc().GetSpecificIntrinsic())};
|
2020-05-13 00:53:58 +08:00
|
|
|
if (scope_.IsDerivedType()) { // C750, C754
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
if ((table_.IsIntrinsic(intrin.name) &&
|
|
|
|
badIntrinsicsForComponents_.find(intrin.name) !=
|
|
|
|
badIntrinsicsForComponents_.end()) ||
|
|
|
|
IsProhibitedFunction(intrin.name)) {
|
|
|
|
return "reference to intrinsic '"s + intrin.name +
|
2020-05-13 00:53:58 +08:00
|
|
|
"' not allowed for derived type components or type parameter"
|
|
|
|
" values";
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
}
|
|
|
|
if (table_.GetIntrinsicClass(intrin.name) ==
|
|
|
|
IntrinsicClass::inquiryFunction &&
|
|
|
|
!IsConstantExpr(x)) {
|
|
|
|
return "non-constant reference to inquiry intrinsic '"s +
|
2020-05-13 00:53:58 +08:00
|
|
|
intrin.name +
|
|
|
|
"' not allowed for derived type components or type"
|
|
|
|
" parameter values";
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
}
|
|
|
|
} else if (intrin.name == "present") {
|
2020-03-29 12:00:16 +08:00
|
|
|
return std::nullopt; // no need to check argument(s)
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
if (IsConstantExpr(x)) {
|
2019-09-21 05:28:15 +08:00
|
|
|
// inquiry functions may not need to check argument(s)
|
|
|
|
return std::nullopt;
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return (*this)(x.arguments());
|
|
|
|
}
|
2019-09-21 05:28:15 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
const semantics::Scope &scope_;
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
const IntrinsicProcTable &table_;
|
|
|
|
const std::set<std::string> badIntrinsicsForComponents_{
|
|
|
|
"allocated", "associated", "extends_type_of", "present", "same_type_as"};
|
|
|
|
static bool IsProhibitedFunction(std::string name) { return false; }
|
2019-09-19 06:43:12 +08:00
|
|
|
};
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename A>
|
2019-09-21 05:28:15 +08:00
|
|
|
void CheckSpecificationExpr(const A &x, parser::ContextualMessages &messages,
|
2020-05-13 00:53:58 +08:00
|
|
|
const semantics::Scope &scope, const IntrinsicProcTable &table) {
|
|
|
|
if (auto why{CheckSpecificationExprHelper{scope, table}(x)}) {
|
2019-09-17 07:58:13 +08:00
|
|
|
messages.Say("Invalid specification expression: %s"_err_en_US, *why);
|
2019-09-19 06:43:12 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-21 05:28:15 +08:00
|
|
|
template void CheckSpecificationExpr(const Expr<SomeType> &,
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
parser::ContextualMessages &, const semantics::Scope &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const IntrinsicProcTable &);
|
2020-03-14 03:19:44 +08:00
|
|
|
template void CheckSpecificationExpr(const Expr<SomeInteger> &,
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
parser::ContextualMessages &, const semantics::Scope &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const IntrinsicProcTable &);
|
2020-03-14 03:19:44 +08:00
|
|
|
template void CheckSpecificationExpr(const Expr<SubscriptInteger> &,
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
parser::ContextualMessages &, const semantics::Scope &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const IntrinsicProcTable &);
|
2020-03-14 03:19:44 +08:00
|
|
|
template void CheckSpecificationExpr(const std::optional<Expr<SomeType>> &,
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
parser::ContextualMessages &, const semantics::Scope &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const IntrinsicProcTable &);
|
2019-09-21 05:28:15 +08:00
|
|
|
template void CheckSpecificationExpr(const std::optional<Expr<SomeInteger>> &,
|
[flang] New implementation for checks for constraints C741 through C750
Summary:
Most of these checks were already implemented, and I just added references to
them to the code and tests. Also, much of this code was already
reviewed in the old flang/f18 GitHub repository, but I didn't get to
merge it before we switched repositories.
I implemented the check for C747 to not allow coarray components in derived
types that are of type C_PTR, C_FUNPTR, or type TEAM_TYPE.
I implemented the check for C748 that requires a data component whose type has
a coarray ultimate component to be a nonpointer, nonallocatable scalar and not
be a coarray.
I implemented the check for C750 that adds additional restrictions to the
bounds expressions of a derived type component that's an array.
These bounds expressions are sepcification expressions as defined in
10.1.11. There was already code in lib/Evaluate/check-expression.cpp to
check semantics for specification expressions, but it did not check for
the extra requirements of C750.
C750 prohibits specification functions, the intrinsic functions
ALLOCATED, ASSOCIATED, EXTENDS_TYPE_OF, PRESENT, and SAME_TYPE_AS. It
also requires every specification inquiry reference to be a constant
expression, and requires that the value of the bound not depend on the
value of a variable.
To implement these additional checks, I added code to the intrinsic proc
table to get the intrinsic class of a procedure. I also added an
enumeration to distinguish between specification expressions for
derived type component bounds versus for type parameters. I then
changed the code to pass an enumeration value to
"CheckSpecificationExpr()" to indicate that the expression was a bounds
expression and used this value to determine whether to emit an error
message when violations of C750 are found.
I changed the implementation of IsPureProcedure() to handle statement
functions and changed some references in the code that tested for the
PURE attribute to call IsPureProcedure().
I also fixed some unrelated tests that got new errors when I implemented these
new checks.
Reviewers: tskeith, DavidTruby, sscalpone
Subscribers: jfb, llvm-commits
Tags: #llvm, #flang
Differential Revision: https://reviews.llvm.org/D79263
2020-05-02 04:00:28 +08:00
|
|
|
parser::ContextualMessages &, const semantics::Scope &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const IntrinsicProcTable &);
|
2019-09-19 06:43:12 +08:00
|
|
|
template void CheckSpecificationExpr(
|
2019-09-21 05:28:15 +08:00
|
|
|
const std::optional<Expr<SubscriptInteger>> &, parser::ContextualMessages &,
|
2020-05-13 00:53:58 +08:00
|
|
|
const semantics::Scope &, const IntrinsicProcTable &);
|
2019-09-17 07:58:13 +08:00
|
|
|
|
|
|
|
// IsSimplyContiguous() -- 9.5.4
|
|
|
|
class IsSimplyContiguousHelper
|
2020-03-29 12:00:16 +08:00
|
|
|
: public AnyTraverse<IsSimplyContiguousHelper, std::optional<bool>> {
|
2019-09-17 07:58:13 +08:00
|
|
|
public:
|
2020-03-29 12:00:16 +08:00
|
|
|
using Result = std::optional<bool>; // tri-state
|
2019-09-17 07:58:13 +08:00
|
|
|
using Base = AnyTraverse<IsSimplyContiguousHelper, Result>;
|
|
|
|
explicit IsSimplyContiguousHelper(const IntrinsicProcTable &t)
|
2020-03-29 12:00:16 +08:00
|
|
|
: Base{*this}, table_{t} {}
|
2019-09-17 07:58:13 +08:00
|
|
|
using Base::operator();
|
|
|
|
|
|
|
|
Result operator()(const semantics::Symbol &symbol) const {
|
2020-01-08 05:39:42 +08:00
|
|
|
if (symbol.attrs().test(semantics::Attr::CONTIGUOUS) ||
|
|
|
|
symbol.Rank() == 0) {
|
2019-09-17 07:58:13 +08:00
|
|
|
return true;
|
|
|
|
} else if (semantics::IsPointer(symbol)) {
|
|
|
|
return false;
|
|
|
|
} else if (const auto *details{
|
|
|
|
symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
2019-10-17 06:36:54 +08:00
|
|
|
// N.B. ALLOCATABLEs are deferred shape, not assumed, and
|
|
|
|
// are obviously contiguous.
|
2019-09-17 07:58:13 +08:00
|
|
|
return !details->IsAssumedShape() && !details->IsAssumedRank();
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Result operator()(const ArrayRef &x) const {
|
2020-01-29 07:06:03 +08:00
|
|
|
const auto &symbol{x.GetLastSymbol()};
|
|
|
|
if (!(*this)(symbol)) {
|
|
|
|
return false;
|
|
|
|
} else if (auto rank{CheckSubscripts(x.subscript())}) {
|
|
|
|
// a(:)%b(1,1) is not contiguous; a(1)%b(:,:) is
|
|
|
|
return *rank > 0 || x.Rank() == 0;
|
|
|
|
} else {
|
|
|
|
return false;
|
|
|
|
}
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
Result operator()(const CoarrayRef &x) const {
|
2020-01-29 07:06:03 +08:00
|
|
|
return CheckSubscripts(x.subscript()).has_value();
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
2020-01-27 02:42:34 +08:00
|
|
|
Result operator()(const Component &x) const {
|
|
|
|
return x.base().Rank() == 0 && (*this)(x.GetLastSymbol());
|
|
|
|
}
|
2019-09-17 07:58:13 +08:00
|
|
|
Result operator()(const ComplexPart &) const { return false; }
|
|
|
|
Result operator()(const Substring &) const { return false; }
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename T> Result operator()(const FunctionRef<T> &x) const {
|
2019-09-17 07:58:13 +08:00
|
|
|
if (auto chars{
|
|
|
|
characteristics::Procedure::Characterize(x.proc(), table_)}) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (chars->functionResult) {
|
2019-09-17 07:58:13 +08:00
|
|
|
const auto &result{*chars->functionResult};
|
|
|
|
return !result.IsProcedurePointer() &&
|
|
|
|
result.attrs.test(characteristics::FunctionResult::Attr::Pointer) &&
|
|
|
|
result.attrs.test(
|
|
|
|
characteristics::FunctionResult::Attr::Contiguous);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
2020-01-29 07:06:03 +08:00
|
|
|
// If the subscripts can possibly be on a simply-contiguous array reference,
|
|
|
|
// return the rank.
|
|
|
|
static std::optional<int> CheckSubscripts(
|
|
|
|
const std::vector<Subscript> &subscript) {
|
2019-09-17 07:58:13 +08:00
|
|
|
bool anyTriplet{false};
|
2020-01-29 07:06:03 +08:00
|
|
|
int rank{0};
|
2019-09-17 07:58:13 +08:00
|
|
|
for (auto j{subscript.size()}; j-- > 0;) {
|
|
|
|
if (const auto *triplet{std::get_if<Triplet>(&subscript[j].u)}) {
|
|
|
|
if (!triplet->IsStrideOne()) {
|
2020-01-29 07:06:03 +08:00
|
|
|
return std::nullopt;
|
2019-09-17 07:58:13 +08:00
|
|
|
} else if (anyTriplet) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (triplet->lower() || triplet->upper()) {
|
2020-01-29 07:06:03 +08:00
|
|
|
// all triplets before the last one must be just ":"
|
|
|
|
return std::nullopt;
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
} else {
|
|
|
|
anyTriplet = true;
|
|
|
|
}
|
2020-01-29 07:06:03 +08:00
|
|
|
++rank;
|
2019-09-17 07:58:13 +08:00
|
|
|
} else if (anyTriplet || subscript[j].Rank() > 0) {
|
2020-01-29 07:06:03 +08:00
|
|
|
return std::nullopt;
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
}
|
2020-01-29 07:06:03 +08:00
|
|
|
return rank;
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
const IntrinsicProcTable &table_;
|
|
|
|
};
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
template <typename A>
|
2019-09-17 07:58:13 +08:00
|
|
|
bool IsSimplyContiguous(const A &x, const IntrinsicProcTable &table) {
|
|
|
|
if (IsVariable(x)) {
|
2020-01-08 05:39:42 +08:00
|
|
|
auto known{IsSimplyContiguousHelper{table}(x)};
|
|
|
|
return known && *known;
|
|
|
|
} else {
|
2020-03-29 12:00:16 +08:00
|
|
|
return true; // not a variable
|
2019-09-17 07:58:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
template bool IsSimplyContiguous(
|
|
|
|
const Expr<SomeType> &, const IntrinsicProcTable &);
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::evaluate
|