Repository: llvm/llvm-project
File: flang/lib/Semantics/resolve-directives.cpp (C++)

Code before:
          std::string crayPtrName{
              semantics::GetCrayPointer(*symbol).name().ToString()};
          if (!IsObjectWithDSA(*currScope().FindSymbol(crayPtrName))) {
            context_.Say(dirContext.directiveSource,
                "The DEFAULT(NONE) clause requires that the Cray Pointer '%s' must be listed in a data-sharing attribute clause"_err_en_US,
                crayPtrName);
          }
        } else {
          context_.Say(dirContext.directiveSource,
              "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
              symbol->name());
        }
      } else if (dirDepth == (int)dirContext_.size() - 1) {
        if (symbol->GetUltimate().test(Symbol::Flag::CrayPointee)) {
          std::string crayPtrName{
              semantics::GetCrayPointer(*symbol).name().ToString()};
          if (!IsObjectWithDSA(*currScope().FindSymbol(crayPtrName))) {
            context_.Say(name.source,
                "The DEFAULT(NONE) clause requires that the Cray Pointer '%s' must be listed in a data-sharing attribute clause"_err_en_US,
                crayPtrName);
          }
        } else {
          context_.Say(name.source,
              "The DEFAULT(NONE) clause requires that '%s' must be listed in a data-sharing attribute clause"_err_en_US,
              symbol->name());
        }
      }
    }

    if (dsa.any()) {
      if (parallelDir || taskGenDir || teamsDir) {
        Symbol *prevDeclSymbol{lastDeclSymbol};
        // NOTE As `dsa` will match that of the symbol in the current scope
        //      (if any), we won't override the DSA of any existing symbol.
        if ((dsa & dataSharingAttributeFlags).any()) {
          makeSymbol(dsa);
        }
        // Fix host association of explicit symbols, as they can be created
        // before implicit ones in enclosing scope.
        if (prevDeclSymbol && prevDeclSymbol != lastDeclSymbol &&
            lastDeclSymbol->test(Symbol::Flag::OmpExplicit)) {
          const auto *hostAssoc{lastDeclSymbol->detailsIf<HostAssocDetails>()};
          if (hostAssoc && hostAssoc->symbol() != *prevDeclSymbol) {
            lastDeclSymbol->set_details(HostAssocDetails{*prevDeclSymbol});
          }
        }
      }
      prevDSA = dsa;
      PRINT_IMPLICIT_RULE("0) already has DSA");
      continue;
    }

Review comment (suggestion):
This part is almost identical as above.
Consider moving it to a separate function or lambda, that receives the source used in the error message as a parameter.

Code after:
    }
    prevDSA = dsa;
  }
}

static bool IsOpenMPPointer(const Symbol &symbol) {
  if (IsPointer(symbol) || IsBuiltinCPtr(symbol))
    return true;
  return false;
}

static bool IsOpenMPAggregate(const Symbol &symbol) {
  if (IsAllocatable(symbol) || IsOpenMPPointer(symbol))
    return false;

  const auto *type{symbol.GetType()};
  // OpenMP categorizes Fortran characters as aggregates.
  if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character)
    return true;

  if (const auto *det{symbol.GetUltimate()
              .detailsIf<Fortran::semantics::ObjectEntityDetails>()})
    if (det->IsArray())
      return true;

  if (type->AsDerived())
    return true;

  if (IsDeferredShape(symbol) || IsAssumedRank(symbol) ||
      IsAssumedShape(symbol))
    return true;
  return false;
}

static bool IsOpenMPScalar(const Symbol &symbol) {
  if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) ||
      IsAllocatable(symbol))
    return false;
  const auto *type{symbol.GetType()};
  if ((!symbol.GetShape() || symbol.GetShape()->empty()) &&
      (type->category() ==
              Fortran::semantics::DeclTypeSpec::Category::Numeric ||
          type->category() ==
              Fortran::semantics::DeclTypeSpec::Category::Logical))
    return true;
  return false;
}

static bool DefaultMapCategoryMatchesSymbol(
    parser::OmpVariableCategory::Value category, const Symbol &symbol) {
  using VarCat = parser::OmpVariableCategory::Value;