@@ -54,7 +54,8 @@ static constexpr bool useKahanSummation{false};
54
54
// Utilities
55
55
template <typename T> class Folder {
56
56
public:
57
- explicit Folder (FoldingContext &c) : context_{c} {}
57
+ explicit Folder (FoldingContext &c, bool forOptionalArgument = false )
58
+ : context_{c}, forOptionalArgument_{forOptionalArgument} {}
58
59
std::optional<Constant<T>> GetNamedConstant (const Symbol &);
59
60
std::optional<Constant<T>> ApplySubscripts (const Constant<T> &array,
60
61
const std::vector<Constant<SubscriptInteger>> &subscripts);
@@ -81,6 +82,7 @@ template <typename T> class Folder {
81
82
82
83
private:
83
84
FoldingContext &context_;
85
+ bool forOptionalArgument_{false };
84
86
};
85
87
86
88
std::optional<Constant<SubscriptInteger>> GetConstantSubscript (
@@ -407,7 +409,14 @@ Constant<T> *Folder<T>::Folding(std::optional<ActualArgument> &arg) {
407
409
if (auto *expr{UnwrapExpr<Expr<SomeType>>(arg)}) {
408
410
if constexpr (T::category != TypeCategory::Derived) {
409
411
if (!UnwrapExpr<Expr<T>>(*expr)) {
410
- if (auto converted{ConvertToType (T::GetType (), std::move (*expr))}) {
412
+ if (const Symbol *
413
+ var{forOptionalArgument_
414
+ ? UnwrapWholeSymbolOrComponentDataRef (*expr)
415
+ : nullptr };
416
+ var && (IsOptional (*var) || IsAllocatableOrObjectPointer (var))) {
417
+ // can't safely convert item that may not be present
418
+ } else if (auto converted{
419
+ ConvertToType (T::GetType (), std::move (*expr))}) {
411
420
*expr = Fold (context_, std::move (*converted));
412
421
}
413
422
}
@@ -420,10 +429,10 @@ Constant<T> *Folder<T>::Folding(std::optional<ActualArgument> &arg) {
420
429
template <typename ... A, std::size_t ... I>
421
430
std::optional<std::tuple<const Constant<A> *...>> GetConstantArgumentsHelper (
422
431
FoldingContext &context, ActualArguments &arguments,
423
- std::index_sequence<I...>) {
432
+ bool hasOptionalArgument, std::index_sequence<I...>) {
424
433
static_assert (sizeof ...(A) > 0 );
425
434
std::tuple<const Constant<A> *...> args{
426
- Folder<A>{context}.Folding (arguments.at (I))...};
435
+ Folder<A>{context, hasOptionalArgument }.Folding (arguments.at (I))...};
427
436
if ((... && (std::get<I>(args)))) {
428
437
return args;
429
438
} else {
@@ -433,15 +442,17 @@ std::optional<std::tuple<const Constant<A> *...>> GetConstantArgumentsHelper(
433
442
434
443
template <typename ... A>
435
444
std::optional<std::tuple<const Constant<A> *...>> GetConstantArguments (
436
- FoldingContext &context, ActualArguments &args) {
445
+ FoldingContext &context, ActualArguments &args, bool hasOptionalArgument ) {
437
446
return GetConstantArgumentsHelper<A...>(
438
- context, args, std::index_sequence_for<A...>{});
447
+ context, args, hasOptionalArgument, std::index_sequence_for<A...>{});
439
448
}
440
449
441
450
template <typename ... A, std::size_t ... I>
442
451
std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArgumentsHelper (
443
- FoldingContext &context, ActualArguments &args, std::index_sequence<I...>) {
444
- if (auto constArgs{GetConstantArguments<A...>(context, args)}) {
452
+ FoldingContext &context, ActualArguments &args, bool hasOptionalArgument,
453
+ std::index_sequence<I...>) {
454
+ if (auto constArgs{
455
+ GetConstantArguments<A...>(context, args, hasOptionalArgument)}) {
445
456
return std::tuple<Scalar<A>...>{
446
457
std::get<I>(*constArgs)->GetScalarValue ().value ()...};
447
458
} else {
@@ -451,9 +462,9 @@ std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArgumentsHelper(
451
462
452
463
template <typename ... A>
453
464
std::optional<std::tuple<Scalar<A>...>> GetScalarConstantArguments (
454
- FoldingContext &context, ActualArguments &args) {
465
+ FoldingContext &context, ActualArguments &args, bool hasOptionalArgument ) {
455
466
return GetScalarConstantArgumentsHelper<A...>(
456
- context, args, std::index_sequence_for<A...>{});
467
+ context, args, hasOptionalArgument, std::index_sequence_for<A...>{});
457
468
}
458
469
459
470
// helpers to fold intrinsic function references
@@ -470,9 +481,10 @@ template <template <typename, typename...> typename WrapperType, typename TR,
470
481
typename ... TA, std::size_t ... I>
471
482
Expr<TR> FoldElementalIntrinsicHelper (FoldingContext &context,
472
483
FunctionRef<TR> &&funcRef, WrapperType<TR, TA...> func,
473
- std::index_sequence<I...>) {
484
+ bool hasOptionalArgument, std::index_sequence<I...>) {
474
485
if (std::optional<std::tuple<const Constant<TA> *...>> args{
475
- GetConstantArguments<TA...>(context, funcRef.arguments ())}) {
486
+ GetConstantArguments<TA...>(
487
+ context, funcRef.arguments (), hasOptionalArgument)}) {
476
488
// Compute the shape of the result based on shapes of arguments
477
489
ConstantSubscripts shape;
478
490
int rank{0 };
@@ -542,15 +554,19 @@ Expr<TR> FoldElementalIntrinsicHelper(FoldingContext &context,
542
554
543
555
template <typename TR, typename ... TA>
544
556
Expr<TR> FoldElementalIntrinsic (FoldingContext &context,
545
- FunctionRef<TR> &&funcRef, ScalarFunc<TR, TA...> func) {
546
- return FoldElementalIntrinsicHelper<ScalarFunc, TR, TA...>(
547
- context, std::move (funcRef), func, std::index_sequence_for<TA...>{});
557
+ FunctionRef<TR> &&funcRef, ScalarFunc<TR, TA...> func,
558
+ bool hasOptionalArgument = false ) {
559
+ return FoldElementalIntrinsicHelper<ScalarFunc, TR, TA...>(context,
560
+ std::move (funcRef), func, hasOptionalArgument,
561
+ std::index_sequence_for<TA...>{});
548
562
}
549
563
template <typename TR, typename ... TA>
550
564
Expr<TR> FoldElementalIntrinsic (FoldingContext &context,
551
- FunctionRef<TR> &&funcRef, ScalarFuncWithContext<TR, TA...> func) {
552
- return FoldElementalIntrinsicHelper<ScalarFuncWithContext, TR, TA...>(
553
- context, std::move (funcRef), func, std::index_sequence_for<TA...>{});
565
+ FunctionRef<TR> &&funcRef, ScalarFuncWithContext<TR, TA...> func,
566
+ bool hasOptionalArgument = false ) {
567
+ return FoldElementalIntrinsicHelper<ScalarFuncWithContext, TR, TA...>(context,
568
+ std::move (funcRef), func, hasOptionalArgument,
569
+ std::index_sequence_for<TA...>{});
554
570
}
555
571
556
572
std::optional<std::int64_t > GetInt64ArgOr (
0 commit comments