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
2 changes: 1 addition & 1 deletion src/parser/cxx/control.cc
Original file line number Diff line number Diff line change
Expand Up @@ -851,4 +851,4 @@ auto Control::instantiate(TranslationUnit* unit, Symbol* symbol,
return instantiate(symbol);
}

} // namespace cxx
} // namespace cxx
57 changes: 53 additions & 4 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2508,14 +2508,14 @@ void Parser::check_member_expression(MemberExpressionAST* ast) {

auto Parser::check_member_access(MemberExpressionAST* ast) -> bool {
const Type* objectType = ast->baseExpression->type;
auto cv = strip_cv(objectType);
auto cv1 = 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);
cv1 = strip_cv(objectType);
}

auto classType = type_cast<ClassType>(objectType);
Expand All @@ -2532,9 +2532,36 @@ auto Parser::check_member_access(MemberExpressionAST* ast) -> bool {

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

// TODO: value category
if (symbol->isEnumerator()) {
ast->valueCategory = ValueCategory::kPrValue;
} else {
if (is_lvalue(ast->baseExpression)) {
ast->valueCategory = ValueCategory::kLValue;
} else {
ast->valueCategory = ValueCategory::kXValue;
}

if (auto field = symbol_cast<FieldSymbol>(symbol);
field && !field->isStatic()) {
auto cv2 = strip_cv(ast->type);

auto vq = is_volatile(cv1) || is_volatile(cv2);
auto cq = is_const(cv1) || is_const(cv2);

CvQualifiers cv = CvQualifiers::kNone;
if (vq) cv = CvQualifiers::kVolatile;

if (!field->isMutable() && cq) {
cv = merge_cv(cv, CvQualifiers::kConst);
}

if (cv != CvQualifiers::kNone) {
ast->type = control_->getQualType(ast->type, cv);
}
}
}
}

return true;
}
Expand Down Expand Up @@ -6297,6 +6324,27 @@ auto Parser::strip_cv(const Type*& type) -> CvQualifiers {
return {};
}

auto Parser::is_const(CvQualifiers cv) const -> bool {
return cv == CvQualifiers::kConst || cv == CvQualifiers::kConstVolatile;
}

auto Parser::is_volatile(CvQualifiers cv) const -> bool {
return cv == CvQualifiers::kVolatile || cv == CvQualifiers::kConstVolatile;
}

auto Parser::merge_cv(CvQualifiers cv1, CvQualifiers cv2) const
-> CvQualifiers {
CvQualifiers cv = CvQualifiers::kNone;
if (is_const(cv1) || is_const(cv2)) cv = CvQualifiers::kConst;
if (is_volatile(cv1) || is_volatile(cv2)) {
if (cv == CvQualifiers::kConst)
cv = CvQualifiers::kConstVolatile;
else
cv = CvQualifiers::kVolatile;
}
return cv;
}

auto Parser::lvalue_to_rvalue_conversion(ExpressionAST*& expr) -> bool {
if (!is_glvalue(expr)) return false;

Expand Down Expand Up @@ -10007,6 +10055,7 @@ auto Parser::declareField(DeclaratorAST* declarator, const Decl& decl)
applySpecifiers(fieldSymbol, decl.specs);
fieldSymbol->setName(name);
fieldSymbol->setType(type);
fieldSymbol->setMutable(decl.specs.isMutable);
if (auto alignment = control_->memoryLayout()->alignmentOf(type)) {
fieldSymbol->setAlignment(alignment.value());
}
Expand Down
4 changes: 4 additions & 0 deletions src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ class Parser final {

[[nodiscard]] auto strip_parentheses(ExpressionAST* ast) -> ExpressionAST*;
[[nodiscard]] auto strip_cv(const Type*& type) -> CvQualifiers;
[[nodiscard]] auto merge_cv(CvQualifiers cv1, CvQualifiers cv2) const
-> CvQualifiers;
[[nodiscard]] auto is_const(CvQualifiers cv) const -> bool;
[[nodiscard]] auto is_volatile(CvQualifiers cv) const -> bool;

// standard conversions
[[nodiscard]] auto lvalue_to_rvalue_conversion(ExpressionAST*& expr) -> bool;
Expand Down
4 changes: 4 additions & 0 deletions src/parser/cxx/symbols.cc
Original file line number Diff line number Diff line change
Expand Up @@ -564,6 +564,10 @@ auto FieldSymbol::isInline() const -> bool { return isInline_; }

void FieldSymbol::setInline(bool isInline) { isInline_ = isInline; }

auto FieldSymbol::isMutable() const -> bool { return isMutable_; }

void FieldSymbol::setMutable(bool isMutable) { isMutable_ = isMutable; }

auto FieldSymbol::offset() const -> int { return offset_; }

void FieldSymbol::setOffset(int offset) { offset_ = offset; }
Expand Down
4 changes: 4 additions & 0 deletions src/parser/cxx/symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,9 @@ class FieldSymbol final : public Symbol {
[[nodiscard]] auto isInline() const -> bool;
void setInline(bool isInline);

[[nodiscard]] auto isMutable() const -> bool;
void setMutable(bool isMutable);

[[nodiscard]] auto offset() const -> int;
void setOffset(int offset);

Expand All @@ -590,6 +593,7 @@ class FieldSymbol final : public Symbol {
std::uint32_t isConstexpr_ : 1;
std::uint32_t isConstinit_ : 1;
std::uint32_t isInline_ : 1;
std::uint32_t isMutable_ : 1;
};
};
int offset_{};
Expand Down
30 changes: 30 additions & 0 deletions tests/unit_tests/sema/member_access_02.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,16 @@ struct X {
static int s_value;
};

struct W {
int& r;
const int& cr;

const int const_k = 0;
int k = 0;

mutable int m = 0;
};

auto main() -> int {
X x;
static_assert(__is_reference(decltype(x.kValue)) == false);
Expand All @@ -27,5 +37,25 @@ auto main() -> int {
static_assert(__is_reference(decltype(px->s_value)) == false);
static_assert(__is_same(decltype(px->s_value), int));

int i;
W w{i, i};

static_assert(__is_lvalue_reference(decltype(w.r)));
static_assert(__is_same(decltype(w.r), int&));

static_assert(__is_lvalue_reference(decltype(w.cr)));
static_assert(__is_same(decltype(w.cr), const int&));

static_assert(__is_same(decltype((w.const_k)), const int&));
static_assert(__is_same(decltype((w.k)), int&));

const W cw{i, i};
static_assert(__is_same(decltype(cw.const_k), const int));
static_assert(__is_same(decltype(cw.k), int));

static_assert(__is_same(decltype((cw.const_k)), const int&));
static_assert(__is_same(decltype((cw.k)), const int&));
static_assert(__is_same(decltype((cw.m)), int&));

return 0;
}