From ba85bbdf090b38e75e810d44e55f621ac29a797f Mon Sep 17 00:00:00 2001 From: "Adam D. Ruppe" Date: Tue, 19 Nov 2024 11:30:53 -0500 Subject: [PATCH] check nogc on default func args but do not check nogc in if(__ctfe) blocks --- compiler/src/dmd/expression.d | 2 ++ compiler/src/dmd/expressionsem.d | 26 +++++++++++++++++++++++++- compiler/src/dmd/nogc.d | 5 ++++- 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/compiler/src/dmd/expression.d b/compiler/src/dmd/expression.d index 1d048f37ef..d5b1b541ab 100644 --- a/compiler/src/dmd/expression.d +++ b/compiler/src/dmd/expression.d @@ -348,6 +348,8 @@ extern (C++) /* IN_LLVM abstract */ class Expression : ASTNode Loc loc; // file location const EXP op; // to minimize use of dynamic_cast + bool ctfe = false; // TODO: bake this byte flag or move to relevant Expressions + extern (D) this(const ref Loc loc, EXP op) scope @safe { //printf("Expression::Expression(op = %d) this = %p\n", op, this); diff --git a/compiler/src/dmd/expressionsem.d b/compiler/src/dmd/expressionsem.d index e270fafca0..572efc0c0a 100644 --- a/compiler/src/dmd/expressionsem.d +++ b/compiler/src/dmd/expressionsem.d @@ -2899,9 +2899,27 @@ private bool functionParameters(const ref Loc loc, Scope* sc, arg = p.defaultArg; if (!arg.type) arg = arg.expressionSemantic(sc); + + if (auto efd = sc.getEnclosingFunction()) { + TypeFunction etf = efd.type.toTypeFunction(); + if (etf && etf.isnogc) { + if (auto ce = arg.isCallExp()) { + if (TypeFunction atf = ce.f.type.toTypeFunction()) { + // Both conditions works + if (!atf.isnogc) { + // if (!ce.f.setGC(arg.loc, "`@nogc` %s `%s` cannot call non-@nogc")) { + error(loc, "`@nogc` `%s` cannot call `%s` with non-@nogc argument `%s`", efd.toChars(), tf.toChars(), arg.toChars()); + return true; + } + } + } + } + } + arg = inlineCopy(arg, sc); // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__ arg = arg.resolveLoc(loc, sc); + if (i >= nargs) { arguments.push(arg); @@ -14190,7 +14208,13 @@ extern (C++) Expression expressionSemantic(Expression e, Scope* sc) { scope v = new ExpressionSemanticVisitor(sc); e.accept(v); - return v.result; + + auto res = v.result; + + if(sc && (sc.flags & SCOPE.ctfeBlock)) + e.ctfe = true; + + return res; } private Expression dotIdSemanticPropX(DotIdExp exp, Scope* sc) diff --git a/compiler/src/dmd/nogc.d b/compiler/src/dmd/nogc.d index d433ce8965..277c251a1f 100644 --- a/compiler/src/dmd/nogc.d +++ b/compiler/src/dmd/nogc.d @@ -150,7 +150,7 @@ public: if (global.params.ehnogc && e.thrownew) return; // separate allocator is called for this, not the GC if (explicit_gc) - return; // `new` is an explicit allocation + return; // `new` is an explicit allocation if (setGC(e, "cannot use `new` in `@nogc` %s `%s`")) return; f.printGCUsage(e.loc, "`new` causes a GC allocation"); @@ -219,6 +219,9 @@ Expression checkGC(Scope* sc, Expression e) if (sc.flags & SCOPE.ctfeBlock) // ignore GC in ctfe blocks return e; + if (e.ctfe) + return e; + /* If betterC, allow GC to happen in non-CTFE code. * Just don't generate code for it. * Detect non-CTFE use of the GC in betterC code.