/* Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
   file Copyright.txt or https://cmake.org/licensing for details.  */
#include "cmGeneratorExpressionNode.h"

#include <algorithm>
#include <cassert>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <map>
#include <memory>
#include <set>
#include <sstream>
#include <utility>

#include <cm/iterator>
#include <cm/string_view>
#include <cm/vector>
#include <cmext/algorithm>
#include <cmext/string_view>

#include "cmsys/RegularExpression.hxx"
#include "cmsys/String.h"

#include "cmAlgorithms.h"
#include "cmGeneratorExpression.h"
#include "cmGeneratorExpressionContext.h"
#include "cmGeneratorExpressionDAGChecker.h"
#include "cmGeneratorExpressionEvaluator.h"
#include "cmGeneratorTarget.h"
#include "cmGlobalGenerator.h"
#include "cmLinkItem.h"
#include "cmLocalGenerator.h"
#include "cmMakefile.h"
#include "cmMessageType.h"
#include "cmOutputConverter.h"
#include "cmPolicies.h"
#include "cmProperty.h"
#include "cmRange.h"
#include "cmState.h"
#include "cmStateSnapshot.h"
#include "cmStateTypes.h"
#include "cmStringAlgorithms.h"
#include "cmSystemTools.h"
#include "cmTarget.h"
#include "cmake.h"

std::string cmGeneratorExpressionNode::EvaluateDependentExpression(
  std::string const& prop, cmLocalGenerator* lg,
  cmGeneratorExpressionContext* context, cmGeneratorTarget const* headTarget,
  cmGeneratorExpressionDAGChecker* dagChecker,
  cmGeneratorTarget const* currentTarget)
{
  cmGeneratorExpression ge(context->Backtrace);
  std::unique_ptr<cmCompiledGeneratorExpression> cge = ge.Parse(prop);
  cge->SetEvaluateForBuildsystem(context->EvaluateForBuildsystem);
  cge->SetQuiet(context->Quiet);
  std::string result =
    cge->Evaluate(lg, context->Config, headTarget, dagChecker, currentTarget,
                  context->Language);
  if (cge->GetHadContextSensitiveCondition()) {
    context->HadContextSensitiveCondition = true;
  }
  if (cge->GetHadHeadSensitiveCondition()) {
    context->HadHeadSensitiveCondition = true;
  }
  if (cge->GetHadLinkLanguageSensitiveCondition()) {
    context->HadLinkLanguageSensitiveCondition = true;
  }
  return result;
}

static const struct ZeroNode : public cmGeneratorExpressionNode
{
  ZeroNode() {} // NOLINT(modernize-use-equals-default)

  bool GeneratesContent() const override { return false; }

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& /*parameters*/,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return std::string();
  }
} zeroNode;

static const struct OneNode : public cmGeneratorExpressionNode
{
  OneNode() {} // NOLINT(modernize-use-equals-default)

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return parameters.front();
  }
} oneNode;

static const struct OneNode buildInterfaceNode;

static const struct ZeroNode installInterfaceNode;

struct BooleanOpNode : public cmGeneratorExpressionNode
{
  BooleanOpNode(const char* op_, const char* successVal_,
                const char* failureVal_)
    : op(op_)
    , successVal(successVal_)
    , failureVal(failureVal_)
  {
  }

  int NumExpectedParameters() const override { return OneOrMoreParameters; }

  std::string Evaluate(const std::vector<std::string>& parameters,
                       cmGeneratorExpressionContext* context,
                       const GeneratorExpressionContent* content,
                       cmGeneratorExpressionDAGChecker*) const override
  {
    for (std::string const& param : parameters) {
      if (param == this->failureVal) {
        return this->failureVal;
      }
      if (param != this->successVal) {
        std::ostringstream e;
        e << "Parameters to $<" << this->op;
        e << "> must resolve to either '0' or '1'.";
        reportError(context, content->GetOriginalExpression(), e.str());
        return std::string();
      }
    }
    return this->successVal;
  }

  const char *const op, *const successVal, *const failureVal;
};

static const BooleanOpNode andNode("AND", "1", "0"), orNode("OR", "0", "1");

static const struct NotNode : public cmGeneratorExpressionNode
{
  NotNode() {} // NOLINT(modernize-use-equals-default)

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.front() != "0" && parameters.front() != "1") {
      reportError(
        context, content->GetOriginalExpression(),
        "$<NOT> parameter must resolve to exactly one '0' or '1' value.");
      return std::string();
    }
    return parameters.front() == "0" ? "1" : "0";
  }
} notNode;

static const struct BoolNode : public cmGeneratorExpressionNode
{
  BoolNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return !cmIsOff(parameters.front()) ? "1" : "0";
  }
} boolNode;

static const struct IfNode : public cmGeneratorExpressionNode
{
  IfNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 3; }

  std::string Evaluate(const std::vector<std::string>& parameters,
                       cmGeneratorExpressionContext* context,
                       const GeneratorExpressionContent* content,
                       cmGeneratorExpressionDAGChecker*) const override
  {
    if (parameters[0] != "1" && parameters[0] != "0") {
      reportError(context, content->GetOriginalExpression(),
                  "First parameter to $<IF> must resolve to exactly one '0' "
                  "or '1' value.");
      return std::string();
    }
    return parameters[0] == "1" ? parameters[1] : parameters[2];
  }
} ifNode;

static const struct StrEqualNode : public cmGeneratorExpressionNode
{
  StrEqualNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return parameters.front() == parameters[1] ? "1" : "0";
  }
} strEqualNode;

static const struct EqualNode : public cmGeneratorExpressionNode
{
  EqualNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    long numbers[2];
    for (int i = 0; i < 2; ++i) {
      if (!ParameterToLong(parameters[i].c_str(), &numbers[i])) {
        reportError(context, content->GetOriginalExpression(),
                    "$<EQUAL> parameter " + parameters[i] +
                      " is not a valid integer.");
        return {};
      }
    }
    return numbers[0] == numbers[1] ? "1" : "0";
  }

  static bool ParameterToLong(const char* param, long* outResult)
  {
    const char isNegative = param[0] == '-';

    int base = 0;
    if (cmHasLiteralPrefix(param, "0b") || cmHasLiteralPrefix(param, "0B")) {
      base = 2;
      param += 2;
    } else if (cmHasLiteralPrefix(param, "-0b") ||
               cmHasLiteralPrefix(param, "-0B") ||
               cmHasLiteralPrefix(param, "+0b") ||
               cmHasLiteralPrefix(param, "+0B")) {
      base = 2;
      param += 3;
    }

    char* pEnd;
    long result = strtol(param, &pEnd, base);
    if (pEnd == param || *pEnd != '\0' || errno == ERANGE) {
      return false;
    }
    if (isNegative && result > 0) {
      result *= -1;
    }
    *outResult = result;
    return true;
  }
} equalNode;

static const struct InListNode : public cmGeneratorExpressionNode
{
  InListNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    std::vector<std::string> values;
    std::vector<std::string> checkValues;
    bool check = false;
    switch (context->LG->GetPolicyStatus(cmPolicies::CMP0085)) {
      case cmPolicies::WARN:
        if (parameters.front().empty()) {
          check = true;
          cmExpandList(parameters[1], checkValues, true);
        }
        CM_FALLTHROUGH;
      case cmPolicies::OLD:
        cmExpandList(parameters[1], values);
        if (check && values != checkValues) {
          std::ostringstream e;
          e << cmPolicies::GetPolicyWarning(cmPolicies::CMP0085)
            << "\nSearch Item:\n  \"" << parameters.front()
            << "\"\nList:\n  \"" << parameters[1] << "\"\n";
          context->LG->GetCMakeInstance()->IssueMessage(
            MessageType ::AUTHOR_WARNING, e.str(), context->Backtrace);
          return "0";
        }
        if (values.empty()) {
          return "0";
        }
        break;
      case cmPolicies::REQUIRED_IF_USED:
      case cmPolicies::REQUIRED_ALWAYS:
      case cmPolicies::NEW:
        cmExpandList(parameters[1], values, true);
        break;
    }

    return cm::contains(values, parameters.front()) ? "1" : "0";
  }
} inListNode;

static const struct FilterNode : public cmGeneratorExpressionNode
{
  FilterNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 3; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.size() != 3) {
      reportError(context, content->GetOriginalExpression(),
                  "$<FILTER:...> expression requires three parameters");
      return {};
    }

    if (parameters[1] != "INCLUDE" && parameters[1] != "EXCLUDE") {
      reportError(
        context, content->GetOriginalExpression(),
        "$<FILTER:...> second parameter must be either INCLUDE or EXCLUDE");
      return {};
    }

    const bool exclude = parameters[1] == "EXCLUDE";

    cmsys::RegularExpression re;
    if (!re.compile(parameters[2])) {
      reportError(context, content->GetOriginalExpression(),
                  "$<FILTER:...> failed to compile regex");
      return {};
    }

    std::vector<std::string> values;
    std::vector<std::string> result;
    cmExpandList(parameters.front(), values, true);

    std::copy_if(values.cbegin(), values.cend(), std::back_inserter(result),
                 [&re, exclude](std::string const& input) {
                   return exclude ^ re.find(input);
                 });
    return cmJoin(cmMakeRange(result.cbegin(), result.cend()), ";");
  }
} filterNode;

static const struct RemoveDuplicatesNode : public cmGeneratorExpressionNode
{
  RemoveDuplicatesNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.size() != 1) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<REMOVE_DUPLICATES:...> expression requires one parameter");
    }

    std::vector<std::string> values = cmExpandedList(parameters.front(), true);

    auto valuesEnd = cmRemoveDuplicates(values);
    auto valuesBegin = values.cbegin();
    return cmJoin(cmMakeRange(valuesBegin, valuesEnd), ";");
  }

} removeDuplicatesNode;

static const struct TargetExistsNode : public cmGeneratorExpressionNode
{
  TargetExistsNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.size() != 1) {
      reportError(context, content->GetOriginalExpression(),
                  "$<TARGET_EXISTS:...> expression requires one parameter");
      return std::string();
    }

    std::string targetName = parameters.front();
    if (targetName.empty() ||
        !cmGeneratorExpression::IsValidTargetName(targetName)) {
      reportError(context, content->GetOriginalExpression(),
                  "$<TARGET_EXISTS:tgt> expression requires a non-empty "
                  "valid target name.");
      return std::string();
    }

    return context->LG->GetMakefile()->FindTargetToUse(targetName) ? "1" : "0";
  }
} targetExistsNode;

static const struct TargetNameIfExistsNode : public cmGeneratorExpressionNode
{
  TargetNameIfExistsNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.size() != 1) {
      reportError(context, content->GetOriginalExpression(),
                  "$<TARGET_NAME_IF_EXISTS:...> expression requires one "
                  "parameter");
      return std::string();
    }

    std::string targetName = parameters.front();
    if (targetName.empty() ||
        !cmGeneratorExpression::IsValidTargetName(targetName)) {
      reportError(context, content->GetOriginalExpression(),
                  "$<TARGET_NAME_IF_EXISTS:tgt> expression requires a "
                  "non-empty valid target name.");
      return std::string();
    }

    return context->LG->GetMakefile()->FindTargetToUse(targetName)
      ? targetName
      : std::string();
  }
} targetNameIfExistsNode;

struct GenexEvaluator : public cmGeneratorExpressionNode
{
  GenexEvaluator() {} // NOLINT(modernize-use-equals-default)

protected:
  std::string EvaluateExpression(
    const std::string& genexOperator, const std::string& expression,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagCheckerParent) const
  {
    if (context->HeadTarget) {
      cmGeneratorExpressionDAGChecker dagChecker(
        context->Backtrace, context->HeadTarget,
        genexOperator + ":" + expression, content, dagCheckerParent);
      switch (dagChecker.Check()) {
        case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
        case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE: {
          dagChecker.ReportError(context, content->GetOriginalExpression());
          return std::string();
        }
        case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
        case cmGeneratorExpressionDAGChecker::DAG:
          break;
      }

      return this->EvaluateDependentExpression(
        expression, context->LG, context, context->HeadTarget, &dagChecker,
        context->CurrentTarget);
    }

    return this->EvaluateDependentExpression(
      expression, context->LG, context, context->HeadTarget, dagCheckerParent,
      context->CurrentTarget);
  }
};

static const struct TargetGenexEvalNode : public GenexEvaluator
{
  TargetGenexEvalNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
  {
    const std::string& targetName = parameters.front();
    if (targetName.empty() ||
        !cmGeneratorExpression::IsValidTargetName(targetName)) {
      reportError(context, content->GetOriginalExpression(),
                  "$<TARGET_GENEX_EVAL:tgt, ...> expression requires a "
                  "non-empty valid target name.");
      return std::string();
    }

    const auto* target = context->LG->FindGeneratorTargetToUse(targetName);
    if (!target) {
      std::ostringstream e;
      e << "$<TARGET_GENEX_EVAL:tgt, ...> target \"" << targetName
        << "\" not found.";
      reportError(context, content->GetOriginalExpression(), e.str());
      return std::string();
    }

    const std::string& expression = parameters[1];
    if (expression.empty()) {
      return expression;
    }

    cmGeneratorExpressionContext targetContext(
      context->LG, context->Config, context->Quiet, target, target,
      context->EvaluateForBuildsystem, context->Backtrace, context->Language);

    return this->EvaluateExpression("TARGET_GENEX_EVAL", expression,
                                    &targetContext, content, dagCheckerParent);
  }
} targetGenexEvalNode;

static const struct GenexEvalNode : public GenexEvaluator
{
  GenexEvalNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
  {
    const std::string& expression = parameters[0];
    if (expression.empty()) {
      return expression;
    }

    return this->EvaluateExpression("GENEX_EVAL", expression, context, content,
                                    dagCheckerParent);
  }
} genexEvalNode;

static const struct LowerCaseNode : public cmGeneratorExpressionNode
{
  LowerCaseNode() {} // NOLINT(modernize-use-equals-default)

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return cmSystemTools::LowerCase(parameters.front());
  }
} lowerCaseNode;

static const struct UpperCaseNode : public cmGeneratorExpressionNode
{
  UpperCaseNode() {} // NOLINT(modernize-use-equals-default)

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return cmSystemTools::UpperCase(parameters.front());
  }
} upperCaseNode;

static const struct MakeCIdentifierNode : public cmGeneratorExpressionNode
{
  MakeCIdentifierNode() {} // NOLINT(modernize-use-equals-default)

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return cmSystemTools::MakeCidentifier(parameters.front());
  }
} makeCIdentifierNode;

template <char C>
struct CharacterNode : public cmGeneratorExpressionNode
{
  CharacterNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 0; }

  std::string Evaluate(
    const std::vector<std::string>& /*parameters*/,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return { C };
  }
};
static const CharacterNode<'>'> angle_rNode;
static const CharacterNode<','> commaNode;
static const CharacterNode<';'> semicolonNode;

struct CompilerIdNode : public cmGeneratorExpressionNode
{
  CompilerIdNode(const char* compilerLang)
    : CompilerLanguage(compilerLang)
  {
  }

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget) {
      std::ostringstream e;
      e << "$<" << this->CompilerLanguage
        << "_COMPILER_ID> may only be used with binary targets.  It may "
           "not be used with add_custom_command or add_custom_target.";
      reportError(context, content->GetOriginalExpression(), e.str());
      return {};
    }
    return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
                                      this->CompilerLanguage);
  }

  std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
                                   cmGeneratorExpressionContext* context,
                                   const GeneratorExpressionContent* content,
                                   cmGeneratorExpressionDAGChecker* /*unused*/,
                                   const std::string& lang) const
  {
    std::string const& compilerId =
      context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
                                                    "_COMPILER_ID");
    if (parameters.empty()) {
      return compilerId;
    }
    if (compilerId.empty()) {
      return parameters.front().empty() ? "1" : "0";
    }
    static cmsys::RegularExpression compilerIdValidator("^[A-Za-z0-9_]*$");

    for (auto& param : parameters) {

      if (!compilerIdValidator.find(param)) {
        reportError(context, content->GetOriginalExpression(),
                    "Expression syntax not recognized.");
        return std::string();
      }

      if (strcmp(param.c_str(), compilerId.c_str()) == 0) {
        return "1";
      }

      if (cmsysString_strcasecmp(param.c_str(), compilerId.c_str()) == 0) {
        switch (context->LG->GetPolicyStatus(cmPolicies::CMP0044)) {
          case cmPolicies::WARN: {
            context->LG->GetCMakeInstance()->IssueMessage(
              MessageType::AUTHOR_WARNING,
              cmPolicies::GetPolicyWarning(cmPolicies::CMP0044),
              context->Backtrace);
            CM_FALLTHROUGH;
          }
          case cmPolicies::OLD:
            return "1";
          case cmPolicies::NEW:
          case cmPolicies::REQUIRED_ALWAYS:
          case cmPolicies::REQUIRED_IF_USED:
            break;
        }
      }
    }
    return "0";
  }

  const char* const CompilerLanguage;
};

static const CompilerIdNode cCompilerIdNode("C"), cxxCompilerIdNode("CXX"),
  cudaCompilerIdNode("CUDA"), objcCompilerIdNode("OBJC"),
  objcxxCompilerIdNode("OBJCXX"), fortranCompilerIdNode("Fortran");

struct CompilerVersionNode : public cmGeneratorExpressionNode
{
  CompilerVersionNode(const char* compilerLang)
    : CompilerLanguage(compilerLang)
  {
  }

  int NumExpectedParameters() const override { return OneOrZeroParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget) {
      std::ostringstream e;
      e << "$<" << this->CompilerLanguage
        << "_COMPILER_VERSION> may only be used with binary targets.  It "
           "may not be used with add_custom_command or add_custom_target.";
      reportError(context, content->GetOriginalExpression(), e.str());
      return {};
    }
    return this->EvaluateWithLanguage(parameters, context, content, dagChecker,
                                      this->CompilerLanguage);
  }

  std::string EvaluateWithLanguage(const std::vector<std::string>& parameters,
                                   cmGeneratorExpressionContext* context,
                                   const GeneratorExpressionContent* content,
                                   cmGeneratorExpressionDAGChecker* /*unused*/,
                                   const std::string& lang) const
  {
    std::string const& compilerVersion =
      context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
                                                    "_COMPILER_VERSION");
    if (parameters.empty()) {
      return compilerVersion;
    }

    static cmsys::RegularExpression compilerIdValidator("^[0-9\\.]*$");
    if (!compilerIdValidator.find(parameters.front())) {
      reportError(context, content->GetOriginalExpression(),
                  "Expression syntax not recognized.");
      return {};
    }
    if (compilerVersion.empty()) {
      return parameters.front().empty() ? "1" : "0";
    }

    return cmSystemTools::VersionCompare(cmSystemTools::OP_EQUAL,
                                         parameters.front().c_str(),
                                         compilerVersion.c_str())
      ? "1"
      : "0";
  }

  const char* const CompilerLanguage;
};

static const CompilerVersionNode cCompilerVersionNode("C"),
  cxxCompilerVersionNode("CXX"), cudaCompilerVersionNode("CUDA"),
  objcCompilerVersionNode("OBJC"), objcxxCompilerVersionNode("OBJCXX"),
  fortranCompilerVersionNode("Fortran");

struct PlatformIdNode : public cmGeneratorExpressionNode
{
  PlatformIdNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    std::string const& platformId =
      context->LG->GetMakefile()->GetSafeDefinition("CMAKE_SYSTEM_NAME");
    if (parameters.empty()) {
      return platformId;
    }

    if (platformId.empty()) {
      return parameters.front().empty() ? "1" : "0";
    }

    for (auto& param : parameters) {
      if (param == platformId) {
        return "1";
      }
    }
    return "0";
  }
} platformIdNode;

template <cmSystemTools::CompareOp Op>
struct VersionNode : public cmGeneratorExpressionNode
{
  VersionNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return cmSystemTools::VersionCompare(Op, parameters.front().c_str(),
                                         parameters[1].c_str())
      ? "1"
      : "0";
  }
};

static const VersionNode<cmSystemTools::OP_GREATER> versionGreaterNode;
static const VersionNode<cmSystemTools::OP_GREATER_EQUAL> versionGreaterEqNode;
static const VersionNode<cmSystemTools::OP_LESS> versionLessNode;
static const VersionNode<cmSystemTools::OP_LESS_EQUAL> versionLessEqNode;
static const VersionNode<cmSystemTools::OP_EQUAL> versionEqualNode;

static const struct LinkOnlyNode : public cmGeneratorExpressionNode
{
  LinkOnlyNode() {} // NOLINT(modernize-use-equals-default)

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!dagChecker) {
      reportError(context, content->GetOriginalExpression(),
                  "$<LINK_ONLY:...> may only be used for linking");
      return std::string();
    }
    if (!dagChecker->GetTransitivePropertiesOnly()) {
      return parameters.front();
    }
    return std::string();
  }
} linkOnlyNode;

static const struct ConfigurationNode : public cmGeneratorExpressionNode
{
  ConfigurationNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 0; }

  std::string Evaluate(
    const std::vector<std::string>& /*parameters*/,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    context->HadContextSensitiveCondition = true;
    return context->Config;
  }
} configurationNode;

static const struct ConfigurationTestNode : public cmGeneratorExpressionNode
{
  ConfigurationTestNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return OneOrZeroParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (parameters.empty()) {
      return configurationNode.Evaluate(parameters, context, content, nullptr);
    }
    static cmsys::RegularExpression configValidator("^[A-Za-z0-9_]*$");
    if (!configValidator.find(parameters.front())) {
      reportError(context, content->GetOriginalExpression(),
                  "Expression syntax not recognized.");
      return std::string();
    }
    context->HadContextSensitiveCondition = true;
    if (context->Config.empty()) {
      return parameters.front().empty() ? "1" : "0";
    }

    if (cmsysString_strcasecmp(parameters.front().c_str(),
                               context->Config.c_str()) == 0) {
      return "1";
    }

    if (context->CurrentTarget && context->CurrentTarget->IsImported()) {
      cmProp loc = nullptr;
      cmProp imp = nullptr;
      std::string suffix;
      if (context->CurrentTarget->Target->GetMappedConfig(context->Config, loc,
                                                          imp, suffix)) {
        // This imported target has an appropriate location
        // for this (possibly mapped) config.
        // Check if there is a proper config mapping for the tested config.
        std::vector<std::string> mappedConfigs;
        std::string mapProp = cmStrCat(
          "MAP_IMPORTED_CONFIG_", cmSystemTools::UpperCase(context->Config));
        if (cmProp mapValue = context->CurrentTarget->GetProperty(mapProp)) {
          cmExpandList(cmSystemTools::UpperCase(*mapValue), mappedConfigs);
          return cm::contains(mappedConfigs,
                              cmSystemTools::UpperCase(parameters.front()))
            ? "1"
            : "0";
        }
      }
    }
    return "0";
  }
} configurationTestNode;

static const struct JoinNode : public cmGeneratorExpressionNode
{
  JoinNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 2; }

  bool AcceptsArbitraryContentParameter() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    std::vector<std::string> list = cmExpandedList(parameters.front());
    return cmJoin(list, parameters[1]);
  }
} joinNode;

static const struct CompileLanguageNode : public cmGeneratorExpressionNode
{
  CompileLanguageNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (context->Language.empty()) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<COMPILE_LANGUAGE:...> may only be used to specify include "
        "directories, compile definitions, compile options, and to evaluate "
        "components of the file(GENERATE) command.");
      return std::string();
    }

    cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
    std::string genName = gg->GetName();
    if (genName.find("Makefiles") == std::string::npos &&
        genName.find("Ninja") == std::string::npos &&
        genName.find("Visual Studio") == std::string::npos &&
        genName.find("Xcode") == std::string::npos &&
        genName.find("Watcom WMake") == std::string::npos) {
      reportError(context, content->GetOriginalExpression(),
                  "$<COMPILE_LANGUAGE:...> not supported for this generator.");
      return std::string();
    }
    if (parameters.empty()) {
      return context->Language;
    }

    for (auto& param : parameters) {
      if (context->Language == param) {
        return "1";
      }
    }
    return "0";
  }
} languageNode;

static const struct CompileLanguageAndIdNode : public cmGeneratorExpressionNode
{
  CompileLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return TwoOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget || context->Language.empty()) {
      // reportError(context, content->GetOriginalExpression(), "");
      reportError(
        context, content->GetOriginalExpression(),
        "$<COMPILE_LANG_AND_ID:lang,id> may only be used with binary targets "
        "to specify include directories, compile definitions, and compile "
        "options.  It may not be used with the add_custom_command, "
        "add_custom_target, or file(GENERATE) commands.");
      return std::string();
    }
    cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
    std::string genName = gg->GetName();
    if (genName.find("Makefiles") == std::string::npos &&
        genName.find("Ninja") == std::string::npos &&
        genName.find("Visual Studio") == std::string::npos &&
        genName.find("Xcode") == std::string::npos &&
        genName.find("Watcom WMake") == std::string::npos) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<COMPILE_LANG_AND_ID:lang,id> not supported for this generator.");
      return std::string();
    }

    const std::string& lang = context->Language;
    if (lang == parameters.front()) {
      std::vector<std::string> idParameter((parameters.cbegin() + 1),
                                           parameters.cend());
      return CompilerIdNode{ lang.c_str() }.EvaluateWithLanguage(
        idParameter, context, content, dagChecker, lang);
    }
    return "0";
  }
} languageAndIdNode;

static const struct LinkLanguageNode : public cmGeneratorExpressionNode
{
  LinkLanguageNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget || !dagChecker ||
        !(dagChecker->EvaluatingLinkExpression() ||
          dagChecker->EvaluatingLinkLibraries())) {
      reportError(context, content->GetOriginalExpression(),
                  "$<LINK_LANGUAGE:...> may only be used with binary targets "
                  "to specify link libraries, link directories, link options "
                  "and link depends.");
      return std::string();
    }
    if (dagChecker->EvaluatingLinkLibraries() && parameters.empty()) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<LINK_LANGUAGE> is not supported in link libraries expression.");
      return std::string();
    }

    cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
    std::string genName = gg->GetName();
    if (genName.find("Makefiles") == std::string::npos &&
        genName.find("Ninja") == std::string::npos &&
        genName.find("Visual Studio") == std::string::npos &&
        genName.find("Xcode") == std::string::npos &&
        genName.find("Watcom WMake") == std::string::npos) {
      reportError(context, content->GetOriginalExpression(),
                  "$<LINK_LANGUAGE:...> not supported for this generator.");
      return std::string();
    }

    if (dagChecker->EvaluatingLinkLibraries()) {
      context->HadHeadSensitiveCondition = true;
      context->HadLinkLanguageSensitiveCondition = true;
    }

    if (parameters.empty()) {
      return context->Language;
    }

    for (auto& param : parameters) {
      if (context->Language == param) {
        return "1";
      }
    }
    return "0";
  }
} linkLanguageNode;

namespace {
struct LinkerId
{
  static std::string Evaluate(const std::vector<std::string>& parameters,
                              cmGeneratorExpressionContext* context,
                              const GeneratorExpressionContent* content,
                              const std::string& lang)
  {
    std::string const& linkerId =
      context->LG->GetMakefile()->GetSafeDefinition("CMAKE_" + lang +
                                                    "_COMPILER_ID");
    if (parameters.empty()) {
      return linkerId;
    }
    if (linkerId.empty()) {
      return parameters.front().empty() ? "1" : "0";
    }
    static cmsys::RegularExpression linkerIdValidator("^[A-Za-z0-9_]*$");

    for (auto& param : parameters) {
      if (!linkerIdValidator.find(param)) {
        reportError(context, content->GetOriginalExpression(),
                    "Expression syntax not recognized.");
        return std::string();
      }

      if (param == linkerId) {
        return "1";
      }
    }
    return "0";
  }
};
}

static const struct LinkLanguageAndIdNode : public cmGeneratorExpressionNode
{
  LinkLanguageAndIdNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return TwoOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget || !dagChecker ||
        !(dagChecker->EvaluatingLinkExpression() ||
          dagChecker->EvaluatingLinkLibraries())) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<LINK_LANG_AND_ID:lang,id> may only be used with binary targets "
        "to specify link libraries, link directories, link options, and link "
        "depends.");
      return std::string();
    }

    cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
    std::string genName = gg->GetName();
    if (genName.find("Makefiles") == std::string::npos &&
        genName.find("Ninja") == std::string::npos &&
        genName.find("Visual Studio") == std::string::npos &&
        genName.find("Xcode") == std::string::npos &&
        genName.find("Watcom WMake") == std::string::npos) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<LINK_LANG_AND_ID:lang,id> not supported for this generator.");
      return std::string();
    }

    if (dagChecker->EvaluatingLinkLibraries()) {
      context->HadHeadSensitiveCondition = true;
      context->HadLinkLanguageSensitiveCondition = true;
    }

    const std::string& lang = context->Language;
    if (lang == parameters.front()) {
      std::vector<std::string> idParameter((parameters.cbegin() + 1),
                                           parameters.cend());
      return LinkerId::Evaluate(idParameter, context, content, lang);
    }
    return "0";
  }
} linkLanguageAndIdNode;

static const struct HostLinkNode : public cmGeneratorExpressionNode
{
  HostLinkNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget || !dagChecker ||
        !dagChecker->EvaluatingLinkOptionsExpression()) {
      reportError(context, content->GetOriginalExpression(),
                  "$<HOST_LINK:...> may only be used with binary targets "
                  "to specify link options.");
      return std::string();
    }

    return context->HeadTarget->IsDeviceLink() ? std::string()
                                               : cmJoin(parameters, ";");
  }
} hostLinkNode;

static const struct DeviceLinkNode : public cmGeneratorExpressionNode
{
  DeviceLinkNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return ZeroOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    if (!context->HeadTarget || !dagChecker ||
        !dagChecker->EvaluatingLinkOptionsExpression()) {
      reportError(context, content->GetOriginalExpression(),
                  "$<DEVICE_LINK:...> may only be used with binary targets "
                  "to specify link options.");
      return std::string();
    }

    if (context->HeadTarget->IsDeviceLink()) {
      std::vector<std::string> list;
      cmExpandLists(parameters.begin(), parameters.end(), list);
      const auto DL_BEGIN = "<DEVICE_LINK>"_s;
      const auto DL_END = "</DEVICE_LINK>"_s;
      cm::erase_if(list, [&](const std::string& item) {
        return item == DL_BEGIN || item == DL_END;
      });

      list.insert(list.begin(), static_cast<std::string>(DL_BEGIN));
      list.push_back(static_cast<std::string>(DL_END));

      return cmJoin(list, ";");
    }

    return std::string();
  }
} deviceLinkNode;

std::string getLinkedTargetsContent(
  cmGeneratorTarget const* target, std::string const& prop,
  cmGeneratorExpressionContext* context,
  cmGeneratorExpressionDAGChecker* dagChecker)
{
  std::string result;
  if (cmLinkImplementationLibraries const* impl =
        target->GetLinkImplementationLibraries(context->Config)) {
    for (cmLinkImplItem const& lib : impl->Libraries) {
      if (lib.Target) {
        // Pretend $<TARGET_PROPERTY:lib.Target,prop> appeared in our
        // caller's property and hand-evaluate it as if it were compiled.
        // Create a context as cmCompiledGeneratorExpression::Evaluate does.
        cmGeneratorExpressionContext libContext(
          target->GetLocalGenerator(), context->Config, context->Quiet, target,
          target, context->EvaluateForBuildsystem, lib.Backtrace,
          context->Language);
        std::string libResult =
          lib.Target->EvaluateInterfaceProperty(prop, &libContext, dagChecker);
        if (!libResult.empty()) {
          if (result.empty()) {
            result = std::move(libResult);
          } else {
            result.reserve(result.size() + 1 + libResult.size());
            result += ";";
            result += libResult;
          }
        }
      }
    }
  }
  return result;
}

static const struct TargetPropertyNode : public cmGeneratorExpressionNode
{
  TargetPropertyNode() {} // NOLINT(modernize-use-equals-default)

  // This node handles errors on parameter count itself.
  int NumExpectedParameters() const override { return OneOrMoreParameters; }

  static const char* GetErrorText(std::string const& targetName,
                                  std::string const& propertyName)
  {
    static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");
    if (targetName.empty() && propertyName.empty()) {
      return "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
             "target name and property name.";
    }
    if (targetName.empty()) {
      return "$<TARGET_PROPERTY:tgt,prop> expression requires a non-empty "
             "target name.";
    }
    if (!cmGeneratorExpression::IsValidTargetName(targetName)) {
      if (!propertyNameValidator.find(propertyName)) {
        return "Target name and property name not supported.";
      }
      return "Target name not supported.";
    }
    return nullptr;
  }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagCheckerParent) const override
  {
    static cmsys::RegularExpression propertyNameValidator("^[A-Za-z0-9_]+$");

    cmGeneratorTarget const* target = nullptr;
    std::string targetName;
    std::string propertyName;

    if (parameters.size() == 2) {
      targetName = parameters[0];
      propertyName = parameters[1];

      if (const char* e = GetErrorText(targetName, propertyName)) {
        reportError(context, content->GetOriginalExpression(), e);
        return std::string();
      }
      if (propertyName == "ALIASED_TARGET"_s) {
        if (context->LG->GetMakefile()->IsAlias(targetName)) {
          if (cmGeneratorTarget* tgt =
                context->LG->FindGeneratorTargetToUse(targetName)) {
            return tgt->GetName();
          }
        }
        return std::string();
      }
      if (propertyName == "ALIAS_GLOBAL"_s) {
        if (context->LG->GetMakefile()->IsAlias(targetName)) {
          return context->LG->GetGlobalGenerator()->IsAlias(targetName)
            ? "TRUE"
            : "FALSE";
        }
        return std::string();
      }
      target = context->LG->FindGeneratorTargetToUse(targetName);

      if (!target) {
        std::ostringstream e;
        e << "Target \"" << targetName << "\" not found.";
        reportError(context, content->GetOriginalExpression(), e.str());
        return std::string();
      }
      context->AllTargets.insert(target);

    } else if (parameters.size() == 1) {
      target = context->HeadTarget;
      propertyName = parameters[0];

      // Keep track of the properties seen while processing.
      // The evaluation of the LINK_LIBRARIES generator expressions
      // will check this to ensure that properties have one consistent
      // value for all evaluations.
      context->SeenTargetProperties.insert(propertyName);

      context->HadHeadSensitiveCondition = true;
      if (!target) {
        reportError(
          context, content->GetOriginalExpression(),
          "$<TARGET_PROPERTY:prop>  may only be used with binary targets.  "
          "It may not be used with add_custom_command or add_custom_target.  "
          " "
          "Specify the target to read a property from using the "
          "$<TARGET_PROPERTY:tgt,prop> signature instead.");
        return std::string();
      }
    } else {
      reportError(
        context, content->GetOriginalExpression(),
        "$<TARGET_PROPERTY:...> expression requires one or two parameters");
      return std::string();
    }

    if (propertyName == "SOURCES") {
      context->SourceSensitiveTargets.insert(target);
    }

    if (propertyName.empty()) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<TARGET_PROPERTY:...> expression requires a non-empty property "
        "name.");
      return std::string();
    }

    if (!propertyNameValidator.find(propertyName)) {
      ::reportError(context, content->GetOriginalExpression(),
                    "Property name not supported.");
      return std::string();
    }

    assert(target);

    if (propertyName == "LINKER_LANGUAGE") {
      if (target->LinkLanguagePropagatesToDependents() && dagCheckerParent &&
          (dagCheckerParent->EvaluatingLinkLibraries() ||
           dagCheckerParent->EvaluatingSources())) {
        reportError(
          context, content->GetOriginalExpression(),
          "LINKER_LANGUAGE target property can not be used while evaluating "
          "link libraries for a static library");
        return std::string();
      }
      return target->GetLinkerLanguage(context->Config);
    }

    std::string interfacePropertyName;
    bool isInterfaceProperty = false;

#define POPULATE_INTERFACE_PROPERTY_NAME(prop)                                \
  if (propertyName == #prop) {                                                \
    interfacePropertyName = "INTERFACE_" #prop;                               \
  } else if (propertyName == "INTERFACE_" #prop) {                            \
    interfacePropertyName = "INTERFACE_" #prop;                               \
    isInterfaceProperty = true;                                               \
  } else

    CM_FOR_EACH_TRANSITIVE_PROPERTY_NAME(POPULATE_INTERFACE_PROPERTY_NAME)
    // Note that the above macro terminates with an else
    /* else */ if (cmHasLiteralPrefix(propertyName, "COMPILE_DEFINITIONS_")) {
      cmPolicies::PolicyStatus polSt =
        context->LG->GetPolicyStatus(cmPolicies::CMP0043);
      if (polSt == cmPolicies::WARN || polSt == cmPolicies::OLD) {
        interfacePropertyName = "INTERFACE_COMPILE_DEFINITIONS";
      }
    }
#undef POPULATE_INTERFACE_PROPERTY_NAME

    bool evaluatingLinkLibraries = false;

    if (dagCheckerParent) {
      if (dagCheckerParent->EvaluatingGenexExpression() ||
          dagCheckerParent->EvaluatingPICExpression()) {
        // No check required.
      } else if (dagCheckerParent->EvaluatingLinkLibraries()) {
        evaluatingLinkLibraries = true;
        if (!interfacePropertyName.empty()) {
          reportError(
            context, content->GetOriginalExpression(),
            "$<TARGET_PROPERTY:...> expression in link libraries "
            "evaluation depends on target property which is transitive "
            "over the link libraries, creating a recursion.");
          return std::string();
        }
      } else {
#define ASSERT_TRANSITIVE_PROPERTY_METHOD(METHOD) dagCheckerParent->METHOD() ||
        assert(CM_FOR_EACH_TRANSITIVE_PROPERTY_METHOD(
          ASSERT_TRANSITIVE_PROPERTY_METHOD) false); // NOLINT(clang-tidy)
#undef ASSERT_TRANSITIVE_PROPERTY_METHOD
      }
    }

    if (isInterfaceProperty) {
      return target->EvaluateInterfaceProperty(propertyName, context,
                                               dagCheckerParent);
    }

    cmGeneratorExpressionDAGChecker dagChecker(
      context->Backtrace, target, propertyName, content, dagCheckerParent);

    switch (dagChecker.Check()) {
      case cmGeneratorExpressionDAGChecker::SELF_REFERENCE:
        dagChecker.ReportError(context, content->GetOriginalExpression());
        return std::string();
      case cmGeneratorExpressionDAGChecker::CYCLIC_REFERENCE:
        // No error. We just skip cyclic references.
        return std::string();
      case cmGeneratorExpressionDAGChecker::ALREADY_SEEN:
        // We handle transitive properties above.  For non-transitive
        // properties we accept repeats anyway.
      case cmGeneratorExpressionDAGChecker::DAG:
        break;
    }

    std::string result;
    bool haveProp = false;
    if (cmProp p = target->GetProperty(propertyName)) {
      result = *p;
      haveProp = true;
    } else if (evaluatingLinkLibraries) {
      return std::string();
    }

    if (!haveProp && !target->IsImported() &&
        target->GetType() != cmStateEnums::INTERFACE_LIBRARY) {
      if (target->IsLinkInterfaceDependentBoolProperty(propertyName,
                                                       context->Config)) {
        context->HadContextSensitiveCondition = true;
        return target->GetLinkInterfaceDependentBoolProperty(propertyName,
                                                             context->Config)
          ? "1"
          : "0";
      }
      if (target->IsLinkInterfaceDependentStringProperty(propertyName,
                                                         context->Config)) {
        context->HadContextSensitiveCondition = true;
        const char* propContent =
          target->GetLinkInterfaceDependentStringProperty(propertyName,
                                                          context->Config);
        return propContent ? propContent : "";
      }
      if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
                                                            context->Config)) {
        context->HadContextSensitiveCondition = true;
        const char* propContent =
          target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
                                                             context->Config);
        return propContent ? propContent : "";
      }
      if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
                                                            context->Config)) {
        context->HadContextSensitiveCondition = true;
        const char* propContent =
          target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
                                                             context->Config);
        return propContent ? propContent : "";
      }
    }

    if (!target->IsImported() && dagCheckerParent &&
        !dagCheckerParent->EvaluatingLinkLibraries()) {
      if (target->IsLinkInterfaceDependentNumberMinProperty(propertyName,
                                                            context->Config)) {
        context->HadContextSensitiveCondition = true;
        const char* propContent =
          target->GetLinkInterfaceDependentNumberMinProperty(propertyName,
                                                             context->Config);
        return propContent ? propContent : "";
      }
      if (target->IsLinkInterfaceDependentNumberMaxProperty(propertyName,
                                                            context->Config)) {
        context->HadContextSensitiveCondition = true;
        const char* propContent =
          target->GetLinkInterfaceDependentNumberMaxProperty(propertyName,
                                                             context->Config);
        return propContent ? propContent : "";
      }
    }

    if (!interfacePropertyName.empty()) {
      result = this->EvaluateDependentExpression(result, context->LG, context,
                                                 target, &dagChecker, target);
      std::string linkedTargetsContent = getLinkedTargetsContent(
        target, interfacePropertyName, context, &dagChecker);
      if (!linkedTargetsContent.empty()) {
        result += (result.empty() ? "" : ";") + linkedTargetsContent;
      }
    }
    return result;
  }
} targetPropertyNode;

static const struct TargetNameNode : public cmGeneratorExpressionNode
{
  TargetNameNode() {} // NOLINT(modernize-use-equals-default)

  bool GeneratesContent() const override { return true; }

  bool AcceptsArbitraryContentParameter() const override { return true; }
  bool RequiresLiteralInput() const override { return true; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* /*context*/,
    const GeneratorExpressionContent* /*content*/,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    return parameters.front();
  }

  int NumExpectedParameters() const override { return 1; }

} targetNameNode;

static const struct TargetObjectsNode : public cmGeneratorExpressionNode
{
  TargetObjectsNode() {} // NOLINT(modernize-use-equals-default)

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    std::string tgtName = parameters.front();
    cmGeneratorTarget* gt = context->LG->FindGeneratorTargetToUse(tgtName);
    if (!gt) {
      std::ostringstream e;
      e << "Objects of target \"" << tgtName
        << "\" referenced but no such target exists.";
      reportError(context, content->GetOriginalExpression(), e.str());
      return std::string();
    }
    cmStateEnums::TargetType type = gt->GetType();
    if (type != cmStateEnums::EXECUTABLE &&
        type != cmStateEnums::STATIC_LIBRARY &&
        type != cmStateEnums::SHARED_LIBRARY &&
        type != cmStateEnums::MODULE_LIBRARY &&
        type != cmStateEnums::OBJECT_LIBRARY) {
      std::ostringstream e;
      e << "Objects of target \"" << tgtName
        << "\" referenced but is not an allowed library types (EXECUTABLE, "
        << "STATIC, SHARED, MODULE, OBJECT).";
      reportError(context, content->GetOriginalExpression(), e.str());
      return std::string();
    }
    if (!context->EvaluateForBuildsystem) {
      cmGlobalGenerator* gg = context->LG->GetGlobalGenerator();
      std::string reason;
      if (!gg->HasKnownObjectFileLocation(&reason)) {
        std::ostringstream e;
        e << "The evaluation of the TARGET_OBJECTS generator expression "
             "is only suitable for consumption by CMake (limited"
          << reason
          << ").  "
             "It is not suitable for writing out elsewhere.";
        reportError(context, content->GetOriginalExpression(), e.str());
        return std::string();
      }
    }

    std::vector<std::string> objects;

    if (gt->IsImported()) {
      cmProp loc = nullptr;
      cmProp imp = nullptr;
      std::string suffix;
      if (gt->Target->GetMappedConfig(context->Config, loc, imp, suffix)) {
        cmExpandList(*loc, objects);
      }
      context->HadContextSensitiveCondition = true;
    } else {
      gt->GetTargetObjectNames(context->Config, objects);

      std::string obj_dir;
      if (context->EvaluateForBuildsystem) {
        // Use object file directory with buildsystem placeholder.
        obj_dir = gt->ObjectDirectory;
        // Here we assume that the set of object files produced
        // by an object library does not vary with configuration
        // and do not set HadContextSensitiveCondition to true.
      } else {
        // Use object file directory with per-config location.
        obj_dir = gt->GetObjectDirectory(context->Config);
        context->HadContextSensitiveCondition = true;
      }

      for (std::string& o : objects) {
        o = cmStrCat(obj_dir, o);
      }
    }

    // Create the cmSourceFile instances in the referencing directory.
    cmMakefile* mf = context->LG->GetMakefile();
    for (std::string& o : objects) {
      mf->AddTargetObject(tgtName, o);
    }

    return cmJoin(objects, ";");
  }
} targetObjectsNode;

static const struct CompileFeaturesNode : public cmGeneratorExpressionNode
{
  CompileFeaturesNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return OneOrMoreParameters; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    cmGeneratorTarget const* target = context->HeadTarget;
    if (!target) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<COMPILE_FEATURE> may only be used with binary targets.  It may "
        "not be used with add_custom_command or add_custom_target.");
      return std::string();
    }
    context->HadHeadSensitiveCondition = true;

    using LangMap = std::map<std::string, std::vector<std::string>>;
    static LangMap availableFeatures;

    LangMap testedFeatures;

    for (std::string const& p : parameters) {
      std::string error;
      std::string lang;
      if (!context->LG->GetMakefile()->CompileFeatureKnown(
            context->HeadTarget->Target, p, lang, &error)) {
        reportError(context, content->GetOriginalExpression(), error);
        return std::string();
      }
      testedFeatures[lang].push_back(p);

      if (availableFeatures.find(lang) == availableFeatures.end()) {
        const char* featuresKnown =
          context->LG->GetMakefile()->CompileFeaturesAvailable(lang, &error);
        if (!featuresKnown) {
          reportError(context, content->GetOriginalExpression(), error);
          return std::string();
        }
        cmExpandList(featuresKnown, availableFeatures[lang]);
      }
    }

    bool evalLL = dagChecker && dagChecker->EvaluatingLinkLibraries();

    for (auto const& lit : testedFeatures) {
      std::vector<std::string> const& langAvailable =
        availableFeatures[lit.first];
      cmProp standardDefault = context->LG->GetMakefile()->GetDef(
        "CMAKE_" + lit.first + "_STANDARD_DEFAULT");
      for (std::string const& it : lit.second) {
        if (!cm::contains(langAvailable, it)) {
          return "0";
        }
        if (standardDefault && standardDefault->empty()) {
          // This compiler has no notion of language standard levels.
          // All features known for the language are always available.
          continue;
        }
        if (!context->LG->GetMakefile()->HaveStandardAvailable(
              target->Target, lit.first, it)) {
          if (evalLL) {
            cmProp l = target->GetProperty(lit.first + "_STANDARD");
            if (!l) {
              l = standardDefault;
            }
            assert(l);
            context->MaxLanguageStandard[target][lit.first] = *l;
          } else {
            return "0";
          }
        }
      }
    }
    return "1";
  }
} compileFeaturesNode;

static const char* targetPolicyWhitelist[] = {
  nullptr
#define TARGET_POLICY_STRING(POLICY) , #POLICY

  CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_STRING)

#undef TARGET_POLICY_STRING
};

cmPolicies::PolicyStatus statusForTarget(cmGeneratorTarget const* tgt,
                                         const char* policy)
{
#define RETURN_POLICY(POLICY)                                                 \
  if (strcmp(policy, #POLICY) == 0) {                                         \
    return tgt->GetPolicyStatus##POLICY();                                    \
  }

  CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY)

#undef RETURN_POLICY

  assert(false && "Unreachable code. Not a valid policy");
  return cmPolicies::WARN;
}

cmPolicies::PolicyID policyForString(const char* policy_id)
{
#define RETURN_POLICY_ID(POLICY_ID)                                           \
  if (strcmp(policy_id, #POLICY_ID) == 0) {                                   \
    return cmPolicies::POLICY_ID;                                             \
  }

  CM_FOR_EACH_TARGET_POLICY(RETURN_POLICY_ID)

#undef RETURN_POLICY_ID

  assert(false && "Unreachable code. Not a valid policy");
  return cmPolicies::CMP0002;
}

static const struct TargetPolicyNode : public cmGeneratorExpressionNode
{
  TargetPolicyNode() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    if (!context->HeadTarget) {
      reportError(
        context, content->GetOriginalExpression(),
        "$<TARGET_POLICY:prop> may only be used with binary targets.  It "
        "may not be used with add_custom_command or add_custom_target.");
      return std::string();
    }

    context->HadContextSensitiveCondition = true;
    context->HadHeadSensitiveCondition = true;

    for (size_t i = 1; i < cm::size(targetPolicyWhitelist); ++i) {
      const char* policy = targetPolicyWhitelist[i];
      if (parameters.front() == policy) {
        cmLocalGenerator* lg = context->HeadTarget->GetLocalGenerator();
        switch (statusForTarget(context->HeadTarget, policy)) {
          case cmPolicies::WARN:
            lg->IssueMessage(
              MessageType::AUTHOR_WARNING,
              cmPolicies::GetPolicyWarning(policyForString(policy)));
            CM_FALLTHROUGH;
          case cmPolicies::REQUIRED_IF_USED:
          case cmPolicies::REQUIRED_ALWAYS:
          case cmPolicies::OLD:
            return "0";
          case cmPolicies::NEW:
            return "1";
        }
      }
    }
    reportError(
      context, content->GetOriginalExpression(),
      "$<TARGET_POLICY:prop> may only be used with a limited number of "
      "policies.  Currently it may be used with the following policies:\n"

#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)

#define TARGET_POLICY_LIST_ITEM(POLICY) " * " STRINGIFY(POLICY) "\n"

      CM_FOR_EACH_TARGET_POLICY(TARGET_POLICY_LIST_ITEM)

#undef TARGET_POLICY_LIST_ITEM
    );
    return std::string();
  }

} targetPolicyNode;

static const struct InstallPrefixNode : public cmGeneratorExpressionNode
{
  InstallPrefixNode() {} // NOLINT(modernize-use-equals-default)

  bool GeneratesContent() const override { return true; }
  int NumExpectedParameters() const override { return 0; }

  std::string Evaluate(
    const std::vector<std::string>& /*parameters*/,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    reportError(context, content->GetOriginalExpression(),
                "INSTALL_PREFIX is a marker for install(EXPORT) only.  It "
                "should never be evaluated.");
    return std::string();
  }

} installPrefixNode;

class ArtifactDirTag;
class ArtifactLinkerTag;
class ArtifactNameTag;
class ArtifactPathTag;
class ArtifactPdbTag;
class ArtifactSonameTag;
class ArtifactBundleDirTag;
class ArtifactBundleContentDirTag;

template <typename ArtifactT>
struct TargetFilesystemArtifactResultCreator
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content);
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactSonameTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content)
  {
    // The target soname file (.so.1).
    if (target->IsDLLPlatform()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_SONAME_FILE is not allowed "
                    "for DLL target platforms.");
      return std::string();
    }
    if (target->GetType() != cmStateEnums::SHARED_LIBRARY) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_SONAME_FILE is allowed only for "
                    "SHARED libraries.");
      return std::string();
    }
    std::string result = cmStrCat(target->GetDirectory(context->Config), '/',
                                  target->GetSOName(context->Config));
    return result;
  }
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactPdbTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content)
  {
    if (target->IsImported()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_PDB_FILE not allowed for IMPORTED targets.");
      return std::string();
    }

    std::string language = target->GetLinkerLanguage(context->Config);

    std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";

    if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_PDB_FILE is not supported by the target linker.");
      return std::string();
    }

    cmStateEnums::TargetType targetType = target->GetType();

    if (targetType != cmStateEnums::SHARED_LIBRARY &&
        targetType != cmStateEnums::MODULE_LIBRARY &&
        targetType != cmStateEnums::EXECUTABLE) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_PDB_FILE is allowed only for "
                    "targets with linker created artifacts.");
      return std::string();
    }

    std::string result = cmStrCat(target->GetPDBDirectory(context->Config),
                                  '/', target->GetPDBName(context->Config));
    return result;
  }
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactLinkerTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content)
  {
    // The file used to link to the target (.so, .lib, .a).
    if (!target->IsLinkable()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_LINKER_FILE is allowed only for libraries and "
                    "executables with ENABLE_EXPORTS.");
      return std::string();
    }
    cmStateEnums::ArtifactType artifact =
      target->HasImportLibrary(context->Config)
      ? cmStateEnums::ImportLibraryArtifact
      : cmStateEnums::RuntimeBinaryArtifact;
    return target->GetFullPath(context->Config, artifact);
  }
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactBundleDirTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content)
  {
    if (target->IsImported()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_BUNDLE_DIR not allowed for IMPORTED targets.");
      return std::string();
    }
    if (!target->IsBundleOnApple()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_BUNDLE_DIR is allowed only for Bundle targets.");
      return std::string();
    }

    std::string outpath = target->GetDirectory(context->Config) + '/';
    return target->BuildBundleDirectory(outpath, context->Config,
                                        cmGeneratorTarget::BundleDirLevel);
  }
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactBundleContentDirTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* content)
  {
    if (target->IsImported()) {
      ::reportError(
        context, content->GetOriginalExpression(),
        "TARGET_BUNDLE_CONTENT_DIR not allowed for IMPORTED targets.");
      return std::string();
    }
    if (!target->IsBundleOnApple()) {
      ::reportError(
        context, content->GetOriginalExpression(),
        "TARGET_BUNDLE_CONTENT_DIR is allowed only for Bundle targets.");
      return std::string();
    }

    std::string outpath = target->GetDirectory(context->Config) + '/';
    return target->BuildBundleDirectory(outpath, context->Config,
                                        cmGeneratorTarget::ContentLevel);
  }
};

template <>
struct TargetFilesystemArtifactResultCreator<ArtifactNameTag>
{
  static std::string Create(cmGeneratorTarget* target,
                            cmGeneratorExpressionContext* context,
                            const GeneratorExpressionContent* /*unused*/)
  {
    return target->GetFullPath(context->Config,
                               cmStateEnums::RuntimeBinaryArtifact, true);
  }
};

template <typename ArtifactT>
struct TargetFilesystemArtifactResultGetter
{
  static std::string Get(const std::string& result);
};

template <>
struct TargetFilesystemArtifactResultGetter<ArtifactNameTag>
{
  static std::string Get(const std::string& result)
  {
    return cmSystemTools::GetFilenameName(result);
  }
};

template <>
struct TargetFilesystemArtifactResultGetter<ArtifactDirTag>
{
  static std::string Get(const std::string& result)
  {
    return cmSystemTools::GetFilenamePath(result);
  }
};

template <>
struct TargetFilesystemArtifactResultGetter<ArtifactPathTag>
{
  static std::string Get(const std::string& result) { return result; }
};

struct TargetArtifactBase : public cmGeneratorExpressionNode
{
  TargetArtifactBase() {} // NOLINT(modernize-use-equals-default)

protected:
  cmGeneratorTarget* GetTarget(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const
  {
    // Lookup the referenced target.
    std::string name = parameters.front();

    if (!cmGeneratorExpression::IsValidTargetName(name)) {
      ::reportError(context, content->GetOriginalExpression(),
                    "Expression syntax not recognized.");
      return nullptr;
    }
    cmGeneratorTarget* target = context->LG->FindGeneratorTargetToUse(name);
    if (!target) {
      ::reportError(context, content->GetOriginalExpression(),
                    "No target \"" + name + "\"");
      return nullptr;
    }
    if (target->GetType() >= cmStateEnums::OBJECT_LIBRARY &&
        target->GetType() != cmStateEnums::UNKNOWN_LIBRARY) {
      ::reportError(context, content->GetOriginalExpression(),
                    "Target \"" + name +
                      "\" is not an executable or library.");
      return nullptr;
    }
    if (dagChecker &&
        (dagChecker->EvaluatingLinkLibraries(target) ||
         (dagChecker->EvaluatingSources() &&
          target == dagChecker->TopTarget()))) {
      ::reportError(context, content->GetOriginalExpression(),
                    "Expressions which require the linker language may not "
                    "be used while evaluating link libraries");
      return nullptr;
    }

    return target;
  }
};

template <typename ArtifactT, typename ComponentT>
struct TargetFilesystemArtifact : public TargetArtifactBase
{
  TargetFilesystemArtifact() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    cmGeneratorTarget* target =
      this->GetTarget(parameters, context, content, dagChecker);
    if (!target) {
      return std::string();
    }
    context->DependTargets.insert(target);
    context->AllTargets.insert(target);

    std::string result =
      TargetFilesystemArtifactResultCreator<ArtifactT>::Create(target, context,
                                                               content);
    if (context->HadError) {
      return std::string();
    }
    return TargetFilesystemArtifactResultGetter<ComponentT>::Get(result);
  }
};

template <typename ArtifactT>
struct TargetFilesystemArtifactNodeGroup
{
  TargetFilesystemArtifactNodeGroup() // NOLINT(modernize-use-equals-default)
  {
  }

  TargetFilesystemArtifact<ArtifactT, ArtifactPathTag> File;
  TargetFilesystemArtifact<ArtifactT, ArtifactNameTag> FileName;
  TargetFilesystemArtifact<ArtifactT, ArtifactDirTag> FileDir;
};

static const TargetFilesystemArtifactNodeGroup<ArtifactNameTag>
  targetNodeGroup;

static const TargetFilesystemArtifactNodeGroup<ArtifactLinkerTag>
  targetLinkerNodeGroup;

static const TargetFilesystemArtifactNodeGroup<ArtifactSonameTag>
  targetSoNameNodeGroup;

static const TargetFilesystemArtifactNodeGroup<ArtifactPdbTag>
  targetPdbNodeGroup;

static const TargetFilesystemArtifact<ArtifactBundleDirTag, ArtifactPathTag>
  targetBundleDirNode;

static const TargetFilesystemArtifact<ArtifactBundleContentDirTag,
                                      ArtifactPathTag>
  targetBundleContentDirNode;

//
// To retrieve base name for various artifacts
//
template <typename ArtifactT>
struct TargetOutputNameArtifactResultGetter
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content);
};

template <>
struct TargetOutputNameArtifactResultGetter<ArtifactNameTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* /*unused*/)
  {
    return target->GetOutputName(context->Config,
                                 cmStateEnums::RuntimeBinaryArtifact) +
      target->GetFilePostfix(context->Config);
  }
};

template <>
struct TargetOutputNameArtifactResultGetter<ArtifactLinkerTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content)
  {
    // The file used to link to the target (.so, .lib, .a).
    if (!target->IsLinkable()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_LINKER_FILE_BASE_NAME is allowed only for "
                    "libraries and executables with ENABLE_EXPORTS.");
      return std::string();
    }
    cmStateEnums::ArtifactType artifact =
      target->HasImportLibrary(context->Config)
      ? cmStateEnums::ImportLibraryArtifact
      : cmStateEnums::RuntimeBinaryArtifact;
    return target->GetOutputName(context->Config, artifact) +
      target->GetFilePostfix(context->Config);
  }
};

template <>
struct TargetOutputNameArtifactResultGetter<ArtifactPdbTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content)
  {
    if (target->IsImported()) {
      ::reportError(
        context, content->GetOriginalExpression(),
        "TARGET_PDB_FILE_BASE_NAME not allowed for IMPORTED targets.");
      return std::string();
    }

    std::string language = target->GetLinkerLanguage(context->Config);

    std::string pdbSupportVar = "CMAKE_" + language + "_LINKER_SUPPORTS_PDB";

    if (!context->LG->GetMakefile()->IsOn(pdbSupportVar)) {
      ::reportError(
        context, content->GetOriginalExpression(),
        "TARGET_PDB_FILE_BASE_NAME is not supported by the target linker.");
      return std::string();
    }

    cmStateEnums::TargetType targetType = target->GetType();

    if (targetType != cmStateEnums::SHARED_LIBRARY &&
        targetType != cmStateEnums::MODULE_LIBRARY &&
        targetType != cmStateEnums::EXECUTABLE) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_PDB_FILE_BASE_NAME is allowed only for "
                    "targets with linker created artifacts.");
      return std::string();
    }

    return target->GetPDBOutputName(context->Config) +
      target->GetFilePostfix(context->Config);
  }
};

template <typename ArtifactT>
struct TargetFileBaseNameArtifact : public TargetArtifactBase
{
  TargetFileBaseNameArtifact() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    cmGeneratorTarget* target =
      this->GetTarget(parameters, context, content, dagChecker);
    if (!target) {
      return std::string();
    }

    std::string result = TargetOutputNameArtifactResultGetter<ArtifactT>::Get(
      target, context, content);
    if (context->HadError) {
      return std::string();
    }
    return result;
  }
};

static const TargetFileBaseNameArtifact<ArtifactNameTag>
  targetFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactLinkerTag>
  targetLinkerFileBaseNameNode;
static const TargetFileBaseNameArtifact<ArtifactPdbTag>
  targetPdbFileBaseNameNode;

class ArtifactFilePrefixTag;
class ArtifactLinkerFilePrefixTag;
class ArtifactFileSuffixTag;
class ArtifactLinkerFileSuffixTag;

template <typename ArtifactT>
struct TargetFileArtifactResultGetter
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content);
};

template <>
struct TargetFileArtifactResultGetter<ArtifactFilePrefixTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent*)
  {
    return target->GetFilePrefix(context->Config);
  }
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerFilePrefixTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content)
  {
    if (!target->IsLinkable()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_LINKER_PREFIX is allowed only for libraries and "
                    "executables with ENABLE_EXPORTS.");
      return std::string();
    }

    cmStateEnums::ArtifactType artifact =
      target->HasImportLibrary(context->Config)
      ? cmStateEnums::ImportLibraryArtifact
      : cmStateEnums::RuntimeBinaryArtifact;

    return target->GetFilePrefix(context->Config, artifact);
  }
};
template <>
struct TargetFileArtifactResultGetter<ArtifactFileSuffixTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent*)
  {
    return target->GetFileSuffix(context->Config);
  }
};
template <>
struct TargetFileArtifactResultGetter<ArtifactLinkerFileSuffixTag>
{
  static std::string Get(cmGeneratorTarget* target,
                         cmGeneratorExpressionContext* context,
                         const GeneratorExpressionContent* content)
  {
    if (!target->IsLinkable()) {
      ::reportError(context, content->GetOriginalExpression(),
                    "TARGET_LINKER_SUFFIX is allowed only for libraries and "
                    "executables with ENABLE_EXPORTS.");
      return std::string();
    }

    cmStateEnums::ArtifactType artifact =
      target->HasImportLibrary(context->Config)
      ? cmStateEnums::ImportLibraryArtifact
      : cmStateEnums::RuntimeBinaryArtifact;

    return target->GetFileSuffix(context->Config, artifact);
  }
};

template <typename ArtifactT>
struct TargetFileArtifact : public TargetArtifactBase
{
  TargetFileArtifact() {} // NOLINT(modernize-use-equals-default)

  int NumExpectedParameters() const override { return 1; }

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* dagChecker) const override
  {
    cmGeneratorTarget* target =
      this->GetTarget(parameters, context, content, dagChecker);
    if (!target) {
      return std::string();
    }

    std::string result =
      TargetFileArtifactResultGetter<ArtifactT>::Get(target, context, content);
    if (context->HadError) {
      return std::string();
    }
    return result;
  }
};

static const TargetFileArtifact<ArtifactFilePrefixTag> targetFilePrefixNode;
static const TargetFileArtifact<ArtifactLinkerFilePrefixTag>
  targetLinkerFilePrefixNode;
static const TargetFileArtifact<ArtifactFileSuffixTag> targetFileSuffixNode;
static const TargetFileArtifact<ArtifactLinkerFileSuffixTag>
  targetLinkerFileSuffixNode;

static const struct ShellPathNode : public cmGeneratorExpressionNode
{
  ShellPathNode() {} // NOLINT(modernize-use-equals-default)

  std::string Evaluate(
    const std::vector<std::string>& parameters,
    cmGeneratorExpressionContext* context,
    const GeneratorExpressionContent* content,
    cmGeneratorExpressionDAGChecker* /*dagChecker*/) const override
  {
    std::vector<std::string> listIn = cmExpandedList(parameters.front());
    if (listIn.empty()) {
      reportError(context, content->GetOriginalExpression(),
                  "\"\" is not an absolute path.");
      return std::string();
    }
    cmStateSnapshot snapshot = context->LG->GetStateSnapshot();
    cmOutputConverter converter(snapshot);
    const char* separator = snapshot.GetState()->UseWindowsShell() ? ";" : ":";
    std::vector<std::string> listOut;
    listOut.reserve(listIn.size());
    for (auto const& in : listIn) {
      if (!cmSystemTools::FileIsFullPath(in)) {
        reportError(context, content->GetOriginalExpression(),
                    "\"" + in + "\" is not an absolute path.");
        return std::string();
      }
      listOut.emplace_back(converter.ConvertDirectorySeparatorsForShell(in));
    }
    return cmJoin(listOut, separator);
  }
} shellPathNode;

const cmGeneratorExpressionNode* cmGeneratorExpressionNode::GetNode(
  const std::string& identifier)
{
  static std::map<std::string, cmGeneratorExpressionNode const*> const nodeMap{
    { "0", &zeroNode },
    { "1", &oneNode },
    { "AND", &andNode },
    { "OR", &orNode },
    { "NOT", &notNode },
    { "C_COMPILER_ID", &cCompilerIdNode },
    { "CXX_COMPILER_ID", &cxxCompilerIdNode },
    { "OBJC_COMPILER_ID", &objcCompilerIdNode },
    { "OBJCXX_COMPILER_ID", &objcxxCompilerIdNode },
    { "CUDA_COMPILER_ID", &cudaCompilerIdNode },
    { "Fortran_COMPILER_ID", &fortranCompilerIdNode },
    { "VERSION_GREATER", &versionGreaterNode },
    { "VERSION_GREATER_EQUAL", &versionGreaterEqNode },
    { "VERSION_LESS", &versionLessNode },
    { "VERSION_LESS_EQUAL", &versionLessEqNode },
    { "VERSION_EQUAL", &versionEqualNode },
    { "C_COMPILER_VERSION", &cCompilerVersionNode },
    { "CXX_COMPILER_VERSION", &cxxCompilerVersionNode },
    { "CUDA_COMPILER_VERSION", &cudaCompilerVersionNode },
    { "OBJC_COMPILER_VERSION", &objcCompilerVersionNode },
    { "OBJCXX_COMPILER_VERSION", &objcxxCompilerVersionNode },
    { "Fortran_COMPILER_VERSION", &fortranCompilerVersionNode },
    { "PLATFORM_ID", &platformIdNode },
    { "COMPILE_FEATURES", &compileFeaturesNode },
    { "CONFIGURATION", &configurationNode },
    { "CONFIG", &configurationTestNode },
    { "TARGET_FILE", &targetNodeGroup.File },
    { "TARGET_LINKER_FILE", &targetLinkerNodeGroup.File },
    { "TARGET_SONAME_FILE", &targetSoNameNodeGroup.File },
    { "TARGET_PDB_FILE", &targetPdbNodeGroup.File },
    { "TARGET_FILE_BASE_NAME", &targetFileBaseNameNode },
    { "TARGET_LINKER_FILE_BASE_NAME", &targetLinkerFileBaseNameNode },
    { "TARGET_PDB_FILE_BASE_NAME", &targetPdbFileBaseNameNode },
    { "TARGET_FILE_PREFIX", &targetFilePrefixNode },
    { "TARGET_LINKER_FILE_PREFIX", &targetLinkerFilePrefixNode },
    { "TARGET_FILE_SUFFIX", &targetFileSuffixNode },
    { "TARGET_LINKER_FILE_SUFFIX", &targetLinkerFileSuffixNode },
    { "TARGET_FILE_NAME", &targetNodeGroup.FileName },
    { "TARGET_LINKER_FILE_NAME", &targetLinkerNodeGroup.FileName },
    { "TARGET_SONAME_FILE_NAME", &targetSoNameNodeGroup.FileName },
    { "TARGET_PDB_FILE_NAME", &targetPdbNodeGroup.FileName },
    { "TARGET_FILE_DIR", &targetNodeGroup.FileDir },
    { "TARGET_LINKER_FILE_DIR", &targetLinkerNodeGroup.FileDir },
    { "TARGET_SONAME_FILE_DIR", &targetSoNameNodeGroup.FileDir },
    { "TARGET_PDB_FILE_DIR", &targetPdbNodeGroup.FileDir },
    { "TARGET_BUNDLE_DIR", &targetBundleDirNode },
    { "TARGET_BUNDLE_CONTENT_DIR", &targetBundleContentDirNode },
    { "STREQUAL", &strEqualNode },
    { "EQUAL", &equalNode },
    { "IN_LIST", &inListNode },
    { "FILTER", &filterNode },
    { "REMOVE_DUPLICATES", &removeDuplicatesNode },
    { "LOWER_CASE", &lowerCaseNode },
    { "UPPER_CASE", &upperCaseNode },
    { "MAKE_C_IDENTIFIER", &makeCIdentifierNode },
    { "BOOL", &boolNode },
    { "IF", &ifNode },
    { "ANGLE-R", &angle_rNode },
    { "COMMA", &commaNode },
    { "SEMICOLON", &semicolonNode },
    { "TARGET_PROPERTY", &targetPropertyNode },
    { "TARGET_NAME", &targetNameNode },
    { "TARGET_OBJECTS", &targetObjectsNode },
    { "TARGET_POLICY", &targetPolicyNode },
    { "TARGET_EXISTS", &targetExistsNode },
    { "TARGET_NAME_IF_EXISTS", &targetNameIfExistsNode },
    { "TARGET_GENEX_EVAL", &targetGenexEvalNode },
    { "GENEX_EVAL", &genexEvalNode },
    { "BUILD_INTERFACE", &buildInterfaceNode },
    { "INSTALL_INTERFACE", &installInterfaceNode },
    { "INSTALL_PREFIX", &installPrefixNode },
    { "JOIN", &joinNode },
    { "LINK_ONLY", &linkOnlyNode },
    { "COMPILE_LANG_AND_ID", &languageAndIdNode },
    { "COMPILE_LANGUAGE", &languageNode },
    { "LINK_LANG_AND_ID", &linkLanguageAndIdNode },
    { "LINK_LANGUAGE", &linkLanguageNode },
    { "HOST_LINK", &hostLinkNode },
    { "DEVICE_LINK", &deviceLinkNode },
    { "SHELL_PATH", &shellPathNode }
  };

  {
    auto itr = nodeMap.find(identifier);
    if (itr != nodeMap.end()) {
      return itr->second;
    }
  }
  return nullptr;
}

void reportError(cmGeneratorExpressionContext* context,
                 const std::string& expr, const std::string& result)
{
  context->HadError = true;
  if (context->Quiet) {
    return;
  }

  std::ostringstream e;
  /* clang-format off */
  e << "Error evaluating generator expression:\n"
    << "  " << expr << "\n"
    << result;
  /* clang-format on */
  context->LG->GetCMakeInstance()->IssueMessage(MessageType::FATAL_ERROR,
                                                e.str(), context->Backtrace);
}
