diff --git a/src/parser/cxx/parser.cc b/src/parser/cxx/parser.cc index 5a1f0508..8df37e5a 100644 --- a/src/parser/cxx/parser.cc +++ b/src/parser/cxx/parser.cc @@ -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(ast->type)) { - ast->type = refType->elementType(); - ast->valueCategory = ValueCategory::kLValue; - return; - } - - if (auto rvalueRefType = type_cast(ast->type)) { - ast->type = rvalueRefType->elementType(); - - if (type_cast(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(sourceType)) { - cv1 = qualType->cvQualifiers(); - sourceType = qualType->elementType(); - } - - auto targetRefType = type_cast(targetType); - if (!targetRefType) return false; - - targetType = targetRefType->elementType(); - - CvQualifiers cv2 = CvQualifiers::kNone; - if (auto qualType = type_cast(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; } @@ -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(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(ast->expression); - idExpr && idExpr->nestedNameSpecifier) { - auto symbol = idExpr->symbol; - if (auto field = symbol_cast(symbol); - field && !field->isStatic()) { - auto parentClass = field->enclosingSymbol(); - auto classType = type_cast(parentClass->type()); - - ast->type = - control_->getMemberObjectPointerType(classType, field->type()); - - ast->valueCategory = ValueCategory::kPrValue; - - break; - } - - if (auto function = symbol_cast(symbol); - function && !function->isStatic()) { - auto functionType = type_cast(function->type()); - auto parentClass = function->enclosingSymbol(); - auto classType = type_cast(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(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(ty)) { - if (ptrTy && !control_->is_void(ptrTy->elementType())) { - ast->type = ptrTy; - ast->valueCategory = ValueCategory::kLValue; - } - } - - break; - } - - default: - break; - } // switch + check(ast); return true; } @@ -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; } @@ -6216,6 +5955,7 @@ 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); } @@ -6223,15 +5963,10 @@ 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; @@ -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); } diff --git a/src/parser/cxx/parser.h b/src/parser/cxx/parser.h index 45fb901d..71a47e7f 100644 --- a/src/parser/cxx/parser.h +++ b/src/parser/cxx/parser.h @@ -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; diff --git a/src/parser/cxx/type_checker.cc b/src/parser/cxx/type_checker.cc index 022485ce..d4bc01de 100644 --- a/src/parser/cxx/type_checker.cc +++ b/src/parser/cxx/type_checker.cc @@ -48,6 +48,11 @@ struct TypeChecker::Visitor { return check.unit_->control(); } + void error(SourceLocation loc, std::string message) { + if (!check.reportErrors_) return; + check.unit_->error(loc, std::move(message)); + } + [[nodiscard]] auto strip_parentheses(ExpressionAST* ast) -> ExpressionAST*; [[nodiscard]] auto strip_cv(const Type*& type) -> CvQualifiers; [[nodiscard]] auto merge_cv(CvQualifiers cv1, CvQualifiers cv2) const @@ -102,6 +107,13 @@ struct TypeChecker::Visitor { [[nodiscard]] auto is_lvalue(ExpressionAST* expr) const -> bool; [[nodiscard]] auto is_xvalue(ExpressionAST* expr) const -> bool; [[nodiscard]] auto is_glvalue(ExpressionAST* expr) const -> bool; + [[nodiscard]] auto check_cv_qualifiers(CvQualifiers target, + CvQualifiers source) const -> bool; + + void check_cpp_cast_expression(CppCastExpressionAST* ast); + [[nodiscard]] auto check_static_cast(CppCastExpressionAST* ast) -> bool; + [[nodiscard]] auto check_cast_to_derived(const Type* targetType, + ExpressionAST* expression) -> bool; void operator()(GeneratedLiteralExpressionAST* ast); void operator()(CharLiteralExpressionAST* ast); @@ -245,7 +257,94 @@ void TypeChecker::Visitor::operator()(MemberExpressionAST* ast) {} void TypeChecker::Visitor::operator()(PostIncrExpressionAST* ast) {} -void TypeChecker::Visitor::operator()(CppCastExpressionAST* ast) {} +void TypeChecker::Visitor::operator()(CppCastExpressionAST* ast) { + check_cpp_cast_expression(ast); + + switch (check.unit_->tokenKind(ast->castLoc)) { + case TokenKind::T_STATIC_CAST: + if (check_static_cast(ast)) break; + error(ast->firstSourceLocation(), "invalid static_cast"); + break; + + default: + break; + } // switch +} + +void TypeChecker::Visitor::check_cpp_cast_expression( + CppCastExpressionAST* ast) { + if (!ast->typeId) { + return; + } + + ast->type = ast->typeId->type; + + if (auto refType = type_cast(ast->type)) { + ast->type = refType->elementType(); + ast->valueCategory = ValueCategory::kLValue; + return; + } + + if (auto rvalueRefType = type_cast(ast->type)) { + ast->type = rvalueRefType->elementType(); + + if (type_cast(ast->type)) { + ast->valueCategory = ValueCategory::kLValue; + } else { + ast->valueCategory = ValueCategory::kXValue; + } + } +} + +auto TypeChecker::Visitor::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 = control()->get_cv_qualifiers(ast->expression->type); + const auto cv2 = control()->get_cv_qualifiers(targetType); + + if (!check_cv_qualifiers(cv2, cv1)) return false; + + if (implicit_conversion(ast->expression, ast->type)) return true; + + return false; +} + +auto TypeChecker::Visitor::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(sourceType)) { + cv1 = qualType->cvQualifiers(); + sourceType = qualType->elementType(); + } + + auto targetRefType = type_cast(targetType); + if (!targetRefType) return false; + + targetType = targetRefType->elementType(); + + CvQualifiers cv2 = CvQualifiers::kNone; + if (auto qualType = type_cast(targetType)) { + cv2 = qualType->cvQualifiers(); + targetType = qualType->elementType(); + } + + if (!check_cv_qualifiers(cv2, cv1)) return false; + + if (!control()->is_base_of(sourceType, targetType)) return false; + + return true; +} void TypeChecker::Visitor::operator()(BuiltinBitCastExpressionAST* ast) {} @@ -265,7 +364,166 @@ void TypeChecker::Visitor::operator()(TypeIdReflectExpressionAST* ast) {} void TypeChecker::Visitor::operator()(ReflectExpressionAST* ast) {} -void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) {} +void TypeChecker::Visitor::operator()(UnaryExpressionAST* ast) { + switch (ast->op) { + case TokenKind::T_STAR: { + auto pointerType = type_cast(ast->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(ast->expression); + idExpr && idExpr->nestedNameSpecifier) { + auto symbol = idExpr->symbol; + if (auto field = symbol_cast(symbol); + field && !field->isStatic()) { + auto parentClass = field->enclosingSymbol(); + auto classType = type_cast(parentClass->type()); + + ast->type = + control()->getMemberObjectPointerType(classType, field->type()); + + ast->valueCategory = ValueCategory::kPrValue; + + break; + } + + if (auto function = symbol_cast(symbol); + function && !function->isStatic()) { + auto functionType = type_cast(function->type()); + auto parentClass = function->enclosingSymbol(); + auto classType = type_cast(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(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(ty)) { + if (ptrTy && !control()->is_void(ptrTy->elementType())) { + ast->type = ptrTy; + ast->valueCategory = ValueCategory::kLValue; + } + } + + break; + } + + default: + break; + } // switch +} void TypeChecker::Visitor::operator()(AwaitExpressionAST* ast) {} @@ -407,7 +665,15 @@ void TypeChecker::Visitor::operator()(YieldExpressionAST* ast) {} void TypeChecker::Visitor::operator()(ThrowExpressionAST* ast) {} -void TypeChecker::Visitor::operator()(AssignmentExpressionAST* ast) {} +void TypeChecker::Visitor::operator()(AssignmentExpressionAST* ast) { + if (!ast->leftExpression) return; + if (!ast->rightExpression) return; + + ast->type = ast->leftExpression->type; + ast->valueCategory = ast->leftExpression->valueCategory; + + (void)implicit_conversion(ast->rightExpression, ast->type); +} void TypeChecker::Visitor::operator()(PackExpansionExpressionAST* ast) {} @@ -1123,6 +1389,15 @@ auto TypeChecker::Visitor::is_glvalue(ExpressionAST* expr) const -> bool { expr->valueCategory == ValueCategory::kXValue; } +auto TypeChecker::Visitor::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; +} + TypeChecker::TypeChecker(TranslationUnit* unit) : unit_(unit) {} void TypeChecker::operator()(ExpressionAST* ast) { @@ -1135,10 +1410,6 @@ void TypeChecker::check(ExpressionAST* ast) { visit(Visitor{*this}, ast); } -auto TypeChecker::integral_promotion(ExpressionAST*& expr) -> bool { - return Visitor{*this}.integral_promotion(expr); -} - auto TypeChecker::ensure_prvalue(ExpressionAST*& expr) -> bool { return Visitor{*this}.ensure_prvalue(expr); } diff --git a/src/parser/cxx/type_checker.h b/src/parser/cxx/type_checker.h index d9d61108..aa10c907 100644 --- a/src/parser/cxx/type_checker.h +++ b/src/parser/cxx/type_checker.h @@ -34,6 +34,9 @@ class TypeChecker { return unit_; } + [[nodiscard]] auto reportErrors() const -> bool { return reportErrors_; } + void setReportErrors(bool reportErrors) { reportErrors_ = reportErrors; } + void setScope(Scope* scope) { scope_ = scope; } void operator()(ExpressionAST* ast); @@ -45,13 +48,12 @@ class TypeChecker { [[nodiscard]] auto implicit_conversion(ExpressionAST*& expr, const Type* destinationType) -> bool; - [[nodiscard]] auto integral_promotion(ExpressionAST*& expr) -> bool; - private: struct Visitor; TranslationUnit* unit_; Scope* scope_ = nullptr; + bool reportErrors_ = false; }; } // namespace cxx diff --git a/tests/unit_tests/ast/array_to_pointer_conv_01.cc b/tests/unit_tests/ast/array_to_pointer_conv_01.cc index 38fd6e2c..a143e4bf 100644 --- a/tests/unit_tests/ast/array_to_pointer_conv_01.cc +++ b/tests/unit_tests/ast/array_to_pointer_conv_01.cc @@ -55,7 +55,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: p // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue int*] +// CHECK-NEXT: expression: assignment-expression [lvalue int*] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue int*] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/boolean_conv_01.cc b/tests/unit_tests/ast/boolean_conv_01.cc index b006bb82..cd12242d 100644 --- a/tests/unit_tests/ast/boolean_conv_01.cc +++ b/tests/unit_tests/ast/boolean_conv_01.cc @@ -50,7 +50,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: b // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue bool] +// CHECK-NEXT: expression: assignment-expression [lvalue bool] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue bool] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/floating_integral_conv_01.cc b/tests/unit_tests/ast/floating_integral_conv_01.cc index bc2dad33..1112b9cd 100644 --- a/tests/unit_tests/ast/floating_integral_conv_01.cc +++ b/tests/unit_tests/ast/floating_integral_conv_01.cc @@ -82,7 +82,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: i // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue double] +// CHECK-NEXT: expression: assignment-expression [lvalue double] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue double] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/floating_point_conv_01.cc b/tests/unit_tests/ast/floating_point_conv_01.cc index d4cdcf27..a7eaa7e3 100644 --- a/tests/unit_tests/ast/floating_point_conv_01.cc +++ b/tests/unit_tests/ast/floating_point_conv_01.cc @@ -82,7 +82,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: d // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue float] +// CHECK-NEXT: expression: assignment-expression [lvalue float] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue float] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/floating_point_promotion_01.cc b/tests/unit_tests/ast/floating_point_promotion_01.cc index 51b80881..35c647c7 100644 --- a/tests/unit_tests/ast/floating_point_promotion_01.cc +++ b/tests/unit_tests/ast/floating_point_promotion_01.cc @@ -82,7 +82,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: d // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue double] +// CHECK-NEXT: expression: assignment-expression [lvalue double] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue double] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/function_to_pointer_conv_01.cc b/tests/unit_tests/ast/function_to_pointer_conv_01.cc index 5b8ac4cc..d4737171 100644 --- a/tests/unit_tests/ast/function_to_pointer_conv_01.cc +++ b/tests/unit_tests/ast/function_to_pointer_conv_01.cc @@ -85,7 +85,7 @@ auto main() -> int { // CHECK-NEXT: integral-type-specifier // CHECK-NEXT: specifier: int // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue void (*)(int, int)] +// CHECK-NEXT: expression: assignment-expression [lvalue void (*)(int, int)] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue void (*)(int, int)] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/integral_conversion_01.cc b/tests/unit_tests/ast/integral_conversion_01.cc index 81d52717..2254d617 100644 --- a/tests/unit_tests/ast/integral_conversion_01.cc +++ b/tests/unit_tests/ast/integral_conversion_01.cc @@ -82,7 +82,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: i // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue char] +// CHECK-NEXT: expression: assignment-expression [lvalue char] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue char] // CHECK-NEXT: unqualified-id: name-id diff --git a/tests/unit_tests/ast/integral_promotion_conv_01.cc b/tests/unit_tests/ast/integral_promotion_conv_01.cc index 37bf467b..558a6aa6 100644 --- a/tests/unit_tests/ast/integral_promotion_conv_01.cc +++ b/tests/unit_tests/ast/integral_promotion_conv_01.cc @@ -82,7 +82,7 @@ auto main() -> int { // CHECK-NEXT: unqualified-id: name-id // CHECK-NEXT: identifier: i // CHECK-NEXT: expression-statement -// CHECK-NEXT: expression: assignment-expression [prvalue int] +// CHECK-NEXT: expression: assignment-expression [lvalue int] // CHECK-NEXT: op: = // CHECK-NEXT: left-expression: id-expression [lvalue int] // CHECK-NEXT: unqualified-id: name-id