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

Code before:

bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
  auto &mods{OmpGetModifiers(x)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
  }
  return true;
}

bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
  auto &mods{OmpGetModifiers(x.v)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
  }
  return true;
}

bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
  auto &mods{OmpGetModifiers(x.v)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(const_cast<parser::OmpMapper &>(*mapper));
  }
  return true;
}

void OmpVisitor::ResolveMapperModifier(parser::OmpMapper &mapper) {
  if (auto *symbol{FindSymbol(currScope(), mapper.v)}) {
    auto &ultimate{symbol->GetUltimate()};
    auto *misc{ultimate.detailsIf<MiscDetails>()};
    auto *md{ultimate.detailsIf<MapperDetails>()};
    if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
      context().Say(mapper.v.source,
          "Name '%s' should be a mapper name"_err_en_US, mapper.v.source);
    else
      mapper.v.symbol = symbol;
  } else {
    // Allow the special 'default' mapper identifier without prior
    // declaration so lowering can recognize and handle it. Emit an
    // error for any other missing mapper identifier.
    if (mapper.v.source.ToString() == "default") {
      mapper.v.symbol =
          &MakeSymbol(mapper.v, MiscDetails{MiscDetails::Kind::ConstructName});
    } else {
      context().Say(
          mapper.v.source, "'%s' not declared"_err_en_US, mapper.v.source);
    }
  }
}

void OmpVisitor::ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
    const parser::OmpClauseList &clauses) {

Review comment (suggestion):
This could be `const parser::OmpMapper &mapper`.  IIRC, the "symbol" data members are mutable.  This should also remove the need for the const_casts above.

Code after:
void OmpVisitor::Post(const parser::OmpStylizedInstance &x) { //
  PopScope();
}

bool OmpVisitor::Pre(const parser::OmpMapClause &x) {
  auto &mods{OmpGetModifiers(x)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(*mapper);
  }
  return true;
}

bool OmpVisitor::Pre(const parser::OmpClause::To &x) {
  auto &mods{OmpGetModifiers(x.v)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(*mapper);
  }
  return true;
}

bool OmpVisitor::Pre(const parser::OmpClause::From &x) {
  auto &mods{OmpGetModifiers(x.v)};
  if (auto *mapper{OmpGetUniqueModifier<parser::OmpMapper>(mods)}) {
    ResolveMapperModifier(*mapper);
  }
  return true;
}

void OmpVisitor::ResolveMapperModifier(const parser::OmpMapper &mapper) {
  if (auto *symbol{FindSymbol(currScope(), mapper.v)}) {
    auto &ultimate{symbol->GetUltimate()};
    auto *misc{ultimate.detailsIf<MiscDetails>()};
    auto *md{ultimate.detailsIf<MapperDetails>()};
    if (!md && (!misc || misc->kind() != MiscDetails::Kind::ConstructName))
      context().Say(mapper.v.source,
          "Name '%s' should be a mapper name"_err_en_US, mapper.v.source);
    else
      mapper.v.symbol = symbol;
  } else {
    // Allow the special 'default' mapper identifier without prior
    // declaration so lowering can recognize and handle it. Emit an
    // error for any other missing mapper identifier.
    if (mapper.v.source.ToString() == "default") {
      mapper.v.symbol =
          &MakeSymbol(mapper.v, MiscDetails{MiscDetails::Kind::ConstructName});
    } else {
      context().Say(
          mapper.v.source, "'%s' not declared"_err_en_US, mapper.v.source);
    }
  }
}