少々厄介なオーバーロードバグ

とあるユーザー様から、下記のようなコードがうまくコンパイルできないというバグ報告をいただきました。


function func(n As double) as String
print "double";n
endfunction

function func(n As dword) as String
print "dword";n
endfunction

func(123) 'オーバーロードを解決できません
func(1.23) 'オーバーロードを解決できません


一見すると、エラーなどはでないハズなのですが、AB5β5で試すと確かにエラーがでます。


最適化中...
コンパイル中...
test5.bas(11) - "func" オーバーロードを解決できません
test5.bas(12) - "func" オーバーロードを解決できません

                                                                                                        • -

コンパイルは中断されました(エラー:2、警告:0)。


色々と調べた結果、実体オブジェクトを戻り値にしていることが引き金となって生じるバグでした。このバグの原理はこうです。


実体オブジェクトを戻り値に持つ場合は、隠れ第一パラメータ(クラスメソッドのときは第二)というものが存在し、そこには戻り値を格納するためのオブジェクトポインタを保有することになっています。オーバーロード解決時に実体オブジェクトの戻り値が隠れパラメータとして存在してしまうと、今回のような不具合を生じさせてしまうということなのです。


下記は現在の間違った手順でオーバーロードが解決される流れです。

  1. 戻り値の実態オブジェクトを隠れパラメータとして考慮
  2. オーバーロードを解決
  3. 呼び出し


呼び出し側はまさか戻り値用の隠れパラメータが考慮された上でオーバーロードが解決されるなどとは知る由もないので、この手順を下記のように修正します。

  1. オーバーロードを解決
  2. 戻り値の実態オブジェクトを隠れパラメータとして考慮
  3. 呼び出し


隠れパラメータは呼び出し直前に考慮しろってことですね。隠れパラメータがあるパラメータリスト、ないパラメータリストの2つを管理するのが面倒という発想でコード設計をしてしまったのがいけなかったのかもしれません。原因も明確になりましたし、次回のバージョンアップでキッチリと修正しようと思います。