@@ -393,37 +393,23 @@ private int tryMain(size_t argc, const(char)** argv)
393393 global.params.mscrtlib = vsopt.defaultRuntimeLibrary(global.params.is64bit);
394394 }
395395 }
396- if (global.params.release)
397- {
398- global.params.useInvariants = false ;
399- global.params.useIn = false ;
400- global.params.useOut = false ;
401-
402- if (global.params.useArrayBounds == CHECKENABLE ._default)
403- global.params.useArrayBounds = CHECKENABLE .safeonly;
404-
405- if (global.params.useAssert == CHECKENABLE ._default)
406- global.params.useAssert = CHECKENABLE .off;
407-
408- if (global.params.useSwitchError == CHECKENABLE ._default)
409- global.params.useSwitchError = CHECKENABLE .off;
410- }
411396 if (global.params.betterC)
412397 {
413398 global.params.checkAction = CHECKACTION .C;
414399 global.params.useModuleInfo = false ;
415400 global.params.useTypeInfo = false ;
416401 global.params.useExceptions = false ;
417402 }
403+ // -release -unittest enables assertions in unittests AND function bodies
418404 if (global.params.useUnitTests)
419405 global.params.useAssert = CHECKENABLE .on;
420406
421- if (global.params.useArrayBounds == CHECKENABLE ._default)
422- global.params.useArrayBounds = CHECKENABLE .on;
423-
424407 if (global.params.useAssert == CHECKENABLE ._default)
425408 global.params.useAssert = CHECKENABLE .on;
426409
410+ if (global.params.useArrayBounds == CHECKENABLE ._default)
411+ global.params.useArrayBounds = CHECKENABLE .on;
412+
427413 if (global.params.useSwitchError == CHECKENABLE ._default)
428414 global.params.useSwitchError = CHECKENABLE .on;
429415
@@ -1488,9 +1474,9 @@ private bool parseCommandLine(const ref Strings arguments, const size_t argc, re
14881474{
14891475 bool errors;
14901476
1491- void error (const (char )* format, const ( char * ) arg = null )
1477+ void error (Args ... )( const (char )* format, Args args )
14921478 {
1493- dmd.errors.error(Loc.initial, format, arg );
1479+ dmd.errors.error(Loc.initial, format, args );
14941480 errors = true ;
14951481 }
14961482
@@ -1992,8 +1978,66 @@ private bool parseCommandLine(const ref Strings arguments, const size_t argc, re
19921978 {
19931979 // Ignore
19941980 }
1995- else if (arg == " -release" ) // https://dlang.org/dmd.html#switch-release
1996- params.release = true ;
1981+ else if (startsWith(p + 1 , " release" )) // https://dlang.org/dmd.html#switch-release
1982+ {
1983+ // Parse:
1984+ // -release[=assert[,in,out,invariant]]
1985+ if (p[" -release" .length] == ' =' )
1986+ {
1987+ if (arg.length == " -release=" .length)
1988+ goto Lnoarg;
1989+
1990+ auto tail = arg[" -release=" .length .. $];
1991+ while (true )
1992+ {
1993+ auto delim = strchr(tail.ptr, ' ,' );
1994+ auto check = tail[0 .. delim ? delim - tail.ptr : $];
1995+ switch (check)
1996+ {
1997+ case " assert" :
1998+ // can be overridden by -unittest
1999+ if (params.useAssert == CHECKENABLE ._default)
2000+ params.useAssert = CHECKENABLE .off;
2001+ break ;
2002+ case " in" :
2003+ params.useIn = false ;
2004+ break ;
2005+ case " out" :
2006+ params.useOut = false ;
2007+ break ;
2008+ case " invariant" :
2009+ params.useInvariants = false ;
2010+ break ;
2011+ default :
2012+ error(" unrecognized argument '%.*s' for -release=" , cast (int )check.length, check.ptr);
2013+ break ;
2014+ }
2015+ if (check.length == tail.length)
2016+ break ;
2017+ tail = tail[check.length + " ," .length .. $];
2018+ }
2019+ }
2020+ else if (arg.length > " -release" .length)
2021+ goto Lerror;
2022+ else // -release
2023+ {
2024+ if (params.useAssert == CHECKENABLE ._default)
2025+ params.useAssert = CHECKENABLE .off;
2026+ params.useIn = false ;
2027+ params.useOut = false ;
2028+ params.useInvariants = false ;
2029+ }
2030+
2031+ // for additional linker flags
2032+ params.linkRelease = true ;
2033+
2034+ if (params.useArrayBounds == CHECKENABLE ._default)
2035+ params.useArrayBounds = CHECKENABLE .safeonly;
2036+
2037+ // switch without default is now a compile-time error anyhow
2038+ if (params.useSwitchError == CHECKENABLE ._default)
2039+ params.useSwitchError = CHECKENABLE .off;
2040+ }
19972041 else if (arg == " -betterC" ) // https://dlang.org/dmd.html#switch-betterC
19982042 params.betterC = true ;
19992043 else if (arg == " -noboundscheck" ) // https://dlang.org/dmd.html#switch-noboundscheck
@@ -2232,6 +2276,53 @@ private bool parseCommandLine(const ref Strings arguments, const size_t argc, re
22322276 return errors;
22332277}
22342278
2279+ unittest
2280+ {
2281+ global.gag = 1 ;
2282+ immutable errorsave = global.errors;
2283+ scope (exit) { global.gag = 0 ; global.errors = errorsave; }
2284+
2285+ static bool test (const (char * )[] args, out Param params, out Strings files)
2286+ {
2287+ Strings sargs;
2288+ sargs.setDim(args.length + 1 );
2289+ sargs[0 ] = " dmd" ;
2290+ foreach (i, ref sarg; sargs[1 .. sargs.dim])
2291+ sarg = args[i];
2292+ return ! parseCommandLine(sargs, sargs.dim, params, files);
2293+ }
2294+
2295+ Param params;
2296+ Strings files;
2297+ assert (test([" -release" ], params, files));
2298+ assert (params.release);
2299+ assert (params.useAssert == CHECKENABLE .off && ! params.useIn && ! params.useOut && ! params.useInvariants);
2300+ assert (params.useArrayBounds == CHECKENABLE .safeonly && params.useSwitchError == CHECKENABLE .off);
2301+ assert (test([" -release=assert,in,out,invariant" ], params, files));
2302+ assert (params.release);
2303+ assert (params.useAssert == CHECKENABLE .off && ! params.useIn && ! params.useOut && ! params.useInvariants);
2304+ assert (params.useArrayBounds == CHECKENABLE .safeonly && params.useSwitchError == CHECKENABLE .off);
2305+ assert (test([" -release=in" ], params, files));
2306+ assert (params.release);
2307+ assert (params.useAssert == CHECKENABLE ._default);
2308+ assert (! params.useIn && params.useOut && params.useInvariants);
2309+ assert (params.useArrayBounds == CHECKENABLE .safeonly && params.useSwitchError == CHECKENABLE .off);
2310+ assert (test([" -release=in,out" ], params, files));
2311+ assert (params.release);
2312+ assert (params.useAssert == CHECKENABLE ._default && ! params.useIn && ! params.useOut && params.useInvariants);
2313+ assert (params.useArrayBounds == CHECKENABLE .safeonly && params.useSwitchError == CHECKENABLE .off);
2314+ assert (test([" -release=in,out,assert,invariant" ], params, files));
2315+ assert (params.release);
2316+ assert (params.useAssert == CHECKENABLE .off && ! params.useIn && ! params.useOut && ! params.useInvariants);
2317+ assert (params.useArrayBounds == CHECKENABLE .safeonly && params.useSwitchError == CHECKENABLE .off);
2318+
2319+ assert (! test([" -release=" ], params, files));
2320+ assert (! test([" -release=in," ], params, files));
2321+ assert (! test([" -release=foo" ], params, files));
2322+ assert (! test([" -release=assert,in,put" ], params, files));
2323+ assert (! test([" -release=assert;in" ], params, files));
2324+ assert (! test([" -release:in,out" ], params, files));
2325+ }
22352326
22362327private __gshared bool includeImports = false ;
22372328// array of module patterns used to include/exclude imported modules
0 commit comments