[flang] Allow assignment between INTEGER and LOGICAL as extension

Extend documentation

Original-commit: flang-compiler/f18@7a719198fc
Reviewed-on: https://github.com/flang-compiler/f18/pull/856
This commit is contained in:
peter klausler 2019-12-05 16:18:39 -08:00
parent 371399b8e1
commit 00c3c274de
3 changed files with 35 additions and 5 deletions

View File

@ -109,6 +109,8 @@ Extensions, deletions, and legacy features supported by default
* When a dummy argument is `POINTER` or `ALLOCATABLE` and is `INTENT(IN)`, we
relax enforcement of some requirements on actual arguments that must otherwise
hold true for definable arguments.
* Assignment of `LOGICAL` to `INTEGER` and vice versa (but not other types).
The values are normalized.
Extensions supported when enabled by options
--------------------------------------------
@ -140,7 +142,7 @@ Extensions and legacy features deliberately not supported
* Defining an explicit interface for a subprogram within itself (PGI only)
* USE association of a procedure interface within that same procedure's definition
* NULL() as a structure constructor expression for an ALLOCATABLE component (PGI).
* Conversion of LOGICAL to INTEGER.
* Conversion of LOGICAL to INTEGER in expressions.
* IF (integer expression) THEN ... END IF (PGI/Intel)
* Comparsion of LOGICAL with ==/.EQ. rather than .EQV. (also .NEQV.) (PGI/Intel)
* Procedure pointers in COMMON blocks (PGI/Intel)

View File

@ -33,7 +33,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
Hollerith, ArithmeticIF, Assign, AssignedGOTO, Pause, OpenMP,
CruftAfterAmpersand, ClassicCComments, AdditionalFormats, BigIntLiterals,
RealDoControls, EquivalenceNumericWithCharacter, AdditionalIntrinsics,
AnonymousParents, OldLabelDoEndStatements)
AnonymousParents, OldLabelDoEndStatements, LogicalIntegerAssignment)
using LanguageFeatures = EnumSet<LanguageFeature, LanguageFeature_enumSize>;

View File

@ -2578,8 +2578,12 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
using semantics::Tristate;
const Expr<SomeType> &lhs{GetExpr(0)};
const Expr<SomeType> &rhs{GetExpr(1)};
Tristate isDefined{semantics::IsDefinedAssignment(
lhs.GetType(), lhs.Rank(), rhs.GetType(), rhs.Rank())};
std::optional<DynamicType> lhsType{lhs.GetType()};
std::optional<DynamicType> rhsType{rhs.GetType()};
int lhsRank{lhs.Rank()};
int rhsRank{rhs.Rank()};
Tristate isDefined{
semantics::IsDefinedAssignment(lhsType, lhsRank, rhsType, rhsRank)};
if (isDefined == Tristate::No) {
return std::nullopt; // user-defined assignment not allowed for these args
}
@ -2587,7 +2591,31 @@ std::optional<ProcedureRef> ArgumentAnalyzer::TryDefinedAssignment() {
auto procRef{GetDefinedAssignmentProc()};
if (!procRef) {
if (isDefined == Tristate::Yes) {
SayNoMatch("ASSIGNMENT(=)", true);
if (context_.context().languageFeatures().IsEnabled(
common::LanguageFeature::LogicalIntegerAssignment) &&
lhsType && rhsType && (lhsRank == rhsRank || rhsRank == 0)) {
if (lhsType->category() == TypeCategory::Integer &&
rhsType->category() == TypeCategory::Logical) {
// allow assignment to LOGICAL from INTEGER as a legacy extension
if (context_.context().languageFeatures().ShouldWarn(
common::LanguageFeature::LogicalIntegerAssignment)) {
context_.Say(
"nonstandard usage: assignment of LOGICAL to INTEGER"_en_US);
}
} else if (lhsType->category() == TypeCategory::Logical &&
rhsType->category() == TypeCategory::Integer) {
// ... and assignment to LOGICAL from INTEGER
if (context_.context().languageFeatures().ShouldWarn(
common::LanguageFeature::LogicalIntegerAssignment)) {
context_.Say(
"nonstandard usage: assignment of INTEGER to LOGICAL"_en_US);
}
} else {
SayNoMatch("ASSIGNMENT(=)", true);
}
} else {
SayNoMatch("ASSIGNMENT(=)", true);
}
}
return std::nullopt;
}