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
276 changes: 6 additions & 270 deletions src/parser/cxx/parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2671,99 +2671,7 @@ auto Parser::parse_cpp_cast_expression(ExpressionAST*& yyast,

expect(TokenKind::T_RPAREN, ast->rparenLoc);

check_cpp_cast_expression(ast);

switch (unit->tokenKind(ast->castLoc)) {
case TokenKind::T_STATIC_CAST:
if (check_static_cast(ast)) break;
if (config_.checkTypes) {
parse_error(ast->firstSourceLocation(), "invalid static_cast");
}
break;

default:
break;
} // switch

return true;
}

void Parser::check_cpp_cast_expression(CppCastExpressionAST* ast) {
if (!ast->typeId) {
return;
}

ast->type = ast->typeId->type;

if (auto refType = type_cast<LvalueReferenceType>(ast->type)) {
ast->type = refType->elementType();
ast->valueCategory = ValueCategory::kLValue;
return;
}

if (auto rvalueRefType = type_cast<RvalueReferenceType>(ast->type)) {
ast->type = rvalueRefType->elementType();

if (type_cast<FunctionType>(ast->type)) {
ast->valueCategory = ValueCategory::kLValue;
} else {
ast->valueCategory = ValueCategory::kXValue;
}
}
}

auto Parser::check_static_cast(CppCastExpressionAST* ast) -> bool {
if (!ast->typeId) return false;
auto targetType = ast->typeId->type;

if (control_->is_void(targetType)) return true;

if (check_cast_to_derived(targetType, ast->expression)) return true;

const auto cv1 = get_cv_qualifiers(ast->expression->type);
const auto cv2 = get_cv_qualifiers(targetType);

if (!check_cv_qualifiers(cv2, cv1)) return false;

if (implicit_conversion(ast->expression, ast->type)) return true;

return false;
};

auto Parser::check_cv_qualifiers(CvQualifiers target, CvQualifiers source) const
-> bool {
if (source == target) return true;
if (source == CvQualifiers::kNone) return true;
if (target == CvQualifiers::kConstVolatile) return true;
return false;
}

auto Parser::check_cast_to_derived(const Type* targetType,
ExpressionAST* expression) -> bool {
if (!is_lvalue(expression)) return false;

auto sourceType = expression->type;

CvQualifiers cv1 = CvQualifiers::kNone;
if (auto qualType = type_cast<QualType>(sourceType)) {
cv1 = qualType->cvQualifiers();
sourceType = qualType->elementType();
}

auto targetRefType = type_cast<LvalueReferenceType>(targetType);
if (!targetRefType) return false;

targetType = targetRefType->elementType();

CvQualifiers cv2 = CvQualifiers::kNone;
if (auto qualType = type_cast<QualType>(targetType)) {
cv2 = qualType->cvQualifiers();
targetType = qualType->elementType();
}

if (!check_cv_qualifiers(cv2, cv1)) return false;

if (!control_->is_base_of(sourceType, targetType)) return false;
check(ast);

return true;
}
Expand Down Expand Up @@ -3100,164 +3008,7 @@ 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<PointerType>(expression->type);
if (pointerType) {
(void)ensure_prvalue(ast->expression);
ast->type = pointerType->elementType();
ast->valueCategory = ValueCategory::kLValue;
}
break;
}

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;
(void)ensure_prvalue(expr);
auto ty = control_->remove_cvref(expr->type);
if (control_->is_arithmetic_or_unscoped_enum(ty) ||
control_->is_pointer(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_MINUS: {
ExpressionAST* expr = ast->expression;
(void)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;
(void)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;
}

case TokenKind::T_PLUS_PLUS: {
if (!is_glvalue(ast->expression)) {
break;
}

auto ty = ast->expression->type;

if (control_->is_arithmetic(ty) && !control_->is_const(ty)) {
ast->type = ty;
ast->valueCategory = ValueCategory::kLValue;
break;
}

if (auto ptrTy = type_cast<PointerType>(ty)) {
if (ptrTy && !control_->is_void(ptrTy->elementType())) {
ast->type = ptrTy;
ast->valueCategory = ValueCategory::kLValue;
}
}

break;
}

case TokenKind::T_MINUS_MINUS: {
if (!is_glvalue(ast->expression)) {
break;
}

auto ty = ast->expression->type;

if (control_->is_arithmetic(ty) && !control_->is_const(ty)) {
ast->type = ty;
ast->valueCategory = ValueCategory::kLValue;
break;
}

if (auto ptrTy = type_cast<PointerType>(ty)) {
if (ptrTy && !control_->is_void(ptrTy->elementType())) {
ast->type = ptrTy;
ast->valueCategory = ValueCategory::kLValue;
}
}

break;
}

default:
break;
} // switch
check(ast);

return true;
}
Expand Down Expand Up @@ -3877,19 +3628,7 @@ auto Parser::parse_maybe_assignment_expression(ExpressionAST*& yyast,
ast->rightExpression = expression;
ast->op = op;

if (ast->leftExpression && ast->rightExpression) {
ast->type = ast->leftExpression->type;

auto sourceType = ast->rightExpression->type;

(void)implicit_conversion(ast->rightExpression, ast->type);

#if false
parse_warning(ast->opLoc,
std::format("did convert {} to {}", to_string(sourceType),
to_string(ast->type)));
#endif
}
check(ast);

yyast = ast;
}
Expand Down Expand Up @@ -6216,22 +5955,18 @@ auto Parser::merge_cv(CvQualifiers cv1, CvQualifiers cv2) const
auto Parser::ensure_prvalue(ExpressionAST*& expr) -> bool {
TypeChecker checker{unit};
checker.setScope(scope_);
checker.setReportErrors(config_.checkTypes);
return checker.ensure_prvalue(expr);
}

auto Parser::implicit_conversion(ExpressionAST*& expr,
const Type* destinationType) -> bool {
TypeChecker checker{unit};
checker.setScope(scope_);
checker.setReportErrors(config_.checkTypes);
return checker.implicit_conversion(expr, destinationType);
}

auto Parser::integral_promotion(ExpressionAST*& expr) -> bool {
TypeChecker checker{unit};
checker.setScope(scope_);
return checker.integral_promotion(expr);
}

auto Parser::is_prvalue(ExpressionAST* expr) const -> bool {
if (!expr) return false;
return expr->valueCategory == ValueCategory::kPrValue;
Expand Down Expand Up @@ -11048,6 +10783,7 @@ void Parser::completeFunctionDefinition(FunctionDefinitionAST* ast) {
void Parser::check(ExpressionAST* ast) {
TypeChecker check{unit};
check.setScope(scope_);
check.setReportErrors(config_.checkTypes);
check(ast);
}

Expand Down
12 changes: 0 additions & 12 deletions src/parser/cxx/parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -849,18 +849,6 @@ class Parser final {
[[nodiscard]] auto implicit_conversion(ExpressionAST*& expr,
const Type* destinationType) -> bool;

[[nodiscard]] auto integral_promotion(ExpressionAST*& expr) -> bool;

void check_cpp_cast_expression(CppCastExpressionAST* ast);

[[nodiscard]] auto check_static_cast(CppCastExpressionAST* ast) -> bool;

[[nodiscard]] auto check_cv_qualifiers(CvQualifiers target,
CvQualifiers source) const -> bool;

[[nodiscard]] auto check_cast_to_derived(const Type* targetType,
ExpressionAST* expression) -> bool;

[[nodiscard]] auto get_cv_qualifiers(const Type* type) const -> CvQualifiers;

[[nodiscard]] auto is_prvalue(ExpressionAST* expr) const -> bool;
Expand Down
Loading