Extract Dsymbol.search from dsymbols.d and transform it into a visitor (#15787)

This commit is contained in:
Razvan Nitu 2023-11-19 00:39:57 +02:00 committed by GitHub
parent 428cc6d3c4
commit f29a92dcbf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
25 changed files with 642 additions and 635 deletions

View file

@ -663,7 +663,7 @@ extern (C++) abstract class AggregateDeclaration : ScopeDsymbol
*/
extern (D) final Dsymbol searchCtor()
{
auto s = search(Loc.initial, Id.ctor);
auto s = this.search(Loc.initial, Id.ctor);
if (s)
{
if (!(s.isCtorDeclaration() ||

View file

@ -167,7 +167,6 @@ private:
public:
static StructDeclaration *create(const Loc &loc, Identifier *id, bool inObject);
StructDeclaration *syntaxCopy(Dsymbol *s) override;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
const char *kind() const override;
void finalizeSize() override final;
bool isPOD();
@ -285,7 +284,6 @@ public:
virtual bool isBaseOf(ClassDeclaration *cd, int *poffset);
bool isBaseInfoComplete();
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
void finalizeSize() override;
bool hasMonitor();
bool isFuncHidden(FuncDeclaration *fd);

View file

@ -180,7 +180,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
int cppDtorVtblIndex = -1;
/// to prevent recursive attempts
private bool inuse;
bool inuse;
ThreeState isabstract;
@ -367,7 +367,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
baseok = Baseok.none;
}
extern (D) private void classError(const(char)* fmt, const(char)* arg)
extern (D) final void classError(const(char)* fmt, const(char)* arg)
{
.error(loc, fmt, kind, toPrettyChars, arg);
}
@ -468,67 +468,6 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
return baseok >= Baseok.done;
}
override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
//if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
if (_scope && baseok < Baseok.semanticdone)
{
if (!inuse)
{
// must semantic on base class/interfaces
inuse = true;
dsymbolSemantic(this, null);
inuse = false;
}
}
if (!members || !symtab) // opaque or addMember is not yet done
{
// .stringof is always defined (but may be hidden by some other symbol)
if (ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
//*(char*)0=0;
return null;
}
auto s = ScopeDsymbol.search(loc, ident, flags);
// don't search imports of base classes
if (flags & SearchImportsOnly)
return s;
if (s)
return s;
// Search bases classes in depth-first, left to right order
foreach (b; (*baseclasses)[])
{
if (!b.sym)
continue;
if (!b.sym.symtab)
{
classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
continue;
}
import dmd.access : symbolIsVisible;
s = b.sym.search(loc, ident, flags);
if (!s)
continue;
else if (s == this) // happens if s is nested in this and derives from this
s = null;
else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(this, s))
s = null;
else
break;
}
return s;
}
/************************************
* Search base classes in depth-first, left-to-right order for
* a class or interface named 'ident'.
@ -675,7 +614,7 @@ extern (C++) class ClassDeclaration : AggregateDeclaration
final bool isFuncHidden(FuncDeclaration fd)
{
//printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toPrettyChars());
Dsymbol s = search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors);
Dsymbol s = this.search(Loc.initial, fd.ident, IgnoreAmbiguous | IgnoreErrors);
if (!s)
{
//printf("not found\n");

View file

@ -421,18 +421,6 @@ extern (C++) abstract class Declaration : Dsymbol
return Modifiable.yes;
}
override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
Dsymbol s = Dsymbol.search(loc, ident, flags);
if (!s && type)
{
s = type.toDsymbol(_scope);
if (s)
s = s.search(loc, ident, flags);
}
return s;
}
final bool isStatic() const pure nothrow @nogc @safe
{
return (storage_class & STC.static_) != 0;

View file

@ -124,7 +124,6 @@ public:
const char *kind() const override;
uinteger_t size(const Loc &loc) override final;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override final;
bool isStatic() const { return (storage_class & STCstatic) != 0; }
LINK resolvedLinkage() const; // returns the linkage, resolving the target-specific `System` one

View file

@ -107,19 +107,6 @@ extern (C++) final class EnumDeclaration : ScopeDsymbol
return "enum";
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.EnumDeclaration::search('%s')\n", toChars(), ident.toChars());
if (_scope)
{
// Try one last time to resolve this enum
dsymbolSemantic(this, _scope);
}
Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
return s;
}
// is Dsymbol deprecated?
override bool isDeprecated() const
{

View file

@ -321,19 +321,6 @@ extern (C++) final class Import : Dsymbol
}
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.Import.search(ident = '%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
if (!pkg)
{
load(null);
mod.importAll(null);
mod.dsymbolSemantic(null);
}
// Forward it to the package/module
return pkg.search(loc, ident, flags);
}
override bool overloadInsert(Dsymbol s)
{
/* Allow multiple imports with the same package base, but disallow

View file

@ -268,22 +268,6 @@ extern (C++) class Package : ScopeDsymbol
return isAncestorPackageOf(pkg.parent.isPackage());
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s Package.search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
flags &= ~SearchLocalsOnly; // searching an import is always transitive
if (!isModule() && mod)
{
// Prefer full package name.
Dsymbol s = symtab ? symtab.lookup(ident) : null;
if (s)
return s;
//printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
return mod.search(loc, ident, flags);
}
return ScopeDsymbol.search(loc, ident, flags);
}
override void accept(Visitor v)
{
v.visit(this);
@ -414,10 +398,10 @@ extern (C++) final class Module : Package
return rootimports == ThreeState.yes;
}
private Identifier searchCacheIdent;
private Dsymbol searchCacheSymbol; // cached value of search
private int searchCacheFlags; // cached flags
private bool insearch;
Identifier searchCacheIdent;
Dsymbol searchCacheSymbol; // cached value of search
int searchCacheFlags; // cached flags
bool insearch;
/**
* A root module is one that will be compiled all the way to
@ -1036,47 +1020,6 @@ extern (C++) final class Module : Package
}
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
/* Since modules can be circularly referenced,
* need to stop infinite recursive searches.
* This is done with the cache.
*/
//printf("%s Module.search('%s', flags = x%x) insearch = %d\n", toChars(), ident.toChars(), flags, insearch);
if (insearch)
return null;
/* Qualified module searches always search their imports,
* even if SearchLocalsOnly
*/
if (!(flags & SearchUnqualifiedModule))
flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
if (searchCacheIdent == ident && searchCacheFlags == flags)
{
//printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
// toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
return searchCacheSymbol;
}
uint errors = global.errors;
insearch = true;
Dsymbol s = ScopeDsymbol.search(loc, ident, flags);
insearch = false;
if (errors == global.errors)
{
// https://issues.dlang.org/show_bug.cgi?id=10752
// Can cache the result only when it does not cause
// access error so the side-effect should be reproduced in later search.
searchCacheIdent = ident;
searchCacheSymbol = s;
searchCacheFlags = flags;
}
return s;
}
override bool isPackageAccessible(Package p, Visibility visibility, int flags = 0)
{
if (insearch) // don't follow import cycles

View file

@ -263,23 +263,6 @@ extern (C++) class StructDeclaration : AggregateDeclaration
return sd;
}
override final Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
if (_scope && !symtab)
dsymbolSemantic(this, _scope);
if (!members || !symtab) // opaque or semantic() is not yet called
{
// .stringof is always defined (but may be hidden by some other symbol)
if(ident != Id.stringof && !(flags & IgnoreErrors) && semanticRun < PASS.semanticdone)
.error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
return null;
}
return ScopeDsymbol.search(loc, ident, flags);
}
override const(char)* kind() const
{
return "struct";

View file

@ -35,7 +35,6 @@ import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;
import dmd.func;
import dmd.globals;
import dmd.id;
@ -769,21 +768,6 @@ extern (C++) class Dsymbol : ASTNode
{
}
/*********************************************
* Search for ident as member of s.
* Params:
* loc = location to print for error messages
* ident = identifier to search for
* flags = IgnoreXXXX
* Returns:
* null if not found
*/
Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
{
//printf("Dsymbol::search(this=%p,%s, ident='%s')\n", this, toChars(), ident.toChars());
return null;
}
extern (D) final Dsymbol search_correct(Identifier ident)
{
/***************************************************
@ -808,7 +792,7 @@ extern (C++) class Dsymbol : ASTNode
if (global.gag)
return null; // don't do it for speculative compiles; too time consuming
// search for exact name first
if (auto s = search(Loc.initial, ident, IgnoreErrors))
if (auto s = this.search(Loc.initial, ident, IgnoreErrors))
return s;
return speller!symbol_search_fp(ident.toString());
}
@ -1219,12 +1203,12 @@ extern (C++) class ScopeDsymbol : Dsymbol
Dsymbols* members; // all Dsymbol's in this scope
DsymbolTable symtab; // members[] sorted into table
uint endlinnum; // the linnumber of the statement after the scope (0 if unknown)
private:
/// symbols whose members have been imported, i.e. imported modules and template mixins
Dsymbols* importedScopes;
Visibility.Kind* visibilities; // array of Visibility.Kind, one for each import
private:
import dmd.root.bitarray;
BitArray accessiblePackages, privateAccessiblePackages;// whitelists of accessible (imported) packages
@ -1253,166 +1237,7 @@ public:
return sds;
}
/*****************************************
* This function is #1 on the list of functions that eat cpu time.
* Be very, very careful about slowing it down.
*/
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
//if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
// Look in symbols declared in this module
if (symtab && !(flags & SearchImportsOnly))
{
//printf(" look in locals\n");
auto s1 = symtab.lookup(ident);
if (s1)
{
//printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
return s1;
}
}
//printf(" not found in locals\n");
// Look in imported scopes
if (!importedScopes)
return null;
//printf(" look in imports\n");
Dsymbol s = null;
OverloadSet a = null;
// Look in imported modules
for (size_t i = 0; i < importedScopes.length; i++)
{
// If private import, don't search it
if ((flags & IgnorePrivateImports) && visibilities[i] == Visibility.Kind.private_)
continue;
int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
Dsymbol ss = (*importedScopes)[i];
//printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
if (ss.isModule())
{
if (flags & SearchLocalsOnly)
continue;
}
else // mixin template
{
if (flags & SearchImportsOnly)
continue;
sflags |= SearchLocalsOnly;
}
/* Don't find private members if ss is a module
*/
Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
import dmd.access : symbolIsVisible;
if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(this, s2))
continue;
if (!s)
{
s = s2;
if (s && s.isOverloadSet())
a = mergeOverloadSet(ident, a, s);
}
else if (s2 && s != s2)
{
if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
{
/* After following aliases, we found the same
* symbol, so it's not an ambiguity. But if one
* alias is deprecated or less accessible, prefer
* the other.
*/
if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
s = s2;
}
else
{
/* Two imports of the same module should be regarded as
* the same.
*/
Import i1 = s.isImport();
Import i2 = s2.isImport();
if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
{
/* https://issues.dlang.org/show_bug.cgi?id=8668
* Public selective import adds AliasDeclaration in module.
* To make an overload set, resolve aliases in here and
* get actual overload roots which accessible via s and s2.
*/
s = s.toAlias();
s2 = s2.toAlias();
/* If both s2 and s are overloadable (though we only
* need to check s once)
*/
auto so2 = s2.isOverloadSet();
if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
{
if (symbolIsVisible(this, s2))
{
a = mergeOverloadSet(ident, a, s2);
}
if (!symbolIsVisible(this, s))
s = s2;
continue;
}
/* Two different overflow sets can have the same members
* https://issues.dlang.org/show_bug.cgi?id=16709
*/
auto so = s.isOverloadSet();
if (so && so2)
{
if (so.a.length == so2.a.length)
{
foreach (j; 0 .. so.a.length)
{
if (so.a[j] !is so2.a[j])
goto L1;
}
continue; // the same
L1:
{ } // different
}
}
if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
return null;
/* If two imports from C import files, pick first one, as C has global name space
*/
if (s.isCsymbol() && s2.isCsymbol())
continue;
if (!(flags & IgnoreErrors))
ScopeDsymbol.multiplyDefined(loc, s, s2);
break;
}
}
}
}
if (s)
{
/* Build special symbol if we had multiple finds
*/
if (a)
{
if (!s.isOverloadSet())
a = mergeOverloadSet(ident, a, s);
s = a;
}
//printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
return s;
}
//printf(" not found in imports\n");
return null;
}
extern (D) private OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s)
extern (D) final OverloadSet mergeOverloadSet(Identifier ident, OverloadSet os, Dsymbol s)
{
if (!os)
{
@ -1692,40 +1517,6 @@ extern (C++) final class WithScopeSymbol : ScopeDsymbol
this.withstate = withstate;
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("WithScopeSymbol.search(%s)\n", ident.toChars());
if (flags & SearchImportsOnly)
return null;
// Acts as proxy to the with class declaration
Dsymbol s = null;
Expression eold = null;
for (Expression e = withstate.exp; e && e != eold; e = resolveAliasThis(_scope, e, true))
{
if (auto se = e.isScopeExp())
{
s = se.sds;
}
else if (e.isTypeExp())
{
s = e.type.toDsymbol(null);
}
else
{
Type t = e.type.toBasetype();
s = t.toDsymbol(null);
}
if (s)
{
s = s.search(loc, ident, flags);
if (s)
return s;
}
eold = e;
}
return null;
}
override inout(WithScopeSymbol) isWithScopeSymbol() inout
{
return this;
@ -1744,7 +1535,7 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
{
// either a SliceExp, an IndexExp, an ArrayExp, a TypeTuple or a TupleDeclaration.
// Discriminated using DYNCAST and, for expressions, also EXP
private RootObject arrayContent;
RootObject arrayContent;
extern (D) this(Scope* sc, Expression exp) nothrow @safe
{
@ -1766,194 +1557,6 @@ extern (C++) final class ArrayScopeSymbol : ScopeDsymbol
this.arrayContent = td;
}
/// This override is used to solve `$`
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = IgnoreNone)
{
//printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
if (ident != Id.dollar)
return null;
VarDeclaration* pvar;
Expression ce;
static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
{
/* $ gives the number of type entries in the type tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(sc);
return v;
}
const DYNCAST kind = arrayContent.dyncast();
switch (kind) with (DYNCAST)
{
case dsymbol:
TupleDeclaration td = cast(TupleDeclaration) arrayContent;
/* $ gives the number of elements in the tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(_scope);
return v;
case type:
return dollarFromTypeTuple(loc, cast(TypeTuple) arrayContent, _scope);
default:
break;
}
Expression exp = cast(Expression) arrayContent;
if (auto ie = exp.isIndexExp())
{
/* array[index] where index is some function of $
*/
pvar = &ie.lengthVar;
ce = ie.e1;
}
else if (auto se = exp.isSliceExp())
{
/* array[lwr .. upr] where lwr or upr is some function of $
*/
pvar = &se.lengthVar;
ce = se.e1;
}
else if (auto ae = exp.isArrayExp())
{
/* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
* $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
*/
pvar = &ae.lengthVar;
ce = ae.e1;
}
else
{
/* Didn't find $, look in enclosing scope(s).
*/
return null;
}
ce = ce.lastComma();
/* If we are indexing into an array that is really a type
* tuple, rewrite this as an index into a type tuple and
* try again.
*/
if (auto te = ce.isTypeExp())
{
if (auto ttp = te.type.isTypeTuple())
return dollarFromTypeTuple(loc, ttp, _scope);
}
/* *pvar is lazily initialized, so if we refer to $
* multiple times, it gets set only once.
*/
if (!*pvar) // if not already initialized
{
/* Create variable v and set it to the value of $
*/
VarDeclaration v;
Type t;
if (auto tupexp = ce.isTupleExp())
{
/* It is for an expression tuple, so the
* length will be a const.
*/
Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
v.storage_class |= STC.temp | STC.static_ | STC.const_;
}
else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
{
// Look for opDollar
assert(exp.op == EXP.array || exp.op == EXP.slice);
AggregateDeclaration ad = isAggregate(t);
assert(ad);
Dsymbol s = ad.search(loc, Id.opDollar);
if (!s) // no dollar exists -- search in higher scope
return null;
s = s.toAlias();
Expression e = null;
// Check for multi-dimensional opDollar(dim) template.
if (TemplateDeclaration td = s.isTemplateDeclaration())
{
dinteger_t dim = 0;
if (auto ae = exp.isArrayExp())
{
dim = ae.currentDimension;
}
else if (exp.isSliceExp())
{
dim = 0; // slices are currently always one-dimensional
}
else
{
assert(0);
}
auto tiargs = new Objects();
Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
edim = edim.expressionSemantic(_scope);
tiargs.push(edim);
e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
}
else
{
/* opDollar exists, but it's not a template.
* This is acceptable ONLY for single-dimension indexing.
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
auto ae = exp.isArrayExp();
if (ae && ae.arguments.length != 1)
{
error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
return null;
}
Declaration d = s.isDeclaration();
assert(d);
e = new DotVarExp(loc, ce, d);
}
e = e.expressionSemantic(_scope);
if (!e.type)
error(exp.loc, "`%s` has no value", e.toChars());
t = e.type.toBasetype();
if (t && t.ty == Tfunction)
e = new CallExp(e.loc, e);
v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
}
else
{
/* For arrays, $ will either be a compile-time constant
* (in which case its value in set during constant-folding),
* or a variable (in which case an expression is created in
* toir.c).
*/
// https://issues.dlang.org/show_bug.cgi?id=16213
// For static arrays $ is known at compile time,
// so declare it as a manifest constant.
auto tsa = ce.type ? ce.type.isTypeSArray() : null;
if (tsa)
{
auto e = new ExpInitializer(loc, tsa.dim);
v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
}
else
{
auto e = new VoidInitializer(Loc.initial);
e.type = Type.tsize_t;
v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
}
}
*pvar = v;
}
(*pvar).dsymbolSemantic(_scope);
return (*pvar);
}
override inout(ArrayScopeSymbol) isArrayScopeSymbol() inout
{
return this;

View file

@ -230,7 +230,6 @@ public:
virtual Dsymbol *toAlias2();
virtual void setScope(Scope *sc);
virtual void importAll(Scope *sc);
virtual Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone);
virtual bool overloadInsert(Dsymbol *s);
virtual uinteger_t size(const Loc &loc);
virtual bool isforwardRef();
@ -330,16 +329,14 @@ public:
Dsymbols *members; // all Dsymbol's in this scope
DsymbolTable *symtab; // members[] sorted into table
unsigned endlinnum; // the linnumber of the statement after the scope (0 if unknown)
private:
Dsymbols *importedScopes; // imported Dsymbol's
Visibility::Kind *visibilities; // array of `Visibility.Kind`, one for each import
private:
BitArray accessiblePackages, privateAccessiblePackages;
public:
ScopeDsymbol *syntaxCopy(Dsymbol *s) override;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
virtual void importScope(Dsymbol *s, Visibility visibility);
virtual bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0);
bool isforwardRef() override final;
@ -360,7 +357,6 @@ class WithScopeSymbol final : public ScopeDsymbol
public:
WithStatement *withstate;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
WithScopeSymbol *isWithScopeSymbol() override { return this; }
void accept(Visitor *v) override { v->visit(this); }
@ -370,10 +366,8 @@ public:
class ArrayScopeSymbol final : public ScopeDsymbol
{
private:
RootObject *arrayContent;
public:
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = IgnoreNone) override;
RootObject *arrayContent;
ArrayScopeSymbol *isArrayScopeSymbol() override { return this; }
void accept(Visitor *v) override { v->visit(this); }
@ -435,3 +429,4 @@ public:
};
void addMember(Dsymbol *dsym, Scope *sc, ScopeDsymbol *sds);
Dsymbol *search(Dsymbol *d, const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly);

View file

@ -7791,3 +7791,617 @@ void checkPrintfScanfSignature(FuncDeclaration funcdecl, TypeFunction f, Scope*
p, funcdecl.toChars());
}
}
/*********************************************
* Search for ident as member of d.
* Params:
* d = dsymbol where ident is searched for
* loc = location to print for error messages
* ident = identifier to search for
* flags = IgnoreXXXX
* Returns:
* null if not found
*/
extern(C++) Dsymbol search(Dsymbol d, const ref Loc loc, Identifier ident, int flags = IgnoreNone)
{
scope v = new SearchVisitor(loc, ident, flags);
d.accept(v);
return v.result;
}
private extern(C++) class SearchVisitor : Visitor
{
alias visit = Visitor.visit;
const Loc loc;
Identifier ident;
int flags;
Dsymbol result;
this(const ref Loc loc, Identifier ident, int flags)
{
this.loc = loc;
this.ident = ident;
this.flags = flags;
}
void setResult(Dsymbol d)
{
result = d;
}
override void visit(Dsymbol d)
{
//printf("Dsymbol::search(this=%p,%s, ident='%s')\n", d, d.toChars(), ident.toChars());
return setResult(null);
}
override void visit(ScopeDsymbol sds)
{
//printf("%s.ScopeDsymbol::search(ident='%s', flags=x%x)\n", sds.toChars(), ident.toChars(), flags);
//if (strcmp(ident.toChars(),"c") == 0) *(char*)0=0;
// Look in symbols declared in this module
if (sds.symtab && !(flags & SearchImportsOnly))
{
//printf(" look in locals\n");
auto s1 = sds.symtab.lookup(ident);
if (s1)
{
//printf("\tfound in locals = '%s.%s'\n",toChars(),s1.toChars());
return setResult(s1);
}
}
//printf(" not found in locals\n");
// Look in imported scopes
if (!sds.importedScopes)
return setResult(null);
//printf(" look in imports\n");
Dsymbol s = null;
OverloadSet a = null;
// Look in imported modules
for (size_t i = 0; i < sds.importedScopes.length; i++)
{
// If private import, don't search it
if ((flags & IgnorePrivateImports) && sds.visibilities[i] == Visibility.Kind.private_)
continue;
int sflags = flags & (IgnoreErrors | IgnoreAmbiguous); // remember these in recursive searches
Dsymbol ss = (*sds.importedScopes)[i];
//printf("\tscanning import '%s', visibilities = %d, isModule = %p, isImport = %p\n", ss.toChars(), visibilities[i], ss.isModule(), ss.isImport());
if (ss.isModule())
{
if (flags & SearchLocalsOnly)
continue;
}
else // mixin template
{
if (flags & SearchImportsOnly)
continue;
sflags |= SearchLocalsOnly;
}
/* Don't find private members if ss is a module
*/
Dsymbol s2 = ss.search(loc, ident, sflags | (ss.isModule() ? IgnorePrivateImports : IgnoreNone));
import dmd.access : symbolIsVisible;
if (!s2 || !(flags & IgnoreSymbolVisibility) && !symbolIsVisible(sds, s2))
continue;
if (!s)
{
s = s2;
if (s && s.isOverloadSet())
a = sds.mergeOverloadSet(ident, a, s);
}
else if (s2 && s != s2)
{
if (s.toAlias() == s2.toAlias() || s.getType() == s2.getType() && s.getType())
{
/* After following aliases, we found the same
* symbol, so it's not an ambiguity. But if one
* alias is deprecated or less accessible, prefer
* the other.
*/
if (s.isDeprecated() || s.visible() < s2.visible() && s2.visible().kind != Visibility.Kind.none)
s = s2;
}
else
{
/* Two imports of the same module should be regarded as
* the same.
*/
Import i1 = s.isImport();
Import i2 = s2.isImport();
if (!(i1 && i2 && (i1.mod == i2.mod || (!i1.parent.isImport() && !i2.parent.isImport() && i1.ident.equals(i2.ident)))))
{
/* https://issues.dlang.org/show_bug.cgi?id=8668
* Public selective import adds AliasDeclaration in module.
* To make an overload set, resolve aliases in here and
* get actual overload roots which accessible via s and s2.
*/
s = s.toAlias();
s2 = s2.toAlias();
/* If both s2 and s are overloadable (though we only
* need to check s once)
*/
auto so2 = s2.isOverloadSet();
if ((so2 || s2.isOverloadable()) && (a || s.isOverloadable()))
{
if (symbolIsVisible(sds, s2))
{
a = sds.mergeOverloadSet(ident, a, s2);
}
if (!symbolIsVisible(sds, s))
s = s2;
continue;
}
/* Two different overflow sets can have the same members
* https://issues.dlang.org/show_bug.cgi?id=16709
*/
auto so = s.isOverloadSet();
if (so && so2)
{
if (so.a.length == so2.a.length)
{
foreach (j; 0 .. so.a.length)
{
if (so.a[j] !is so2.a[j])
goto L1;
}
continue; // the same
L1:
{ } // different
}
}
if (flags & IgnoreAmbiguous) // if return NULL on ambiguity
return setResult(null);
/* If two imports from C import files, pick first one, as C has global name space
*/
if (s.isCsymbol() && s2.isCsymbol())
continue;
if (!(flags & IgnoreErrors))
ScopeDsymbol.multiplyDefined(loc, s, s2);
break;
}
}
}
}
if (s)
{
/* Build special symbol if we had multiple finds
*/
if (a)
{
if (!s.isOverloadSet())
a = sds.mergeOverloadSet(ident, a, s);
s = a;
}
//printf("\tfound in imports %s.%s\n", toChars(), s.toChars());
return setResult(s);
}
//printf(" not found in imports\n");
return setResult(null);
}
override void visit(WithScopeSymbol ws)
{
//printf("WithScopeSymbol.search(%s)\n", ident.toChars());
if (flags & SearchImportsOnly)
return setResult(null);
// Acts as proxy to the with class declaration
Dsymbol s = null;
Expression eold = null;
for (Expression e = ws.withstate.exp; e && e != eold; e = resolveAliasThis(ws._scope, e, true))
{
if (auto se = e.isScopeExp())
{
s = se.sds;
}
else if (e.isTypeExp())
{
s = e.type.toDsymbol(null);
}
else
{
Type t = e.type.toBasetype();
s = t.toDsymbol(null);
}
if (s)
{
s = s.search(loc, ident, flags);
if (s)
return setResult(s);
}
eold = e;
}
return setResult(null);
}
override void visit(ArrayScopeSymbol ass)
{
//printf("ArrayScopeSymbol::search('%s', flags = %d)\n", ident.toChars(), flags);
if (ident != Id.dollar)
return setResult(null);
VarDeclaration* pvar;
Expression ce;
static Dsymbol dollarFromTypeTuple(const ref Loc loc, TypeTuple tt, Scope* sc)
{
/* $ gives the number of type entries in the type tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
Expression e = new IntegerExp(Loc.initial, tt.arguments.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(sc);
return v;
}
const DYNCAST kind = ass.arrayContent.dyncast();
switch (kind) with (DYNCAST)
{
case dsymbol:
TupleDeclaration td = cast(TupleDeclaration) ass.arrayContent;
/* $ gives the number of elements in the tuple
*/
auto v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, null);
Expression e = new IntegerExp(Loc.initial, td.objects.length, Type.tsize_t);
v._init = new ExpInitializer(Loc.initial, e);
v.storage_class |= STC.temp | STC.static_ | STC.const_;
v.dsymbolSemantic(ass._scope);
return setResult(v);
case type:
return setResult(dollarFromTypeTuple(loc, cast(TypeTuple) ass.arrayContent, ass._scope));
default:
break;
}
Expression exp = cast(Expression) ass.arrayContent;
if (auto ie = exp.isIndexExp())
{
/* array[index] where index is some function of $
*/
pvar = &ie.lengthVar;
ce = ie.e1;
}
else if (auto se = exp.isSliceExp())
{
/* array[lwr .. upr] where lwr or upr is some function of $
*/
pvar = &se.lengthVar;
ce = se.e1;
}
else if (auto ae = exp.isArrayExp())
{
/* array[e0, e1, e2, e3] where e0, e1, e2 are some function of $
* $ is a opDollar!(dim)() where dim is the dimension(0,1,2,...)
*/
pvar = &ae.lengthVar;
ce = ae.e1;
}
else
{
/* Didn't find $, look in enclosing scope(s).
*/
return setResult(null);
}
ce = ce.lastComma();
/* If we are indexing into an array that is really a type
* tuple, rewrite this as an index into a type tuple and
* try again.
*/
if (auto te = ce.isTypeExp())
{
if (auto ttp = te.type.isTypeTuple())
return setResult(dollarFromTypeTuple(loc, ttp, ass._scope));
}
/* *pvar is lazily initialized, so if we refer to $
* multiple times, it gets set only once.
*/
if (!*pvar) // if not already initialized
{
/* Create variable v and set it to the value of $
*/
VarDeclaration v;
Type t;
if (auto tupexp = ce.isTupleExp())
{
/* It is for an expression tuple, so the
* length will be a const.
*/
Expression e = new IntegerExp(Loc.initial, tupexp.exps.length, Type.tsize_t);
v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, new ExpInitializer(Loc.initial, e));
v.storage_class |= STC.temp | STC.static_ | STC.const_;
}
else if (ce.type && (t = ce.type.toBasetype()) !is null && (t.ty == Tstruct || t.ty == Tclass))
{
// Look for opDollar
assert(exp.op == EXP.array || exp.op == EXP.slice);
AggregateDeclaration ad = isAggregate(t);
assert(ad);
Dsymbol s = ad.search(loc, Id.opDollar);
if (!s) // no dollar exists -- search in higher scope
return setResult(null);
s = s.toAlias();
Expression e = null;
// Check for multi-dimensional opDollar(dim) template.
if (TemplateDeclaration td = s.isTemplateDeclaration())
{
dinteger_t dim = 0;
if (auto ae = exp.isArrayExp())
{
dim = ae.currentDimension;
}
else if (exp.isSliceExp())
{
dim = 0; // slices are currently always one-dimensional
}
else
{
assert(0);
}
auto tiargs = new Objects();
Expression edim = new IntegerExp(Loc.initial, dim, Type.tsize_t);
edim = edim.expressionSemantic(ass._scope);
tiargs.push(edim);
e = new DotTemplateInstanceExp(loc, ce, td.ident, tiargs);
}
else
{
/* opDollar exists, but it's not a template.
* This is acceptable ONLY for single-dimension indexing.
* Note that it's impossible to have both template & function opDollar,
* because both take no arguments.
*/
auto ae = exp.isArrayExp();
if (ae && ae.arguments.length != 1)
{
error(exp.loc, "`%s` only defines opDollar for one dimension", ad.toChars());
return setResult(null);
}
Declaration d = s.isDeclaration();
assert(d);
e = new DotVarExp(loc, ce, d);
}
e = e.expressionSemantic(ass._scope);
if (!e.type)
error(exp.loc, "`%s` has no value", e.toChars());
t = e.type.toBasetype();
if (t && t.ty == Tfunction)
e = new CallExp(e.loc, e);
v = new VarDeclaration(loc, null, Id.dollar, new ExpInitializer(Loc.initial, e));
v.storage_class |= STC.temp | STC.ctfe | STC.rvalue;
}
else
{
/* For arrays, $ will either be a compile-time constant
* (in which case its value in set during constant-folding),
* or a variable (in which case an expression is created in
* toir.c).
*/
// https://issues.dlang.org/show_bug.cgi?id=16213
// For static arrays $ is known at compile time,
// so declare it as a manifest constant.
auto tsa = ce.type ? ce.type.isTypeSArray() : null;
if (tsa)
{
auto e = new ExpInitializer(loc, tsa.dim);
v = new VarDeclaration(loc, tsa.dim.type, Id.dollar, e, STC.manifest);
}
else
{
auto e = new VoidInitializer(Loc.initial);
e.type = Type.tsize_t;
v = new VarDeclaration(loc, Type.tsize_t, Id.dollar, e);
v.storage_class |= STC.temp | STC.ctfe; // it's never a true static variable
}
}
*pvar = v;
}
(*pvar).dsymbolSemantic(ass._scope);
return setResult((*pvar));
}
override void visit(Import imp)
{
//printf("%s.Import.search(ident = '%s', flags = x%x)\n", imp.toChars(), ident.toChars(), flags);
if (!imp.pkg)
{
imp.load(null);
imp.mod.importAll(null);
imp.mod.dsymbolSemantic(null);
}
// Forward it to the package/module
return setResult(imp.pkg.search(loc, ident, flags));
}
override void visit(Nspace ns)
{
//printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
if (ns._scope && !ns.symtab)
dsymbolSemantic(ns, ns._scope);
if (!ns.members || !ns.symtab) // opaque or semantic() is not yet called
{
if (!(flags & IgnoreErrors))
.error(loc, "%s `%s` is forward referenced when looking for `%s`", ns.kind, ns.toPrettyChars, ident.toChars());
return setResult(null);
}
visit(cast(ScopeDsymbol)ns);
}
override void visit(EnumDeclaration em)
{
//printf("%s.EnumDeclaration::search('%s')\n", em.toChars(), ident.toChars());
if (em._scope)
{
// Try one last time to resolve this enum
dsymbolSemantic(em, em._scope);
}
visit(cast(ScopeDsymbol)em);
}
override void visit(Package pkg)
{
//printf("%s Package.search('%s', flags = x%x)\n", pkg.toChars(), ident.toChars(), flags);
flags &= ~SearchLocalsOnly; // searching an import is always transitive
if (!pkg.isModule() && pkg.mod)
{
// Prefer full package name.
Dsymbol s = pkg.symtab ? pkg.symtab.lookup(ident) : null;
if (s)
return setResult(s);
//printf("[%s] through pkdmod: %s\n", loc.toChars(), toChars());
return setResult(pkg.mod.search(loc, ident, flags));
}
visit(cast(ScopeDsymbol)pkg);
}
override void visit(Module m)
{
/* Since modules can be circularly referenced,
* need to stop infinite recursive searches.
* This is done with the cache.
*/
//printf("%s Module.search('%s', flags = x%x) insearch = %d\n", m.toChars(), ident.toChars(), flags, m.insearch);
if (m.insearch)
return setResult(null);
/* Qualified module searches always search their imports,
* even if SearchLocalsOnly
*/
if (!(flags & SearchUnqualifiedModule))
flags &= ~(SearchUnqualifiedModule | SearchLocalsOnly);
if (m.searchCacheIdent == ident && m.searchCacheFlags == flags)
{
//printf("%s Module::search('%s', flags = %d) insearch = %d searchCacheSymbol = %s\n",
// toChars(), ident.toChars(), flags, insearch, searchCacheSymbol ? searchCacheSymbol.toChars() : "null");
return setResult(m.searchCacheSymbol);
}
uint errors = global.errors;
m.insearch = true;
visit(cast(ScopeDsymbol)m);
Dsymbol s = result;
m.insearch = false;
if (errors == global.errors)
{
// https://issues.dlang.org/show_bug.cgi?id=10752
// Can cache the result only when it does not cause
// access error so the side-effect should be reproduced in later search.
m.searchCacheIdent = ident;
m.searchCacheSymbol = s;
m.searchCacheFlags = flags;
}
return setResult(s);
}
override void visit(Declaration decl)
{
Dsymbol s = null;
if (decl.type)
{
s = decl.type.toDsymbol(decl._scope);
if (s)
s = s.search(loc, ident, flags);
}
return setResult(s);
}
override void visit(StructDeclaration sd)
{
//printf("%s.StructDeclaration::search('%s', flags = x%x)\n", sd.toChars(), ident.toChars(), flags);
if (sd._scope && !sd.symtab)
dsymbolSemantic(sd, sd._scope);
if (!sd.members || !sd.symtab) // opaque or semantic() is not yet called
{
// .stringof is always defined (but may be hidden by some other symbol)
if(ident != Id.stringof && !(flags & IgnoreErrors) && sd.semanticRun < PASS.semanticdone)
.error(loc, "%s `%s` is forward referenced when looking for `%s`", sd.kind, sd.toPrettyChars, ident.toChars());
return setResult(null);
}
visit(cast(ScopeDsymbol)sd);
}
override void visit(ClassDeclaration cd)
{
//printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", cd.toChars(), ident.toChars(), flags);
//if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
if (cd._scope && cd.baseok < Baseok.semanticdone)
{
if (!cd.inuse)
{
// must semantic on base class/interfaces
cd.inuse = true;
dsymbolSemantic(cd, null);
cd.inuse = false;
}
}
if (!cd.members || !cd.symtab) // opaque or addMember is not yet done
{
// .stringof is always defined (but may be hidden by some other symbol)
if (ident != Id.stringof && !(flags & IgnoreErrors) && cd.semanticRun < PASS.semanticdone)
cd.classError("%s `%s` is forward referenced when looking for `%s`", ident.toChars());
//*(char*)0=0;
return setResult(null);
}
visit(cast(ScopeDsymbol)cd);
auto s = result;
// don't search imports of base classes
if (flags & SearchImportsOnly)
return setResult(s);
if (s)
return setResult(s);
// Search bases classes in depth-first, left to right order
foreach (b; (*cd.baseclasses)[])
{
if (!b.sym)
continue;
if (!b.sym.symtab)
{
cd.classError("%s `%s` base `%s` is forward referenced", b.sym.ident.toChars());
continue;
}
import dmd.access : symbolIsVisible;
s = b.sym.search(loc, ident, flags);
if (!s)
continue;
else if (s == cd) // happens if s is nested in this and derives from this
s = null;
else if (!(flags & IgnoreSymbolVisibility) && !(s.visible().kind == Visibility.Kind.protected_) && !symbolIsVisible(cd, s))
s = null;
else
break;
}
return setResult(s);
}
}

View file

@ -20,6 +20,7 @@ import dmd.astenums;
import dmd.arraytypes;
import dmd.attrib;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
import dmd.globals;
import dmd.hdrgen;

View file

@ -50,7 +50,6 @@ public:
bool oneMember(Dsymbol **ps, Identifier *ident) override;
Type *getType() override;
const char *kind() const override;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
bool isDeprecated() const override; // is Dsymbol deprecated?
Visibility visible() override;
bool isSpecial() const;

View file

@ -501,7 +501,6 @@ public:
virtual Dsymbol* toAlias2();
virtual void setScope(Scope* sc);
virtual void importAll(Scope* sc);
virtual Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0);
virtual bool overloadInsert(Dsymbol* s);
virtual uinteger_t size(const Loc& loc);
virtual bool isforwardRef();
@ -619,14 +618,13 @@ public:
Array<Dsymbol* >* members;
DsymbolTable* symtab;
uint32_t endlinnum;
private:
Array<Dsymbol* >* importedScopes;
Visibility::Kind* visibilities;
private:
BitArray accessiblePackages;
BitArray privateAccessiblePackages;
public:
ScopeDsymbol* syntaxCopy(Dsymbol* s) override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
virtual void importScope(Dsymbol* s, Visibility visibility);
virtual bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0);
bool isforwardRef() final override;
@ -3941,7 +3939,6 @@ public:
Expression* identExp;
Nspace* syntaxCopy(Dsymbol* s) override;
void setScope(Scope* sc) override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
bool hasPointers() override;
void setFieldOffset(AggregateDeclaration* ad, FieldState& fieldState, bool isunion) override;
const char* kind() const override;
@ -5730,9 +5727,7 @@ public:
bool com;
bool stack;
int32_t cppDtorVtblIndex;
private:
bool inuse;
public:
ThreeState isabstract;
Baseok baseok;
ObjcClassDeclaration objc;
@ -5747,7 +5742,6 @@ public:
virtual bool isBaseOf(ClassDeclaration* cd, int32_t* poffset);
bool isBaseInfoComplete() const;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override;
void finalizeSize() final override;
bool hasMonitor();
bool isFuncHidden(FuncDeclaration* fd);
@ -5803,7 +5797,6 @@ public:
_d_dynamicArray< const char > mangleOverride;
const char* kind() const override;
uinteger_t size(const Loc& loc) final override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override;
bool isStatic() const;
LINK resolvedLinkage() const;
virtual bool isDelete();
@ -6136,7 +6129,6 @@ public:
bool oneMember(Dsymbol** ps, Identifier* ident) override;
Type* getType() override;
const char* kind() const override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
bool isDeprecated() const override;
Visibility visible() override;
bool isSpecial() const;
@ -6179,7 +6171,6 @@ public:
void importAll(Scope* sc) override;
Dsymbol* toAlias() override;
void setScope(Scope* sc) override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
bool overloadInsert(Dsymbol* s) override;
Import* isImport() override;
void accept(Visitor* v) override;
@ -6209,7 +6200,6 @@ public:
bool equals(const RootObject* const o) const override;
Package* isPackage() final override;
bool isAncestorPackageOf(const Package* const pkg) const;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
void accept(Visitor* v) override;
Module* isPackageMod();
void resolvePKGunknown();
@ -6252,12 +6242,10 @@ private:
public:
bool selfImports();
bool rootImports();
private:
Identifier* searchCacheIdent;
Dsymbol* searchCacheSymbol;
int32_t searchCacheFlags;
bool insearch;
public:
Module* importedFrom;
Array<Dsymbol* >* decldefs;
Array<Module* > aimports;
@ -6280,7 +6268,6 @@ public:
void importAll(Scope* prevsc) override;
int32_t needModuleInfo();
void checkImportDeprecation(const Loc& loc, Scope* sc);
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
bool isPackageAccessible(Package* p, Visibility visibility, int32_t flags = 0) override;
Dsymbol* symtabInsert(Dsymbol* s) override;
static void runDeferredSemantic();
@ -6496,7 +6483,6 @@ private:
public:
static StructDeclaration* create(const Loc& loc, Identifier* id, bool inObject);
StructDeclaration* syntaxCopy(Dsymbol* s) override;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) final override;
const char* kind() const override;
void finalizeSize() final override;
bool isPOD();
@ -6521,16 +6507,14 @@ class WithScopeSymbol final : public ScopeDsymbol
{
public:
WithStatement* withstate;
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 8) override;
WithScopeSymbol* isWithScopeSymbol() override;
void accept(Visitor* v) override;
};
class ArrayScopeSymbol final : public ScopeDsymbol
{
RootObject* arrayContent;
public:
Dsymbol* search(const Loc& loc, Identifier* ident, int32_t flags = 0) override;
RootObject* arrayContent;
ArrayScopeSymbol* isArrayScopeSymbol() override;
void accept(Visitor* v) override;
};
@ -6591,6 +6575,8 @@ extern void dsymbolSemantic(Dsymbol* dsym, Scope* sc);
extern void addMember(Dsymbol* dsym, Scope* sc, ScopeDsymbol* sds);
extern Dsymbol* search(Dsymbol* d, const Loc& loc, Identifier* ident, int32_t flags = 0);
extern Expression* isExpression(RootObject* o);
extern Dsymbol* isDsymbol(RootObject* o);

View file

@ -44,7 +44,6 @@ public:
void importAll(Scope *sc) override;
Dsymbol *toAlias() override;
void setScope(Scope* sc) override;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
bool overloadInsert(Dsymbol *s) override;
Import *isImport() override { return this; }

View file

@ -20,6 +20,7 @@ import dmd.dcast;
import dmd.declaration;
import dmd.dscope;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.errors;
import dmd.expression;
import dmd.expressionsem;

View file

@ -24,6 +24,7 @@ import dmd.dinterpret;
import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;

View file

@ -22,6 +22,7 @@ import dmd.astenums;
import dmd.declaration;
import dmd.denum;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.expression;
import dmd.func;

View file

@ -43,7 +43,6 @@ public:
bool isAncestorPackageOf(const Package * const pkg) const;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
void accept(Visitor *v) override { v->visit(this); }
Module *isPackageMod();
@ -124,7 +123,6 @@ public:
Module *parse(); // syntactic parse
void importAll(Scope *sc) override;
int needModuleInfo();
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
bool isPackageAccessible(Package *p, Visibility visibility, int flags = 0) override;
Dsymbol *symtabInsert(Dsymbol *s) override;
static void runDeferredSemantic();

View file

@ -99,22 +99,6 @@ extern (C++) final class Nspace : ScopeDsymbol
}
}
override Dsymbol search(const ref Loc loc, Identifier ident, int flags = SearchLocalsOnly)
{
//printf("%s.Nspace.search('%s')\n", toChars(), ident.toChars());
if (_scope && !symtab)
dsymbolSemantic(this, _scope);
if (!members || !symtab) // opaque or semantic() is not yet called
{
if (!(flags & IgnoreErrors))
.error(loc, "%s `%s` is forward referenced when looking for `%s`", kind, toPrettyChars, ident.toChars());
return null;
}
return ScopeDsymbol.search(loc, ident, flags);
}
override bool hasPointers()
{
//printf("Nspace::hasPointers() %s\n", toChars());

View file

@ -22,7 +22,6 @@ class Nspace final : public ScopeDsymbol
Expression *identExp;
Nspace *syntaxCopy(Dsymbol *s) override;
void setScope(Scope *sc) override;
Dsymbol *search(const Loc &loc, Identifier *ident, int flags = SearchLocalsOnly) override;
bool hasPointers() override;
void setFieldOffset(AggregateDeclaration *ad, FieldState& fieldState, bool isunion) override;
const char *kind() const override;

View file

@ -23,6 +23,7 @@ import dmd.declaration;
import dmd.dscope;
import dmd.dstruct;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dtemplate;
import dmd.errors;
import dmd.expression;

View file

@ -285,7 +285,7 @@ void test_semantic()
semantic2(m, NULL);
semantic3(m, NULL);
Dsymbol *s = m->search(Loc(), Identifier::idPool("Error"));
Dsymbol *s = search(m, Loc(), Identifier::idPool("Error"));
assert(s);
AggregateDeclaration *ad = s->isAggregateDeclaration();
assert(ad && ad->ctor && ad->sizeok == Sizeok::done);
@ -501,7 +501,7 @@ void test_cppmangle()
semantic2(m, NULL);
semantic3(m, NULL);
Dsymbol *s = m->search(Loc(), Identifier::idPool("Derived"));
Dsymbol *s = search(m, Loc(), Identifier::idPool("Derived"));
assert(s);
ClassDeclaration *cd = s->isClassDeclaration();
assert(cd && cd->sizeok == Sizeok::done);

View file

@ -8,6 +8,7 @@ module compilable.searching;
import support : afterEach, beforeEach, compiles;
import dmd.dsymbol;
import dmd.dsymbolsem;
import dmd.dclass : ClassDeclaration;
import dmd.declaration : VarDeclaration;
import dmd.dtemplate : TemplateDeclaration;