Deprecate string literals as (static) assert conditions (#15860)

* Deprecate string literals as assert conditions

Fix Issue 14387 - Disallow string literals as assert conditions

* Avoid running expression semantic, only deprecate literals

Ignore enum strings.

* Fix runnable test
This commit is contained in:
Nick Treleaven 2023-12-29 17:10:55 +00:00 committed by GitHub
parent 7f74cb30db
commit dea9e0e586
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 55 additions and 1 deletions

View file

@ -0,0 +1,18 @@
A string literal as an assert condition is deprecated
Boolean evaluation of a string literal could happen unintentionally
e.g. when an `assert(0, "message")` was meant and the `0` was missing.
```d
assert("unexpected runtime condition");
static assert("unhandled case for `", T, "`");
```
The 2 asserts would silently always have no effect.
Now these cases will be detected with deprecation messages.
If the original behaviour was actually intended, use `expr !is null` instead:
```d
assert("" !is null);
static assert("" !is null);
```

View file

@ -7592,6 +7592,13 @@ private extern (C++) final class ExpressionSemanticVisitor : Visitor
{
printf("AssertExp::semantic('%s')\n", exp.toChars());
}
if (auto e = exp.e1.isStringExp())
{
// deprecated in 2.107
deprecation(e.loc, "assert condition cannot be a string literal");
deprecationSupplemental(e.loc, "If intentional, use `%s !is null` instead to preserve behaviour",
e.toChars());
}
const generateMsg = !exp.msg &&
sc.needsCodegen() && // let ctfe interpreter handle the error message

View file

@ -93,6 +93,13 @@ private extern(C++) final class Semantic2Visitor : Visitor
override void visit(StaticAssert sa)
{
//printf("StaticAssert::semantic2() %s\n", sa.toChars());
if (const e = sa.exp.isStringExp())
{
// deprecated in 2.107
deprecation(e.loc, "static assert condition cannot be a string literal");
deprecationSupplemental(e.loc, "If intentional, use `%s !is null` instead to preserve behaviour",
e.toChars());
}
auto sds = new ScopeDsymbol();
sc = sc.push(sds);
sc.tinst = null;

View file

@ -0,0 +1,22 @@
/*
REQUIRED_ARGS: -de
TEST_OUTPUT:
---
fail_compilation/array_bool.d(13): Deprecation: assert condition cannot be a string literal
fail_compilation/array_bool.d(13): If intentional, use `"foo" !is null` instead to preserve behaviour
fail_compilation/array_bool.d(14): Deprecation: static assert condition cannot be a string literal
fail_compilation/array_bool.d(14): If intentional, use `"foo" !is null` instead to preserve behaviour
---
*/
void main()
{
assert("foo");
static assert("foo");
assert("foo".ptr); // OK
static assert("foo".ptr); // OK
enum e = "bar";
static assert(e); // OK
assert(e); // OK
}

View file

@ -1087,7 +1087,7 @@ bool openDebugInfo(IDiaDataSource* source, IDiaSession* session, IDiaSymbol* glo
{
wchar[MAX_PATH] exepath;
DWORD len = GetModuleFileNameW(null, exepath.ptr, MAX_PATH);
len < MAX_PATH || assert("executable path too long");
len < MAX_PATH || assert(false, "executable path too long");
HRESULT hr = CoInitialize(NULL);