From 56ec1babb92c04a64ee44e0e75f42680d010a892 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Sat, 8 Feb 2025 19:57:57 +0100 Subject: [PATCH] Compute the type of indirection operators Signed-off-by: Roberto Raggi --- src/parser/cxx/parser.cc | 32 +++++++++++++++++ src/parser/cxx/parser.h | 2 ++ tests/unit_tests/ast/asm_declaration_01.cc | 8 +++-- tests/unit_tests/sema/class_01.cc | 40 ++++++++++++++++++---- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index b1fa34d9..d4533c5a 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -2919,6 +2919,21 @@ auto Parser::parse_unop_expression(ExpressionAST*& yyast, ast->op = unit->tokenKind(opLoc); ast->expression = expression; + switch (ast->op) { + case TokenKind::T_STAR: { + auto pointerType = type_cast(expression->type); + if (pointerType) { + ensure_prvalue(ast->expression); + ast->type = pointerType->elementType(); + ast->valueCategory = ValueCategory::kLValue; + } + break; + } + + default: + break; + } // switch + return true; } @@ -6365,6 +6380,23 @@ auto Parser::qualification_conversion(ExpressionAST*& expr, return false; } +void Parser::ensure_prvalue(ExpressionAST*& expr) { + if (lvalue_to_rvalue_conversion(expr)) { + expr->valueCategory = ValueCategory::kPrValue; + return; + } + + if (array_to_pointer_conversion(expr)) { + expr->valueCategory = ValueCategory::kPrValue; + return; + } + + if (function_to_pointer_conversion(expr)) { + expr->valueCategory = ValueCategory::kPrValue; + return; + } +} + auto Parser::implicit_conversion(ExpressionAST*& expr, const Type* destinationType) -> bool { if (!expr || !expr->type) return false; diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index a31af173..ff855509 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -858,6 +858,8 @@ class Parser final { const Type* destinationType) -> bool; + void ensure_prvalue(ExpressionAST*& expr); + [[nodiscard]] auto implicit_conversion(ExpressionAST*& expr, const Type* destinationType) -> bool; diff --git a/tests/unit_tests/ast/asm_declaration_01.cc b/tests/unit_tests/ast/asm_declaration_01.cc index 217d4abd..4aa1afda 100644 --- a/tests/unit_tests/ast/asm_declaration_01.cc +++ b/tests/unit_tests/ast/asm_declaration_01.cc @@ -106,9 +106,11 @@ end:; // CHECK-NEXT: constraint-literal: "+rm" // CHECK-NEXT: expression: unary-expression // CHECK-NEXT: op: * -// CHECK-NEXT: expression: id-expression -// CHECK-NEXT: unqualified-id: name-id -// CHECK-NEXT: identifier: p +// CHECK-NEXT: expression: implicit-cast-expression +// CHECK-NEXT: cast-kind: lvalue-to-rvalue-conversion +// CHECK-NEXT: expression: id-expression +// CHECK-NEXT: unqualified-id: name-id +// CHECK-NEXT: identifier: p // CHECK-NEXT: function-definition // CHECK-NEXT: decl-specifier-list // CHECK-NEXT: void-type-specifier diff --git a/tests/unit_tests/sema/class_01.cc b/tests/unit_tests/sema/class_01.cc index c18aa4b7..0c015efc 100644 --- a/tests/unit_tests/sema/class_01.cc +++ b/tests/unit_tests/sema/class_01.cc @@ -1,14 +1,24 @@ // RUN: %cxx -verify -fcheck %s struct X { - void f() { static_assert(__is_same(decltype(this), X*)); } + void f() { + static_assert(__is_same(decltype(this), X*)); + static_assert(__is_same(decltype(*this), X&)); + } - void f() const { static_assert(__is_same(decltype(this), const X*)); } + void f() const { + static_assert(__is_same(decltype(this), const X*)); + static_assert(__is_same(decltype(*this), const X&)); + } - void f() volatile { static_assert(__is_same(decltype(this), volatile X*)); } + void f() volatile { + static_assert(__is_same(decltype(this), volatile X*)); + static_assert(__is_same(decltype(*this), volatile X&)); + } void f() const volatile { static_assert(__is_same(decltype(this), const volatile X*)); + static_assert(__is_same(decltype(*this), const volatile X&)); } void g(); @@ -17,12 +27,30 @@ struct X { void g() const volatile; }; -void X::g() { static_assert(__is_same(decltype(this), X*)); } +void X::g() { + static_assert(__is_same(decltype(this), X*)); + static_assert(__is_same(decltype(*this), X&)); + + X* self = this; + static_assert(__is_same(decltype(self), X*)); + static_assert(__is_same(decltype(*self), X&)); -void X::g() const { static_assert(__is_same(decltype(this), const X*)); } + X*& x = self; + static_assert(__is_same(decltype(x), X*&)); + static_assert(__is_same(decltype(*x), X&)); +} + +void X::g() const { + static_assert(__is_same(decltype(this), const X*)); + static_assert(__is_same(decltype(*this), const X&)); +} -void X::g() volatile { static_assert(__is_same(decltype(this), volatile X*)); } +void X::g() volatile { + static_assert(__is_same(decltype(this), volatile X*)); + static_assert(__is_same(decltype(*this), volatile X&)); +} void X::g() const volatile { static_assert(__is_same(decltype(this), const volatile X*)); + static_assert(__is_same(decltype(*this), const volatile X&)); }