@@ -109,6 +109,10 @@ struct TypeChecker::Visitor {
109109 ExpressionAST*& other)
110110 -> const Type*;
111111
112+ [[nodiscard]] auto composite_pointer_type (ExpressionAST*& expr,
113+ ExpressionAST*& other)
114+ -> const Type*;
115+
112116 [[nodiscard]] auto is_null_pointer_constant (ExpressionAST* expr) const
113117 -> bool;
114118
@@ -890,11 +894,135 @@ void TypeChecker::Visitor::operator()(BinaryExpressionAST* ast) {
890894 } // switch
891895}
892896
893- void TypeChecker::Visitor::operator ()(ConditionalExpressionAST* ast) {}
897+ void TypeChecker::Visitor::operator ()(ConditionalExpressionAST* ast) {
898+ auto check_void_type = [&] {
899+ if (!control ()->is_void (ast->iftrueExpression ->type ) &&
900+ !control ()->is_void (ast->iffalseExpression ->type ))
901+ return false ;
902+
903+ // one of the two expressions is void
904+ if (ast_cast<ThrowExpressionAST>(
905+ strip_parentheses (ast->iftrueExpression ))) {
906+ ast->type = ast->iffalseExpression ->type ;
907+ ast->valueCategory = ast->iffalseExpression ->valueCategory ;
908+ return true ;
909+ }
910+
911+ if (ast_cast<ThrowExpressionAST>(
912+ strip_parentheses (ast->iffalseExpression ))) {
913+ ast->type = ast->iftrueExpression ->type ;
914+ ast->valueCategory = ast->iftrueExpression ->valueCategory ;
915+ return true ;
916+ }
917+
918+ if (!control ()->is_same (ast->iftrueExpression ->type ,
919+ ast->iffalseExpression ->type )) {
920+ error (ast->questionLoc ,
921+ std::format (
922+ " left operand to ? is '{}', but right operand is of type '{}'" ,
923+ to_string (ast->iftrueExpression ->type ),
924+ to_string (ast->iffalseExpression ->type )));
925+ }
926+
927+ ast->type = control ()->getVoidType ();
928+ ast->valueCategory = ValueCategory::kPrValue ;
929+
930+ return true ;
931+ };
932+
933+ auto check_same_type_and_value_category = [&] {
934+ if (ast->iftrueExpression ->valueCategory !=
935+ ast->iffalseExpression ->valueCategory ) {
936+ return false ;
937+ }
938+
939+ if (!control ()->is_same (control ()->remove_cv (ast->iftrueExpression ->type ),
940+ control ()->remove_cv (ast->iffalseExpression ->type )))
941+ return false ;
942+
943+ ast->valueCategory = ast->iftrueExpression ->valueCategory ;
944+ ast->type = ast->iftrueExpression ->type ;
945+
946+ return true ;
947+ };
948+
949+ auto check_arith_types = [&] {
950+ if (!control ()->is_arithmetic_or_unscoped_enum (ast->iftrueExpression ->type ))
951+ return false ;
952+ if (!control ()->is_arithmetic_or_unscoped_enum (
953+ ast->iffalseExpression ->type ))
954+ return false ;
955+
956+ ast->type = usual_arithmetic_conversion (ast->iftrueExpression ,
957+ ast->iffalseExpression );
958+
959+ if (!ast->type ) return false ;
960+
961+ ast->valueCategory = ValueCategory::kPrValue ;
962+
963+ return true ;
964+ };
965+
966+ auto check_same_types = [&] {
967+ if (!control ()->is_same (ast->iftrueExpression ->type ,
968+ ast->iffalseExpression ->type ))
969+ return false ;
970+
971+ ast->type = ast->iftrueExpression ->type ;
972+ ast->valueCategory = ValueCategory::kPrValue ;
973+ return true ;
974+ };
975+
976+ auto check_compatible_pointers = [&] {
977+ if (!control ()->is_pointer (ast->iftrueExpression ->type ) &&
978+ !control ()->is_pointer (ast->iffalseExpression ->type ))
979+ return false ;
980+
981+ ast->type =
982+ composite_pointer_type (ast->iftrueExpression , ast->iffalseExpression );
983+
984+ ast->valueCategory = ValueCategory::kPrValue ;
985+
986+ if (!ast->type ) return false ;
987+
988+ return true ;
989+ };
990+
991+ if (ast->iftrueExpression && ast->iffalseExpression ) {
992+ if (check_void_type ()) return ;
993+ if (check_same_type_and_value_category ()) return ;
994+
995+ (void )array_to_pointer_conversion (ast->iftrueExpression );
996+ (void )function_to_pointer_conversion (ast->iftrueExpression );
997+
998+ (void )array_to_pointer_conversion (ast->iffalseExpression );
999+ (void )function_to_pointer_conversion (ast->iffalseExpression );
1000+
1001+ if (check_arith_types ()) return ;
1002+ if (check_same_types ()) return ;
1003+ if (check_compatible_pointers ()) return ;
1004+ }
1005+
1006+ if (!ast->type ) {
1007+ auto iftrueType =
1008+ ast->iftrueExpression ? ast->iftrueExpression ->type : nullptr ;
1009+
1010+ auto iffalseType =
1011+ ast->iffalseExpression ? ast->iffalseExpression ->type : nullptr ;
1012+
1013+ error (ast->questionLoc ,
1014+ std::format (
1015+ " left operand to ? is '{}', but right operand is of type '{}'" ,
1016+ to_string (iftrueType), to_string (iffalseType)));
1017+ }
1018+ }
8941019
8951020void TypeChecker::Visitor::operator ()(YieldExpressionAST* ast) {}
8961021
897- void TypeChecker::Visitor::operator ()(ThrowExpressionAST* ast) {}
1022+ void TypeChecker::Visitor::operator ()(ThrowExpressionAST* ast) {
1023+ ast->type = control ()->getVoidType ();
1024+ ast->valueCategory = ValueCategory::kPrValue ;
1025+ }
8981026
8991027void TypeChecker::Visitor::operator ()(AssignmentExpressionAST* ast) {
9001028 if (!ast->leftExpression ) return ;
@@ -914,7 +1042,10 @@ void TypeChecker::Visitor::operator()(TypeTraitExpressionAST* ast) {
9141042 ast->type = control ()->getBoolType ();
9151043}
9161044
917- void TypeChecker::Visitor::operator ()(ConditionExpressionAST* ast) {}
1045+ void TypeChecker::Visitor::operator ()(ConditionExpressionAST* ast) {
1046+ ast->type = control ()->getBoolType ();
1047+ ast->valueCategory = ValueCategory::kPrValue ;
1048+ }
9181049
9191050void TypeChecker::Visitor::operator ()(EqualInitializerAST* ast) {
9201051 if (!ast->expression ) return ;
@@ -1605,6 +1736,45 @@ auto TypeChecker::Visitor::usual_arithmetic_conversion(ExpressionAST*& expr,
16051736 return control ()->getIntType ();
16061737}
16071738
1739+ auto TypeChecker::Visitor::composite_pointer_type (ExpressionAST*& expr,
1740+ ExpressionAST*& other)
1741+ -> const Type* {
1742+ if (control ()->is_null_pointer (expr->type ) &&
1743+ control ()->is_null_pointer (other->type ))
1744+ return control ()->getNullptrType ();
1745+
1746+ if (is_null_pointer_constant (expr)) return other->type ;
1747+ if (is_null_pointer_constant (other)) return expr->type ;
1748+
1749+ auto is_pointer_to_cv_void = [this ](const Type* type) {
1750+ if (!control ()->is_pointer (type)) return false ;
1751+ if (!control ()->is_void (control ()->get_element_type (type))) return false ;
1752+ return true ;
1753+ };
1754+
1755+ if (control ()->is_pointer (expr->type ) && control ()->is_pointer (other->type )) {
1756+ auto t1 = control ()->get_element_type (expr->type );
1757+ const auto cv1 = strip_cv (t1);
1758+
1759+ auto t2 = control ()->get_element_type (other->type );
1760+ const auto cv2 = strip_cv (t2);
1761+
1762+ if (control ()->is_void (t1)) {
1763+ return control ()->getPointerType (control ()->add_cv (t1, cv2));
1764+ }
1765+
1766+ if (control ()->is_void (t2)) {
1767+ return control ()->getPointerType (control ()->add_cv (t2, cv1));
1768+ }
1769+
1770+ // TODO: check for noexcept function pointers
1771+
1772+ // TODO: check for reference related
1773+ }
1774+
1775+ return nullptr ;
1776+ }
1777+
16081778auto TypeChecker::Visitor::is_null_pointer_constant (ExpressionAST* expr) const
16091779 -> bool {
16101780 if (control ()->is_null_pointer (expr->type )) return true ;
0 commit comments