mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-09 06:23:25 +00:00
hacky attempt to reconcile default explicit constructors with enforcement of brace initialization, instead of memsetting imported objects to 0
This commit is contained in:
@@ -200,6 +200,9 @@ proc isImportedCppType(t: PType): bool =
|
||||
result = (t.sym != nil and sfInfixCall in t.sym.flags) or
|
||||
(x.sym != nil and sfInfixCall in x.sym.flags)
|
||||
|
||||
proc isOrHasImportedCppType(typ: PType): bool =
|
||||
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
|
||||
|
||||
proc getTypeDescAux(m: BModule, origTyp: PType, check: var IntSet; kind: TSymKind): Rope
|
||||
|
||||
proc isObjLackingTypeField(typ: PType): bool {.inline.} =
|
||||
@@ -553,7 +556,10 @@ proc genRecordFieldsAux(m: BModule, n: PNode,
|
||||
else:
|
||||
# don't use fieldType here because we need the
|
||||
# tyGenericInst for C++ template support
|
||||
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
if fieldType.isOrHasImportedCppType():
|
||||
result.addf("$1$3 $2{};$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
else:
|
||||
result.addf("$1$3 $2;$n", [getTypeDescAux(m, field.loc.t, check, skField), sname, noAlias])
|
||||
else: internalError(m.config, n.info, "genRecordFieldsAux()")
|
||||
|
||||
proc getRecordFields(m: BModule, typ: PType, check: var IntSet): Rope =
|
||||
|
||||
@@ -487,9 +487,6 @@ proc resetLoc(p: BProc, loc: var TLoc) =
|
||||
# on the bytes following the m_type field?
|
||||
genObjectInit(p, cpsStmts, loc.t, loc, constructObj)
|
||||
|
||||
proc isOrHasImportedCppType(typ: PType): bool =
|
||||
searchTypeFor(typ.skipTypes({tyRef}), isImportedCppType)
|
||||
|
||||
proc constructLoc(p: BProc, loc: var TLoc, isTemp = false) =
|
||||
let typ = loc.t
|
||||
if optSeqDestructors in p.config.globalOptions and skipTypes(typ, abstractInst + {tyStatic}).kind in {tyString, tySequence}:
|
||||
@@ -644,7 +641,23 @@ proc assignGlobalVar(p: BProc, n: PNode; value: Rope) =
|
||||
if sfVolatile in s.flags: decl.add(" volatile")
|
||||
if sfNoalias in s.flags: decl.add(" NIM_NOALIAS")
|
||||
if value != "":
|
||||
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||
if p.module.compileToCpp and value.startsWith "{{}":
|
||||
# TODO: taking this branch, re"\{\{\}(,\s\{\})*\}" might be emitted, resulting in
|
||||
# either warnings (GCC 12.2+) or errors (Clang 15, MSVC 19.3+) of C++11+ compilers **when
|
||||
# explicit constructors are around** due to overload resolution rules in place [^0][^1][^2]
|
||||
# *Workaround* here: have C++'s static initialization mechanism do the default init work,
|
||||
# for us lacking a deeper knowledge of an imported object's constructors' ex-/implicitness
|
||||
# (so far) *and yet* trying to achieve default initialization.
|
||||
# Still, generating {}s in genConstObjConstr() just to omit them here is faaaar from ideal;
|
||||
# need to figure out a better way, possibly by keeping around more data about the
|
||||
# imported objects' contructors?
|
||||
#
|
||||
# [^0]: https://en.cppreference.com/w/cpp/language/aggregate_initialization
|
||||
# [^1]: https://cplusplus.github.io/CWG/issues/1518.html
|
||||
# [^2]: https://eel.is/c++draft/over.match.ctor
|
||||
decl.addf(" $1;$n", [s.loc.r])
|
||||
else:
|
||||
decl.addf(" $1 = $2;$n", [s.loc.r, value])
|
||||
else:
|
||||
decl.addf(" $1;$n", [s.loc.r])
|
||||
else:
|
||||
|
||||
39
tests/ccgbugs/tbug21505.nim
Normal file
39
tests/ccgbugs/tbug21505.nim
Normal file
@@ -0,0 +1,39 @@
|
||||
discard """
|
||||
action: "compile"
|
||||
targets: "cpp"
|
||||
cmd: "nim cpp $file"
|
||||
"""
|
||||
|
||||
# see #21505: ensure compilation of imported C++ objects with explicit constructors while retaining default initialization through codegen changes due to #21279
|
||||
|
||||
{.emit:"""/*TYPESECTION*/
|
||||
|
||||
struct ExplObj
|
||||
{
|
||||
explicit ExplObj(int bar = 0) {}
|
||||
};
|
||||
|
||||
struct BareObj
|
||||
{
|
||||
BareObj() {}
|
||||
};
|
||||
|
||||
""".}
|
||||
|
||||
type
|
||||
ExplObj {.importcpp.} = object
|
||||
BareObj {.importcpp.} = object
|
||||
|
||||
type
|
||||
Composer = object
|
||||
explObj: ExplObj
|
||||
bareObj: BareObj
|
||||
|
||||
proc foo =
|
||||
var composer1 {.used.}: Composer
|
||||
let composer2 {.used.} = Composer()
|
||||
|
||||
var composer1 {.used.}: Composer
|
||||
let composer2 {.used.} = Composer()
|
||||
|
||||
foo()
|
||||
Reference in New Issue
Block a user