mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 13:10:12 +03:00
Extract Dsymbol.search from dsymbols.d and transform it into a visitor (#15787)
This commit is contained in:
parent
428cc6d3c4
commit
f29a92dcbf
25 changed files with 642 additions and 635 deletions
|
@ -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() ||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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; }
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue