[flang-commits] [flang] bb6faec - [flang] Tune handling of LEN type parameter discrepancies on ALLOCATE
Peter Klausler via flang-commits
flang-commits at lists.llvm.org
Mon Mar 27 17:01:47 PDT 2023
Author: Peter Klausler
Date: 2023-03-27T17:01:41-07:00
New Revision: bb6faec1818026a5b7ead29ff98511784ce2cfdd
URL: https://github.com/llvm/llvm-project/commit/bb6faec1818026a5b7ead29ff98511784ce2cfdd
DIFF: https://github.com/llvm/llvm-project/commit/bb6faec1818026a5b7ead29ff98511784ce2cfdd.diff
LOG: [flang] Tune handling of LEN type parameter discrepancies on ALLOCATE
Presently, semantics doesn't check for discrepancies between known
constant corresponding LEN type parameters between the declared type
of an allocatable/pointer and either the type-spec or the SOURCE=/MOLD=
on an ALLOCATE statement.
This allows discrepancies between character lengths to go unchecked.
Some compilers accept mismatched character lengths on SOURCE=/MOLD=
and the allocate object, and that's useful and unambiguous feature
that already works in f18 via truncation or padding. A portability
warning should issue, however.
But for mismatched character lengths between an allocate object and
an explicit type-spec, and for any mismatch between derived type
LEN type parameters, an error is appropriate.
Differential Revision: https://reviews.llvm.org/D146583
Added:
Modified:
flang/docs/Extensions.md
flang/lib/Semantics/check-allocate.cpp
flang/test/Semantics/allocate07.f90
flang/test/Semantics/allocate09.f90
Removed:
################################################################################
diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 7540283db5e8..d1b759178ac9 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -269,6 +269,9 @@ end
* A scalar logical dummy argument to a `BIND(C)` procedure does
not have to have `KIND=C_BOOL` since it can be converted to/from
`_Bool` without loss of information.
+* The character length of the `SOURCE=` or `MOLD=` in `ALLOCATE`
+ may be distinct from the constant character length, if any,
+ of an allocated object.
### Extensions supported when enabled by options
diff --git a/flang/lib/Semantics/check-allocate.cpp b/flang/lib/Semantics/check-allocate.cpp
index c397c9f0a778..fa1951d770f1 100644
--- a/flang/lib/Semantics/check-allocate.cpp
+++ b/flang/lib/Semantics/check-allocate.cpp
@@ -350,30 +350,24 @@ static std::optional<std::int64_t> GetTypeParameterInt64Value(
if (const ParamValue *
paramValue{derivedType.FindParameter(parameterSymbol.name())}) {
return evaluate::ToInt64(paramValue->GetExplicit());
- } else {
- return std::nullopt;
}
+ return std::nullopt;
}
-// HaveCompatibleKindParameters functions assume type1 is type compatible with
-// type2 (except for kind type parameters)
-static bool HaveCompatibleKindParameters(
+static bool HaveCompatibleTypeParameters(
const DerivedTypeSpec &derivedType1, const DerivedTypeSpec &derivedType2) {
for (const Symbol &symbol :
OrderParameterDeclarations(derivedType1.typeSymbol())) {
- if (symbol.get<TypeParamDetails>().attr() == common::TypeParamAttr::Kind) {
- // At this point, it should have been ensured that these contain integer
- // constants, so die if this is not the case.
- if (GetTypeParameterInt64Value(symbol, derivedType1).value() !=
- GetTypeParameterInt64Value(symbol, derivedType2).value()) {
- return false;
- }
+ auto v1{GetTypeParameterInt64Value(symbol, derivedType1)};
+ auto v2{GetTypeParameterInt64Value(symbol, derivedType2)};
+ if (v1 && v2 && *v1 != *v2) {
+ return false;
}
}
return true;
}
-static bool HaveCompatibleKindParameters(
+static bool HaveCompatibleTypeParameters(
const DeclTypeSpec &type1, const evaluate::DynamicType &type2) {
if (type1.category() == DeclTypeSpec::Category::ClassStar) {
return true;
@@ -383,28 +377,56 @@ static bool HaveCompatibleKindParameters(
} else if (type2.IsUnlimitedPolymorphic()) {
return false;
} else if (const DerivedTypeSpec * derivedType1{type1.AsDerived()}) {
- return HaveCompatibleKindParameters(
+ return HaveCompatibleTypeParameters(
*derivedType1, type2.GetDerivedTypeSpec());
} else {
common::die("unexpected type1 category");
}
}
-static bool HaveCompatibleKindParameters(
+static bool HaveCompatibleTypeParameters(
const DeclTypeSpec &type1, const DeclTypeSpec &type2) {
if (type1.category() == DeclTypeSpec::Category::ClassStar) {
return true;
- }
- if (const IntrinsicTypeSpec * intrinsicType1{type1.AsIntrinsic()}) {
- return intrinsicType1->kind() == DEREF(type2.AsIntrinsic()).kind();
+ } else if (const IntrinsicTypeSpec * intrinsicType1{type1.AsIntrinsic()}) {
+ const IntrinsicTypeSpec *intrinsicType2{type2.AsIntrinsic()};
+ return !intrinsicType2 || intrinsicType1->kind() == intrinsicType2->kind();
} else if (const DerivedTypeSpec * derivedType1{type1.AsDerived()}) {
- return HaveCompatibleKindParameters(
- *derivedType1, DEREF(type2.AsDerived()));
+ const DerivedTypeSpec *derivedType2{type2.AsDerived()};
+ return !derivedType2 ||
+ HaveCompatibleTypeParameters(*derivedType1, *derivedType2);
} else {
common::die("unexpected type1 category");
}
}
+static bool HaveCompatibleLengths(
+ const DeclTypeSpec &type1, const DeclTypeSpec &type2) {
+ if (type1.category() == DeclTypeSpec::Character &&
+ type2.category() == DeclTypeSpec::Character) {
+ auto v1{
+ evaluate::ToInt64(type1.characterTypeSpec().length().GetExplicit())};
+ auto v2{
+ evaluate::ToInt64(type2.characterTypeSpec().length().GetExplicit())};
+ return !v1 || !v2 || *v1 == *v2;
+ } else {
+ return true;
+ }
+}
+
+static bool HaveCompatibleLengths(
+ const DeclTypeSpec &type1, const evaluate::DynamicType &type2) {
+ if (type1.category() == DeclTypeSpec::Character &&
+ type2.category() == TypeCategory::Character) {
+ auto v1{
+ evaluate::ToInt64(type1.characterTypeSpec().length().GetExplicit())};
+ auto v2{type2.knownLength()};
+ return !v1 || !v2 || *v1 == *v2;
+ } else {
+ return true;
+ }
+}
+
bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
if (!symbol_) {
CHECK(context.AnyFatalError());
@@ -455,10 +477,15 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
"Allocatable object in ALLOCATE must be type compatible with type-spec"_err_en_US);
return false;
}
- if (!HaveCompatibleKindParameters(*type_, *allocateInfo_.typeSpec)) {
+ if (!HaveCompatibleTypeParameters(*type_, *allocateInfo_.typeSpec)) {
context.Say(name_.source,
// C936
- "Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec"_err_en_US);
+ "Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec"_err_en_US);
+ return false;
+ }
+ if (!HaveCompatibleLengths(*type_, *allocateInfo_.typeSpec)) { // C934
+ context.Say(name_.source,
+ "Character length of allocatable object in ALLOCATE must be the same as the type-spec"_err_en_US);
return false;
}
if (!HaveSameAssumedTypeParameters(*type_, *allocateInfo_.typeSpec)) {
@@ -474,11 +501,18 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
"Allocatable object in ALLOCATE must be type compatible with source expression from MOLD or SOURCE"_err_en_US);
return false;
}
- if (!HaveCompatibleKindParameters(
+ if (!HaveCompatibleTypeParameters(
*type_, allocateInfo_.sourceExprType.value())) {
// C946
context.Say(name_.source,
- "Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression"_err_en_US);
+ "Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression"_err_en_US);
+ return false;
+ }
+ // Character length distinction is allowed, with a warning
+ if (!HaveCompatibleLengths(
+ *type_, allocateInfo_.sourceExprType.value())) { // C945
+ context.Say(name_.source,
+ "Character length of allocatable object in ALLOCATE should be the same as the SOURCE or MOLD"_port_en_US);
return false;
}
}
diff --git a/flang/test/Semantics/allocate07.f90 b/flang/test/Semantics/allocate07.f90
index 8ebdbaa94cdd..94e17f3013fc 100644
--- a/flang/test/Semantics/allocate07.f90
+++ b/flang/test/Semantics/allocate07.f90
@@ -37,6 +37,9 @@ subroutine C936(param_ca_4_assumed, param_ta_4_assumed, param_ca_4_deferred)
class(*), pointer :: whatever
+ character(:), allocatable :: deferredChar
+ character(2), allocatable :: char2
+
! Nominal test cases
allocate(real(kind=4):: x1, x2(10))
allocate(WithParam(4, 2):: param_ta_4_2, param_ca_4_2)
@@ -52,42 +55,49 @@ subroutine C936(param_ca_4_assumed, param_ta_4_assumed, param_ca_4_deferred)
allocate(WithParam(k1=1):: param_defaulted)
allocate(WithParamExtent2(k1=1, l1=2, k2=5, l2=6, k3=5, l3=8 ):: param_defaulted)
allocate(WithParamExtent2(k1=1, l1=2, k2=5, l2=6, k3=5, l3=8 ):: whatever)
+ allocate(character(len=1):: deferredChar)
+ allocate(character(len=2):: char2)
-
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(real(kind=8):: x1)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(real(kind=8):: x2(10))
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, 2):: param_ta_4_2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, 2):: param_ca_4_2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent(8, 2, 8, 3):: param_ca_4_2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, *):: param_ta_4_assumed)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, *):: param_ca_4_assumed)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent(8, *, 8, 3):: param_ca_4_assumed)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, 2):: param_ta_4_deferred)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(8, 2):: param_ca_4_deferred)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent(8, 2, 8, 3):: param_ca_4_deferred)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent2(k1=5, l1=5, k2=5, l2=6, l3=8 ):: extended2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent2(k1=5, l1=2, k2=5, l2=6, k3=5, l3=8 ):: param_ca_4_2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent2(k1=4, l1=5, k2=5, l2=6, k3=5, l3=8 ):: extended2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam:: param_ca_4_2)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(k1=2, l1=2):: param_defaulted)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParam(k1=2):: param_defaulted)
- !ERROR: Kind type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
+ !ERROR: Type parameters of allocatable object in ALLOCATE must be the same as the corresponding ones in type-spec
allocate(WithParamExtent2(k1=5, l1=2, k2=5, l2=6, k3=5, l3=8 ):: param_defaulted)
+
+ !ERROR: Either type-spec or source-expr must appear in ALLOCATE when allocatable object has a deferred type parameters
+ allocate(deferredChar)
+ !ERROR: Character length of allocatable object in ALLOCATE must be the same as the type-spec
+ allocate(character(len=1):: char2)
+
end subroutine
diff --git a/flang/test/Semantics/allocate09.f90 b/flang/test/Semantics/allocate09.f90
index f235cabac657..2c7107ccda71 100644
--- a/flang/test/Semantics/allocate09.f90
+++ b/flang/test/Semantics/allocate09.f90
@@ -57,6 +57,9 @@ subroutine C946(param_ca_4_assumed, param_ta_4_assumed, param_ca_4_deferred)
class(*), pointer :: whatever
+ character(:), allocatable :: deferredChar
+ character(2), allocatable :: char2
+
! Nominal test cases
allocate(x1, x2(10), source=srcx)
allocate(x2(10), source=srcx_array)
@@ -80,51 +83,58 @@ subroutine C946(param_ca_4_assumed, param_ta_4_assumed, param_ca_4_deferred)
allocate(integer_default, source=[(i,i=0,9)])
+ allocate(deferredChar, source="abcd")
+ allocate(deferredChar, mold=deferredChar)
+ !PORTABILITY: Character length of allocatable object in ALLOCATE should be the same as the SOURCE or MOLD
+ allocate(char2, source="a")
+ !PORTABILITY: Character length of allocatable object in ALLOCATE should be the same as the SOURCE or MOLD
+ allocate(char2, source="abc")
+ allocate(char2, mold=deferredChar)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(x1, source=cos(0._8))
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(x2(10), source=srcx8)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(x2(10), mold=srcx8_array)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ta_4_2, source=src_a_8_2)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_2, mold=src_a_8_2)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ta_4_2, source=src_a_8_def)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_2, source=src_b_8_2_8_3)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_2, mold=src_b_8_def_8_3)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ta_4_assumed, source=src_a_8_def)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ta_4_assumed, mold=src_a_8_2)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_assumed, mold=src_a_8_def)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_assumed, source=src_b_8_2_8_3)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ta_4_deferred, mold=src_a_8_2)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_deferred, source=src_a_8_def)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_deferred, mold=src_b_8_2_8_3)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(extended2, source=src_c_5_5_5_6_8_8)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_2, mold=src_c_5_2_5_6_5_8)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(extended2, source=WithParamExtent2(k1=4, l1=5, k2=5, l2=6, k3=5, l3=8)(x=5))
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_ca_4_2, mold=param_defaulted)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_defaulted, source=param_ca_4_2)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_defaulted, mold=WithParam(k1=2)(x=5))
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(param_defaulted, source=src_c_5_2_5_6_5_8)
- !ERROR: Kind type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
+ !ERROR: Derived type parameters of allocatable object must be the same as the corresponding ones of SOURCE or MOLD expression
allocate(integer_default, source=[(i, integer(8)::i=0,9)])
end subroutine
More information about the flang-commits
mailing list