@@ -2891,7 +2891,8 @@ static bool CheckSymbolSupportsType(const Scope &scope,
28912891
28922892static bool IsReductionAllowedForType (
28932893 const parser::OmpReductionIdentifier &ident, const DeclTypeSpec &type,
2894- const Scope &scope, SemanticsContext &context) {
2894+ bool cannotBeBuiltinReduction, const Scope &scope,
2895+ SemanticsContext &context) {
28952896 auto isLogical{[](const DeclTypeSpec &type) -> bool {
28962897 return type.category () == DeclTypeSpec::Logical;
28972898 }};
@@ -2902,6 +2903,10 @@ static bool IsReductionAllowedForType(
29022903 auto checkOperator{[&](const parser::DefinedOperator &dOpr) {
29032904 if (const auto *intrinsicOp{
29042905 std::get_if<parser::DefinedOperator::IntrinsicOperator>(&dOpr.u )}) {
2906+ if (cannotBeBuiltinReduction) {
2907+ return false ;
2908+ }
2909+
29052910 // OMP5.2: The type [...] of a list item that appears in a
29062911 // reduction clause must be valid for the combiner expression
29072912 // See F2023: Table 10.2
@@ -2953,16 +2958,18 @@ static bool IsReductionAllowedForType(
29532958 // IAND: arguments must be integers: F2023 16.9.100
29542959 // IEOR: arguments must be integers: F2023 16.9.106
29552960 // IOR: arguments must be integers: F2023 16.9.111
2956- if (type.IsNumeric (TypeCategory::Integer)) {
2961+ if (type.IsNumeric (TypeCategory::Integer) &&
2962+ !cannotBeBuiltinReduction) {
29572963 return true ;
29582964 }
29592965 } else if (realName == " max" || realName == " min" ) {
29602966 // MAX: arguments must be integer, real, or character:
29612967 // F2023 16.9.135
29622968 // MIN: arguments must be integer, real, or character:
29632969 // F2023 16.9.141
2964- if (type.IsNumeric (TypeCategory::Integer) ||
2965- type.IsNumeric (TypeCategory::Real) || isCharacter (type)) {
2970+ if ((type.IsNumeric (TypeCategory::Integer) ||
2971+ type.IsNumeric (TypeCategory::Real) || isCharacter (type)) &&
2972+ !cannotBeBuiltinReduction) {
29662973 return true ;
29672974 }
29682975 }
@@ -2995,9 +3002,16 @@ void OmpStructureChecker::CheckReductionObjectTypes(
29953002 GetSymbolsInObjectList (objects, symbols);
29963003
29973004 for (auto &[symbol, source] : symbols) {
3005+ // Built in reductions require types which can be used in their initializer
3006+ // and combiner expressions. For example, for +:
3007+ // r = 0; r = r + r2
3008+ // But it might be valid to use these with DECLARE REDUCTION.
3009+ // Assumed size is already caught elsewhere.
3010+ bool cannotBeBuiltinReduction{evaluate::IsAssumedRank (*symbol)};
29983011 if (auto *type{symbol->GetType ()}) {
29993012 const auto &scope{context_.FindScope (symbol->name ())};
3000- if (!IsReductionAllowedForType (ident, *type, scope, context_)) {
3013+ if (!IsReductionAllowedForType (
3014+ ident, *type, cannotBeBuiltinReduction, scope, context_)) {
30013015 context_.Say (source,
30023016 " The type of '%s' is incompatible with the reduction operator." _err_en_US,
30033017 symbol->name ());
0 commit comments