mirror of
https://github.com/dlang/dmd.git
synced 2025-04-26 21:21:48 +03:00
fix Issue 23598 - Circular reference bug with static if and eponymous templates (#14838)
This commit is contained in:
parent
fbf8061eec
commit
4791e9e7fa
10 changed files with 154 additions and 12 deletions
|
@ -207,7 +207,7 @@ extern (C++) abstract class AttribDeclaration : Dsymbol
|
|||
objc.addSymbols(this, classes, categories);
|
||||
}
|
||||
|
||||
override final inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
|
||||
override inout(AttribDeclaration) isAttribDeclaration() inout pure @safe
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
@ -1080,6 +1080,11 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
|
|||
return "static if";
|
||||
}
|
||||
|
||||
override inout(StaticIfDeclaration) isStaticIfDeclaration() inout pure @safe
|
||||
{
|
||||
return this;
|
||||
}
|
||||
|
||||
override void accept(Visitor v)
|
||||
{
|
||||
v.visit(this);
|
||||
|
|
|
@ -37,7 +37,7 @@ public:
|
|||
bool hasStaticCtorOrDtor() override final;
|
||||
void checkCtorConstInit() override final;
|
||||
void addLocalClass(ClassDeclarations *) override final;
|
||||
AttribDeclaration *isAttribDeclaration() override final { return this; }
|
||||
AttribDeclaration *isAttribDeclaration() override { return this; }
|
||||
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
@ -184,6 +184,7 @@ public:
|
|||
void addMember(Scope *sc, ScopeDsymbol *sds) override;
|
||||
void setScope(Scope *sc) override;
|
||||
void importAll(Scope *sc) override;
|
||||
StaticIfDeclaration *isStaticIfDeclaration() override { return this; }
|
||||
const char *kind() const override;
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
|
|
@ -1413,6 +1413,7 @@ extern (C++) class Dsymbol : ASTNode
|
|||
inout(OverloadSet) isOverloadSet() inout { return null; }
|
||||
inout(CompileDeclaration) isCompileDeclaration() inout { return null; }
|
||||
inout(StaticAssert) isStaticAssert() inout { return null; }
|
||||
inout(StaticIfDeclaration) isStaticIfDeclaration() inout { return null; }
|
||||
}
|
||||
|
||||
/***********************************************************
|
||||
|
|
|
@ -72,6 +72,7 @@ class ExpressionDsymbol;
|
|||
class AliasAssign;
|
||||
class OverloadSet;
|
||||
class StaticAssert;
|
||||
class StaticIfDeclaration;
|
||||
struct AA;
|
||||
#ifdef IN_GCC
|
||||
typedef union tree_node Symbol;
|
||||
|
@ -323,6 +324,7 @@ public:
|
|||
virtual OverloadSet *isOverloadSet() { return NULL; }
|
||||
virtual CompileDeclaration *isCompileDeclaration() { return NULL; }
|
||||
virtual StaticAssert *isStaticAssert() { return NULL; }
|
||||
virtual StaticIfDeclaration *isStaticIfDeclaration() { return NULL; }
|
||||
void accept(Visitor *v) override { v->visit(this); }
|
||||
};
|
||||
|
||||
|
|
|
@ -4539,7 +4539,8 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
override void visit(StructDeclaration sd)
|
||||
{
|
||||
//printf("StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
|
||||
enum log = false;
|
||||
if (log) printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
|
||||
|
||||
//static int count; if (++count == 20) assert(0);
|
||||
|
||||
|
@ -4609,6 +4610,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
if (!sd.members) // if opaque declaration
|
||||
{
|
||||
if (log) printf("\topaque declaration %s\n", sd.toChars());
|
||||
sd.semanticRun = PASS.semanticdone;
|
||||
return;
|
||||
}
|
||||
|
@ -4660,7 +4662,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
|
||||
sc2.pop();
|
||||
|
||||
//printf("\tdeferring %s\n", toChars());
|
||||
if (log) printf("\tdeferring %s\n", sd.toChars());
|
||||
return deferDsymbolSemantic(sd, scx);
|
||||
}
|
||||
|
||||
|
@ -4690,7 +4692,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
sd.inv = buildInv(sd, sc2);
|
||||
|
||||
sd.semanticRun = PASS.semanticdone;
|
||||
//printf("-StructDeclaration::semantic(this=%p, '%s')\n", sd, sd.toChars());
|
||||
if (log) printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
|
||||
|
||||
sc2.pop();
|
||||
|
||||
|
@ -4757,6 +4759,7 @@ private extern(C++) final class DsymbolSemanticVisitor : Visitor
|
|||
// Make an error in 2.110
|
||||
if (sd.storage_class & STC.scope_)
|
||||
deprecation(sd.loc, "`scope` as a type constraint is deprecated. Use `scope` at the usage site.");
|
||||
//printf("-StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", sd, sd.toPrettyChars(), sd.sizeok);
|
||||
}
|
||||
|
||||
void interfaceSemantic(ClassDeclaration cd)
|
||||
|
@ -6147,7 +6150,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
|
|||
Dsymbol s;
|
||||
if (Dsymbol.oneMembers(tempinst.members, &s, tempdecl.ident) && s)
|
||||
{
|
||||
//printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
|
||||
//printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
|
||||
//printf("setting aliasdecl\n");
|
||||
tempinst.aliasdecl = s;
|
||||
}
|
||||
|
@ -6194,7 +6197,7 @@ void templateInstanceSemantic(TemplateInstance tempinst, Scope* sc, Expressions*
|
|||
{
|
||||
if (!tempinst.aliasdecl || tempinst.aliasdecl != s)
|
||||
{
|
||||
//printf("tempdecl.ident = %s, s = '%s'\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
|
||||
//printf("tempdecl.ident = %s, s = `%s %s`\n", tempdecl.ident.toChars(), s.kind(), s.toPrettyChars());
|
||||
//printf("setting aliasdecl 2\n");
|
||||
tempinst.aliasdecl = s;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import dmd.aliasthis;
|
|||
import dmd.arraytypes;
|
||||
import dmd.astenums;
|
||||
import dmd.ast_node;
|
||||
import dmd.attrib;
|
||||
import dmd.dcast;
|
||||
import dmd.dclass;
|
||||
import dmd.declaration;
|
||||
|
@ -1226,7 +1227,7 @@ extern (C++) final class TemplateDeclaration : ScopeDsymbol
|
|||
paramscope.pop();
|
||||
static if (LOGM)
|
||||
{
|
||||
printf("-TemplateDeclaration.matchWithInstance(this = %p, ti = %p) = %d\n", this, ti, m);
|
||||
printf("-TemplateDeclaration.matchWithInstance(this = %s, ti = %s) = %d\n", toChars(), ti.toChars(), m);
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
@ -7520,6 +7521,43 @@ extern (C++) class TemplateInstance : ScopeDsymbol
|
|||
|
||||
members.foreachDsymbol( (s) { s.importAll(sc2); } );
|
||||
|
||||
if (!aliasdecl)
|
||||
{
|
||||
/* static if's are crucial to evaluating aliasdecl correctly. But
|
||||
* evaluating the if/else bodies may require aliasdecl.
|
||||
* So, evaluate the condition for static if's, but not their if/else bodies.
|
||||
* Then try to set aliasdecl.
|
||||
* Later do the if/else bodies.
|
||||
* https://issues.dlang.org/show_bug.cgi?id=23598
|
||||
* It might be better to do this by attaching a lambda to the StaticIfDeclaration
|
||||
* to do the oneMembers call after the sid.include(sc2) is run as part of dsymbolSemantic().
|
||||
*/
|
||||
bool done;
|
||||
void staticIfDg(Dsymbol s)
|
||||
{
|
||||
if (done || aliasdecl)
|
||||
return;
|
||||
//printf("\t staticIfDg on '%s %s' in '%s'\n", s.kind(), s.toChars(), this.toChars());
|
||||
if (!s.isStaticIfDeclaration())
|
||||
{
|
||||
//s.dsymbolSemantic(sc2);
|
||||
done = true;
|
||||
return;
|
||||
}
|
||||
auto sid = s.isStaticIfDeclaration();
|
||||
sid.include(sc2);
|
||||
if (members.length)
|
||||
{
|
||||
Dsymbol sa;
|
||||
if (Dsymbol.oneMembers(members, &sa, tempdecl.ident) && sa)
|
||||
aliasdecl = sa;
|
||||
}
|
||||
done = true;
|
||||
}
|
||||
|
||||
members.foreachDsymbol(&staticIfDg);
|
||||
}
|
||||
|
||||
void symbolDg(Dsymbol s)
|
||||
{
|
||||
//printf("\t semantic on '%s' %p kind %s in '%s'\n", s.toChars(), s, s.kind(), this.toChars());
|
||||
|
|
|
@ -102,6 +102,7 @@ class VisibilityDeclaration;
|
|||
class OverloadSet;
|
||||
class CompileDeclaration;
|
||||
class StaticAssert;
|
||||
class StaticIfDeclaration;
|
||||
class DsymbolTable;
|
||||
struct MangleOverride;
|
||||
class AliasThis;
|
||||
|
@ -571,6 +572,7 @@ public:
|
|||
virtual OverloadSet* isOverloadSet();
|
||||
virtual CompileDeclaration* isCompileDeclaration();
|
||||
virtual StaticAssert* isStaticAssert();
|
||||
virtual StaticIfDeclaration* isStaticIfDeclaration();
|
||||
};
|
||||
|
||||
typedef uint64_t size_t;
|
||||
|
@ -5387,7 +5389,7 @@ public:
|
|||
void checkCtorConstInit() final override;
|
||||
void addLocalClass(Array<ClassDeclaration* >* aclasses) final override;
|
||||
void addObjcSymbols(Array<ClassDeclaration* >* classes, Array<ClassDeclaration* >* categories) final override;
|
||||
AttribDeclaration* isAttribDeclaration() final override;
|
||||
AttribDeclaration* isAttribDeclaration() override;
|
||||
void accept(Visitor* v) override;
|
||||
};
|
||||
|
||||
|
@ -5524,6 +5526,7 @@ public:
|
|||
void setScope(Scope* sc) override;
|
||||
void importAll(Scope* sc) override;
|
||||
const char* kind() const override;
|
||||
StaticIfDeclaration* isStaticIfDeclaration() override;
|
||||
void accept(Visitor* v) override;
|
||||
};
|
||||
|
||||
|
|
87
compiler/test/compilable/test23598.d
Normal file
87
compiler/test/compilable/test23598.d
Normal file
|
@ -0,0 +1,87 @@
|
|||
// https://issues.dlang.org/show_bug.cgi?id=23598
|
||||
|
||||
alias AliasSeq(a...) = a;
|
||||
|
||||
static if (1)
|
||||
{
|
||||
|
||||
template sort(alias f, a...)
|
||||
{
|
||||
static if (a.length > 0)
|
||||
{
|
||||
alias x = f!(a[0]);
|
||||
alias sort = a;
|
||||
}
|
||||
else
|
||||
alias sort = a;
|
||||
}
|
||||
|
||||
alias SortedItems = sort!(isDependencyOf, String);
|
||||
|
||||
enum isDependencyOf(Item) = Item.DirectDependencies.length == 0;
|
||||
|
||||
struct String
|
||||
{
|
||||
alias DirectDependencies = AliasSeq!();
|
||||
|
||||
enum l = SortedItems.length; // (3)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*****************************************************/
|
||||
|
||||
static if (1)
|
||||
{
|
||||
enum x = 1;
|
||||
enum y = 2;
|
||||
|
||||
template f(T)
|
||||
{
|
||||
alias b = int;
|
||||
static if (x)
|
||||
{
|
||||
alias c = x;
|
||||
}
|
||||
else
|
||||
{
|
||||
alias c = y;
|
||||
}
|
||||
|
||||
static if (is(typeof(c)))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
static assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void g()
|
||||
{
|
||||
int x = f!int.c;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************/
|
||||
|
||||
template forward(args...)
|
||||
{
|
||||
template fwd(alias arg)
|
||||
{
|
||||
alias fwd = arg;
|
||||
}
|
||||
|
||||
alias Result = AliasSeq!();
|
||||
static foreach (arg; args)
|
||||
Result = AliasSeq!(Result, fwd!arg);
|
||||
static if (Result.length == 1)
|
||||
alias forward = Result[0];
|
||||
else
|
||||
alias forward = Result;
|
||||
}
|
||||
|
||||
void func(int i, int j)
|
||||
{
|
||||
func(forward!(i, j));
|
||||
}
|
|
@ -1,13 +1,13 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
----
|
||||
fail_compilation/ice12727.d(16): Error: template instance `IndexTuple!(1, 0)` recursive template expansion
|
||||
fail_compilation/ice12727.d(16): Error: alias `ice12727.IndexTuple!(1, 0).IndexTuple` recursive alias declaration
|
||||
fail_compilation/ice12727.d(23): Error: template instance `ice12727.IndexTuple!(1, 0)` error instantiating
|
||||
fail_compilation/ice12727.d(27): instantiated from here: `Matrix!(float, 3)`
|
||||
fail_compilation/ice12727.d(28): instantiated from here: `Vector!(float, 3)`
|
||||
----
|
||||
*/
|
||||
|
||||
template IndexTuple(int e, int s = 0, T...)
|
||||
{
|
||||
static if (s == e)
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
/*
|
||||
TEST_OUTPUT:
|
||||
---
|
||||
fail_compilation/ice13816.d(15): Error: alias `ice13816.ItemProperty!().ItemProperty` recursive alias declaration
|
||||
fail_compilation/ice13816.d(20): Error: template instance `ice13816.ItemProperty!()` error instantiating
|
||||
fail_compilation/ice13816.d(17): Error: template instance `TypeTuple!(ItemProperty!())` recursive template expansion
|
||||
fail_compilation/ice13816.d(17): Error: alias `ice13816.ItemProperty!().ItemProperty` recursive alias declaration
|
||||
fail_compilation/ice13816.d(22): Error: template instance `ice13816.ItemProperty!()` error instantiating
|
||||
---
|
||||
*/
|
||||
|
||||
|
||||
alias TypeTuple(T...) = T;
|
||||
|
||||
template ItemProperty()
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue