@@ -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