diff --git a/src/parser/cxx/ast_interpreter.cc b/src/parser/cxx/ast_interpreter.cc index 73fee467..34fdae59 100644 --- a/src/parser/cxx/ast_interpreter.cc +++ b/src/parser/cxx/ast_interpreter.cc @@ -32,6 +32,20 @@ namespace cxx { +namespace { + +template +struct ArithmeticCast { + auto operator()(const StringLiteral*) const -> T { + cxx_runtime_error("invalid artihmetic cast"); + return T{}; + } + + auto operator()(auto value) const -> T { return static_cast(value); } +}; + +} // namespace + struct ASTInterpreter::UnitResult {}; struct ASTInterpreter::DeclarationResult {}; @@ -275,6 +289,238 @@ struct ASTInterpreter::ExpressionVisitor { return accept(ast); } + [[nodiscard]] auto toBool(const ConstValue& value) -> bool { + return accept.toBool(value).value_or(false); + } + + [[nodiscard]] auto toInt(const ConstValue& value) -> std::intmax_t { + return accept.toInt(value).value_or(0); + } + + [[nodiscard]] auto toUInt(const ConstValue& value) -> std::uintmax_t { + return accept.toUInt(value).value_or(0); + } + + [[nodiscard]] auto toFloat(const ConstValue& value) -> float { + return accept.toFloat(value).value_or(0.0f); + } + + [[nodiscard]] auto toDouble(const ConstValue& value) -> double { + return accept.toDouble(value).value_or(0.0); + } + + auto star_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) { + return toDouble(*left) * toDouble(*right); + } + + if (control()->is_unsigned(ast->type)) { + return toUInt(*left) * toUInt(*right); + } + + return toInt(*left) * toInt(*right); + } + + auto slash_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) { + auto l = toDouble(*left); + auto r = toDouble(*right); + if (r == 0.0) return std::nullopt; + return l / r; + } + + if (control()->is_unsigned(ast->type)) { + auto l = toUInt(*left); + auto r = toUInt(*right); + if (r == 0) return std::nullopt; + return l / r; + } + + auto l = toInt(*left); + auto r = toInt(*right); + if (r == 0) return std::nullopt; + return l / r; + } + + auto percent_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_unsigned(ast->type)) { + auto l = toUInt(*left); + auto r = toUInt(*right); + if (r == 0) return std::nullopt; + return l % r; + } + + auto l = toInt(*left); + auto r = toInt(*right); + if (r == 0) return std::nullopt; + return l % r; + } + + auto plus_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) { + return toDouble(*left) + toDouble(*right); + } + + if (control()->is_unsigned(ast->type)) { + return toUInt(*left) + toUInt(*right); + } + + return toInt(*left) + toInt(*right); + } + + auto minus_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) { + return toDouble(*left) - toDouble(*right); + } + + if (control()->is_unsigned(ast->type)) { + return toUInt(*left) - toUInt(*right); + } + + return toInt(*left) - toInt(*right); + } + + auto less_less_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_unsigned(ast->type)) { + return toUInt(*left) << toUInt(*right); + } + + return toInt(*left) << toInt(*right); + } + + auto greater_greater_op(BinaryExpressionAST* ast, + const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_unsigned(ast->type)) { + return toUInt(*left) >> toUInt(*right); + } + + return toInt(*left) >> toInt(*right); + } + + auto less_equal_greater_op(BinaryExpressionAST* ast, + const ExpressionResult& left, + const ExpressionResult& right) + -> ExpressionResult { + auto convert = [](std::partial_ordering cmp) -> int { + if (cmp < 0) return -1; + if (cmp > 0) return 1; + return 0; + }; + + if (control()->is_floating_point(ast->type)) + return convert(toDouble(*left) <=> toDouble(*right)); + + if (control()->is_unsigned(ast->type)) + return convert(toUInt(*left) <=> toUInt(*right)); + + return convert(toInt(*left) <=> toInt(*right)); + } + + auto less_equal_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) <= toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) <= toUInt(*right); + + return toInt(*left) <= toInt(*right); + } + + auto greater_equal_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) >= toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) >= toUInt(*right); + + else + return toInt(*left) >= toInt(*right); + } + + auto less_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) < toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) < toUInt(*right); + + return toInt(*left) < toInt(*right); + } + + auto greater_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) > toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) > toUInt(*right); + + return toInt(*left) > toInt(*right); + } + + auto equal_equal_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) == toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) == toUInt(*right); + + return toInt(*left) == toInt(*right); + } + + auto exclaim_equal_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + if (control()->is_floating_point(ast->type)) + return toDouble(*left) != toDouble(*right); + + if (control()->is_unsigned(ast->type)) + return toUInt(*left) != toUInt(*right); + + return toInt(*left) != toInt(*right); + } + + auto amp_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + return toInt(*left) & toInt(*right); + } + + auto caret_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + return toInt(*left) ^ toInt(*right); + } + + auto bar_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + return toInt(*left) | toInt(*right); + } + + auto amp_amp_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + return toBool(*left) && toBool(*right); + } + + auto bar_bar_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + return toBool(*left) || toBool(*right); + } + + auto comma_op(BinaryExpressionAST* ast, const ExpressionResult& left, + const ExpressionResult& right) -> ExpressionResult { + // Comma operator returns the right operand + return right; + } + [[nodiscard]] auto operator()(GeneratedLiteralExpressionAST* ast) -> ExpressionResult; @@ -1621,7 +1867,7 @@ auto ASTInterpreter::ExpressionVisitor::operator()( auto ASTInterpreter::ExpressionVisitor::operator()( NullptrLiteralExpressionAST* ast) -> ExpressionResult { - return ConstValue(std::uint64_t(0)); + return ConstValue(std::uintmax_t(0)); } auto ASTInterpreter::ExpressionVisitor::operator()( @@ -1933,7 +2179,7 @@ auto ASTInterpreter::ExpressionVisitor::operator()(SizeofExpressionAST* ast) if (!control()->memoryLayout()) return std::nullopt; auto size = control()->memoryLayout()->sizeOf(ast->expression->type); if (!size.has_value()) return std::nullopt; - return std::uint64_t(*size); + return std::uintmax_t(*size); } auto ASTInterpreter::ExpressionVisitor::operator()(SizeofTypeExpressionAST* ast) @@ -1942,7 +2188,7 @@ auto ASTInterpreter::ExpressionVisitor::operator()(SizeofTypeExpressionAST* ast) if (!control()->memoryLayout()) return std::nullopt; auto size = control()->memoryLayout()->sizeOf(ast->typeId->type); if (!size.has_value()) return std::nullopt; - return std::uint64_t(*size); + return std::uintmax_t(*size); } auto ASTInterpreter::ExpressionVisitor::operator()(SizeofPackExpressionAST* ast) @@ -1956,7 +2202,7 @@ auto ASTInterpreter::ExpressionVisitor::operator()( if (!control()->memoryLayout()) return std::nullopt; auto size = control()->memoryLayout()->alignmentOf(ast->typeId->type); if (!size.has_value()) return std::nullopt; - return std::uint64_t(*size); + return std::uintmax_t(*size); } auto ASTInterpreter::ExpressionVisitor::operator()(AlignofExpressionAST* ast) @@ -1967,7 +2213,7 @@ auto ASTInterpreter::ExpressionVisitor::operator()(AlignofExpressionAST* ast) if (!control()->memoryLayout()) return std::nullopt; auto size = control()->memoryLayout()->alignmentOf(ast->expression->type); if (!size.has_value()) return std::nullopt; - return std::uint64_t(*size); + return std::uintmax_t(*size); } auto ASTInterpreter::ExpressionVisitor::operator()(NoexceptExpressionAST* ast) @@ -2014,22 +2260,43 @@ auto ASTInterpreter::ExpressionVisitor::operator()( if (!value.has_value()) return std::nullopt; switch (ast->type->kind()) { - case TypeKind::kBool: - if (std::get_if(&*value)) return ConstValue(true); - return std::visit(ArithmeticConversion{}, *value); - case TypeKind::kFloat: - return std::visit(ArithmeticConversion{}, *value); - case TypeKind::kDouble: - return std::visit(ArithmeticConversion{}, *value); - case TypeKind::kLongDouble: - return std::visit(ArithmeticConversion{}, *value); + case TypeKind::kBool: { + auto result = accept.toBool(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); + } + + case TypeKind::kFloat: { + auto result = accept.toFloat(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); + } + + case TypeKind::kDouble: { + auto result = accept.toDouble(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); + } + + case TypeKind::kLongDouble: { + auto result = accept.toLongDouble(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); + } + default: if (control()->is_integral_or_unscoped_enum(ast->type)) { - if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *value); - else - return std::visit(ArithmeticCast{}, *value); + if (control()->is_unsigned(ast->type)) { + auto result = accept.toUInt(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); + } + + auto result = accept.toInt(*value); + if (!result.has_value()) return std::nullopt; + return result.value(); } + return value; } // switch @@ -2054,195 +2321,64 @@ auto ASTInterpreter::ExpressionVisitor::operator()(BinaryExpressionAST* ast) break; case TokenKind::T_STAR: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) * - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) * - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) * - std::visit(ArithmeticCast{}, *right); - - case TokenKind::T_SLASH: { - if (control()->is_floating_point(ast->type)) { - auto l = std::visit(ArithmeticCast{}, *left); - auto r = std::visit(ArithmeticCast{}, *right); - if (r == 0.0) return std::nullopt; - return l / r; - } - - if (control()->is_unsigned(ast->type)) { - auto l = std::visit(ArithmeticCast{}, *left); - auto r = std::visit(ArithmeticCast{}, *right); - if (r == 0) return std::nullopt; - return l / r; - } + return star_op(ast, left, right); - auto l = std::visit(ArithmeticCast{}, *left); - auto r = std::visit(ArithmeticCast{}, *right); - if (r == 0) return std::nullopt; - return l / r; - } + case TokenKind::T_SLASH: + return slash_op(ast, left, right); - case TokenKind::T_PERCENT: { - if (control()->is_unsigned(ast->type)) { - auto l = std::visit(ArithmeticCast{}, *left); - auto r = std::visit(ArithmeticCast{}, *right); - if (r == 0) return std::nullopt; - return l % r; - } - - auto l = std::visit(ArithmeticCast{}, *left); - auto r = std::visit(ArithmeticCast{}, *right); - if (r == 0) return std::nullopt; - return l % r; - } + case TokenKind::T_PERCENT: + return percent_op(ast, left, right); case TokenKind::T_PLUS: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) + - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) + - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) + - std::visit(ArithmeticCast{}, *right); + return plus_op(ast, left, right); case TokenKind::T_MINUS: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) - - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) - - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) - - std::visit(ArithmeticCast{}, *right); + return minus_op(ast, left, right); case TokenKind::T_LESS_LESS: - if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) - << std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) - << std::visit(ArithmeticCast{}, *right); + return less_less_op(ast, left, right); case TokenKind::T_GREATER_GREATER: - if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) >> - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) >> - std::visit(ArithmeticCast{}, *right); - - case TokenKind::T_LESS_EQUAL_GREATER: { - auto convert = [](std::partial_ordering cmp) -> int { - if (cmp < 0) return -1; - if (cmp > 0) return 1; - return 0; - }; - - if (control()->is_floating_point(ast->type)) - return convert(std::visit(ArithmeticCast{}, *left) <=> - std::visit(ArithmeticCast{}, *right)); - else if (control()->is_unsigned(ast->type)) - return convert(std::visit(ArithmeticCast{}, *left) <=> - std::visit(ArithmeticCast{}, *right)); - else - return convert(std::visit(ArithmeticCast{}, *left) <=> - std::visit(ArithmeticCast{}, *right)); - } + return greater_greater_op(ast, left, right); + + case TokenKind::T_LESS_EQUAL_GREATER: + return less_equal_greater_op(ast, left, right); case TokenKind::T_LESS_EQUAL: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) <= - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) <= - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) <= - std::visit(ArithmeticCast{}, *right); + return less_equal_op(ast, left, right); case TokenKind::T_GREATER_EQUAL: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) >= - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) >= - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) >= - std::visit(ArithmeticCast{}, *right); + return greater_equal_op(ast, left, right); case TokenKind::T_LESS: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) < - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) < - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) < - std::visit(ArithmeticCast{}, *right); + return less_op(ast, left, right); case TokenKind::T_GREATER: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) > - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) > - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) > - std::visit(ArithmeticCast{}, *right); + return greater_op(ast, left, right); case TokenKind::T_EQUAL_EQUAL: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) == - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) == - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) == - std::visit(ArithmeticCast{}, *right); + return equal_equal_op(ast, left, right); case TokenKind::T_EXCLAIM_EQUAL: - if (control()->is_floating_point(ast->type)) - return std::visit(ArithmeticCast{}, *left) != - std::visit(ArithmeticCast{}, *right); - else if (control()->is_unsigned(ast->type)) - return std::visit(ArithmeticCast{}, *left) != - std::visit(ArithmeticCast{}, *right); - else - return std::visit(ArithmeticCast{}, *left) != - std::visit(ArithmeticCast{}, *right); + return exclaim_equal_op(ast, left, right); case TokenKind::T_AMP: - return std::visit(ArithmeticCast{}, *left) & - std::visit(ArithmeticCast{}, *right); + return amp_op(ast, left, right); case TokenKind::T_CARET: - return std::visit(ArithmeticCast{}, *left) ^ - std::visit(ArithmeticCast{}, *right); + return caret_op(ast, left, right); case TokenKind::T_BAR: - return std::visit(ArithmeticCast{}, *left) | - std::visit(ArithmeticCast{}, *right); + return bar_op(ast, left, right); case TokenKind::T_AMP_AMP: - return std::visit(ArithmeticCast{}, *left) && - std::visit(ArithmeticCast{}, *right); + return amp_amp_op(ast, left, right); case TokenKind::T_BAR_BAR: - return std::visit(ArithmeticCast{}, *left) || - std::visit(ArithmeticCast{}, *right); + return bar_bar_op(ast, left, right); case TokenKind::T_COMMA: - return right; + return comma_op(ast, left, right); default: unit()->warning(ast->opLoc, "invalid binary expression"); @@ -3264,4 +3400,28 @@ auto ASTInterpreter::toBool(const ConstValue& value) -> std::optional { return std::visit(ToBool{*this}, value); } +auto ASTInterpreter::toInt(const ConstValue& value) + -> std::optional { + return std::visit(ArithmeticCast{}, value); +} + +auto ASTInterpreter::toUInt(const ConstValue& value) + -> std::optional { + return std::visit(ArithmeticCast{}, value); +} + +auto ASTInterpreter::toFloat(const ConstValue& value) -> std::optional { + return std::visit(ArithmeticCast{}, value); +} + +auto ASTInterpreter::toDouble(const ConstValue& value) + -> std::optional { + return std::visit(ArithmeticCast{}, value); +} + +auto ASTInterpreter::toLongDouble(const ConstValue& value) + -> std::optional { + return std::visit(ArithmeticCast{}, value); +} + } // namespace cxx diff --git a/src/parser/cxx/ast_interpreter.h b/src/parser/cxx/ast_interpreter.h index 73b83492..0e9667c0 100644 --- a/src/parser/cxx/ast_interpreter.h +++ b/src/parser/cxx/ast_interpreter.h @@ -45,6 +45,19 @@ class ASTInterpreter { [[nodiscard]] auto toBool(const ConstValue& value) -> std::optional; + [[nodiscard]] auto toInt(const ConstValue& value) + -> std::optional; + + [[nodiscard]] auto toUInt(const ConstValue& value) + -> std::optional; + + [[nodiscard]] auto toFloat(const ConstValue& value) -> std::optional; + + [[nodiscard]] auto toDouble(const ConstValue& value) -> std::optional; + + [[nodiscard]] auto toLongDouble(const ConstValue& value) + -> std::optional; + private: using ExpressionResult = std::optional; diff --git a/src/parser/cxx/const_value.h b/src/parser/cxx/const_value.h index d037a088..4e8ae025 100644 --- a/src/parser/cxx/const_value.h +++ b/src/parser/cxx/const_value.h @@ -29,28 +29,7 @@ namespace cxx { using ConstValue = - std::variant; - -template -struct ArithmeticConversion { - auto operator()(const StringLiteral* value) const -> ConstValue { - return ConstValue(value); - } - - auto operator()(auto value) const -> ConstValue { - return ConstValue(static_cast(value)); - } -}; - -template -struct ArithmeticCast { - auto operator()(const StringLiteral*) const -> T { - cxx_runtime_error("invalid artihmetic cast"); - return T{}; - } - - auto operator()(auto value) const -> T { return static_cast(value); } -}; + std::variant; } // namespace cxx \ No newline at end of file diff --git a/src/parser/cxx/decl.cc b/src/parser/cxx/decl.cc index c6f6ac2f..ac9ce1e3 100644 --- a/src/parser/cxx/decl.cc +++ b/src/parser/cxx/decl.cc @@ -87,26 +87,6 @@ struct GetDeclaratorType { TranslationUnit* unit = nullptr; const Type* type_ = nullptr; - struct { - auto operator()(float value) const -> std::optional { - return std::nullopt; - } - - auto operator()(double value) const -> std::optional { - return std::nullopt; - } - - auto operator()(const StringLiteral* value) const - -> std::optional { - return std::nullopt; - } - - template - auto operator()(T value) const -> std::optional { - return static_cast(value); - } - } get_size_value; - explicit GetDeclaratorType(TranslationUnit* unit) : unit(unit) {} auto control() const -> Control* { return unit->control(); } @@ -297,11 +277,11 @@ struct GetDeclaratorType { return; } - ASTInterpreter sem{unit}; - auto constValue = sem.evaluate(ast->expression); + ASTInterpreter interp{unit}; + const auto constValue = interp.evaluate(ast->expression); if (constValue) { - if (auto size = std::visit(get_size_value, *constValue)) { + if (auto size = interp.toUInt(constValue.value())) { type_ = control()->getBoundedArrayType(type_, *size); return; } diff --git a/src/parser/cxx/names.cc b/src/parser/cxx/names.cc index 07809570..735177a3 100644 --- a/src/parser/cxx/names.cc +++ b/src/parser/cxx/names.cc @@ -37,17 +37,11 @@ struct ConstValueHash { auto operator()(bool value) const -> std::size_t { return std::hash{}(value); } - auto operator()(std::int32_t value) const -> std::size_t { - return std::hash{}(value); + auto operator()(std::intmax_t value) const -> std::size_t { + return std::hash{}(value); } - auto operator()(std::uint32_t value) const -> std::size_t { - return std::hash{}(value); - } - auto operator()(std::int64_t value) const -> std::size_t { - return std::hash{}(value); - } - auto operator()(std::uint64_t value) const -> std::size_t { - return std::hash{}(value); + auto operator()(std::uintmax_t value) const -> std::size_t { + return std::hash{}(value); } auto operator()(float value) const -> std::size_t { return std::hash{}(value); diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 14a2c898..48bc6a0a 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -49,11 +49,6 @@ namespace cxx { namespace { -inline constexpr struct { - auto operator()(const StringLiteral*) const -> bool { return true; } - auto operator()(auto value) const -> bool { return !!value; } -} to_bool; - class RecordingDiagnosticsClient : public DiagnosticsClient { public: void reset() { messages_.clear(); } @@ -4480,7 +4475,8 @@ auto Parser::parse_static_assert_declaration(DeclarationAST*& yyast) -> bool { bool value = false; if (constValue.has_value()) { - value = visit(to_bool, *constValue); + ASTInterpreter interp{unit}; + value = interp.toBool(constValue.value()).value_or(false); } if (!value && config().checkTypes) { diff --git a/tests/api_tests/test_rewriter.cc b/tests/api_tests/test_rewriter.cc index 2cb83fe7..355fd4f7 100644 --- a/tests/api_tests/test_rewriter.cc +++ b/tests/api_tests/test_rewriter.cc @@ -183,7 +183,7 @@ constexpr int y = c<123 * 2>; auto value = interp.evaluate(init->expression); ASSERT_TRUE(value.has_value()); - ASSERT_EQ(std::visit(ArithmeticCast{}, *value), 123 * 2 + 321 + 123 * 2); + ASSERT_EQ(interp.toInt(*value).value(), 123 * 2 + 321 + 123 * 2); } TEST(Rewriter, Pack) { @@ -254,7 +254,7 @@ const auto N = S<0, 1, 2>; const auto value = interp.evaluate(eq->expression); ASSERT_TRUE(value.has_value()); - ASSERT_EQ(std::visit(ArithmeticCast{}, *value), 0 * 0 + 1 * 1 + 2 * 2); + ASSERT_EQ(interp.toInt(*value).value(), 0 * 0 + 1 * 1 + 2 * 2); } TEST(Rewriter, Class) {