Refix MSVC Debug crash

This commit is contained in:
a3d4 2022-04-21 01:44:25 +02:00
parent 559174054f
commit 048b253a93
2 changed files with 31 additions and 25 deletions

View File

@ -56,6 +56,17 @@ struct VisitorFallback<R> { template<typename T> R operator()(T&&) const { retur
template<> template<>
struct VisitorFallback<> { template<typename T> void operator()(T&&) const {} }; struct VisitorFallback<> { template<typename T> void operator()(T&&) const {} };
template <typename... Visitors> struct GenericVisitor: Visitors... { using Visitors::operator()...; }; // MSVC. Empty base class optimization does not happen in some scenarios.
// Enforcing it with __declspec(empty_bases) avoids MSVC Debug test crash
// (Run-Time Check Failure #2 - Stack around the variable '....' was corrupted).
// See https://docs.microsoft.com/en-us/cpp/cpp/empty-bases,
// https://developercommunity.visualstudio.com/t/10005513.
#if defined(_MSC_VER)
#define SOLC_EMPTY_BASES __declspec(empty_bases)
#else
#define SOLC_EMPTY_BASES
#endif
template <typename... Visitors> struct SOLC_EMPTY_BASES GenericVisitor: Visitors... { using Visitors::operator()...; };
template <typename... Visitors> GenericVisitor(Visitors...) -> GenericVisitor<Visitors...>; template <typename... Visitors> GenericVisitor(Visitors...) -> GenericVisitor<Visitors...>;
} }

View File

@ -93,31 +93,26 @@ void StructuralSimplifier::operator()(Block& _block)
void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements) void StructuralSimplifier::simplify(std::vector<yul::Statement>& _statements)
{ {
// Explicit local variables ifLambda, switchLambda, forLoopLambda are created to avoid MSVC C++17 Debug test crash util::GenericVisitor visitor{
// (Run-Time Check Failure #2 - Stack around the variable '....' was corrupted). util::VisitorFallback<OptionalStatements>{},
// As soon as the issue is fixed, this workaround can be removed. [&](If& _ifStmt) -> OptionalStatements {
auto ifLambda = [&](If& _ifStmt) -> OptionalStatements if (expressionAlwaysTrue(*_ifStmt.condition))
{ return {std::move(_ifStmt.body.statements)};
if (expressionAlwaysTrue(*_ifStmt.condition)) else if (expressionAlwaysFalse(*_ifStmt.condition))
return {std::move(_ifStmt.body.statements)}; return {vector<Statement>{}};
else if (expressionAlwaysFalse(*_ifStmt.condition)) return {};
return {vector<Statement>{}}; },
return {}; [&](Switch& _switchStmt) -> OptionalStatements {
if (std::optional<u256> const constExprVal = hasLiteralValue(*_switchStmt.expression))
return replaceConstArgSwitch(_switchStmt, constExprVal.value());
return {};
},
[&](ForLoop& _forLoop) -> OptionalStatements {
if (expressionAlwaysFalse(*_forLoop.condition))
return {std::move(_forLoop.pre.statements)};
return {};
}
}; };
auto switchLambda = [&](Switch& _switchStmt) -> OptionalStatements
{
if (std::optional<u256> const constExprVal = hasLiteralValue(*_switchStmt.expression))
return replaceConstArgSwitch(_switchStmt, constExprVal.value());
return {};
};
auto forLoopLambda = [&](ForLoop& _forLoop) -> OptionalStatements
{
if (expressionAlwaysFalse(*_forLoop.condition))
return {std::move(_forLoop.pre.statements)};
return {};
};
util::GenericVisitor visitor{util::VisitorFallback<OptionalStatements>{}, ifLambda, switchLambda, forLoopLambda};
util::iterateReplacing( util::iterateReplacing(
_statements, _statements,