[Assembler] Revert uses of std::bad_variant_access for backwards compatability
MODIFY
src/assembler/assembler.h
src/assembler/assembler.h
@@ -22,11 +22,9 @@ namespace Assembler {
*/
#define runPass(resName, resType, passFunction, ...) \
auto passFunction##_res = passFunction(__VA_ARGS__); \
- try { \
- auto& errors = std::get<Errors>(passFunction##_res); \
- result.errors.insert(result.errors.end(), errors.begin(), errors.end()); \
+ if (auto* errors = std::get_if<Errors>(&passFunction##_res)) { \
+ result.errors.insert(result.errors.end(), errors->begin(), errors->end()); \
return result; \
- } catch (const std::bad_variant_access&) { \
} \
auto resName = std::get<resType>(passFunction##_res);
@@ -37,10 +35,9 @@ namespace Assembler {
*/
#define runOperation(resName, resType, operationFunction, ...) \
auto operationFunction##_res = operationFunction(__VA_ARGS__); \
- try { \
- errors.push_back(std::get<Error>(operationFunction##_res)); \
+ if (auto* error = std::get_if<Error>(&operationFunction##_res)) { \
+ errors.push_back(*error); \
continue; \
- } catch (const std::bad_variant_access&) { \
} \
auto resName = std::get<resType>(operationFunction##_res);
@@ -96,11 +93,9 @@ protected:
auto tokens = line.split(splitter);
tokens.removeAll(QStringLiteral(""));
auto joinedtokens = joinParentheses(tokens);
- try {
- auto err = std::get<Error>(joinedtokens);
- err.first = sourceLine;
- return err;
- } catch (const std::bad_variant_access&) {
+ if (auto* err = std::get_if<Error>(&joinedtokens)) {
+ err->first = sourceLine;
+ return *err;
}
return std::get<LineTokens>(joinedtokens);
}
@@ -287,20 +282,18 @@ public:
std::pair<QString, std::optional<Error>> disassemble(const uint32_t word, const ReverseSymbolMap& symbols,
const uint32_t baseAddress = 0) const override {
auto match = m_matcher->matchInstruction(word);
- try {
- auto& error = std::get<Error>(match);
- return {"unknown instruction", error};
- } catch (const std::bad_variant_access&) {
+ if (auto* error = std::get_if<Error>(&match)) {
+ return {"unknown instruction", *error};
+ }
+
// Got match, disassemble
auto tokens = std::get<const Instruction*>(match)->disassemble(word, baseAddress, symbols);
- try {
- auto& error = std::get<Error>(match);
+ if (auto* error = std::get_if<Error>(&match)) {
// Error during disassembling
- return {"invalid instruction", error};
- } catch (const std::bad_variant_access&) {
- return {std::get<LineTokens>(tokens).join(' '), {}};
- }
+ return {"invalid instruction", *error};
}
+
+ return {std::get<LineTokens>(tokens).join(' '), {}};
}
const Matcher& getMatcher() { return *m_matcher; }
@@ -519,12 +512,10 @@ protected:
// No recorded symbol for the token; our last option is to try and evaluate a possible
// expression.
auto evaluate_res = evaluate(symbol, &symbolMap);
- try {
- auto err = std::get<Error>(evaluate_res);
- err.first = linkRequest.sourceLine;
- errors.push_back(err);
+ if (auto* err = std::get_if<Error>(&evaluate_res)) {
+ err->first = linkRequest.sourceLine;
+ errors.push_back(*err);
continue;
- } catch (const std::bad_variant_access&) {
}
// Expression evaluated successfully
symbolValue = std::get<long>(evaluate_res);
@@ -570,16 +561,15 @@ protected:
return PseudoExpandRes(std::nullopt);
}
auto res = m_pseudoInstructionMap.at(opcode)->expand(line);
- try {
- auto& error = std::get<Error>(res);
+ if (auto* error = std::get_if<Error>(&res)) {
if (m_instructionMap.count(opcode) != 0) {
// If this pseudo-instruction aliases with an instruction but threw an error (could arise if ie.
// arguments provided were intended for the normal instruction and not the pseudoinstruction), then
// return as if not a pseudo-instruction, falling to normal instruction handling
return PseudoExpandRes(std::nullopt);
}
- } catch (const std::bad_variant_access&) {
}
+
// Return result (containing either a valid pseudo-instruction expand error or the expanded pseudo
// instruction
return {res};

MODIFY
src/assembler/expreval.cpp
src/assembler/expreval.cpp
@@ -13,13 +13,8 @@ const QRegularExpression s_exprOperatorsRegex = QRegularExpression(R"((\+|\-|\/|
const QString s_exprOperators QStringLiteral("+-*/%");
const QString s_exprTokens QStringLiteral("()+-*/%");
-#define IfExpr(TExpr, boundVar) \
- try { \
- auto boundVar = std::get<TExpr>(*expr);
-#define FiExpr \
- } \
- catch (const std::bad_variant_access&) { \
- }
+#define IfExpr(TExpr, boundVar) if (auto* boundVar = std::get_if<TExpr>(expr.get())) {
+#define FiExpr }
struct Expr;
@@ -85,7 +80,7 @@ struct Expr : std::variant<Literal, Add, Mul, Div, Sub, Mod, And, Or> {
friend std::ostream& operator<<(std::ostream& os, const std::shared_ptr<Expr>& expr) {
#define tryPrint(type) \
IfExpr(type, v) { \
- v.print(os); \
+ v->print(os); \
return os; \
} \
FiExpr;
@@ -134,9 +129,8 @@ ExprRes parseRight(const QString& s, int& pos, int& depth);
template <typename BinOp>
ExprRes rightRec(std::shared_ptr<Expr> lhs, const QString& s, int& pos, int& depth) {
auto rhs = parseRight(s, pos, depth);
- try {
- return {std::get<Error>(rhs)};
- } catch (std::bad_variant_access&) {
+ if (auto* err = std::get_if<Error>(&rhs)) {
+ return {*err};
}
return {std::make_shared<Expr>(BinOp{lhs, std::get<std::shared_ptr<Expr>>(rhs)})};
}
@@ -169,10 +163,10 @@ ExprRes parseRight(const QString& s, int& pos, int& depth) {
ExprRes parseLeft(const QString& s, int& pos, int& depth) {
auto left = parseRight(s, pos, depth);
- try {
- return {std::get<Error>(left)};
- } catch (std::bad_variant_access&) {
+ if (auto* err = std::get_if<Error>(&left)) {
+ return {*err};
}
+
auto& res = std::get<std::shared_ptr<Expr>>(left);
if (pos < s.length()) {
auto& ch = s.at(pos);
@@ -198,28 +192,28 @@ ExprRes parseLeft(const QString& s, int& pos, int& depth) {
long evaluate(const std::shared_ptr<Expr>& expr, const SymbolMap* variables) {
// There is a bug in GCC for variant visitors on incomplete variant types (recursive), So instead we'll macro
// our way towards something that looks like a pattern match for the variant type.
- IfExpr(Add, v) { return evaluate(v.lhs, variables) + evaluate(v.rhs, variables); }
+ IfExpr(Add, v) { return evaluate(v->lhs, variables) + evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(Div, v) { return evaluate(v.lhs, variables) / evaluate(v.rhs, variables); }
+ IfExpr(Div, v) { return evaluate(v->lhs, variables) / evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(Mul, v) { return evaluate(v.lhs, variables) * evaluate(v.rhs, variables); }
+ IfExpr(Mul, v) { return evaluate(v->lhs, variables) * evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(Sub, v) { return evaluate(v.lhs, variables) - evaluate(v.rhs, variables); }
+ IfExpr(Sub, v) { return evaluate(v->lhs, variables) - evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(Mod, v) { return evaluate(v.lhs, variables) % evaluate(v.rhs, variables); }
+ IfExpr(Mod, v) { return evaluate(v->lhs, variables) % evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(And, v) { return evaluate(v.lhs, variables) & evaluate(v.rhs, variables); }
+ IfExpr(And, v) { return evaluate(v->lhs, variables) & evaluate(v->rhs, variables); }
FiExpr;
- IfExpr(Or, v) { return evaluate(v.lhs, variables) | evaluate(v.rhs, variables); }
+ IfExpr(Or, v) { return evaluate(v->lhs, variables) | evaluate(v->rhs, variables); }
FiExpr;
IfExpr(Literal, v) {
bool canConvert;
- auto value = getImmediate(v.v, canConvert);
+ auto value = getImmediate(v->v, canConvert);
if (!canConvert) {
- if (variables != nullptr && variables->count(v.v) != 0) {
- value = variables->at(v.v);
+ if (variables != nullptr && variables->count(v->v) != 0) {
+ value = variables->at(v->v);
} else {
- throw std::runtime_error(QString("Unknown symbol '%1'").arg(v.v).toStdString());
+ throw std::runtime_error(QString("Unknown symbol '%1'").arg(v->v).toStdString());
}
}
return value;
@@ -235,9 +229,8 @@ std::variant<Error, long> evaluate(const QString& s, const SymbolMap* variables)
int pos = 0;
int depth = 0;
auto exprTree = parseLeft(sNoWhitespace, pos, depth);
- try {
- return std::get<Error>(exprTree);
- } catch (std::bad_variant_access&) {
+ if (auto* err = std::get_if<Error>(&exprTree)) {
+ return *err;
}
const auto exprTreeRes = std::get<std::shared_ptr<Expr>>(exprTree);
try {

MODIFY
test/tst_assembler.cpp
test/tst_assembler.cpp
@@ -210,11 +210,10 @@ void tst_Assembler::tst_matcher() {
for (const auto& iter : toMatch) {
auto match = assembler.getMatcher().matchInstruction(iter.second);
- try {
- auto& error = std::get<Error>(match);
- QFAIL(error.second.toStdString().c_str());
- } catch (const std::bad_variant_access&) {
+ if (auto* error = std::get_if<Error>(&match)) {
+ QFAIL(error->second.toStdString().c_str());
}
+
auto matchInstr = std::get<const Instruction*>(match);
if (matchInstr->name() != iter.first) {
QString error =
@@ -223,11 +222,10 @@ void tst_Assembler::tst_matcher() {
}
auto disRes = matchInstr->disassemble(iter.second, 0, {});
- try {
- auto& error = std::get<Error>(disRes);
- QFAIL(error.second.toStdString().c_str());
- } catch (const std::bad_variant_access&) {
+ if (auto* error = std::get_if<Error>(&disRes)) {
+ QFAIL(error->second.toStdString().c_str());
}
+
auto disassembled = std::get<LineTokens>(disRes);
qDebug() << QString::number(iter.second, 2) << " = " << disassembled;

MODIFY
test/tst_expreval.cpp
test/tst_expreval.cpp
@@ -12,10 +12,8 @@ private slots:
};
void expect(std::variant<Error, long> res, long expected) {
- try {
- std::get<Error>(res);
+ if (auto* err = std::get_if<Error>(&res)) {
QFAIL("Got error");
- } catch (std::bad_variant_access&) {
}
QCOMPARE(std::get<long>(res), expected);
}

[Assembler] Revert uses of std::bad_variant_access for backwards compatability