HaxeFoundation / haxe

Haxe - The Cross-Platform Toolkit
https://haxe.org
6.15k stars 656 forks source link

extern inline new causes `this` used as variable name in cpp code #9028

Open romamik opened 4 years ago

romamik commented 4 years ago

This code generates invalid cpp code

class Foo {

    var map: Map<Int, Int>;
    var keys: Iterator<Int>;

    extern inline public function new(bar: Bar ) {
        this.map = bar.map;
        this.keys = map.keys();
    }

    inline public function foo(): Void {
        while (keys.hasNext()) {
            trace(keys.next());
        }
    }
}

class Bar {
    public var map: Map<Int, Int> = new Map();
    public function new() {
    }
}
class Main {

  static function main() {

      var bar: Bar = new Bar();
      bar.map[100] = 200;
      var foo: Foo = new Foo(bar);
      foo.foo();
  }
}

Cpp compilation fails with errors

./src/Foo.cpp(27): error C2059: syntax error: ';'
./src/Foo.cpp(27): error C2059: syntax error: 'this'
./src/Foo.cpp(31): error C2059: syntax error: '}'
./src/Foo.cpp(31): error C2143: syntax error: missing ';' before '}'
./src/Foo.cpp(33): error C2143: syntax error: missing ';' before '{'
./src/Foo.cpp(33): error C2447: '{': missing function header (old-style formal list?)

Generated code looks like this

23 void Foo_obj::__construct( ::Bar bar){
24              HX_STACKFRAME(&_hx_pos_33f1e4dc58dc3aff_6_new)
25 HXLINE(   7)     this->map = bar->map;
26 HXLINE(   8)     this->keys = {
27 HXLINE(   8)         ::Dynamic this = this->map;
28 HXDLIN(   8)         ::haxe::IMap_obj::keys(this);
29                  }
30 ;
31              }
romamik commented 4 years ago
  1. Foo_obj::__construct should not be generated at all because of extern inline new.
  2. Removing extern fixes the issue.
RealyUniqueName commented 4 years ago

You can also add -dce full to workaround the issue.

RealyUniqueName commented 4 years ago

It's not related to cpp. Some local var gets name this, which should not happen.

RealyUniqueName commented 4 years ago

Also, Foo's constructor is generated liek this (dump=pretty):

public inline function new(bar:Bar) {
    this.map = bar.map;
    this.keys = {
        var this = this.map;
        cast this.keys();
    };
}

Afaik blocks in value places should not reach generators.