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
39 changes: 31 additions & 8 deletions src/mlir/cxx/mlir/codegen_expressions.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1363,16 +1363,39 @@ auto Codegen::ExpressionVisitor::operator()(BinaryExpressionAST* ast)

auto Codegen::ExpressionVisitor::operator()(ConditionalExpressionAST* ast)
-> ExpressionResult {
auto op =
gen.emitTodoExpr(ast->firstSourceLocation(), to_string(ast->kind()));
auto trueBlock = gen.newBlock();
auto falseBlock = gen.newBlock();
auto endBlock = gen.newBlock();

#if false
auto conditionResult = gen.expression(ast->condition);
auto iftrueExpressionResult = gen.expression(ast->iftrueExpression);
auto iffalseExpressionResult = gen.expression(ast->iffalseExpression);
#endif
auto t = gen.newTemp(ast->type, ast->questionLoc);

return {op};
gen.condition(ast->condition, trueBlock, falseBlock);

auto endLoc = gen.getLocation(ast->lastSourceLocation());

// place the true block
gen.builder_.setInsertionPointToEnd(trueBlock);
auto trueExpressionResult = gen.expression(ast->iftrueExpression);
auto trueValue = gen.builder_.create<mlir::cxx::StoreOp>(
gen.getLocation(ast->questionLoc), trueExpressionResult.value, t);
gen.branch(endLoc, endBlock);

// place the false block
gen.builder_.setInsertionPointToEnd(falseBlock);
auto falseExpressionResult = gen.expression(ast->iffalseExpression);
auto falseValue = gen.builder_.create<mlir::cxx::StoreOp>(
gen.getLocation(ast->colonLoc), falseExpressionResult.value, t);
gen.branch(endLoc, endBlock);

// place the end block
gen.builder_.setInsertionPointToEnd(endBlock);

if (format == ExpressionFormat::kSideEffect) return {};

auto resultType = gen.convertType(ast->type);
auto loadOp = gen.builder_.create<mlir::cxx::LoadOp>(
gen.getLocation(ast->colonLoc), resultType, t);
return {loadOp};
}

auto Codegen::ExpressionVisitor::operator()(YieldExpressionAST* ast)
Expand Down
59 changes: 37 additions & 22 deletions src/parser/cxx/type_checker.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1229,9 +1229,10 @@ void TypeChecker::Visitor::operator()(ConditionalExpressionAST* ast) {
control()->remove_cv(ast->iffalseExpression->type)))
return false;

ast->valueCategory = ast->iftrueExpression->valueCategory;
ast->type = ast->iftrueExpression->type;

ast->valueCategory = ast->iftrueExpression->valueCategory;

return true;
};

Expand Down Expand Up @@ -1277,33 +1278,47 @@ void TypeChecker::Visitor::operator()(ConditionalExpressionAST* ast) {
return true;
};

if (ast->iftrueExpression && ast->iffalseExpression) {
if (check_void_type()) return;
if (check_same_type_and_value_category()) return;

(void)array_to_pointer_conversion(ast->iftrueExpression);
(void)function_to_pointer_conversion(ast->iftrueExpression);
if (!ast->iftrueExpression) {
error(ast->questionLoc,
"left operand to ? is null, but right operand is not null");
return;
}

(void)array_to_pointer_conversion(ast->iffalseExpression);
(void)function_to_pointer_conversion(ast->iffalseExpression);
if (!ast->iffalseExpression) {
error(ast->colonLoc,
"right operand to ? is null, but left operand is not null");
return;
}

if (check_arith_types()) return;
if (check_same_types()) return;
if (check_compatible_pointers()) return;
if (is_parsing_c()) {
// in C, both expressions must be prvalues
(void)ensure_prvalue(ast->iftrueExpression);
(void)ensure_prvalue(ast->iffalseExpression);
}

if (!ast->type) {
auto iftrueType =
ast->iftrueExpression ? ast->iftrueExpression->type : nullptr;
if (check_void_type()) return;
if (check_same_type_and_value_category()) return;

auto iffalseType =
ast->iffalseExpression ? ast->iffalseExpression->type : nullptr;
(void)array_to_pointer_conversion(ast->iftrueExpression);
(void)function_to_pointer_conversion(ast->iftrueExpression);

error(ast->questionLoc,
std::format(
"left operand to ? is '{}', but right operand is of type '{}'",
to_string(iftrueType), to_string(iffalseType)));
}
(void)array_to_pointer_conversion(ast->iffalseExpression);
(void)function_to_pointer_conversion(ast->iffalseExpression);

if (check_arith_types()) return;
if (check_same_types()) return;
if (check_compatible_pointers()) return;

auto iftrueType =
ast->iftrueExpression ? ast->iftrueExpression->type : nullptr;

auto iffalseType =
ast->iffalseExpression ? ast->iffalseExpression->type : nullptr;

error(ast->questionLoc,
std::format(
"left operand to ? is '{}', but right operand is of type '{}'",
to_string(iftrueType), to_string(iffalseType)));
}

void TypeChecker::Visitor::operator()(YieldExpressionAST* ast) {}
Expand Down
Loading