From b9efc8a7b10ba34efa9674b788bd9deb35c3959f Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sun, 9 Feb 2025 11:59:31 +0100 Subject: [PATCH] Compute types of increment expressions Signed-off-by: Roberto Raggi --- src/parser/cxx/parser.cc | 76 +++++++++++++++++++++++--------- tests/unit_tests/sema/incr_01.cc | 41 +++++++++++++++++ 2 files changed, 97 insertions(+), 20 deletions(-) create mode 100644 tests/unit_tests/sema/incr_01.cc diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 16510244..17fd5e83 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -2902,26 +2902,16 @@ auto Parser::parse_expression_list(List*& yyast, auto Parser::parse_unary_expression(ExpressionAST*& yyast, const ExprContext& ctx) -> bool { - if (parse_unop_expression(yyast, ctx)) - return true; - else if (parse_complex_expression(yyast, ctx)) - return true; - else if (parse_await_expression(yyast, ctx)) - return true; - else if (parse_sizeof_expression(yyast, ctx)) - return true; - else if (parse_alignof_expression(yyast, ctx)) - return true; - else if (parse_noexcept_expression(yyast, ctx)) - return true; - else if (parse_new_expression(yyast, ctx)) - return true; - else if (parse_delete_expression(yyast, ctx)) - return true; - else if (parse_reflect_expression(yyast, ctx)) - return true; - else - return parse_postfix_expression(yyast, ctx); + if (parse_unop_expression(yyast, ctx)) return true; + if (parse_complex_expression(yyast, ctx)) return true; + if (parse_await_expression(yyast, ctx)) return true; + if (parse_sizeof_expression(yyast, ctx)) return true; + if (parse_alignof_expression(yyast, ctx)) return true; + if (parse_noexcept_expression(yyast, ctx)) return true; + if (parse_new_expression(yyast, ctx)) return true; + if (parse_delete_expression(yyast, ctx)) return true; + if (parse_reflect_expression(yyast, ctx)) return true; + return parse_postfix_expression(yyast, ctx); } auto Parser::parse_unop_expression(ExpressionAST*& yyast, @@ -3052,6 +3042,52 @@ auto Parser::parse_unop_expression(ExpressionAST*& yyast, break; } + case TokenKind::T_PLUS_PLUS: { + if (!is_glvalue(ast->expression)) { + break; + } + + auto ty = ast->expression->type; + + if (control_->is_arithmetic(ty) && !control_->is_const(ty)) { + ast->type = ty; + ast->valueCategory = ValueCategory::kLValue; + break; + } + + if (auto ptrTy = type_cast(ty)) { + if (ptrTy && !control_->is_void(ptrTy->elementType())) { + ast->type = ptrTy; + ast->valueCategory = ValueCategory::kLValue; + } + } + + break; + } + + case TokenKind::T_MINUS_MINUS: { + if (!is_glvalue(ast->expression)) { + break; + } + + auto ty = ast->expression->type; + + if (control_->is_arithmetic(ty) && !control_->is_const(ty)) { + ast->type = ty; + ast->valueCategory = ValueCategory::kLValue; + break; + } + + if (auto ptrTy = type_cast(ty)) { + if (ptrTy && !control_->is_void(ptrTy->elementType())) { + ast->type = ptrTy; + ast->valueCategory = ValueCategory::kLValue; + } + } + + break; + } + default: break; } // switch diff --git a/tests/unit_tests/sema/incr_01.cc b/tests/unit_tests/sema/incr_01.cc new file mode 100644 index 00000000..59d6f201 --- /dev/null +++ b/tests/unit_tests/sema/incr_01.cc @@ -0,0 +1,41 @@ +// RUN: %cxx -verify -fcheck %s + +auto main() -> int { + char c{}; + static_assert(__is_same(decltype(++c), char&)); + static_assert(__is_same(decltype(--c), char&)); + static_assert(__is_lvalue_reference(decltype(++c))); + static_assert(__is_lvalue_reference(decltype(--c))); + + int x{}; + static_assert(__is_same(decltype(++x), int&)); + static_assert(__is_same(decltype(--x), int&)); + static_assert(__is_lvalue_reference(decltype(++x))); + static_assert(__is_lvalue_reference(decltype(--x))); + + float f{}; + static_assert(__is_same(decltype(++f), float&)); + static_assert(__is_same(decltype(--f), float&)); + static_assert(__is_lvalue_reference(decltype(++f))); + static_assert(__is_lvalue_reference(decltype(--f))); + + double d{}; + static_assert(__is_same(decltype(++d), double&)); + static_assert(__is_same(decltype(--d), double&)); + static_assert(__is_lvalue_reference(decltype(++d))); + static_assert(__is_lvalue_reference(decltype(--d))); + + char* p{}; + static_assert(__is_same(decltype(++p), char*&)); + static_assert(__is_same(decltype(--p), char*&)); + static_assert(__is_lvalue_reference(decltype(++p))); + static_assert(__is_lvalue_reference(decltype(--p))); + + char*& pr = p; + static_assert(__is_same(decltype(++pr), char*&)); + static_assert(__is_same(decltype(--pr), char*&)); + static_assert(__is_lvalue_reference(decltype(++pr))); + static_assert(__is_lvalue_reference(decltype(--pr))); + + return 0; +} \ No newline at end of file