@@ -1311,6 +1311,14 @@ static const SpecificIntrinsicInterface specificIntrinsicFunction[]{
13111311
13121312static const IntrinsicInterface intrinsicSubroutine[]{
13131313 {" abort" , {}, {}, Rank::elemental, IntrinsicClass::impureSubroutine},
1314+ {" atomic_add" ,
1315+ {{" atom" , AtomicInt, Rank::atom, Optionality::required,
1316+ common::Intent::InOut},
1317+ {" value" , AnyInt, Rank::scalar, Optionality::required,
1318+ common::Intent::In},
1319+ {" stat" , AnyInt, Rank::scalar, Optionality::optional,
1320+ common::Intent::Out}},
1321+ {}, Rank::elemental, IntrinsicClass::atomicSubroutine},
13141322 {" atomic_and" ,
13151323 {{" atom" , AtomicInt, Rank::atom, Optionality::required,
13161324 common::Intent::InOut},
@@ -1585,7 +1593,6 @@ static const IntrinsicInterface intrinsicSubroutine[]{
15851593};
15861594
15871595// TODO: Intrinsic subroutine EVENT_QUERY
1588- // TODO: Atomic intrinsic subroutines: ATOMIC_ADD
15891596// TODO: Collective intrinsic subroutines: co_reduce
15901597
15911598// Finds a built-in derived type and returns it as a DynamicType.
@@ -1713,8 +1720,8 @@ static bool CheckAndPushMinMaxArgument(ActualArgument &arg,
17131720}
17141721
17151722static bool CheckAtomicKind (const ActualArgument &arg,
1716- const semantics::Scope *builtinsScope,
1717- parser::ContextualMessages &messages ) {
1723+ const semantics::Scope *builtinsScope, parser::ContextualMessages &messages,
1724+ const char *keyword ) {
17181725 std::string atomicKindStr;
17191726 std::optional<DynamicType> type{arg.GetType ()};
17201727
@@ -1727,11 +1734,12 @@ static bool CheckAtomicKind(const ActualArgument &arg,
17271734 " must be used with IntType or LogicalType" );
17281735 }
17291736
1730- bool argOk = type->kind () ==
1731- GetBuiltinKind (builtinsScope, (" __builtin_" + atomicKindStr).c_str ());
1737+ bool argOk{ type->kind () ==
1738+ GetBuiltinKind (builtinsScope, (" __builtin_" + atomicKindStr).c_str ())} ;
17321739 if (!argOk) {
17331740 messages.Say (arg.sourceLocation (),
1734- " Actual argument for 'atom=' must have kind=atomic_int_kind or atomic_logical_kind, but is '%s'" _err_en_US,
1741+ " Actual argument for '%s=' must have kind=atomic_%s_kind, but is '%s'" _err_en_US,
1742+ keyword, type->category () == TypeCategory::Integer ? " int" : " logical" ,
17351743 type->AsFortran ());
17361744 }
17371745 return argOk;
@@ -2052,7 +2060,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
20522060 case KindCode::sameAtom:
20532061 if (!sameArg) {
20542062 sameArg = arg;
2055- argOk = CheckAtomicKind (DEREF (arg), builtinsScope, messages);
2063+ argOk = CheckAtomicKind (DEREF (arg), builtinsScope, messages, d. keyword );
20562064 } else {
20572065 argOk = type->IsTkCompatibleWith (sameArg->GetType ().value ());
20582066 if (!argOk) {
@@ -2061,23 +2069,21 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
20612069 d.keyword , type->AsFortran ());
20622070 }
20632071 }
2064- if (!argOk)
2072+ if (!argOk) {
20652073 return std::nullopt ;
2074+ }
20662075 break ;
20672076 case KindCode::atomicIntKind:
2068- argOk = type->kind () ==
2069- GetBuiltinKind (builtinsScope, " __builtin_atomic_int_kind" );
2077+ argOk = CheckAtomicKind (DEREF (arg), builtinsScope, messages, d.keyword );
20702078 if (!argOk) {
2071- messages.Say (arg->sourceLocation (),
2072- " Actual argument for '%s=' must have kind=atomic_int_kind, but is '%s'" _err_en_US,
2073- d.keyword , type->AsFortran ());
20742079 return std::nullopt ;
20752080 }
20762081 break ;
20772082 case KindCode::atomicIntOrLogicalKind:
2078- argOk = CheckAtomicKind (DEREF (arg), builtinsScope, messages);
2079- if (!argOk)
2083+ argOk = CheckAtomicKind (DEREF (arg), builtinsScope, messages, d. keyword );
2084+ if (!argOk) {
20802085 return std::nullopt ;
2086+ }
20812087 break ;
20822088 default :
20832089 CRASH_NO_CASE;
@@ -3232,8 +3238,8 @@ static bool ApplySpecificChecks(SpecificCall &call, FoldingContext &context) {
32323238 arg ? arg->sourceLocation () : context.messages ().at (),
32333239 " Argument of ALLOCATED() must be an ALLOCATABLE object or component" _err_en_US);
32343240 }
3235- } else if (name == " atomic_and " || name == " atomic_or " ||
3236- name == " atomic_xor" ) {
3241+ } else if (name == " atomic_add " || name == " atomic_and " ||
3242+ name == " atomic_or " || name == " atomic_xor" ) {
32373243 return CheckForCoindexedObject (
32383244 context.messages (), call.arguments [2 ], name, " stat" );
32393245 } else if (name == " atomic_cas" ) {
0 commit comments