Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 41 additions & 2 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2494,14 +2494,52 @@ auto Parser::parse_member_expression(ExpressionAST*& yyast) -> bool {
/*inRequiresClause*/ false))
parse_error("expected an unqualified id");

(void)check_psuedo_destructor_access(ast);
check_member_expression(ast);

yyast = ast;

return true;
}

auto Parser::check_psuedo_destructor_access(MemberExpressionAST* ast) -> bool {
void Parser::check_member_expression(MemberExpressionAST* ast) {
if (check_pseudo_destructor_access(ast)) return;
if (check_member_access(ast)) return;
}

auto Parser::check_member_access(MemberExpressionAST* ast) -> bool {
const Type* objectType = ast->baseExpression->type;
auto cv = strip_cv(objectType);

if (ast->accessOp == TokenKind::T_MINUS_GREATER) {
auto pointerType = type_cast<PointerType>(objectType);
if (!pointerType) return false;

objectType = pointerType->elementType();
cv = strip_cv(objectType);
}

auto classType = type_cast<ClassType>(objectType);
if (!classType) return false;

auto memberName = convertName(ast->unqualifiedId);

auto classSymbol = classType->symbol();

auto symbol =
Lookup{scope_}.qualifiedLookup(classSymbol->scope(), memberName);

ast->symbol = symbol;

if (symbol) {
ast->type = symbol->type();
}

// TODO: value category

return true;
}

auto Parser::check_pseudo_destructor_access(MemberExpressionAST* ast) -> bool {
auto objectType = ast->baseExpression->type;
auto cv = strip_cv(objectType);

Expand Down Expand Up @@ -2538,6 +2576,7 @@ auto Parser::check_psuedo_destructor_access(MemberExpressionAST* ast) -> bool {
}

ast->symbol = symbol;
ast->type = control_->getFunctionType(control_->getVoidType(), {});

return true;
}
Expand Down
6 changes: 5 additions & 1 deletion src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,11 @@ class Parser final {
-> bool;

[[nodiscard]] auto parse_member_expression(ExpressionAST*& yyast) -> bool;
[[nodiscard]] auto check_psuedo_destructor_access(MemberExpressionAST* ast)

void check_member_expression(MemberExpressionAST* ast);

[[nodiscard]] auto check_member_access(MemberExpressionAST* ast) -> bool;
[[nodiscard]] auto check_pseudo_destructor_access(MemberExpressionAST* ast)
-> bool;

[[nodiscard]] auto parse_subscript_expression(ExpressionAST*& yyast,
Expand Down
31 changes: 31 additions & 0 deletions tests/unit_tests/sema/member_access_02.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// RUN: %cxx -verify -fcheck -freport-missing-types %s

struct X {
enum E { kValue = 0 };

static int s_value;
};

auto main() -> int {
X x;
static_assert(__is_reference(decltype(x.kValue)) == false);
static_assert(__is_same(decltype(x.kValue), X::E));

X& xr = x;
static_assert(__is_reference(decltype(xr.kValue)) == false);
static_assert(__is_same(decltype(xr.kValue), X::E));

const X& cxr = x;
static_assert(__is_reference(decltype(cxr.kValue)) == false);
static_assert(__is_same(decltype(cxr.kValue), X::E));

X* px = &x;

static_assert(__is_reference(decltype(px->kValue)) == false);
static_assert(__is_same(decltype(px->kValue), X::E));

static_assert(__is_reference(decltype(px->s_value)) == false);
static_assert(__is_same(decltype(px->s_value), int));

return 0;
}