From edc3f60ff094f6844134e193eb3c8bda5bc2beb5 Mon Sep 17 00:00:00 2001 From: Ary Borenszweig <aborenszweig@manas.com.ar> Date: Mon, 1 Dec 2014 09:21:25 -0300 Subject: [PATCH] Fixed another const initialization issue --- spec/compiler/codegen/const_spec.cr | 27 +++++++++++++++++++++++++ src/compiler/crystal/codegen/codegen.cr | 22 +++++++++++--------- 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/spec/compiler/codegen/const_spec.cr b/spec/compiler/codegen/const_spec.cr index 5df31097a6..aafc10b165 100644 --- a/spec/compiler/codegen/const_spec.cr +++ b/spec/compiler/codegen/const_spec.cr @@ -243,4 +243,31 @@ describe "Codegen: const" do Foo::Y.value )).to_i.should eq(1) end + + it "codegens constant that is declared later because of virtual dispatch" do + run(%( + class Base + def base + end + end + + class Base2 < Base + def base + end + end + + b = Base.new || Base2.new + b.base + + class MyBase < Base + CONST = 1 + + def base + CONST + end + end + + MyBase.new.base + )).to_i.should eq(1) + end end diff --git a/src/compiler/crystal/codegen/codegen.cr b/src/compiler/crystal/codegen/codegen.cr index 86434a7004..84378eb59d 100644 --- a/src/compiler/crystal/codegen/codegen.cr +++ b/src/compiler/crystal/codegen/codegen.cr @@ -159,8 +159,8 @@ module Crystal alloca_vars @mod.vars, @mod - declare_const(@mod.types["ARGC_UNSAFE"] as Const) - declare_const(@mod.types["ARGV_UNSAFE"] as Const) + initialize_const(@mod.types["ARGC_UNSAFE"] as Const) + initialize_const(@mod.types["ARGV_UNSAFE"] as Const) end def wrap_builder(builder) @@ -479,7 +479,7 @@ module Crystal def visit(node : EnumDef) node.enum_type.try &.types.each_value do |type| - declare_const(type as Const) + initialize_const(type as Const) end @last = llvm_nil false @@ -642,7 +642,7 @@ module Crystal # Initialize constants if they are used if target.is_a?(Path) const = target.target_const.not_nil! - declare_const const + initialize_const const @last = llvm_nil return false end @@ -878,11 +878,7 @@ module Crystal @last = initializer else global_name = const.llvm_name - - global = @main_mod.globals[global_name]? - unless global - node.raise "Bug: global not found for #{const}" - end + global = declare_const(const, global_name) if @llvm_mod != @main_mod global = @llvm_mod.globals[global_name]? @@ -908,9 +904,15 @@ module Crystal end def declare_const(const, global_name = const.llvm_name) + @main_mod.globals[global_name]? || + @main_mod.globals.add(llvm_type(const.value.type), global_name) + end + + def initialize_const(const, global_name = const.llvm_name) return unless const.used - global = @main_mod.globals.add(llvm_type(const.value.type), global_name) + # It might be that the constant is already declared by not initialized + global = declare_const(const, global_name) in_const_block(const.container) do alloca_vars const.vars -- GitLab