Skip to content

Commit 1a26a40

Browse files
authored
Handle instantiation of unmanaged class via object literal (#1189)
1 parent 125944a commit 1a26a40

5 files changed

+2519
-9
lines changed

Diff for: src/compiler.ts

+24-9
Original file line numberDiff line numberDiff line change
@@ -6652,13 +6652,20 @@ export class Compiler extends DiagnosticEmitter {
66526652
}
66536653

66546654
/** Checks that an unsafe expression is allowed. */
6655-
private checkUnsafe(reportNode: Node): void {
6655+
private checkUnsafe(reportNode: Node, relatedReportNode: Node | null = null): void {
66566656
// Library files may always use unsafe features
66576657
if (this.options.noUnsafe && !reportNode.range.source.isLibrary) {
6658-
this.error(
6659-
DiagnosticCode.Operation_is_unsafe,
6660-
reportNode.range
6661-
);
6658+
if (relatedReportNode) {
6659+
this.errorRelated(
6660+
DiagnosticCode.Operation_is_unsafe,
6661+
reportNode.range, relatedReportNode.range
6662+
);
6663+
} else {
6664+
this.error(
6665+
DiagnosticCode.Operation_is_unsafe,
6666+
reportNode.range
6667+
);
6668+
}
66626669
}
66636670
}
66646671

@@ -8664,6 +8671,11 @@ export class Compiler extends DiagnosticEmitter {
86648671
if (ctor.hasDecorator(DecoratorFlags.UNSAFE)) this.checkUnsafe(expression);
86658672
}
86668673

8674+
var isManaged = classReference.type.isManaged;
8675+
if (!isManaged) {
8676+
this.checkUnsafe(expression, findDecorator(DecoratorKind.UNMANAGED, classReference.decoratorNodes));
8677+
}
8678+
86678679
// check and compile field values
86688680
var names = expression.names;
86698681
var numNames = names.length;
@@ -8672,7 +8684,9 @@ export class Compiler extends DiagnosticEmitter {
86728684
var hasErrors = false;
86738685
var exprs = new Array<ExpressionRef>(numNames + 2);
86748686
var flow = this.currentFlow;
8675-
var tempLocal = flow.getAutoreleaseLocal(classReference.type);
8687+
var tempLocal = isManaged
8688+
? flow.getAutoreleaseLocal(classReference.type)
8689+
: flow.getTempLocal(classReference.type);
86768690
assert(numNames == values.length);
86778691
for (let i = 0, k = numNames; i < k; ++i) {
86788692
let member = members ? members.get(names[i].text) : null;
@@ -8700,14 +8714,15 @@ export class Compiler extends DiagnosticEmitter {
87008714
// allocate a new instance first and assign 'this' to the temp. local
87018715
exprs[0] = module.local_set(
87028716
tempLocal.index,
8703-
this.makeRetain(
8704-
this.makeAllocation(classReference)
8705-
)
8717+
isManaged
8718+
? this.makeRetain(this.makeAllocation(classReference))
8719+
: this.makeAllocation(classReference)
87068720
);
87078721

87088722
// once all field values have been set, return 'this'
87098723
exprs[exprs.length - 1] = module.local_get(tempLocal.index, this.options.nativeSizeType);
87108724

8725+
if (!isManaged) flow.freeTempLocal(tempLocal);
87118726
this.currentType = classReference.type;
87128727
return module.flatten(exprs, this.options.nativeSizeType);
87138728
}

Diff for: tests/compiler/std/object-literal-unmanaged.json

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"asc_flags": [
3+
"--runtime half",
4+
"--use ASC_RTRACE=1"
5+
]
6+
}

0 commit comments

Comments
 (0)