//===-- lib/Semantics/check-data.cpp --------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

// DATA statement semantic analysis.
// - Applies static semantic checks to the variables in each data-stmt-set with
//   class DataVarChecker;
// - Invokes conversion of DATA statement values to static initializers

#include "check-data.h"
#include "data-to-inits.h"
#include "flang/Evaluate/traverse.h"
#include "flang/Parser/parse-tree.h"
#include "flang/Parser/tools.h"
#include "flang/Semantics/tools.h"
#include <algorithm>
#include <vector>

namespace Fortran::semantics {

// Ensures that references to an implied DO loop control variable are
// represented as such in the "body" of the implied DO loop.
void DataChecker::Enter(const parser::DataImpliedDo &x) {
  const auto &name{parser::UnwrapRef<parser::Name>(
      std::get<parser::DataImpliedDo::Bounds>(x.t).Name())};
  int kind{evaluate::ResultType<evaluate::ImpliedDoIndex>::kind};
  if (const auto dynamicType{evaluate::DynamicType::From(DEREF(name.symbol))}) {
    if (dynamicType->category() == TypeCategory::Integer) {
      kind = dynamicType->kind();
    }
  }
  exprAnalyzer_.AddImpliedDo(name.source, kind);
}

void DataChecker::Leave(const parser::DataImpliedDo &x) {
  const auto &name{parser::UnwrapRef<parser::Name>(
      std::get<parser::DataImpliedDo::Bounds>(x.t).Name())};
  exprAnalyzer_.RemoveImpliedDo(name.source);
}

// DataVarChecker applies static checks once to each variable that appears
// in a data-stmt-set.  These checks are independent of the values that
// correspond to the variables.
class DataVarChecker : public evaluate::AllTraverse<DataVarChecker, true> {
public:
  using Base = evaluate::AllTraverse<DataVarChecker, true>;
  DataVarChecker(SemanticsContext &c, parser::CharBlock src)
      : Base{*this}, context_{c}, source_{src} {}
  using Base::operator();
  bool HasComponentWithoutSubscripts() const {
    return hasComponent_ && !hasSubscript_;
  }
  bool operator()(const Symbol &symbol) { // C876
    // 8.6.7p(2) - precludes non-pointers of derived types with
    // default component values
    const Scope &scope{context_.FindScope(source_)};
    bool isFirstSymbol{isFirstSymbol_};
    isFirstSymbol_ = false;
    // Ordered so that most egregious errors are first
    if (const char *whyNot{IsProcedure(symbol) && !IsPointer(symbol)
                ? "Procedure"
                : isFirstSymbol && IsHostAssociated(symbol, scope)
                ? "Host-associated object"
                : isFirstSymbol && IsUseAssociated(symbol, scope)
                ? "USE-associated object"
                : IsDummy(symbol)          ? "Dummy argument"
                : IsFunctionResult(symbol) ? "Function result"
                : IsAutomatic(symbol)      ? "Automatic variable"
                : IsAllocatable(symbol)    ? "Allocatable"
                : IsInitialized(symbol, true /*ignore DATA*/,
                      true /*ignore allocatable components*/,
                      true /*ignore uninitialized pointer components*/)
                ? "Default-initialized"
                : symbol.has<AssocEntityDetails>() ? "Construct association"
                : isFirstSymbol && IsPointer(symbol) &&
                    (hasComponent_ || hasSubscript_)
                ? "Target of pointer"
                : nullptr}) {
      context_.Say(source_,
          "%s '%s' must not be initialized in a DATA statement"_err_en_US,
          whyNot, symbol.name());
      return false;
    }
    if (IsProcedurePointer(symbol)) {
      if (!context_.IsEnabled(common::LanguageFeature::DataStmtExtensions)) {
        context_.Say(source_,
            "Procedure pointer '%s' may not appear in a DATA statement"_err_en_US,
            symbol.name());
        return false;
      } else {
        context_.Warn(common::LanguageFeature::DataStmtExtensions, source_,
            "Procedure pointer '%s' in a DATA statement is not standard"_port_en_US,
            symbol.name());
      }
    }
    if (IsInBlankCommon(symbol)) {
      if (!context_.IsEnabled(common::LanguageFeature::DataStmtExtensions)) {
        context_.Say(source_,
            "Blank COMMON object '%s' may not appear in a DATA statement"_err_en_US,
            symbol.name());
        return false;
      } else {
        context_.Warn(common::LanguageFeature::DataStmtExtensions, source_,
            "Blank COMMON object '%s' in a DATA statement is not standard"_port_en_US,
            symbol.name());
      }
    }
    return true;
  }
  bool operator()(const evaluate::Component &component) {
    hasComponent_ = true;
    const Symbol &lastSymbol{component.GetLastSymbol()};
    if (isPointerAllowed_) {
      if (IsPointer(lastSymbol) && hasSubscript_) { // C877
        context_.Say(source_,
            "Rightmost data object pointer '%s' must not be subscripted"_err_en_US,
            lastSymbol.name().ToString());
        return false;
      }
      auto restorer{common::ScopedSet(isPointerAllowed_, false)};
      return (*this)(component.base()) && (*this)(lastSymbol);
    } else if (IsPointer(lastSymbol)) { // C877
      context_.Say(source_,
          "Data object must not contain pointer '%s' as a non-rightmost part"_err_en_US,
          lastSymbol.name().ToString());
      return false;
    } else {
      return (*this)(component.base()) && (*this)(lastSymbol);
    }
  }
  bool operator()(const evaluate::ArrayRef &arrayRef) {
    hasSubscript_ = true;
    return (*this)(arrayRef.base()) && (*this)(arrayRef.subscript());
  }
  bool operator()(const evaluate::Substring &substring) {
    hasSubscript_ = true;
    return (*this)(substring.parent()) && (*this)(substring.lower()) &&
        (*this)(substring.upper());
  }
  bool operator()(const evaluate::CoarrayRef &) { // C874
    context_.Say(
        source_, "Data object must not be a coindexed variable"_err_en_US);
    return false;
  }
  bool operator()(const evaluate::Subscript &subs) {
    auto restorer1{common::ScopedSet(isPointerAllowed_, false)};
    auto restorer2{common::ScopedSet(isFunctionAllowed_, true)};
    return common::visit(
        common::visitors{
            [&](const evaluate::IndirectSubscriptIntegerExpr &expr) {
              return CheckSubscriptExpr(expr);
            },
            [&](const evaluate::Triplet &triplet) {
              return CheckSubscriptExpr(triplet.lower()) &&
                  CheckSubscriptExpr(triplet.upper()) &&
                  CheckSubscriptExpr(triplet.stride());
            },
        },
        subs.u);
  }
  template <typename T>
  bool operator()(const evaluate::FunctionRef<T> &) const { // C875
    if (isFunctionAllowed_) {
      // Must have been validated as a constant expression
      return true;
    } else {
      context_.Say(source_,
          "Data object variable must not be a function reference"_err_en_US);
      return false;
    }
  }

private:
  bool CheckSubscriptExpr(
      const std::optional<evaluate::IndirectSubscriptIntegerExpr> &x) const {
    return !x || CheckSubscriptExpr(*x);
  }
  bool CheckSubscriptExpr(
      const evaluate::IndirectSubscriptIntegerExpr &expr) const {
    return CheckSubscriptExpr(expr.value());
  }
  bool CheckSubscriptExpr(
      const evaluate::Expr<evaluate::SubscriptInteger> &expr) const {
    if (!evaluate::IsConstantExpr(expr, /*context=*/
            nullptr /* to accept unbound implied DO indices */)) { // C875,C881
      context_.Say(
          source_, "Data object must have constant subscripts"_err_en_US);
      return false;
    } else {
      return true;
    }
  }

  SemanticsContext &context_;
  parser::CharBlock source_;
  bool hasComponent_{false};
  bool hasSubscript_{false};
  bool isPointerAllowed_{true};
  bool isFirstSymbol_{true};
  bool isFunctionAllowed_{false};
};

static bool IsValidDataObject(const SomeExpr &expr) { // C878, C879
  return !evaluate::IsConstantExpr(expr) &&
      (evaluate::IsVariable(expr) || evaluate::IsProcedurePointer(expr));
}

void DataChecker::Leave(const parser::DataIDoObject &object) {
  if (const auto *designator{
          std::get_if<parser::Scalar<common::Indirection<parser::Designator>>>(
              &object.u)}) {
    if (MaybeExpr expr{exprAnalyzer_.Analyze(*designator)}) {
      auto source{parser::UnwrapRef<parser::Designator>(*designator).source};
      DataVarChecker checker{exprAnalyzer_.context(), source};
      if (checker(*expr)) {
        if (checker.HasComponentWithoutSubscripts()) { // C880
          exprAnalyzer_.context().Say(source,
              "Data implied do structure component must be subscripted"_err_en_US);
        } else if (!IsValidDataObject(*expr)) {
          exprAnalyzer_.context().Say(
              source, "Data implied do object must be a variable"_err_en_US);
        } else {
          return;
        }
      }
    }
    currentSetHasFatalErrors_ = true;
  }
}

void DataChecker::Leave(const parser::DataStmtObject &dataObject) {
  common::visit(
      common::visitors{
          [](const parser::DataImpliedDo &) { // has own Enter()/Leave()
          },
          [&](const auto &var) {
            auto expr{exprAnalyzer_.Analyze(var)};
            auto source{parser::FindSourceLocation(dataObject)};
            if (!expr ||
                !DataVarChecker{exprAnalyzer_.context(), source}(*expr)) {
              currentSetHasFatalErrors_ = true;
            } else if (!IsValidDataObject(*expr)) {
              exprAnalyzer_.context().Say(
                  source, "Data statement object must be a variable"_err_en_US);
              currentSetHasFatalErrors_ = true;
            }
          },
      },
      dataObject.u);
}

void DataChecker::Leave(const parser::DataStmtSet &set) {
  if (!currentSetHasFatalErrors_) {
    AccumulateDataInitializations(inits_, exprAnalyzer_, set);
  }
  currentSetHasFatalErrors_ = false;
}

void DataChecker::Leave(const parser::EntityDecl &decl) {
  if (const auto &init{
          std::get<std::optional<parser::Initialization>>(decl.t)}) {
    const Symbol *name{std::get<parser::Name>(decl.t).symbol};
    const auto *list{
        std::get_if<std::list<common::Indirection<parser::DataStmtValue>>>(
            &init->u)};
    if (name && list) {
      AccumulateDataInitializations(inits_, exprAnalyzer_, *name, *list);
    }
  }
}

void DataChecker::CompileDataInitializationsIntoInitializers() {
  ConvertToInitializers(inits_, exprAnalyzer_, /*forDerivedTypesOnly=*/false);
}

} // namespace Fortran::semantics
