diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim index a32be954e076..32e31e204eb2 100644 --- a/compiler/ccgtypes.nim +++ b/compiler/ccgtypes.nim @@ -1149,11 +1149,14 @@ proc isReloadable(m: BModule; prc: PSym): bool = proc isNonReloadable(m: BModule; prc: PSym): bool = return m.hcrOn and sfNonReloadable in prc.flags -proc parseVFunctionDecl(val: string; name, params, retType, superCall: var string; isFnConst, isOverride: var bool; isCtor: bool) = - var afterParams: string = "" +proc parseVFunctionDecl(val: string; name, params, retType, superCall: var string; isFnConst, isOverride, isMemberVirtual: var bool; isCtor: bool) = + var afterParams: string if scanf(val, "$*($*)$s$*", name, params, afterParams): isFnConst = afterParams.find("const") > -1 isOverride = afterParams.find("override") > -1 + isMemberVirtual = name.find("virtual ") > -1 + if isMemberVirtual: + name = name.replace("virtual ", "") if isCtor: discard scanf(afterParams, ":$s$*", superCall) else: @@ -1164,7 +1167,6 @@ proc parseVFunctionDecl(val: string; name, params, retType, superCall: var strin proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = false, isFwdDecl : bool = false) = assert sfCppMember * prc.flags != {} let isCtor = sfConstructor in prc.flags - let isVirtual = sfVirtual in prc.flags var check = initIntSet() fillBackendName(m, prc) fillLoc(prc.loc, locProc, prc.ast[namePos], OnUnknown) @@ -1179,10 +1181,11 @@ proc genMemberProcHeader(m: BModule; prc: PSym; result: var Rope; asPtr: bool = memberOp = "#->" var typDesc = getTypeDescWeak(m, typ, check, dkParam) let asPtrStr = rope(if asPtr: "_PTR" else: "") - var name, params, rettype, superCall: string = "" - var isFnConst, isOverride: bool = false - parseVFunctionDecl(prc.constraint.strVal, name, params, rettype, superCall, isFnConst, isOverride, isCtor) + var name, params, rettype, superCall: string + var isFnConst, isOverride, isMemberVirtual: bool + parseVFunctionDecl(prc.constraint.strVal, name, params, rettype, superCall, isFnConst, isOverride, isMemberVirtual, isCtor) genMemberProcParams(m, prc, superCall, rettype, name, params, check, true, false) + let isVirtual = sfVirtual in prc.flags or isMemberVirtual var fnConst, override: string if isCtor: name = typDesc diff --git a/tests/cpp/tmember.nim b/tests/cpp/tmember.nim index b0f630a9209a..3f498c722488 100644 --- a/tests/cpp/tmember.nim +++ b/tests/cpp/tmember.nim @@ -4,6 +4,9 @@ discard """ output: ''' 2 false +hello foo +hello boo +hello boo destructing destructing ''' @@ -11,18 +14,40 @@ destructing proc print(s: cstring) {.importcpp:"printf(@)", header:"".} type - Foo {.exportc.} = object + Doo {.exportc.} = object test: int -proc memberProc(f: Foo) {.exportc, member.} = +proc memberProc(f: Doo) {.exportc, member.} = echo $f.test -proc destructor(f: Foo) {.member: "~'1()", used.} = +proc destructor(f: Doo) {.member: "~'1()", used.} = print "destructing\n" -proc `==`(self, other: Foo): bool {.member:"operator==('2 const & #2) const -> '0"} = +proc `==`(self, other: Doo): bool {.member:"operator==('2 const & #2) const -> '0"} = self.test == other.test -let foo = Foo(test: 2) -foo.memberProc() -echo foo == Foo(test: 1) +let doo = Doo(test: 2) +doo.memberProc() +echo doo == Doo(test: 1) + +#virtual +proc newCpp*[T](): ptr T {.importcpp:"new '*0()".} +type + Foo = object of RootObj + FooPtr = ptr Foo + Boo = object of Foo + BooPtr = ptr Boo + +proc salute(self: FooPtr) {.member: "virtual $1()".} = + echo "hello foo" + +proc salute(self: BooPtr) {.member: "virtual $1()".} = + echo "hello boo" + +let foo = newCpp[Foo]() +let boo = newCpp[Boo]() +let booAsFoo = cast[FooPtr](newCpp[Boo]()) + +foo.salute() +boo.salute() +booAsFoo.salute()