diff --git a/flang/include/flang/atomic_int_kind.h b/flang/include/flang/atomic_int_kind.h new file mode 100644 --- /dev/null +++ b/flang/include/flang/atomic_int_kind.h @@ -0,0 +1,16 @@ +/*===-- include/flang/atomic_int_kind.h ---------------------------*- C++ -*-=== + * + * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. + * See https://llvm.org/LICENSE.txt for license information. + * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + * + * ===-----------------------------------------------------------------------=== + */ + +#ifndef ATOMIC_INT_KIND_H_ +#define ATOMIC_INT_KIND_H_ + +int atom_int_kind = 8; // figure out how to use the value from iso_fortran_env +// extern int atom_int_kind; + +#endif /* ATOMIC_INT_KIND_H_ */ diff --git a/flang/lib/Evaluate/intrinsics.cpp b/flang/lib/Evaluate/intrinsics.cpp --- a/flang/lib/Evaluate/intrinsics.cpp +++ b/flang/lib/Evaluate/intrinsics.cpp @@ -19,6 +19,7 @@ #include "flang/Evaluate/type.h" #include "flang/Semantics/scope.h" #include "flang/Semantics/tools.h" +#include "flang/atomic_int_kind.h" #include "llvm/Support/raw_ostream.h" #include #include @@ -90,6 +91,7 @@ addressable, // for PRESENT(), &c.; anything (incl. procedure) but BOZ nullPointerType, // for ASSOCIATED(NULL()) exactKind, // a single explicit exactKindValue + atomicIntKind, // atomic_int_kind from iso_fortran_env ) struct TypePattern { @@ -173,6 +175,8 @@ static constexpr TypePattern KINDChar{CharType, KindCode::effectiveKind}; static constexpr TypePattern KINDLogical{LogicalType, KindCode::effectiveKind}; +static constexpr TypePattern AtomicInt{IntType, KindCode::atomicIntKind}; + // The default rank pattern for dummy arguments and function results is // "elemental". ENUM_CLASS(Rank, @@ -183,6 +187,7 @@ matrix, array, // not scalar, rank is known and greater than zero coarray, // rank is known and can be scalar; has nonzero corank + atom, // has nonzero corank and is scalar or is coindexed known, // rank is known and can be scalar anyOrAssumedRank, // rank can be unknown; assumed-type TYPE(*) allowed conformable, // scalar, or array of same rank & shape as "array" argument @@ -1077,6 +1082,16 @@ static const IntrinsicInterface intrinsicSubroutine[]{ {"abort", {}, {}, Rank::elemental, IntrinsicClass::impureSubroutine}, + {"atomic_fetch_or", + {{"atom", AtomicInt, Rank::atom, Optionality::required, + common::Intent::InOut}, + {"value", AnyInt, Rank::scalar, Optionality::required, + common::Intent::In}, + {"old", AtomicInt, Rank::scalar, Optionality::required, + common::Intent::Out}, + {"stat", AnyInt, Rank::scalar, Optionality::optional, + common::Intent::Out}}, + {}, Rank::elemental, IntrinsicClass::atomicSubroutine}, {"cpu_time", {{"time", AnyReal, Rank::scalar, Optionality::required, common::Intent::Out}}, @@ -1473,6 +1488,15 @@ case KindCode::exactKind: argOk = type->kind() == d.typePattern.exactKindValue; break; + case KindCode::atomicIntKind: + argOk = type->kind() == atom_int_kind; + if (!argOk) { + messages.Say(arg->sourceLocation(), + "Actual argument for '%s=' must have kind=atomic_int_kind, but is '%s'"_err_en_US, + d.keyword, type->AsFortran()); + return std::nullopt; + } + break; default: CRASH_NO_CASE; } @@ -1556,6 +1580,24 @@ return std::nullopt; } break; + case Rank::atom: + if (IsCoarray(*arg)) { + argOk = rank == 0; + if (!argOk) { + messages.Say(arg->sourceLocation(), + "'%s=' argument must be a scalar coarray for intrinsic '%s'"_err_en_US, + d.keyword, name); + return std::nullopt; + } + } else if (ExtractCoarrayRef(*arg)) { + argOk = true; + } else { + messages.Say(arg->sourceLocation(), + "'%s=' argument must be a coarray or a coindexed object for intrinsic '%s'"_err_en_US, + d.keyword, name); + return std::nullopt; + } + break; case Rank::known: if (!knownArg) { knownArg = arg; @@ -1804,6 +1846,7 @@ case Rank::shape: case Rank::array: case Rank::coarray: + case Rank::atom: case Rank::known: case Rank::anyOrAssumedRank: case Rank::reduceOperation: diff --git a/flang/module/get_atomic_int_kind.f90 b/flang/module/get_atomic_int_kind.f90 new file mode 100644 --- /dev/null +++ b/flang/module/get_atomic_int_kind.f90 @@ -0,0 +1,17 @@ +!===-- module/get_atomic_int_kind.f90 --------------------------------------===! +! +! Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +! See https://llvm.org/LICENSE.txt for license information. +! SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +! +!===------------------------------------------------------------------------===! + +module get_atomic_int_kind_m + use iso_fortran_env, only: atomic_int_kind + implicit none + +contains + + integer, bind(c) :: atom_int_kind = atomic_int_kind + +end module get_atomic_int_kind_m diff --git a/flang/test/Semantics/atomic07.f90 b/flang/test/Semantics/atomic07.f90 --- a/flang/test/Semantics/atomic07.f90 +++ b/flang/test/Semantics/atomic07.f90 @@ -1,5 +1,4 @@ ! RUN: %python %S/test_errors.py %s %flang_fc1 -! XFAIL: * ! This test checks for semantic errors in atomic_fetch_or subroutine calls based on ! the interface defined in section 16.9.26 of the Fortran 2018 standard. @@ -120,7 +119,7 @@ call atomic_fetch_or(scalar_coarray, val, old_val, atom=repeated_atom) !ERROR: keyword argument to intrinsic 'atomic_fetch_or' was supplied positionally by an earlier actual argument - call atomic_fetch_or(scalar_coarray, val, old_val, val=repeated_val) + call atomic_fetch_or(scalar_coarray, val, old_val, value=repeated_val) !ERROR: keyword argument to intrinsic 'atomic_fetch_or' was supplied positionally by an earlier actual argument call atomic_fetch_or(scalar_coarray, val, old_val, status, stat=repeated_status)