Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[declaration.d] move checkDisabled and expandInitializer to expre… #16941

Merged
merged 1 commit into from
Oct 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 0 additions & 103 deletions compiler/src/dmd/declaration.d
Original file line number Diff line number Diff line change
Expand Up @@ -125,90 +125,6 @@ extern (C++) abstract class Declaration : Dsymbol
return sz;
}

/**
* Issue an error if an attempt to call a disabled method is made
*
* If the declaration is disabled but inside a disabled function,
* returns `true` but do not issue an error message.
*
* Params:
* loc = Location information of the call
* sc = Scope in which the call occurs
* isAliasedDeclaration = if `true` searches overload set
*
* Returns:
* `true` if this `Declaration` is `@disable`d, `false` otherwise.
*/
extern (D) final bool checkDisabled(Loc loc, Scope* sc, bool isAliasedDeclaration = false)
{
if (!(storage_class & STC.disable))
return false;

if (sc.func && sc.func.storage_class & STC.disable)
return true;

if (auto p = toParent())
{
if (auto postblit = isPostBlitDeclaration())
{
/* https://issues.dlang.org/show_bug.cgi?id=21885
*
* If the generated postblit is disabled, it
* means that one of the fields has a disabled
* postblit. Print the first field that has
* a disabled postblit.
*/
if (postblit.isGenerated())
{
auto sd = p.isStructDeclaration();
assert(sd);
for (size_t i = 0; i < sd.fields.length; i++)
{
auto structField = sd.fields[i];
if (structField.overlapped)
continue;
Type tv = structField.type.baseElemOf();
if (tv.ty != Tstruct)
continue;
auto sdv = (cast(TypeStruct)tv).sym;
if (!sdv.postblit)
continue;
if (sdv.postblit.isDisabled())
{
.error(loc, "%s `%s` is not copyable because field `%s` is not copyable", p.kind, p.toPrettyChars, structField.toChars());
return true;
}
}
}
.error(loc, "%s `%s` is not copyable because it has a disabled postblit", p.kind, p.toPrettyChars);
return true;
}
}

// if the function is @disabled, maybe there
// is an overload in the overload set that isn't
if (isAliasedDeclaration)
{
if (FuncDeclaration fd = isFuncDeclaration())
{
for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
if (!(ovl.storage_class & STC.disable))
return false;
}
}

if (auto ctor = isCtorDeclaration())
{
if (ctor.isCpCtor && ctor.isGenerated())
{
.error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", parent.toPrettyChars());
return true;
}
}
.error(loc, "%s `%s` cannot be used because it is annotated with `@disable`", kind, toPrettyChars);
return true;
}

final bool isStatic() const pure nothrow @nogc @safe
{
return (storage_class & STC.static_) != 0;
Expand Down Expand Up @@ -1206,25 +1122,6 @@ extern (C++) class VarDeclaration : Declaration
return e;
}

/*******************************************
* Helper function for the expansion of manifest constant.
*/
extern (D) final Expression expandInitializer(Loc loc)
{
assert((storage_class & STC.manifest) && _init);

auto e = getConstInitializer();
if (!e)
{
.error(loc, "cannot make expression out of initializer for `%s`", toChars());
return ErrorExp.get();
}

e = e.copy();
e.loc = loc; // for better error message
return e;
}

override final void checkCtorConstInit()
{
version (none)
Expand Down
115 changes: 106 additions & 9 deletions compiler/src/dmd/expressionsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -14481,14 +14481,6 @@
return exp;
}

private bool checkDisabled(Dsymbol s, ref Loc loc, Scope* sc)
{
if (auto d = s.isDeclaration())
return d.checkDisabled(loc, sc);

return false;
}

/******************************
* Resolve properties, i.e. `e1.ident`, without seeing UFCS.
* Params:
Expand Down Expand Up @@ -14583,7 +14575,8 @@
s = s.toAlias();

s.checkDeprecated(exp.loc, sc);
s.checkDisabled(exp.loc, sc);
if (auto d = s.isDeclaration())
d.checkDisabled(exp.loc, sc);

if (auto em = s.isEnumMember())
{
Expand Down Expand Up @@ -17271,3 +17264,107 @@
default: semanticTypeInfo(sc, tb.nextOf()); break;
}
}

/**
* Issue an error if an attempt to call a disabled method is made
*
* If the declaration is disabled but inside a disabled function,
* returns `true` but do not issue an error message.
*
* Params:
* d = Declaration to check
* loc = Location information of the call
* sc = Scope in which the call occurs
* isAliasedDeclaration = if `true` searches overload set
*
* Returns:
* `true` if this `Declaration` is `@disable`d, `false` otherwise.
*/
bool checkDisabled(Declaration d, Loc loc, Scope* sc, bool isAliasedDeclaration = false)
{
if (!(d.storage_class & STC.disable))
return false;

if (sc.func && sc.func.storage_class & STC.disable)
return true;

if (auto p = d.toParent())
{
if (auto postblit = d.isPostBlitDeclaration())
{
/* https://issues.dlang.org/show_bug.cgi?id=21885
*
* If the generated postblit is disabled, it
* means that one of the fields has a disabled
* postblit. Print the first field that has
* a disabled postblit.
*/
if (postblit.isGenerated())
{
auto sd = p.isStructDeclaration();
assert(sd);
for (size_t i = 0; i < sd.fields.length; i++)
{
auto structField = sd.fields[i];
if (structField.overlapped)
continue;

Check warning on line 17310 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L17310

Added line #L17310 was not covered by tests
Type tv = structField.type.baseElemOf();
if (tv.ty != Tstruct)
continue;
auto sdv = (cast(TypeStruct)tv).sym;
if (!sdv.postblit)
continue;

Check warning on line 17316 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L17316

Added line #L17316 was not covered by tests
if (sdv.postblit.isDisabled())
{
.error(loc, "%s `%s` is not copyable because field `%s` is not copyable", p.kind, p.toPrettyChars, structField.toChars());
return true;
}
}
}
.error(loc, "%s `%s` is not copyable because it has a disabled postblit", p.kind, p.toPrettyChars);
return true;
}
}

// if the function is @disabled, maybe there
// is an overload in the overload set that isn't
if (isAliasedDeclaration)
{
if (FuncDeclaration fd = d.isFuncDeclaration())
{
for (FuncDeclaration ovl = fd; ovl; ovl = cast(FuncDeclaration)ovl.overnext)
if (!(ovl.storage_class & STC.disable))
return false;
}
}

if (auto ctor = d.isCtorDeclaration())
{
if (ctor.isCpCtor && ctor.isGenerated())
{
.error(loc, "generating an `inout` copy constructor for `struct %s` failed, therefore instances of it are uncopyable", d.parent.toPrettyChars());
return true;

Check warning on line 17346 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L17345-L17346

Added lines #L17345 - L17346 were not covered by tests
}
}
.error(loc, "%s `%s` cannot be used because it is annotated with `@disable`", d.kind, d.toPrettyChars);
return true;
}

/*******************************************
* Helper function for the expansion of manifest constant.
*/
private Expression expandInitializer(VarDeclaration vd, Loc loc)
{
assert((vd.storage_class & STC.manifest) && vd._init);

auto e = vd.getConstInitializer();
if (!e)
{
.error(loc, "cannot make expression out of initializer for `%s`", vd.toChars());
return ErrorExp.get();

Check warning on line 17364 in compiler/src/dmd/expressionsem.d

View check run for this annotation

Codecov / codecov/patch

compiler/src/dmd/expressionsem.d#L17363-L17364

Added lines #L17363 - L17364 were not covered by tests
}

e = e.copy();
e.loc = loc; // for better error message
return e;
}
1 change: 1 addition & 0 deletions compiler/src/dmd/funcsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -1648,6 +1648,7 @@ FuncDeclaration resolveFuncCall(const ref Loc loc, Scope* sc, Dsymbol s,
return null;
}

import dmd.expressionsem : checkDisabled;
// remove when deprecation period of class allocators and deallocators is over
if (fd.isNewDeclaration() && fd.checkDisabled(loc, sc))
return null;
Expand Down
Loading