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
117 changes: 115 additions & 2 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,29 @@ struct Parser::GetDeclaratorType {
}
}

void operator()(PtrToMemberOperatorAST* ast) {}
void operator()(PtrToMemberOperatorAST* ast) {
if (!type_) return;

auto symbol = ast->nestedNameSpecifier->symbol;
if (!symbol) return;

auto classType = type_cast<ClassType>(symbol->type());
if (!classType) return;

if (auto functionType = type_cast<FunctionType>(type_)) {
type_ = control()->getMemberFunctionPointerType(classType, functionType);
} else {
type_ = control()->getMemberObjectPointerType(classType, type_);
}

for (auto it = ast->cvQualifierList; it; it = it->next) {
if (ast_cast<ConstQualifierAST>(it->value)) {
type_ = control()->getConstType(type_);
} else if (ast_cast<VolatileQualifierAST>(it->value)) {
type_ = control()->getVolatileType(type_);
}
}
}

void operator()(BitfieldDeclaratorAST* ast) {}

Expand Down Expand Up @@ -1562,6 +1584,7 @@ auto Parser::parse_type_nested_name_specifier(NestedNameSpecifierAST*& yyast,
return true;
}

namespace {
struct IsReferencingTemplateParameter {
Parser& p;
int depth = 0;
Expand Down Expand Up @@ -1592,6 +1615,7 @@ struct IsReferencingTemplateParameter {
return false;
}
};
} // namespace

auto Parser::parse_template_nested_name_specifier(
NestedNameSpecifierAST*& yyast, NestedNameSpecifierContext ctx, int depth)
Expand Down Expand Up @@ -2930,7 +2954,54 @@ auto Parser::parse_unop_expression(ExpressionAST*& yyast,
break;
}

case cxx::TokenKind::T_PLUS: {
case TokenKind::T_AMP: {
if (!ast->expression->type) {
break;
}

if (!is_glvalue(ast->expression)) {
break;
}

// TODO xvalue to lvalue

if (auto idExpr = ast_cast<IdExpressionAST>(ast->expression);
idExpr && idExpr->nestedNameSpecifier) {
auto symbol = idExpr->symbol;
if (auto field = symbol_cast<FieldSymbol>(symbol);
field && !field->isStatic()) {
auto parentClass = field->enclosingSymbol();
auto classType = type_cast<ClassType>(parentClass->type());

ast->type =
control_->getMemberObjectPointerType(classType, field->type());

ast->valueCategory = ValueCategory::kPrValue;

break;
}

if (auto function = symbol_cast<FunctionSymbol>(symbol);
function && !function->isStatic()) {
auto functionType = type_cast<FunctionType>(function->type());
auto parentClass = function->enclosingSymbol();
auto classType = type_cast<ClassType>(parentClass->type());

ast->type =
control_->getMemberFunctionPointerType(classType, functionType);

ast->valueCategory = ValueCategory::kPrValue;

break;
}
} // id expression

ast->type = control_->getPointerType(ast->expression->type);
ast->valueCategory = ValueCategory::kPrValue;
break;
}

case TokenKind::T_PLUS: {
ExpressionAST* expr = ast->expression;
ensure_prvalue(expr);
auto ty = control_->remove_cvref(expr->type);
Expand All @@ -2946,6 +3017,41 @@ auto Parser::parse_unop_expression(ExpressionAST*& yyast,
break;
}

case TokenKind::T_MINUS: {
ExpressionAST* expr = ast->expression;
ensure_prvalue(expr);
auto ty = control_->remove_cvref(expr->type);
if (control_->is_arithmetic_or_unscoped_enum(ty)) {
if (control_->is_integral_or_unscoped_enum(ty)) {
(void)integral_promotion(expr);
}
ast->expression = expr;
ast->type = expr->type;
ast->valueCategory = ValueCategory::kPrValue;
}
break;
}

case TokenKind::T_EXCLAIM: {
(void)implicit_conversion(ast->expression, control_->getBoolType());
ast->type = control_->getBoolType();
ast->valueCategory = ValueCategory::kPrValue;
break;
}

case TokenKind::T_TILDE: {
ExpressionAST* expr = ast->expression;
ensure_prvalue(expr);
auto ty = control_->remove_cvref(expr->type);
if (control_->is_integral_or_unscoped_enum(ty)) {
(void)integral_promotion(expr);
ast->expression = expr;
ast->type = expr->type;
ast->valueCategory = ValueCategory::kPrValue;
}
break;
}

default:
break;
} // switch
Expand Down Expand Up @@ -5948,6 +6054,13 @@ void Parser::check_type_traits() {
rewind(typeTraitLoc);
}

auto Parser::strip_parentheses(ExpressionAST* ast) -> ExpressionAST* {
while (auto paren = ast_cast<NestedExpressionAST>(ast)) {
ast = paren->expression;
}
return ast;
}

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

Expand Down
2 changes: 2 additions & 0 deletions src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -827,6 +827,8 @@ class Parser final {

void check_type_traits();

[[nodiscard]] auto strip_parentheses(ExpressionAST* ast) -> ExpressionAST*;

// standard conversions
[[nodiscard]] auto lvalue_to_rvalue_conversion(ExpressionAST*& expr) -> bool;
[[nodiscard]] auto array_to_pointer_conversion(ExpressionAST*& expr) -> bool;
Expand Down
41 changes: 41 additions & 0 deletions tests/unit_tests/sema/address_op_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// RUN: %cxx -verify -fcheck %s

struct X {
int m{};
const int ci{};
const volatile int cvi{};

void f();
void g(int a, const void* ptr) const;
};

auto main() -> int {
static_assert(__is_same(decltype(&X::m), int X::*));
static_assert(__is_same(decltype(&X::ci), const int X::*));
static_assert(__is_same(decltype(&X::cvi), const volatile int X::*));
static_assert(__is_same(decltype(&X::f), void (X::*)()));
static_assert(
__is_same(decltype(&X::g), void (X::*)(int, const void*) const));

char ch{};
static_assert(__is_same(decltype(&ch), char*));

int i{};
static_assert(__is_same(decltype(&i), int*));

const void* p = nullptr;
static_assert(__is_same(decltype(&p), const void**));

int a[2];
static_assert(__is_same(decltype(&a), int(*)[2]));

X x;
static_assert(__is_same(decltype(&x), X*));
static_assert(__is_same(decltype(*&x), X&));

const X cx;
static_assert(__is_same(decltype(&cx), const X*));
static_assert(__is_same(decltype(*&cx), const X&));

return 0;
}
18 changes: 18 additions & 0 deletions tests/unit_tests/sema/bitwise_not_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// RUN: %cxx -verify -fcheck %s

auto main() -> int {
static_assert(__is_same(decltype(~'a'), int));
static_assert(__is_same(decltype(~1), int));
static_assert(__is_same(decltype(~1l), long));
static_assert(__is_same(decltype(~1ll), long long));
static_assert(__is_same(decltype(~1ul), unsigned long));
static_assert(__is_same(decltype(~1ull), unsigned long long));

short x{};
static_assert(__is_same(decltype(~x), int));

short& y = x;
static_assert(__is_same(decltype(~y), int));

return 0;
}
24 changes: 24 additions & 0 deletions tests/unit_tests/sema/logical_neg_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
// RUN: %cxx -verify -fcheck %s

auto main() -> int {
static_assert(__is_same(decltype(!true), bool));
static_assert(__is_same(decltype(!!true), bool));

static_assert(__is_same(decltype(!1), bool));
static_assert(__is_same(decltype(!1.0), bool));

const void* p = nullptr;
static_assert(__is_same(decltype(!p), bool));

static_assert(__is_same(decltype(!main), bool));

const int a[2] = {1, 2};
static_assert(__is_same(decltype(!a), bool));

int x{}, &y = x;

static_assert(__is_same(decltype(!x), bool));
static_assert(__is_same(decltype(!y), bool));

return 0;
}
23 changes: 23 additions & 0 deletions tests/unit_tests/sema/unary_minus_01.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// RUN: %cxx -verify -fcheck %s

auto main() -> int {
static_assert(__is_same(decltype(-'a'), int));
static_assert(__is_same(decltype(-1), int));
static_assert(__is_same(decltype(-1l), long));
static_assert(__is_same(decltype(-1ll), long long));
static_assert(__is_same(decltype(-1ul), unsigned long));
static_assert(__is_same(decltype(-1ull), unsigned long long));
static_assert(__is_same(decltype(-1.0f), float));
static_assert(__is_same(decltype(-1.0), double));

short x{};
static_assert(__is_same(decltype(-x), int));

short& y = x;
static_assert(__is_same(decltype(-y), int));

unsigned u{};
static_assert(__is_same(decltype(-u), unsigned));

return 0;
}