@@ -247,8 +247,10 @@ ENUM_CLASS(Optionality, required,
247247)
248248
249249ENUM_CLASS (ArgFlag, none,
250- canBeNull, // actual argument can be NULL(with or without MOLD=)
251- canBeMoldNull, // actual argument can be NULL(with MOLD=)
250+ canBeNullPointer, // actual argument can be NULL(with or without
251+ // MOLD=pointer)
252+ canBeMoldNull, // actual argument can be NULL(MOLD=any)
253+ canBeNullAllocatable, // actual argument can be NULL(MOLD=allocatable)
252254 defaultsToSameKind, // for MatchingDefaultKIND
253255 defaultsToSizeKind, // for SizeDefaultKIND
254256 defaultsToDefaultForResult, // for DefaultingKIND
@@ -343,8 +345,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
343345 Rank::dimReduced, IntrinsicClass::transformationalFunction},
344346 {" allocated" , {{" scalar" , AnyData, Rank::scalar}}, DefaultLogical,
345347 Rank::elemental, IntrinsicClass::inquiryFunction},
346- {" allocated" , {{" array" , AnyData, Rank::anyOrAssumedRank}}, DefaultLogical,
347- Rank::elemental, IntrinsicClass::inquiryFunction},
348+ {" allocated" ,
349+ {{" array" , AnyData, Rank::anyOrAssumedRank, Optionality::required,
350+ common::Intent::In, {ArgFlag::canBeNullAllocatable}}},
351+ DefaultLogical, Rank::elemental, IntrinsicClass::inquiryFunction},
348352 {" anint" , {{" a" , SameReal}, MatchingDefaultKIND}, KINDReal},
349353 {" any" , {{" mask" , SameLogical, Rank::array}, OptionalDIM}, SameLogical,
350354 Rank::dimReduced, IntrinsicClass::transformationalFunction},
@@ -353,10 +357,10 @@ static const IntrinsicInterface genericIntrinsicFunction[]{
353357 {" asinh" , {{" x" , SameFloating}}, SameFloating},
354358 {" associated" ,
355359 {{" pointer" , AnyPointer, Rank::anyOrAssumedRank, Optionality::required,
356- common::Intent::In, {ArgFlag::canBeNull }},
360+ common::Intent::In, {ArgFlag::canBeNullPointer }},
357361 {" target" , Addressable, Rank::anyOrAssumedRank,
358362 Optionality::optional, common::Intent::In,
359- {ArgFlag::canBeNull }}},
363+ {ArgFlag::canBeNullPointer }}},
360364 DefaultLogical, Rank::elemental, IntrinsicClass::inquiryFunction},
361365 {" atan" , {{" x" , SameFloating}}, SameFloating},
362366 {" atan" , {{" y" , OperandReal}, {" x" , OperandReal}}, OperandReal},
@@ -1883,9 +1887,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18831887 d.keyword );
18841888 return std::nullopt ;
18851889 }
1886- if (!d.flags .test (ArgFlag::canBeNull )) {
1887- if (const auto *expr{arg->UnwrapExpr ()}; expr && IsNullPointer (* expr)) {
1888- if (!IsBareNullPointer (expr) && IsNullObjectPointer (* expr) &&
1890+ if (!d.flags .test (ArgFlag::canBeNullPointer )) {
1891+ if (const auto *expr{arg->UnwrapExpr ()}; IsNullPointer (expr)) {
1892+ if (!IsBareNullPointer (expr) && IsNullObjectPointer (expr) &&
18891893 d.flags .test (ArgFlag::canBeMoldNull)) {
18901894 // ok
18911895 } else {
@@ -1896,6 +1900,13 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18961900 }
18971901 }
18981902 }
1903+ if (!d.flags .test (ArgFlag::canBeNullAllocatable) &&
1904+ IsNullAllocatable (arg->UnwrapExpr ())) {
1905+ messages.Say (arg->sourceLocation (),
1906+ " A NULL() allocatable is not allowed for '%s=' intrinsic argument" _err_en_US,
1907+ d.keyword );
1908+ return std::nullopt ;
1909+ }
18991910 if (d.flags .test (ArgFlag::notAssumedSize)) {
19001911 if (auto named{ExtractNamedEntity (*arg)}) {
19011912 if (semantics::IsAssumedSizeArray (named->GetLastSymbol ())) {
@@ -2853,14 +2864,15 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28532864 " MOLD= argument to NULL() must not be assumed-rank" _err_en_US);
28542865 }
28552866 bool isProcPtrTarget{
2856- IsProcedurePointerTarget (*mold) && !IsNullObjectPointer (* mold)};
2867+ IsProcedurePointerTarget (*mold) && !IsNullObjectPointer (mold)};
28572868 if (isProcPtrTarget || IsAllocatableOrPointerObject (*mold)) {
28582869 characteristics::DummyArguments args;
28592870 std::optional<characteristics::FunctionResult> fResult ;
2871+ bool isAllocatableMold{false };
28602872 if (isProcPtrTarget) {
28612873 // MOLD= procedure pointer
28622874 std::optional<characteristics::Procedure> procPointer;
2863- if (IsNullProcedurePointer (* mold)) {
2875+ if (IsNullProcedurePointer (mold)) {
28642876 procPointer =
28652877 characteristics::Procedure::Characterize (*mold, context);
28662878 } else {
@@ -2876,20 +2888,23 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28762888 fResult .emplace (std::move (*procPointer));
28772889 }
28782890 } else if (auto type{mold->GetType ()}) {
2879- // MOLD= object pointer
2891+ // MOLD= object pointer or allocatable
28802892 characteristics::TypeAndShape typeAndShape{
28812893 *type, GetShape (context, *mold)};
28822894 args.emplace_back (
28832895 " mold" s, characteristics::DummyDataObject{typeAndShape});
28842896 fResult .emplace (std::move (typeAndShape));
2897+ isAllocatableMold = IsAllocatableDesignator (*mold);
28852898 } else {
28862899 context.messages ().Say (arguments[0 ]->sourceLocation (),
28872900 " MOLD= argument to NULL() lacks type" _err_en_US);
28882901 }
28892902 if (fResult ) {
28902903 fResult ->attrs .set (characteristics::FunctionResult::Attr::Pointer);
28912904 characteristics::Procedure::Attrs attrs;
2892- attrs.set (characteristics::Procedure::Attr::NullPointer);
2905+ attrs.set (isAllocatableMold
2906+ ? characteristics::Procedure::Attr::NullAllocatable
2907+ : characteristics::Procedure::Attr::NullPointer);
28932908 characteristics::Procedure chars{
28942909 std::move (*fResult ), std::move (args), attrs};
28952910 return SpecificCall{SpecificIntrinsic{" null" s, std::move (chars)},
@@ -3248,7 +3263,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
32483263 const auto &arg{call.arguments [0 ]};
32493264 if (arg) {
32503265 if (const auto *expr{arg->UnwrapExpr ()}) {
3251- ok = evaluate:: IsAllocatableDesignator (*expr);
3266+ ok = IsAllocatableDesignator (*expr) || IsNullAllocatable ( expr);
32523267 }
32533268 }
32543269 if (!ok) {
0 commit comments