@@ -2663,6 +2663,8 @@ class IntrinsicProcTable::Implementation {
26632663 ActualArguments &, FoldingContext &) const ;
26642664 std::optional<SpecificCall> HandleC_Loc (
26652665 ActualArguments &, FoldingContext &) const ;
2666+ std::optional<SpecificCall> HandleC_Devloc (
2667+ ActualArguments &, FoldingContext &) const ;
26662668 const std::string &ResolveAlias (const std::string &name) const {
26672669 auto iter{aliases_.find (name)};
26682670 return iter == aliases_.end () ? name : iter->second ;
@@ -2690,7 +2692,8 @@ bool IntrinsicProcTable::Implementation::IsIntrinsicFunction(
26902692 return true ;
26912693 }
26922694 // special cases
2693- return name == " __builtin_c_loc" || name == " null" ;
2695+ return name == " __builtin_c_loc" || name == " __builtin_c_devloc" ||
2696+ name == " null" ;
26942697}
26952698bool IntrinsicProcTable::Implementation::IsIntrinsicSubroutine (
26962699 const std::string &name0) const {
@@ -3080,6 +3083,73 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::HandleC_Loc(
30803083 return std::nullopt ;
30813084}
30823085
3086+ // CUDA Fortran C_DEVLOC(x)
3087+ std::optional<SpecificCall> IntrinsicProcTable::Implementation::HandleC_Devloc (
3088+ ActualArguments &arguments, FoldingContext &context) const {
3089+ static const char *const keywords[]{" cptr" , nullptr };
3090+
3091+ if (CheckAndRearrangeArguments (arguments, context.messages (), keywords)) {
3092+ CHECK (arguments.size () == 1 );
3093+ const auto *expr{arguments[0 ].value ().UnwrapExpr ()};
3094+ if (auto typeAndShape{characteristics::TypeAndShape::Characterize (
3095+ arguments[0 ], context)}) {
3096+ if (expr && !IsContiguous (*expr, context).value_or (true )) {
3097+ context.messages ().Say (arguments[0 ]->sourceLocation (),
3098+ " C_DEVLOC() argument must be contiguous" _err_en_US);
3099+ }
3100+ if (auto constExtents{AsConstantExtents (context, typeAndShape->shape ())};
3101+ constExtents && GetSize (*constExtents) == 0 ) {
3102+ context.messages ().Say (arguments[0 ]->sourceLocation (),
3103+ " C_DEVLOC() argument may not be a zero-sized array" _err_en_US);
3104+ }
3105+ if (!(typeAndShape->type ().category () != TypeCategory::Derived ||
3106+ typeAndShape->type ().IsAssumedType () ||
3107+ (!typeAndShape->type ().IsPolymorphic () &&
3108+ CountNonConstantLenParameters (
3109+ typeAndShape->type ().GetDerivedTypeSpec ()) == 0 ))) {
3110+ context.messages ().Say (arguments[0 ]->sourceLocation (),
3111+ " C_DEVLOC() argument must have an intrinsic type, assumed type, or non-polymorphic derived type with no non-constant length parameter" _err_en_US);
3112+ } else if (typeAndShape->type ().knownLength ().value_or (1 ) == 0 ) {
3113+ context.messages ().Say (arguments[0 ]->sourceLocation (),
3114+ " C_DEVLOC() argument may not be zero-length character" _err_en_US);
3115+ } else if (typeAndShape->type ().category () != TypeCategory::Derived &&
3116+ !IsInteroperableIntrinsicType (typeAndShape->type ()).value_or (true )) {
3117+ if (typeAndShape->type ().category () == TypeCategory::Character &&
3118+ typeAndShape->type ().kind () == 1 ) {
3119+ // Default character kind, but length is not known to be 1
3120+ if (context.languageFeatures ().ShouldWarn (
3121+ common::UsageWarning::CharacterInteroperability)) {
3122+ context.messages ().Say (
3123+ common::UsageWarning::CharacterInteroperability,
3124+ arguments[0 ]->sourceLocation (),
3125+ " C_DEVLOC() argument has non-interoperable character length" _warn_en_US);
3126+ }
3127+ } else if (context.languageFeatures ().ShouldWarn (
3128+ common::UsageWarning::Interoperability)) {
3129+ context.messages ().Say (common::UsageWarning::Interoperability,
3130+ arguments[0 ]->sourceLocation (),
3131+ " C_DEVLOC() argument has non-interoperable intrinsic type or kind" _warn_en_US);
3132+ }
3133+ }
3134+
3135+ characteristics::DummyDataObject ddo{std::move (*typeAndShape)};
3136+ ddo.intent = common::Intent::In;
3137+ return SpecificCall{
3138+ SpecificIntrinsic{" __builtin_c_devloc" s,
3139+ characteristics::Procedure{
3140+ characteristics::FunctionResult{
3141+ DynamicType{GetBuiltinDerivedType (
3142+ builtinsScope_, " __builtin_c_devptr" )}},
3143+ characteristics::DummyArguments{
3144+ characteristics::DummyArgument{" cptr" s, std::move (ddo)}},
3145+ characteristics::Procedure::Attrs{
3146+ characteristics::Procedure::Attr::Pure}}},
3147+ std::move (arguments)};
3148+ }
3149+ }
3150+ return std::nullopt ;
3151+ }
3152+
30833153static bool CheckForNonPositiveValues (FoldingContext &context,
30843154 const ActualArgument &arg, const std::string &procName,
30853155 const std::string &argName) {
@@ -3270,6 +3340,8 @@ std::optional<SpecificCall> IntrinsicProcTable::Implementation::Probe(
32703340 } else { // function
32713341 if (call.name == " __builtin_c_loc" ) {
32723342 return HandleC_Loc (arguments, context);
3343+ } else if (call.name == " __builtin_c_devloc" ) {
3344+ return HandleC_Devloc (arguments, context);
32733345 } else if (call.name == " null" ) {
32743346 return HandleNull (arguments, context);
32753347 }
0 commit comments