@@ -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},
@@ -1892,9 +1896,9 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
18921896 d.keyword );
18931897 return std::nullopt ;
18941898 }
1895- if (!d.flags .test (ArgFlag::canBeNull )) {
1896- if (const auto *expr{arg->UnwrapExpr ()}; expr && IsNullPointer (* expr)) {
1897- if (!IsBareNullPointer (expr) && IsNullObjectPointer (* expr) &&
1899+ if (!d.flags .test (ArgFlag::canBeNullPointer )) {
1900+ if (const auto *expr{arg->UnwrapExpr ()}; IsNullPointer (expr)) {
1901+ if (!IsBareNullPointer (expr) && IsNullObjectPointer (expr) &&
18981902 d.flags .test (ArgFlag::canBeMoldNull)) {
18991903 // ok
19001904 } else {
@@ -1905,6 +1909,14 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
19051909 }
19061910 }
19071911 }
1912+ if (!d.flags .test (ArgFlag::canBeNullAllocatable) &&
1913+ IsNullAllocatable (arg->UnwrapExpr ()) &&
1914+ !d.flags .test (ArgFlag::canBeMoldNull)) {
1915+ messages.Say (arg->sourceLocation (),
1916+ " A NULL() allocatable is not allowed for '%s=' intrinsic argument" _err_en_US,
1917+ d.keyword );
1918+ return std::nullopt ;
1919+ }
19081920 if (d.flags .test (ArgFlag::notAssumedSize)) {
19091921 if (auto named{ExtractNamedEntity (*arg)}) {
19101922 if (semantics::IsAssumedSizeArray (named->GetLastSymbol ())) {
@@ -2862,14 +2874,15 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28622874 " MOLD= argument to NULL() must not be assumed-rank" _err_en_US);
28632875 }
28642876 bool isProcPtrTarget{
2865- IsProcedurePointerTarget (*mold) && !IsNullObjectPointer (* mold)};
2877+ IsProcedurePointerTarget (*mold) && !IsNullObjectPointer (mold)};
28662878 if (isProcPtrTarget || IsAllocatableOrPointerObject (*mold)) {
28672879 characteristics::DummyArguments args;
28682880 std::optional<characteristics::FunctionResult> fResult ;
2881+ bool isAllocatableMold{false };
28692882 if (isProcPtrTarget) {
28702883 // MOLD= procedure pointer
28712884 std::optional<characteristics::Procedure> procPointer;
2872- if (IsNullProcedurePointer (* mold)) {
2885+ if (IsNullProcedurePointer (mold)) {
28732886 procPointer =
28742887 characteristics::Procedure::Characterize (*mold, context);
28752888 } else {
@@ -2885,20 +2898,23 @@ SpecificCall IntrinsicProcTable::Implementation::HandleNull(
28852898 fResult .emplace (std::move (*procPointer));
28862899 }
28872900 } else if (auto type{mold->GetType ()}) {
2888- // MOLD= object pointer
2901+ // MOLD= object pointer or allocatable
28892902 characteristics::TypeAndShape typeAndShape{
28902903 *type, GetShape (context, *mold)};
28912904 args.emplace_back (
28922905 " mold" s, characteristics::DummyDataObject{typeAndShape});
28932906 fResult .emplace (std::move (typeAndShape));
2907+ isAllocatableMold = IsAllocatableDesignator (*mold);
28942908 } else {
28952909 context.messages ().Say (arguments[0 ]->sourceLocation (),
28962910 " MOLD= argument to NULL() lacks type" _err_en_US);
28972911 }
28982912 if (fResult ) {
28992913 fResult ->attrs .set (characteristics::FunctionResult::Attr::Pointer);
29002914 characteristics::Procedure::Attrs attrs;
2901- attrs.set (characteristics::Procedure::Attr::NullPointer);
2915+ attrs.set (isAllocatableMold
2916+ ? characteristics::Procedure::Attr::NullAllocatable
2917+ : characteristics::Procedure::Attr::NullPointer);
29022918 characteristics::Procedure chars{
29032919 std::move (*fResult ), std::move (args), attrs};
29042920 return SpecificCall{SpecificIntrinsic{" null" s, std::move (chars)},
@@ -3257,7 +3273,7 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
32573273 const auto &arg{call.arguments [0 ]};
32583274 if (arg) {
32593275 if (const auto *expr{arg->UnwrapExpr ()}) {
3260- ok = evaluate:: IsAllocatableDesignator (*expr);
3276+ ok = IsAllocatableDesignator (*expr) || IsNullAllocatable ( expr);
32613277 }
32623278 }
32633279 if (!ok) {
0 commit comments