diff --git a/flang/include/flang/Runtime/numeric.h b/flang/include/flang/Runtime/numeric.h index 3d9cb8b5b0acd..7d3f91360c8cf 100644 --- a/flang/include/flang/Runtime/numeric.h +++ b/flang/include/flang/Runtime/numeric.h @@ -356,10 +356,18 @@ CppTypeFor RTDECL(Scale16)( CppTypeFor, std::int64_t); #endif +// SELECTED_CHAR_KIND +CppTypeFor RTDECL(SelectedCharKind)( + const char *, int, const char *, std::size_t); + // SELECTED_INT_KIND CppTypeFor RTDECL(SelectedIntKind)( const char *, int, void *, int); +// SELECTED_LOGICAL_KIND +CppTypeFor RTDECL(SelectedLogicalKind)( + const char *, int, void *, int); + // SELECTED_REAL_KIND CppTypeFor RTDECL(SelectedRealKind)( const char *, int, void *, int, void *, int, void *, int); diff --git a/flang/lib/Evaluate/type.cpp b/flang/lib/Evaluate/type.cpp index a369e07f94a1f..ee1e5b398d9b0 100644 --- a/flang/lib/Evaluate/type.cpp +++ b/flang/lib/Evaluate/type.cpp @@ -731,7 +731,7 @@ bool SomeKind::operator==( return PointeeComparison(derivedTypeSpec_, that.derivedTypeSpec_); } -int SelectedCharKind(const std::string &s, int defaultKind) { // 16.9.168 +int SelectedCharKind(const std::string &s, int defaultKind) { // F'2023 16.9.180 auto lower{parser::ToLowerCaseLetters(s)}; auto n{lower.size()}; while (n > 0 && lower[0] == ' ') { diff --git a/flang/runtime/numeric.cpp b/flang/runtime/numeric.cpp index abd3e500029fe..52b5a56894d88 100644 --- a/flang/runtime/numeric.cpp +++ b/flang/runtime/numeric.cpp @@ -9,6 +9,7 @@ #include "flang/Runtime/numeric.h" #include "numeric-templates.h" #include "terminator.h" +#include "tools.h" #include "flang/Common/float128.h" #include #include @@ -18,30 +19,30 @@ namespace Fortran::runtime { template -inline RT_API_ATTRS RES getIntArgValue(const char *source, int line, void *arg, - int kind, std::int64_t defaultValue, int resKind) { +inline RT_API_ATTRS RES GetIntArgValue(const char *source, int line, + const void *arg, int kind, std::int64_t defaultValue, int resKind) { RES res; if (!arg) { res = static_cast(defaultValue); } else if (kind == 1) { res = static_cast( - *static_cast *>(arg)); + *static_cast *>(arg)); } else if (kind == 2) { res = static_cast( - *static_cast *>(arg)); + *static_cast *>(arg)); } else if (kind == 4) { res = static_cast( - *static_cast *>(arg)); + *static_cast *>(arg)); } else if (kind == 8) { res = static_cast( - *static_cast *>(arg)); + *static_cast *>(arg)); #ifdef __SIZEOF_INT128__ } else if (kind == 16) { if (resKind != 16) { Terminator{source, line}.Crash("Unexpected integer kind in runtime"); } res = static_cast( - *static_cast *>(arg)); + *static_cast *>(arg)); #endif } else { Terminator{source, line}.Crash("Unexpected integer kind in runtime"); @@ -112,6 +113,22 @@ inline RT_API_ATTRS CppTypeFor SelectedIntKind(T x) { return -1; } +// SELECTED_LOGICAL_KIND (F'2023 16.9.182) +template +inline RT_API_ATTRS CppTypeFor SelectedLogicalKind( + T x) { + if (x <= 2) { + return 1; + } else if (x <= 4) { + return 2; + } else if (x <= 9) { + return 4; + } else if (x <= 18) { + return 8; + } + return -1; +} + // SELECTED_REAL_KIND (16.9.170) template inline RT_API_ATTRS CppTypeFor SelectedRealKind( @@ -717,40 +734,72 @@ CppTypeFor RTDEF(Scale10)( } #endif +// SELECTED_CHAR_KIND +CppTypeFor RTDEF(SelectedCharKind)( + const char *source, int line, const char *x, std::size_t length) { + static const char *keywords[]{ + "ASCII", "DEFAULT", "UCS-2", "ISO_10646", "UCS-4", nullptr}; + switch (IdentifyValue(x, length, keywords)) { + case 0: // ASCII + case 1: // DEFAULT + return 1; + case 2: // UCS-2 + return 2; + case 3: // ISO_10646 + case 4: // UCS-4 + return 4; + default: + return -1; + } +} // SELECTED_INT_KIND CppTypeFor RTDEF(SelectedIntKind)( const char *source, int line, void *x, int xKind) { #ifdef __SIZEOF_INT128__ CppTypeFor r = - getIntArgValue>( + GetIntArgValue>( source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16); #else - std::int64_t r = getIntArgValue( + std::int64_t r = GetIntArgValue( source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8); #endif return SelectedIntKind(r); } +// SELECTED_LOGICAL_KIND +CppTypeFor RTDEF(SelectedLogicalKind)( + const char *source, int line, void *x, int xKind) { +#ifdef __SIZEOF_INT128__ + CppTypeFor r = + GetIntArgValue>( + source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 16); +#else + std::int64_t r = GetIntArgValue( + source, line, x, xKind, /*defaultValue*/ 0, /*resKind*/ 8); +#endif + return SelectedLogicalKind(r); +} + // SELECTED_REAL_KIND CppTypeFor RTDEF(SelectedRealKind)(const char *source, int line, void *precision, int pKind, void *range, int rKind, void *radix, int dKind) { #ifdef __SIZEOF_INT128__ CppTypeFor p = - getIntArgValue>( + GetIntArgValue>( source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 16); CppTypeFor r = - getIntArgValue>( + GetIntArgValue>( source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 16); CppTypeFor d = - getIntArgValue>( + GetIntArgValue>( source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 16); #else - std::int64_t p = getIntArgValue( + std::int64_t p = GetIntArgValue( source, line, precision, pKind, /*defaultValue*/ 0, /*resKind*/ 8); - std::int64_t r = getIntArgValue( + std::int64_t r = GetIntArgValue( source, line, range, rKind, /*defaultValue*/ 0, /*resKind*/ 8); - std::int64_t d = getIntArgValue( + std::int64_t d = GetIntArgValue( source, line, radix, dKind, /*defaultValue*/ 2, /*resKind*/ 8); #endif return SelectedRealKind(p, r, d);