Extract Dsymbol.oneMember to a visitor in dsymbolsem (#20915)

This commit is contained in:
Matthew Qiu 2025-02-25 08:19:58 -05:00 committed by GitHub
parent 53a1cc8d13
commit 996acb0528
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 134 additions and 121 deletions

View file

@ -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;
@ -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;
@ -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);
@ -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";

View file

@ -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; }
@ -43,7 +42,6 @@ public:
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); }
@ -142,7 +140,6 @@ public:
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); }
};
@ -169,7 +166,6 @@ public:
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); }
};

View file

@ -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;

View file

@ -51,6 +51,7 @@ import dmd.statement;
import dmd.staticassert;
import dmd.tokens;
import dmd.visitor;
import dmd.dsymbolsem;
import dmd.common.outbuffer;
@ -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.
*/
@ -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)
{

View file

@ -237,7 +237,6 @@ public:
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 *) { }
@ -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);
}

View file

@ -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;
}
}

View file

@ -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;
@ -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());

View file

@ -52,7 +52,6 @@ public:
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?

View file

@ -510,7 +510,6 @@ public:
virtual bool needThis();
virtual Visibility visible();
virtual Dsymbol* syntaxCopy(Dsymbol* s);
virtual bool oneMember(Dsymbol*& ps, Identifier* ident);
virtual bool hasPointers();
virtual bool hasStaticCtorOrDtor();
virtual void addObjcSymbols(Array<ClassDeclaration* >* classes, Array<ClassDeclaration* >* categories);
@ -1632,7 +1631,6 @@ public:
TemplateInstance* syntaxCopy(Dsymbol* s) override;
Dsymbol* toAlias() final override;
const char* kind() const override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
const char* toPrettyCharsHelper() final override;
Identifier* getIdent() final override;
bool equalsx(TemplateInstance* ti);
@ -1657,7 +1655,6 @@ public:
TypeQualified* tqual;
TemplateInstance* syntaxCopy(Dsymbol* s) override;
const char* kind() const override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
bool hasPointers() override;
TemplateMixin* isTemplateMixin() override;
void accept(Visitor* v) override;
@ -5378,7 +5375,6 @@ public:
Expression* exp;
Array<Expression* >* msgs;
StaticAssert* syntaxCopy(Dsymbol* s) override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
const char* kind() const override;
StaticAssert* isStaticAssert() override;
void accept(Visitor* v) override;
@ -6330,7 +6326,6 @@ class AttribDeclaration : public Dsymbol
public:
Array<Dsymbol* >* decl;
const char* kind() const override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
bool hasPointers() final override;
bool hasStaticCtorOrDtor() final override;
void addObjcSymbols(Array<ClassDeclaration* >* classes, Array<ClassDeclaration* >* categories) final override;
@ -6343,7 +6338,6 @@ class StorageClassDeclaration : public AttribDeclaration
public:
StorageClass stc;
StorageClassDeclaration* syntaxCopy(Dsymbol* s) override;
bool oneMember(Dsymbol*& ps, Identifier* ident) final override;
StorageClassDeclaration* isStorageClassDeclaration() override;
void accept(Visitor* v) override;
};
@ -6433,7 +6427,6 @@ public:
Condition* condition;
Array<Dsymbol* >* elsedecl;
ConditionalDeclaration* syntaxCopy(Dsymbol* s) override;
bool oneMember(Dsymbol*& ps, Identifier* ident) final override;
void accept(Visitor* v) override;
};
@ -6458,7 +6451,6 @@ public:
bool cached;
Array<Dsymbol* >* cache;
StaticForeachDeclaration* syntaxCopy(Dsymbol* s) override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
const char* kind() const override;
void accept(Visitor* v) override;
};
@ -7011,7 +7003,6 @@ private:
public:
Symbol* sinit;
EnumDeclaration* syntaxCopy(Dsymbol* s) override;
bool oneMember(Dsymbol*& ps, Identifier* ident) override;
Type* getType() override;
const char* kind() const override;
bool isDeprecated() const override;

View file

@ -49,13 +49,6 @@ extern (C++) final class StaticAssert : Dsymbol
return new StaticAssert(loc, exp.syntaxCopy(), msgs ? Expression.arraySyntaxCopy(msgs) : null);
}
override bool oneMember(out Dsymbol ps, Identifier ident)
{
//printf("StaticAssert::oneMember())\n");
ps = null;
return true;
}
override const(char)* kind() const
{
return "static assert";

View file

@ -21,7 +21,6 @@ public:
Expressions *msg;
StaticAssert *syntaxCopy(Dsymbol *s) override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
const char *kind() const override;
StaticAssert *isStaticAssert() override { return this; }
void accept(Visitor *v) override { v->visit(this); }

View file

@ -270,7 +270,6 @@ public:
TemplateInstance *syntaxCopy(Dsymbol *) override;
Dsymbol *toAlias() override final; // resolve real symbol
const char *kind() const override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
const char* toPrettyCharsHelper() override final;
Identifier *getIdent() override final;
@ -288,7 +287,6 @@ public:
TemplateMixin *syntaxCopy(Dsymbol *s) override;
const char *kind() const override;
bool oneMember(Dsymbol *&ps, Identifier *ident) override;
bool hasPointers() override;
TemplateMixin *isTemplateMixin() override { return this; }