Skip to content

Commit 1e0ea2e

Browse files
committed
Compute types of address expressions
Signed-off-by: Roberto Raggi <[email protected]>
1 parent 54cf058 commit 1e0ea2e

File tree

3 files changed

+120
-1
lines changed

3 files changed

+120
-1
lines changed

src/parser/cxx/parser.cc

Lines changed: 77 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,29 @@ struct Parser::GetDeclaratorType {
307307
}
308308
}
309309

310-
void operator()(PtrToMemberOperatorAST* ast) {}
310+
void operator()(PtrToMemberOperatorAST* ast) {
311+
if (!type_) return;
312+
313+
auto symbol = ast->nestedNameSpecifier->symbol;
314+
if (!symbol) return;
315+
316+
auto classType = type_cast<ClassType>(symbol->type());
317+
if (!classType) return;
318+
319+
if (auto functionType = type_cast<FunctionType>(type_)) {
320+
type_ = control()->getMemberFunctionPointerType(classType, functionType);
321+
} else {
322+
type_ = control()->getMemberObjectPointerType(classType, type_);
323+
}
324+
325+
for (auto it = ast->cvQualifierList; it; it = it->next) {
326+
if (ast_cast<ConstQualifierAST>(it->value)) {
327+
type_ = control()->getConstType(type_);
328+
} else if (ast_cast<VolatileQualifierAST>(it->value)) {
329+
type_ = control()->getVolatileType(type_);
330+
}
331+
}
332+
}
311333

312334
void operator()(BitfieldDeclaratorAST* ast) {}
313335

@@ -2932,6 +2954,53 @@ auto Parser::parse_unop_expression(ExpressionAST*& yyast,
29322954
break;
29332955
}
29342956

2957+
case TokenKind::T_AMP: {
2958+
if (!ast->expression->type) {
2959+
break;
2960+
}
2961+
2962+
if (!is_glvalue(ast->expression)) {
2963+
break;
2964+
}
2965+
2966+
// TODO xvalue to lvalue
2967+
2968+
if (auto idExpr = ast_cast<IdExpressionAST>(ast->expression);
2969+
idExpr && idExpr->nestedNameSpecifier) {
2970+
auto symbol = idExpr->symbol;
2971+
if (auto field = symbol_cast<FieldSymbol>(symbol);
2972+
field && !field->isStatic()) {
2973+
auto parentClass = field->enclosingSymbol();
2974+
auto classType = type_cast<ClassType>(parentClass->type());
2975+
2976+
ast->type =
2977+
control_->getMemberObjectPointerType(classType, field->type());
2978+
2979+
ast->valueCategory = ValueCategory::kPrValue;
2980+
2981+
break;
2982+
}
2983+
2984+
if (auto function = symbol_cast<FunctionSymbol>(symbol);
2985+
function && !function->isStatic()) {
2986+
auto functionType = type_cast<FunctionType>(function->type());
2987+
auto parentClass = function->enclosingSymbol();
2988+
auto classType = type_cast<ClassType>(parentClass->type());
2989+
2990+
ast->type =
2991+
control_->getMemberFunctionPointerType(classType, functionType);
2992+
2993+
ast->valueCategory = ValueCategory::kPrValue;
2994+
2995+
break;
2996+
}
2997+
} // id expression
2998+
2999+
ast->type = control_->getPointerType(ast->expression->type);
3000+
ast->valueCategory = ValueCategory::kPrValue;
3001+
break;
3002+
}
3003+
29353004
case TokenKind::T_PLUS: {
29363005
ExpressionAST* expr = ast->expression;
29373006
ensure_prvalue(expr);
@@ -5985,6 +6054,13 @@ void Parser::check_type_traits() {
59856054
rewind(typeTraitLoc);
59866055
}
59876056

6057+
auto Parser::strip_parentheses(ExpressionAST* ast) -> ExpressionAST* {
6058+
while (auto paren = ast_cast<NestedExpressionAST>(ast)) {
6059+
ast = paren->expression;
6060+
}
6061+
return ast;
6062+
}
6063+
59886064
auto Parser::lvalue_to_rvalue_conversion(ExpressionAST*& expr) -> bool {
59896065
if (!is_glvalue(expr)) return false;
59906066

src/parser/cxx/parser.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,8 @@ class Parser final {
827827

828828
void check_type_traits();
829829

830+
[[nodiscard]] auto strip_parentheses(ExpressionAST* ast) -> ExpressionAST*;
831+
830832
// standard conversions
831833
[[nodiscard]] auto lvalue_to_rvalue_conversion(ExpressionAST*& expr) -> bool;
832834
[[nodiscard]] auto array_to_pointer_conversion(ExpressionAST*& expr) -> bool;
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// RUN: %cxx -verify -fcheck %s
2+
3+
struct X {
4+
int m{};
5+
const int ci{};
6+
const volatile int cvi{};
7+
8+
void f();
9+
void g(int a, const void* ptr) const;
10+
};
11+
12+
auto main() -> int {
13+
static_assert(__is_same(decltype(&X::m), int X::*));
14+
static_assert(__is_same(decltype(&X::ci), const int X::*));
15+
static_assert(__is_same(decltype(&X::cvi), const volatile int X::*));
16+
static_assert(__is_same(decltype(&X::f), void (X::*)()));
17+
static_assert(
18+
__is_same(decltype(&X::g), void (X::*)(int, const void*) const));
19+
20+
char ch{};
21+
static_assert(__is_same(decltype(&ch), char*));
22+
23+
int i{};
24+
static_assert(__is_same(decltype(&i), int*));
25+
26+
const void* p = nullptr;
27+
static_assert(__is_same(decltype(&p), const void**));
28+
29+
int a[2];
30+
static_assert(__is_same(decltype(&a), int(*)[2]));
31+
32+
X x;
33+
static_assert(__is_same(decltype(&x), X*));
34+
static_assert(__is_same(decltype(*&x), X&));
35+
36+
const X cx;
37+
static_assert(__is_same(decltype(&cx), const X*));
38+
static_assert(__is_same(decltype(*&cx), const X&));
39+
40+
return 0;
41+
}

0 commit comments

Comments
 (0)