[vcpkg] Remove use of std::variant and std::visit to fix VS2015. (#12242)

Fixes #12220

Co-authored-by: Robert Schumacher <roschuma@microsoft.com>
This commit is contained in:
ras0219 2020-07-06 11:03:38 -07:00 committed by GitHub
parent c21893b4dc
commit e82e56f27f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 145 additions and 185 deletions

View File

@ -43,20 +43,7 @@ namespace vcpkg
std::string to_string() const;
void to_string(std::string& out) const;
constexpr StringView substr(size_t pos, size_t count = std::numeric_limits<size_t>::max()) const
{
if (pos > m_size)
{
return StringView();
}
if (count > m_size - pos)
{
return StringView(m_ptr + pos, m_size - pos);
}
return StringView(m_ptr + pos, count);
}
StringView substr(size_t pos, size_t count = std::numeric_limits<size_t>::max()) const;
constexpr char byte_at_index(size_t pos) const { return m_ptr[pos]; }

View File

@ -71,11 +71,26 @@ namespace vcpkg
return result.front();
}
StringView::StringView(const std::string& s) : m_ptr(s.data()), m_size(s.size()) { }
StringView::StringView(const std::string& s) : m_ptr(s.data()), m_size(s.size()) {}
std::string StringView::to_string() const { return std::string(m_ptr, m_size); }
void StringView::to_string(std::string& s) const { s.append(m_ptr, m_size); }
StringView StringView::substr(size_t pos, size_t count) const
{
if (pos > m_size)
{
return StringView();
}
if (count > m_size - pos)
{
return StringView(m_ptr + pos, m_size - pos);
}
return StringView(m_ptr + pos, count);
}
bool operator==(StringView lhs, StringView rhs) noexcept
{
return lhs.size() == rhs.size() && memcmp(lhs.data(), rhs.data(), lhs.size()) == 0;

View File

@ -3,10 +3,10 @@
#include <vcpkg/base/parse.h>
#include <vcpkg/base/strings.h>
#include <vcpkg/base/system.print.h>
#include <vcpkg/base/util.h>
#include <vcpkg/platform-expression.h>
#include <string>
#include <variant>
#include <vector>
namespace vcpkg::PlatformExpression
@ -61,68 +61,43 @@ namespace vcpkg::PlatformExpression
namespace detail
{
struct ExprIdentifier
enum class ExprKind
{
std::string identifier;
};
struct ExprNot
{
std::unique_ptr<ExprImpl> expr;
};
struct ExprAnd
{
std::vector<ExprImpl> exprs;
};
struct ExprOr
{
std::vector<ExprImpl> exprs;
identifier,
op_not,
op_and,
op_or
};
struct ExprImpl
{
std::variant<ExprIdentifier, ExprNot, ExprAnd, ExprOr> underlying;
explicit ExprImpl(ExprIdentifier e) : underlying(std::move(e)) { }
explicit ExprImpl(ExprNot e) : underlying(std::move(e)) { }
explicit ExprImpl(ExprAnd e) : underlying(std::move(e)) { }
explicit ExprImpl(ExprOr e) : underlying(std::move(e)) { }
ExprImpl clone() const
ExprImpl(ExprKind k, std::string i, std::vector<std::unique_ptr<ExprImpl>> es)
: kind(k), identifier(std::move(i)), exprs(std::move(es))
{
struct Visitor
{
ExprImpl operator()(const ExprIdentifier& e) { return ExprImpl(e); }
ExprImpl operator()(const ExprNot& e)
{
return ExprImpl(ExprNot{std::make_unique<ExprImpl>(e.expr->clone())});
}
ExprImpl operator()(const ExprAnd& e)
{
ExprAnd res;
for (const auto& expr : e.exprs)
{
res.exprs.push_back(expr.clone());
}
return ExprImpl(std::move(res));
}
ExprImpl operator()(const ExprOr& e)
{
ExprOr res;
for (const auto& expr : e.exprs)
{
res.exprs.push_back(expr.clone());
}
return ExprImpl(std::move(res));
}
};
return std::visit(Visitor{}, underlying);
}
ExprImpl(ExprKind k, std::string i) : kind(k), identifier(std::move(i)) {}
ExprImpl(ExprKind k, std::unique_ptr<ExprImpl> a) : kind(k) { exprs.push_back(std::move(a)); }
ExprImpl(ExprKind k, std::vector<std::unique_ptr<ExprImpl>> es) : kind(k), exprs(std::move(es)) {}
ExprKind kind;
std::string identifier;
std::vector<std::unique_ptr<ExprImpl>> exprs;
std::unique_ptr<ExprImpl> clone() const
{
return std::make_unique<ExprImpl>(
ExprImpl{kind, identifier, Util::fmap(exprs, [](auto&& p) { return p->clone(); })});
}
};
class ExpressionParser : public Parse::ParserBase
{
public:
ExpressionParser(StringView str, MultipleBinaryOperators multiple_binary_operators) : Parse::ParserBase(str, "CONTROL"), multiple_binary_operators(multiple_binary_operators) { }
ExpressionParser(StringView str, MultipleBinaryOperators multiple_binary_operators)
: Parse::ParserBase(str, "CONTROL"), multiple_binary_operators(multiple_binary_operators)
{
}
MultipleBinaryOperators multiple_binary_operators;
@ -142,7 +117,7 @@ namespace vcpkg::PlatformExpression
add_error("invalid logic expression, unexpected character");
}
return Expr(std::make_unique<ExprImpl>(std::move(res)));
return Expr(std::move(res));
}
private:
@ -153,16 +128,13 @@ namespace vcpkg::PlatformExpression
// <platform-expression.not>
// <platform-expression.or> | <platform-expression.not>
static bool is_identifier_char(char32_t ch)
{
return is_lower_alpha(ch) || is_ascii_digit(ch);
}
static bool is_identifier_char(char32_t ch) { return is_lower_alpha(ch) || is_ascii_digit(ch); }
// <platform-expression>:
// <platform-expression.not>
// <platform-expression.and>
// <platform-expression.or>
ExprImpl expr()
std::unique_ptr<ExprImpl> expr()
{
auto result = expr_not();
@ -170,15 +142,11 @@ namespace vcpkg::PlatformExpression
{
case '|':
{
ExprOr e;
e.exprs.push_back(std::move(result));
return expr_binary<'|', '&'>(std::move(e));
return expr_binary<'|', '&'>(std::make_unique<ExprImpl>(ExprKind::op_or, std::move(result)));
}
case '&':
{
ExprAnd e;
e.exprs.push_back(std::move(result));
return expr_binary<'&', '|'>(std::move(e));
return expr_binary<'&', '|'>(std::make_unique<ExprImpl>(ExprKind::op_and, std::move(result)));
}
default: return result;
}
@ -187,7 +155,7 @@ namespace vcpkg::PlatformExpression
// <platform-expression.simple>:
// ( <platform-expression> )
// <platform-expression.identifier>
ExprImpl expr_simple()
std::unique_ptr<ExprImpl> expr_simple()
{
if (cur() == '(')
{
@ -209,7 +177,7 @@ namespace vcpkg::PlatformExpression
// <platform-expression.identifier>:
// A lowercase alpha-numeric string
ExprImpl expr_identifier()
std::unique_ptr<ExprImpl> expr_identifier()
{
std::string name = match_zero_or_more(is_identifier_char).to_string();
@ -219,26 +187,26 @@ namespace vcpkg::PlatformExpression
}
skip_whitespace();
return ExprImpl{ExprIdentifier{name}};
return std::make_unique<ExprImpl>(ExprKind::identifier, std::move(name));
}
// <platform-expression.not>:
// <platform-expression.simple>
// ! <platform-expression.simple>
ExprImpl expr_not()
std::unique_ptr<ExprImpl> expr_not()
{
if (cur() == '!')
{
next();
skip_whitespace();
return ExprImpl(ExprNot{std::make_unique<ExprImpl>(expr_simple())});
return std::make_unique<ExprImpl>(ExprKind::op_not, expr_simple());
}
return expr_simple();
}
template<char oper, char other, class ExprKind>
ExprImpl expr_binary(ExprKind&& seed)
template<char oper, char other>
std::unique_ptr<ExprImpl> expr_binary(std::unique_ptr<ExprImpl>&& seed)
{
do
{
@ -249,7 +217,7 @@ namespace vcpkg::PlatformExpression
} while (allow_multiple_binary_operators() && cur() == oper);
skip_whitespace();
seed.exprs.push_back(expr_not());
seed->exprs.push_back(expr_not());
} while (cur() == oper);
if (cur() == other)
@ -258,7 +226,7 @@ namespace vcpkg::PlatformExpression
}
skip_whitespace();
return ExprImpl(std::move(seed));
return std::move(seed);
}
};
}
@ -273,21 +241,14 @@ namespace vcpkg::PlatformExpression
{
if (other.underlying_)
{
underlying_ = std::make_unique<ExprImpl>(other.underlying_->clone());
this->underlying_ = other.underlying_->clone();
}
}
Expr& Expr::operator=(const Expr& other)
{
if (other.underlying_)
{
if (this->underlying_)
{
*this->underlying_ = other.underlying_->clone();
}
else
{
this->underlying_ = std::make_unique<ExprImpl>(other.underlying_->clone());
}
this->underlying_ = other.underlying_->clone();
}
else
{
@ -297,36 +258,28 @@ namespace vcpkg::PlatformExpression
return *this;
}
Expr::Expr(std::unique_ptr<ExprImpl>&& e) : underlying_(std::move(e)) { }
Expr::Expr(std::unique_ptr<ExprImpl>&& e) : underlying_(std::move(e)) {}
Expr::~Expr() = default;
Expr Expr::Identifier(StringView id)
{
return Expr(std::make_unique<ExprImpl>(ExprImpl{ExprIdentifier{id.to_string()}}));
return Expr(std::make_unique<ExprImpl>(ExprKind::identifier, id.to_string()));
}
Expr Expr::Not(Expr&& e) { return Expr(std::make_unique<ExprImpl>(ExprImpl{ExprNot{std::move(e.underlying_)}})); }
Expr Expr::Not(Expr&& e) { return Expr(std::make_unique<ExprImpl>(ExprKind::op_not, std::move(e.underlying_))); }
Expr Expr::And(std::vector<Expr>&& exprs)
{
std::vector<ExprImpl> impls;
for (auto& e : exprs)
{
impls.push_back(std::move(*e.underlying_));
}
return Expr(std::make_unique<ExprImpl>(ExprAnd{std::move(impls)}));
return Expr(std::make_unique<ExprImpl>(
ExprKind::op_and, Util::fmap(exprs, [](Expr& expr) { return std::move(expr.underlying_); })));
}
Expr Expr::Or(std::vector<Expr>&& exprs)
{
std::vector<ExprImpl> impls;
for (auto& e : exprs)
{
impls.push_back(std::move(*e.underlying_));
}
return Expr(std::make_unique<ExprImpl>(ExprOr{std::move(impls)}));
return Expr(std::make_unique<ExprImpl>(
ExprKind::op_or, Util::fmap(exprs, [](Expr& expr) { return std::move(expr.underlying_); })));
}
bool Expr::evaluate(const Context& context) const
{
if (!underlying_)
if (!this->underlying_)
{
return true; // empty expression is always true
}
@ -369,89 +322,96 @@ namespace vcpkg::PlatformExpression
return iter->second == value;
}
bool visit(const ExprImpl& e) const { return std::visit(*this, e.underlying); }
bool operator()(const ExprIdentifier& expr) const
bool visit(const ExprImpl& expr) const
{
if (!override_ctxt.empty())
if (expr.kind == ExprKind::identifier)
{
auto override_id = override_ctxt.find(expr.identifier);
if (override_id != override_ctxt.end())
if (!override_ctxt.empty())
{
return override_id->second;
auto override_id = override_ctxt.find(expr.identifier);
if (override_id != override_ctxt.end())
{
return override_id->second;
}
// Fall through to use the cmake logic if the id does not have an override
}
// Fall through to use the cmake logic if the id does not have an override
}
auto id = string2identifier(expr.identifier);
switch (id)
auto id = string2identifier(expr.identifier);
switch (id)
{
case Identifier::invalid:
// Point out in the diagnostic that they should add to the override list because that is
// what most users should do, however it is also valid to update the built in identifiers to
// recognize the name.
System::printf(
System::Color::error,
"Error: Unrecognized identifer name %s. Add to override list in triplet file.\n",
expr.identifier);
return false;
case Identifier::x64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x64");
case Identifier::x86: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x86");
case Identifier::arm:
// For backwards compatability arm is also true for arm64.
// This is because it previously was only checking for a substring.
return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm") ||
true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
case Identifier::arm64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
case Identifier::windows:
return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "") ||
true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
case Identifier::linux: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Linux");
case Identifier::osx: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Darwin");
case Identifier::uwp:
return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
case Identifier::android: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Android");
case Identifier::emscripten:
return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Emscripten");
case Identifier::wasm32: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "wasm32");
case Identifier::static_link:
return true_if_exists_and_equal("VCPKG_LIBRARY_LINKAGE", "static");
default:
Checks::exit_with_message(
VCPKG_LINE_INFO,
"vcpkg bug: string2identifier returned a value that we don't recognize: %d\n",
static_cast<int>(id));
}
}
else if (expr.kind == ExprKind::op_not)
{
case Identifier::invalid:
// Point out in the diagnostic that they should add to the override list because that is what
// most users should do, however it is also valid to update the built in identifiers to
// recognize the name.
System::printf(System::Color::error,
"Error: Unrecognized identifer name %s. Add to override list in triplet file.\n",
expr.identifier);
return false;
case Identifier::x64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x64");
case Identifier::x86: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "x86");
case Identifier::arm:
// For backwards compatability arm is also true for arm64.
// This is because it previously was only checking for a substring.
return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm") ||
true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
case Identifier::arm64: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "arm64");
case Identifier::windows:
return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "") ||
true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
case Identifier::linux: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Linux");
case Identifier::osx: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Darwin");
case Identifier::uwp: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "WindowsStore");
case Identifier::android: return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Android");
case Identifier::emscripten:
return true_if_exists_and_equal("VCPKG_CMAKE_SYSTEM_NAME", "Emscripten");
case Identifier::wasm32: return true_if_exists_and_equal("VCPKG_TARGET_ARCHITECTURE", "wasm32");
case Identifier::static_link: return true_if_exists_and_equal("VCPKG_LIBRARY_LINKAGE", "static");
default:
Checks::exit_with_message(
VCPKG_LINE_INFO,
"vcpkg bug: string2identifier returned a value that we don't recognize: %d\n",
static_cast<int>(id));
return !visit(*expr.exprs.at(0));
}
}
bool operator()(const ExprNot& expr) const {
bool res = visit(*expr.expr);
return !res;
}
bool operator()(const ExprAnd& expr) const
{
bool valid = true;
// we want to print errors in all expressions, so we check all of the expressions all the time
for (const auto& e : expr.exprs)
else if (expr.kind == ExprKind::op_and)
{
valid &= visit(e);
bool valid = true;
// we want to print errors in all expressions, so we check all of the expressions all the time
for (const auto& e : expr.exprs)
{
valid &= visit(*e);
}
return valid;
}
return valid;
}
bool operator()(const ExprOr& expr) const
{
bool valid = false;
// we want to print errors in all expressions, so we check all of the expressions all the time
for (const auto& e : expr.exprs)
else if (expr.kind == ExprKind::op_or)
{
valid |= visit(e);
bool valid = false;
// we want to print errors in all expressions, so we check all of the expressions all the time
for (const auto& e : expr.exprs)
{
valid |= visit(*e);
}
return valid;
}
else
{
Checks::unreachable(VCPKG_LINE_INFO);
}
return valid;
}
};
return Visitor{context, override_ctxt}.visit(*underlying_);
return Visitor{context, override_ctxt}.visit(*this->underlying_);
}
ExpectedS<Expr> parse_platform_expression(StringView expression, MultipleBinaryOperators multiple_binary_operators)

View File

@ -578,7 +578,7 @@ namespace vcpkg
void VcpkgCmdArguments::append_common_options(HelpTableFormatter& table)
{
constexpr static auto opt = [](StringView arg, StringView joiner, StringView value) {
static auto opt = [](StringView arg, StringView joiner, StringView value) {
return Strings::format("--%s%s%s", arg, joiner, value);
};
@ -683,9 +683,7 @@ namespace vcpkg
{
StringView flag;
bool enabled;
} flags[] = {
{BINARY_CACHING_FEATURE, binary_caching_enabled()}
};
} flags[] = {{BINARY_CACHING_FEATURE, binary_caching_enabled()}};
for (const auto& flag : flags)
{