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

Extracted Dsymbol.oneMember to a visitor in dsymbolsem #20915

Merged
merged 1 commit into from
Feb 25, 2025
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
63 changes: 0 additions & 63 deletions compiler/src/dmd/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -109,12 +109,6 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
return "attribute";
}

override bool oneMember(out Dsymbol ps, Identifier ident)
{
Dsymbols* d = this.include(null);
return Dsymbol.oneMembers(d, ps, ident);
}

override final bool hasPointers()
{
return this.include(null).foreachDsymbol( (s) { return s.hasPointers(); } ) != 0;
Expand Down Expand Up @@ -170,32 +164,6 @@ extern (C++) class StorageClassDeclaration : AttribDeclaration
return new StorageClassDeclaration(stc, Dsymbol.arraySyntaxCopy(decl));
}

override final bool oneMember(out Dsymbol ps, Identifier ident)
{
bool t = Dsymbol.oneMembers(decl, ps, ident);
if (t && ps)
{
/* This is to deal with the following case:
* struct Tick {
* template to(T) { const T to() { ... } }
* }
* For eponymous function templates, the 'const' needs to get attached to 'to'
* before the semantic analysis of 'to', so that template overloading based on the
* 'this' pointer can be successful.
*/
if (FuncDeclaration fd = ps.isFuncDeclaration())
{
/* Use storage_class2 instead of storage_class otherwise when we do .di generation
* we'll wind up with 'const const' rather than 'const'.
*/
/* Don't think we need to worry about mutually exclusive storage classes here
*/
fd.storage_class2 |= stc;
}
}
return t;
}

override inout(StorageClassDeclaration) isStorageClassDeclaration() inout
{
return this;
Expand Down Expand Up @@ -591,22 +559,6 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration
return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
}

override final bool oneMember(out Dsymbol ps, Identifier ident)
{
//printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
if (condition.inc != Include.notComputed)
{
Dsymbols* d = condition.include(null) ? decl : elsedecl;
return Dsymbol.oneMembers(d, ps, ident);
}
else
{
bool res = (Dsymbol.oneMembers(decl, ps, ident) && ps is null && Dsymbol.oneMembers(elsedecl, ps, ident) && ps is null);
ps = null;
return res;
}
}

override void accept(Visitor v)
{
v.visit(this);
Expand Down Expand Up @@ -687,21 +639,6 @@ extern (C++) final class StaticForeachDeclaration : AttribDeclaration
Dsymbol.arraySyntaxCopy(decl));
}

override bool oneMember(out Dsymbol ps, Identifier ident)
{
// Required to support IFTI on a template that contains a
// `static foreach` declaration. `super.oneMember` calls
// include with a `null` scope. As `static foreach` requires
// the scope for expansion, `oneMember` can only return a
// precise result once `static foreach` has been expanded.
if (cached)
{
return super.oneMember(ps, ident);
}
ps = null; // a `static foreach` declaration may in general expand to multiple symbols
return false;
}

override const(char)* kind() const
{
return "static foreach";
Expand Down
4 changes: 0 additions & 4 deletions compiler/src/dmd/attrib.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ class AttribDeclaration : public Dsymbol
public:
Dsymbols *decl; // array of Dsymbol's
const char *kind() const override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
bool hasPointers() override final;
bool hasStaticCtorOrDtor() override final;
AttribDeclaration *isAttribDeclaration() override { return this; }
Expand All @@ -43,7 +42,6 @@ class StorageClassDeclaration : public AttribDeclaration
StorageClass stc;

StorageClassDeclaration *syntaxCopy(Dsymbol *s) override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override final;
StorageClassDeclaration *isStorageClassDeclaration() override { return this; }

void accept(Visitor *v) override { v->visit(this); }
Expand Down Expand Up @@ -142,7 +140,6 @@ class ConditionalDeclaration : public AttribDeclaration
Dsymbols *elsedecl; // array of Dsymbol's for else block

ConditionalDeclaration *syntaxCopy(Dsymbol *s) override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override final;
void accept(Visitor *v) override { v->visit(this); }
};

Expand All @@ -169,7 +166,6 @@ class StaticForeachDeclaration final : public AttribDeclaration
Dsymbols *cache;

StaticForeachDeclaration *syntaxCopy(Dsymbol *s) override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
const char *kind() const override;
void accept(Visitor *v) override { v->visit(this); }
};
Expand Down
7 changes: 0 additions & 7 deletions compiler/src/dmd/denum.d
Original file line number Diff line number Diff line change
Expand Up @@ -81,13 +81,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return ed;
}

override bool oneMember(out Dsymbol ps, Identifier ident)
{
if (isAnonymous())
return Dsymbol.oneMembers(members, ps, ident);
return Dsymbol.oneMember(ps, ident);
}

override Type getType()
{
return type;
Expand Down
17 changes: 2 additions & 15 deletions compiler/src/dmd/dsymbol.d
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ import dmd.statement;
import dmd.staticassert;
import dmd.tokens;
import dmd.visitor;
import dmd.dsymbolsem;

import dmd.common.outbuffer;

Expand Down Expand Up @@ -820,20 +821,6 @@ extern (C++) class Dsymbol : ASTNode
assert(0);
}

/**************************************
* Determine if this symbol is only one.
* Returns:
* false, ps = null: There are 2 or more symbols
* true, ps = null: There are zero symbols
* true, ps = symbol: The one and only one symbol
*/
bool oneMember(out Dsymbol ps, Identifier ident)
{
//printf("Dsymbol::oneMember()\n");
ps = this;
return true;
}

/*****************************************
* Same as Dsymbol::oneMember(), but look at an array of Dsymbols.
*/
Expand All @@ -850,7 +837,7 @@ extern (C++) class Dsymbol : ASTNode
for (size_t i = 0; i < members.length; i++)
{
Dsymbol sx = (*members)[i];
bool x = sx.oneMember(ps, ident);
bool x = sx.oneMember(ps, ident); //MYTODO: this temporarily creates a new dependency to dsymbolsem, will need to extract oneMembers() later
//printf("\t[%d] kind %s = %d, s = %p\n", i, sx.kind(), x, *ps);
if (!x)
{
Expand Down
2 changes: 1 addition & 1 deletion compiler/src/dmd/dsymbol.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,6 @@ class Dsymbol : public ASTNode
virtual bool needThis(); // need a 'this' pointer?
virtual Visibility visible();
virtual Dsymbol *syntaxCopy(Dsymbol *s); // copy only syntax trees
virtual bool oneMember(Dsymbol *&ps, Identifier *ident);
virtual bool hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addObjcSymbols(ClassDeclarations *, ClassDeclarations *) { }
Expand Down Expand Up @@ -433,4 +432,5 @@ namespace dmd
void setScope(Dsymbol *d, Scope *sc);
void importAll(Dsymbol *d, Scope *sc);
void addComment(Dsymbol *d, const char *comment);
bool oneMember(Dsymbol *d, Dsymbol *&ps, Identifier *ident);
}
131 changes: 131 additions & 0 deletions compiler/src/dmd/dsymbolsem.d
Original file line number Diff line number Diff line change
Expand Up @@ -7967,3 +7967,134 @@ private extern(C++) class CheckCtorConstInitVisitor : Visitor

override void visit(Dsymbol d){}
}

/**************************************
* Determine if this symbol is only one.
* Returns:
* false, ps = null: There are 2 or more symbols
* true, ps = null: There are zero symbols
* true, ps = symbol: The one and only one symbol
*/
bool oneMember(Dsymbol d, out Dsymbol ps, Identifier ident)
{
scope v = new OneMemberVisitor(ps, ident);
d.accept(v);
return v.result;
}

private extern(C++) class OneMemberVisitor : Visitor
{
alias visit = Visitor.visit;

Dsymbol* ps;
Identifier ident;
bool result;

this(out Dsymbol ps, Identifier ident)
{
this.ps = &ps;
this.ident = ident;
}

override void visit(AttribDeclaration atb)
{
Dsymbols* d = atb.include(null);
result = Dsymbol.oneMembers(d, *ps, ident);
}

override void visit(StaticForeachDeclaration sfd)
{
// Required to support IFTI on a template that contains a
// `static foreach` declaration. `super.oneMember` calls
// include with a `null` scope. As `static foreach` requires
// the scope for expansion, `oneMember` can only return a
// precise result once `static foreach` has been expanded.
if (sfd.cached)
{
this.visit(cast(AttribDeclaration) sfd);
}
else
{
*ps = null; // a `static foreach` declaration may in general expand to multiple symbols
result = false;
}
}

override void visit(StorageClassDeclaration scd)
{
bool t = Dsymbol.oneMembers(scd.decl, *ps, ident);
if (t && *ps)
{
/* This is to deal with the following case:
* struct Tick {
* template to(T) { const T to() { ... } }
* }
* For eponymous function templates, the 'const' needs to get attached to 'to'
* before the semantic analysis of 'to', so that template overloading based on the
* 'this' pointer can be successful.
*/
if (FuncDeclaration fd = (*ps).isFuncDeclaration())
{
/* Use storage_class2 instead of storage_class otherwise when we do .di generation
* we'll wind up with 'const const' rather than 'const'.
*/
/* Don't think we need to worry about mutually exclusive storage classes here
*/
fd.storage_class2 |= scd.stc;
}
}
result = t;
}

override void visit(ConditionalDeclaration cd)
{
//printf("ConditionalDeclaration::oneMember(), inc = %d\n", condition.inc);
if (cd.condition.inc != Include.notComputed)
{
Dsymbols* d = cd.condition.include(null) ? cd.decl : cd.elsedecl;
result = Dsymbol.oneMembers(d, *ps, ident);
}
else
{
bool res = (Dsymbol.oneMembers(cd.decl, *ps, ident) && *ps is null && Dsymbol.oneMembers(cd.elsedecl, *ps, ident) && *ps is null);
*ps = null;
result = res;
}
}

override void visit(ScopeDsymbol sd)
{
if (sd.isAnonymous())
result = Dsymbol.oneMembers(sd.members, *ps, ident);
else {
// visit(Dsymbol dsym)
*ps = sd;
result = true;
}
}

override void visit(StaticAssert sa)
{
//printf("StaticAssert::oneMember())\n");
*ps = null;
result = true;
}

override void visit(TemplateInstance ti)
{
*ps = null;
result = true;
}

override void visit(TemplateMixin tm)
{
*ps = tm;
result = true;
}

override void visit(Dsymbol dsym)
{
*ps = dsym;
result = true;
}
}
11 changes: 0 additions & 11 deletions compiler/src/dmd/dtemplate.d
Original file line number Diff line number Diff line change
Expand Up @@ -3823,12 +3823,6 @@ extern (C++) class TemplateInstance : ScopeDsymbol
return "template instance";
}

override bool oneMember(out Dsymbol ps, Identifier ident)
{
ps = null;
return true;
}

override final const(char)* toPrettyCharsHelper()
{
OutBuffer buf;
Expand Down Expand Up @@ -5505,11 +5499,6 @@ extern (C++) final class TemplateMixin : TemplateInstance
return "mixin";
}

override bool oneMember(out Dsymbol ps, Identifier ident)
{
return Dsymbol.oneMember(ps, ident);
}

override bool hasPointers()
{
//printf("TemplateMixin.hasPointers() %s\n", toChars());
Expand Down
1 change: 0 additions & 1 deletion compiler/src/dmd/enum.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ class EnumDeclaration final : public ScopeDsymbol
bool inuse(bool v);

EnumDeclaration *syntaxCopy(Dsymbol *s) override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
Type *getType() override;
const char *kind() const override;
bool isDeprecated() const override; // is Dsymbol deprecated?
Expand Down
Loading
Loading