diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 9d3ead3..7624bab 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -56,4 +56,4 @@ jobs: - name: Test working-directory: ${{github.workspace}}/build - run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure -E "codegen/pointer.aw" + run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure diff --git a/lang/source/codegen/llvm/backend_llvm.c++ b/lang/source/codegen/llvm/backend_llvm.c++ index 6b6996d..07ff6e7 100644 --- a/lang/source/codegen/llvm/backend_llvm.c++ +++ b/lang/source/codegen/llvm/backend_llvm.c++ @@ -368,8 +368,12 @@ auto backend_llvm::gen_local(const middle::variable& var) -> llvm::Value* auto* alloca = builder.CreateAlloca(get_llvm_type(context, var.type), nullptr, var.name); - if (var.value) - builder.CreateStore(gen(var.value), alloca); + if (var.value) { + auto* init = gen(var.value); + if (!init) + return nullptr; + builder.CreateStore(init, alloca); + } return alloca; } @@ -497,6 +501,8 @@ auto backend_llvm::gen(const middle::numeric_literal& expr) -> llvm::Constant* return ConstantFP::get(context, APFloat(APFloat::IEEEsingle(), expr.value)); if (type->isDoubleTy()) return ConstantFP::get(context, APFloat(APFloat::IEEEdouble(), expr.value)); + if (type->isPointerTy()) + return ConstantPointerNull::get(cast(type)); } return nullptr; } diff --git a/lang/source/semantic/type_inference.c++ b/lang/source/semantic/type_inference.c++ index 9a61071..1a57aba 100644 --- a/lang/source/semantic/type_inference.c++ +++ b/lang/source/semantic/type_inference.c++ @@ -313,6 +313,11 @@ struct type_inference_visitor auto propagate_type(ir::type* type, numeric_literal& expr) -> ir::type* { + // Only a literal `0` may stand in for a null pointer; any other + // integer literal assigned to a pointer type is a real mismatch. + if (get_if(&type->kind) && expr.value != "0") + return error(diag, diagnostic_id::type_mismathch, location(), type->name, std::string("numeric_literal")); + return (expr.type = type); } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 6b1e523..f807103 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -14,10 +14,12 @@ set(TESTS errors/not_allowed_here.aw errors/not_implemented_yet.aw errors/recovery.aw + errors/pointer_nonzero_init.aw codegen/array.aw codegen/array_of_structs.aw codegen/chain.aw codegen/function.aw + codegen/pointer_null_init.aw modules/main.aw ) @@ -26,6 +28,7 @@ set(NEGATIVE_TESTS errors/not_allowed_here.aw errors/not_implemented_yet.aw errors/recovery.aw + errors/pointer_nonzero_init.aw ) set(RUNTIME_TESTS diff --git a/test/codegen/pointer_null_init.aw b/test/codegen/pointer_null_init.aw new file mode 100644 index 0000000..1378115 --- /dev/null +++ b/test/codegen/pointer_null_init.aw @@ -0,0 +1,4 @@ +func main() +{ + var p: int* = 0; +} diff --git a/test/errors/pointer_nonzero_init.aw b/test/errors/pointer_nonzero_init.aw new file mode 100644 index 0000000..a11124c --- /dev/null +++ b/test/errors/pointer_nonzero_init.aw @@ -0,0 +1,4 @@ +func main() +{ + var p: int* = 5; +}