diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -181,12 +181,13 @@ conformable, // scalar, or array of same rank & shape as "array" argument reduceOperation, // a pure function with constraints for REDUCE dimReduced, // scalar if no DIM= argument, else rank(array)-1 - dimRemoved, // scalar, or rank(array)-1 + dimRemovedOrScalar, // rank(array)-1 (less DIM) or scalar + locReduced, // vector(1:rank) if no DIM= argument, else rank(array)-1 rankPlus1, // rank(known)+1 shaped, // rank is length of SHAPE vector ) -ENUM_CLASS(Optionality, required, optional, +ENUM_CLASS(Optionality, required, optional, missing, defaultsToSameKind, // for MatchingDefaultKIND defaultsToDefaultForResult, // for DefaultingKIND defaultsToSizeKind, // for SizeDefaultKIND @@ -227,6 +228,9 @@ static constexpr IntrinsicDummyArgument OptionalDIM{"dim", {IntType, KindCode::dimArg}, Rank::scalar, Optionality::optional, common::Intent::In}; +static constexpr IntrinsicDummyArgument MissingDIM{"dim", + {IntType, KindCode::dimArg}, Rank::scalar, Optionality::missing, + common::Intent::In}; static constexpr IntrinsicDummyArgument OptionalMASK{"mask", AnyLogical, Rank::conformable, Optionality::optional, common::Intent::In}; @@ -346,8 +350,8 @@ {"count", {{"mask", AnyLogical, Rank::array}, OptionalDIM, DefaultingKIND}, KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, {"cshift", - {{"array", SameType, Rank::array}, {"shift", AnyInt, Rank::dimRemoved}, - OptionalDIM}, + {{"array", SameType, Rank::array}, + {"shift", AnyInt, Rank::dimRemovedOrScalar}, OptionalDIM}, SameType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"dble", {{"a", AnyNumeric, Rank::elementalOrBOZ}}, DoublePrecision}, {"digits", {{"x", AnyIntOrReal, Rank::anyOrAssumedRank}}, DefaultInt, @@ -380,16 +384,16 @@ {"dshiftr", {{"i", BOZ}, {"j", SameInt}, {"shift", AnyInt}}, SameInt}, {"eoshift", {{"array", SameIntrinsic, Rank::array}, - {"shift", AnyInt, Rank::dimRemoved}, - {"boundary", SameIntrinsic, Rank::dimRemoved, + {"shift", AnyInt, Rank::dimRemovedOrScalar}, + {"boundary", SameIntrinsic, Rank::dimReduced, Optionality::optional}, OptionalDIM}, SameIntrinsic, Rank::conformable, IntrinsicClass::transformationalFunction}, {"eoshift", {{"array", SameDerivedType, Rank::array}, - {"shift", AnyInt, Rank::dimRemoved}, - {"boundary", SameDerivedType, Rank::dimRemoved}, OptionalDIM}, + {"shift", AnyInt, Rank::dimReduced}, + {"boundary", SameDerivedType, Rank::dimReduced}, OptionalDIM}, SameDerivedType, Rank::conformable, IntrinsicClass::transformationalFunction}, {"epsilon", {{"x", SameReal, Rank::anyOrAssumedRank}}, SameReal, @@ -410,20 +414,21 @@ {"value", AnyNumeric, Rank::scalar}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, - KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"findloc", {{"array", AnyNumeric, Rank::array}, - {"value", AnyNumeric, Rank::scalar}, OptionalMASK, SizeDefaultKIND, + {"value", AnyNumeric, Rank::scalar}, MissingDIM, OptionalMASK, + SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, KINDInt, Rank::vector, IntrinsicClass::transformationalFunction}, {"findloc", {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, - KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"findloc", {{"array", SameChar, Rank::array}, {"value", SameChar, Rank::scalar}, - OptionalMASK, SizeDefaultKIND, + MissingDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, KINDInt, Rank::vector, IntrinsicClass::transformationalFunction}, {"findloc", @@ -431,10 +436,11 @@ {"value", AnyLogical, Rank::scalar}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, - KINDInt, Rank::dimRemoved, IntrinsicClass::transformationalFunction}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"findloc", {{"array", AnyLogical, Rank::array}, - {"value", AnyLogical, Rank::scalar}, OptionalMASK, SizeDefaultKIND, + {"value", AnyLogical, Rank::scalar}, MissingDIM, OptionalMASK, + SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, KINDInt, Rank::vector, IntrinsicClass::transformationalFunction}, {"floor", {{"a", AnyReal}, DefaultingKIND}, KINDInt}, @@ -444,12 +450,18 @@ Rank::scalar, IntrinsicClass::inquiryFunction}, {"hypot", {{"x", OperandReal}, {"y", OperandReal}}, OperandReal}, {"iachar", {{"c", AnyChar}, DefaultingKIND}, KINDInt}, - {"iall", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK}, + {"iall", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK}, SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, - {"iany", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK}, + {"iall", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK}, + SameInt, Rank::scalar, IntrinsicClass::transformationalFunction}, + {"iany", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK}, SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, - {"iparity", {{"array", SameInt, Rank::array}, OptionalDIM, OptionalMASK}, + {"iany", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK}, + SameInt, Rank::scalar, IntrinsicClass::transformationalFunction}, + {"iparity", {{"array", SameInt, Rank::array}, RequiredDIM, OptionalMASK}, SameInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"iparity", {{"array", SameInt, Rank::array}, MissingDIM, OptionalMASK}, + SameInt, Rank::scalar, IntrinsicClass::transformationalFunction}, {"iand", {{"i", SameInt}, {"j", SameInt, Rank::elementalOrBOZ}}, SameInt}, {"iand", {{"i", BOZ}, {"j", SameInt}}, SameInt}, {"ibclr", {{"i", SameInt}, {"pos", AnyInt}}, SameInt}, @@ -540,14 +552,22 @@ {"maxexponent", {{"x", AnyReal, Rank::anyOrAssumedRank}}, DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction}, {"maxloc", - {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK, + {{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, - KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, + {"maxloc", + {{"array", AnyRelatable, Rank::array}, MissingDIM, OptionalMASK, + SizeDefaultKIND, + {"back", AnyLogical, Rank::scalar, Optionality::optional}}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"maxval", - {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK}, + {{"array", SameRelatable, Rank::array}, RequiredDIM, OptionalMASK}, SameRelatable, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"maxval", + {{"array", SameRelatable, Rank::array}, MissingDIM, OptionalMASK}, + SameRelatable, Rank::scalar, IntrinsicClass::transformationalFunction}, {"merge", {{"tsource", SameType}, {"fsource", SameType}, {"mask", AnyLogical}}, SameType}, @@ -569,14 +589,22 @@ {"minexponent", {{"x", AnyReal, Rank::anyOrAssumedRank}}, DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction}, {"minloc", - {{"array", AnyRelatable, Rank::array}, OptionalDIM, OptionalMASK, + {{"array", AnyRelatable, Rank::array}, RequiredDIM, OptionalMASK, SizeDefaultKIND, {"back", AnyLogical, Rank::scalar, Optionality::optional}}, - KINDInt, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, + {"minloc", + {{"array", AnyRelatable, Rank::array}, MissingDIM, OptionalMASK, + SizeDefaultKIND, + {"back", AnyLogical, Rank::scalar, Optionality::optional}}, + KINDInt, Rank::locReduced, IntrinsicClass::transformationalFunction}, {"minval", - {{"array", SameRelatable, Rank::array}, OptionalDIM, OptionalMASK}, + {{"array", SameRelatable, Rank::array}, RequiredDIM, OptionalMASK}, SameRelatable, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"minval", + {{"array", SameRelatable, Rank::array}, MissingDIM, OptionalMASK}, + SameRelatable, Rank::scalar, IntrinsicClass::transformationalFunction}, {"mod", {{"a", OperandIntOrReal}, {"p", OperandIntOrReal}}, OperandIntOrReal}, {"modulo", {{"a", OperandIntOrReal}, {"p", OperandIntOrReal}}, @@ -611,9 +639,11 @@ {"popcnt", {{"i", AnyInt}}, DefaultInt}, {"poppar", {{"i", AnyInt}}, DefaultInt}, {"product", - {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK}, + {{"array", SameNumeric, Rank::array}, RequiredDIM, OptionalMASK}, SameNumeric, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"product", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK}, + SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction}, {"precision", {{"x", AnyFloating, Rank::anyOrAssumedRank}}, DefaultInt, Rank::scalar, IntrinsicClass::inquiryFunction}, {"present", {{"a", Addressable, Rank::anyOrAssumedRank}}, DefaultLogical, @@ -630,10 +660,16 @@ KINDReal}, {"reduce", {{"array", SameType, Rank::array}, - {"operation", SameType, Rank::reduceOperation}, OptionalDIM, + {"operation", SameType, Rank::reduceOperation}, RequiredDIM, OptionalMASK, {"identity", SameType, Rank::scalar}, {"ordered", AnyLogical, Rank::scalar, Optionality::optional}}, SameType, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"reduce", + {{"array", SameType, Rank::array}, + {"operation", SameType, Rank::reduceOperation}, MissingDIM, + OptionalMASK, {"identity", SameType, Rank::scalar}, + {"ordered", AnyLogical, Rank::scalar, Optionality::optional}}, + SameType, Rank::scalar, IntrinsicClass::transformationalFunction}, {"repeat", {{"string", SameChar, Rank::scalar}, {"ncopies", AnyInt}}, SameChar, Rank::scalar, IntrinsicClass::transformationalFunction}, {"reshape", @@ -695,9 +731,11 @@ {"sqrt", {{"x", SameFloating}}, SameFloating}, {"storage_size", {{"a", AnyData, Rank::anyOrAssumedRank}, SizeDefaultKIND}, KINDInt, Rank::scalar, IntrinsicClass::inquiryFunction}, - {"sum", {{"array", SameNumeric, Rank::array}, OptionalDIM, OptionalMASK}, + {"sum", {{"array", SameNumeric, Rank::array}, RequiredDIM, OptionalMASK}, SameNumeric, Rank::dimReduced, IntrinsicClass::transformationalFunction}, + {"sum", {{"array", SameNumeric, Rank::array}, MissingDIM, OptionalMASK}, + SameNumeric, Rank::scalar, IntrinsicClass::transformationalFunction}, {"tan", {{"x", SameFloating}}, SameFloating}, {"tand", {{"x", SameFloating}}, SameFloating}, {"tanh", {{"x", SameFloating}}, SameFloating}, @@ -1083,6 +1121,9 @@ bool found{false}; int slot{missingActualArguments}; for (std::size_t j{0}; j < nonRepeatedDummies && !found; ++j) { + if (dummy[j].optionality == Optionality::missing) { + continue; + } if (arg->keyword()) { found = *arg->keyword() == dummy[j].keyword; if (found) { @@ -1150,6 +1191,9 @@ } else { continue; } + } else if (d.optionality == Optionality::missing) { + messages.Say("unexpected '%s=' argument"_err_en_US, d.keyword); + return std::nullopt; } if (arg->GetAssumedTypeDummy()) { // TYPE(*) assumed-type dummy argument forwarded to intrinsic @@ -1350,7 +1394,8 @@ CHECK(arrayArg); argOk = rank == 0 || rank == arrayArg->Rank(); break; - case Rank::dimRemoved: + case Rank::dimReduced: + case Rank::dimRemovedOrScalar: CHECK(arrayArg); argOk = rank == 0 || rank + 1 == arrayArg->Rank(); break; @@ -1360,7 +1405,7 @@ CHECK(arrayArg); argOk = rank == 0; break; - case Rank::dimReduced: + case Rank::locReduced: case Rank::rankPlus1: case Rank::shaped: common::die("INTERNAL: result-only rank code appears on argument '%s' " @@ -1518,9 +1563,9 @@ CHECK(arrayArg); resultRank = hasDimArg ? arrayArg->Rank() - 1 : 0; break; - case Rank::dimRemoved: + case Rank::locReduced: CHECK(arrayArg); - resultRank = arrayArg->Rank() - 1; + resultRank = hasDimArg ? arrayArg->Rank() - 1 : 1; break; case Rank::rankPlus1: CHECK(knownArg); @@ -1536,6 +1581,7 @@ case Rank::known: case Rank::anyOrAssumedRank: case Rank::reduceOperation: + case Rank::dimRemovedOrScalar: common::die("INTERNAL: bad Rank code on intrinsic '%s' result", name); break; } diff --git a/flang/lib/Evaluate/shape.cpp b/flang/lib/Evaluate/shape.cpp --- a/flang/lib/Evaluate/shape.cpp +++ b/flang/lib/Evaluate/shape.cpp @@ -575,8 +575,7 @@ } else if (intrinsic->name == "all" || intrinsic->name == "any" || intrinsic->name == "count" || intrinsic->name == "iall" || intrinsic->name == "iany" || intrinsic->name == "iparity" || - intrinsic->name == "maxloc" || intrinsic->name == "maxval" || - intrinsic->name == "minloc" || intrinsic->name == "minval" || + intrinsic->name == "maxval" || intrinsic->name == "minval" || intrinsic->name == "norm2" || intrinsic->name == "parity" || intrinsic->name == "product" || intrinsic->name == "sum") { // Reduction with DIM= @@ -594,6 +593,25 @@ } } } + } else if (intrinsic->name == "maxloc" || intrinsic->name == "minloc") { + // TODO: FINDLOC + if (call.arguments().size() >= 2) { + if (auto arrayShape{ + (*this)(UnwrapExpr>(call.arguments().at(0)))}) { + auto rank{static_cast(arrayShape->size())}; + if (const auto *dimArg{ + UnwrapExpr>(call.arguments()[1])}) { + auto dim{ToInt64(*dimArg)}; + if (dim && *dim >= 1 && *dim <= rank) { + arrayShape->erase(arrayShape->begin() + (*dim - 1)); + return std::move(*arrayShape); + } + } else { + // xxxLOC(no DIM=) result is vector(1:RANK(ARRAY=)) + return Shape{ExtentExpr{rank}}; + } + } + } } else if (intrinsic->name == "cshift" || intrinsic->name == "eoshift") { if (!call.arguments().empty()) { return (*this)(call.arguments()[0]); @@ -723,6 +741,10 @@ } } } + } else if (intrinsic->name == "unpack") { + if (call.arguments().size() >= 2) { + return (*this)(call.arguments()[1]); // MASK= + } } else if (intrinsic->characteristics.value().attrs.test(characteristics:: Procedure::Attr::NullPointer)) { // NULL(MOLD=) return (*this)(call.arguments());