@@ -3073,10 +3073,11 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
30733073 ActualArguments &arguments, FoldingContext &context) const {
30743074 characteristics::Procedure::Attrs attrs;
30753075 attrs.set (characteristics::Procedure::Attr::Subroutine);
3076- static const char *const keywords[]{" cptr" , " fptr" , " shape" , nullptr };
3076+ static const char *const keywords[]{
3077+ " cptr" , " fptr" , " shape" , " lower" , nullptr };
30773078 characteristics::DummyArguments dummies;
3078- if (CheckAndRearrangeArguments (arguments, context.messages (), keywords, 1 )) {
3079- CHECK (arguments.size () == 3 );
3079+ if (CheckAndRearrangeArguments (arguments, context.messages (), keywords, 2 )) {
3080+ CHECK (arguments.size () == 4 );
30803081 if (const auto *expr{arguments[0 ].value ().UnwrapExpr ()}) {
30813082 // General semantic checks will catch an actual argument that's not
30823083 // scalar.
@@ -3169,11 +3170,30 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
31693170 }
31703171 }
31713172 }
3173+ if (arguments[3 ] && fptrRank == 0 ) {
3174+ context.messages ().Say (arguments[3 ]->sourceLocation (),
3175+ " LOWER= argument to C_F_POINTER() may not appear when FPTR= is scalar" _err_en_US);
3176+ } else if (arguments[3 ]) {
3177+ if (const auto *argExpr{arguments[3 ].value ().UnwrapExpr ()}) {
3178+ if (argExpr->Rank () > 1 ) {
3179+ context.messages ().Say (arguments[3 ]->sourceLocation (),
3180+ " LOWER= argument to C_F_POINTER() must be a rank-one array." _err_en_US);
3181+ } else if (argExpr->Rank () == 1 ) {
3182+ if (auto constShape{GetConstantShape (context, *argExpr)}) {
3183+ if (constShape->At (ConstantSubscripts{1 }).ToInt64 () != fptrRank) {
3184+ context.messages ().Say (arguments[3 ]->sourceLocation (),
3185+ " LOWER= argument to C_F_POINTER() must have size equal to the rank of FPTR=" _err_en_US);
3186+ }
3187+ }
3188+ }
3189+ }
3190+ }
31723191 }
31733192 }
31743193 if (dummies.size () == 2 ) {
3194+ // Handle SHAPE
31753195 DynamicType shapeType{TypeCategory::Integer, defaults_.sizeIntegerKind ()};
3176- if (arguments[2 ]) {
3196+ if (arguments. size () >= 3 && arguments [2 ]) {
31773197 if (auto type{arguments[2 ]->GetType ()}) {
31783198 if (type->category () == TypeCategory::Integer) {
31793199 shapeType = *type;
@@ -3185,6 +3205,22 @@ IntrinsicProcTable::Implementation::HandleC_F_Pointer(
31853205 shape.intent = common::Intent::In;
31863206 shape.attrs .set (characteristics::DummyDataObject::Attr::Optional);
31873207 dummies.emplace_back (" shape" s, std::move (shape));
3208+
3209+ // Handle LOWER
3210+ DynamicType lowerType{TypeCategory::Integer, defaults_.sizeIntegerKind ()};
3211+ if (arguments.size () >= 4 && arguments[3 ]) {
3212+ if (auto type{arguments[3 ]->GetType ()}) {
3213+ if (type->category () == TypeCategory::Integer) {
3214+ lowerType = *type;
3215+ }
3216+ }
3217+ }
3218+ characteristics::DummyDataObject lower{
3219+ characteristics::TypeAndShape{lowerType, 1 }};
3220+ lower.intent = common::Intent::In;
3221+ lower.attrs .set (characteristics::DummyDataObject::Attr::Optional);
3222+ dummies.emplace_back (" lower" s, std::move (lower));
3223+
31883224 return SpecificCall{
31893225 SpecificIntrinsic{" __builtin_c_f_pointer" s,
31903226 characteristics::Procedure{std::move (dummies), attrs}},
0 commit comments