mirror of
https://github.com/dlang/dmd.git
synced 2025-04-29 14:40:12 +03:00
Simplify linkage_location unittest
This commit is contained in:
parent
4d4d09ab33
commit
b58d9113ba
1 changed files with 38 additions and 235 deletions
|
@ -1,273 +1,76 @@
|
||||||
module parser.linkage_location;
|
module parser.linkage_location;
|
||||||
|
|
||||||
import dmd.frontend : parseModule;
|
import dmd.frontend : parseModule, initDMD, deinitializeDMD;
|
||||||
import support : afterEach, beforeEach;
|
|
||||||
import dmd.attrib : CPPMangleDeclaration, CPPNamespaceDeclaration, LinkDeclaration;
|
import dmd.attrib : CPPMangleDeclaration, CPPNamespaceDeclaration, LinkDeclaration;
|
||||||
import dmd.location;
|
import dmd.location;
|
||||||
import dmd.visitor : SemanticTimeTransitiveVisitor;
|
import dmd.visitor : SemanticTimeTransitiveVisitor;
|
||||||
|
|
||||||
@beforeEach initializeFrontend()
|
extern (C++) static class LinkVisitor : SemanticTimeTransitiveVisitor
|
||||||
{
|
|
||||||
import dmd.frontend : initDMD;
|
|
||||||
|
|
||||||
initDMD();
|
|
||||||
}
|
|
||||||
|
|
||||||
@afterEach deinitializeFrontend()
|
|
||||||
{
|
|
||||||
import dmd.frontend : deinitializeDMD;
|
|
||||||
deinitializeDMD();
|
|
||||||
}
|
|
||||||
|
|
||||||
extern (C++) static class Visitor : SemanticTimeTransitiveVisitor
|
|
||||||
{
|
{
|
||||||
alias visit = typeof(super).visit;
|
alias visit = typeof(super).visit;
|
||||||
Loc l;
|
Loc[] locs;
|
||||||
|
|
||||||
override void visit(CPPMangleDeclaration md)
|
override void visit(CPPMangleDeclaration md)
|
||||||
{
|
{
|
||||||
l = md.loc;
|
locs ~= md.loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
override void visit(CPPNamespaceDeclaration nd)
|
override void visit(CPPNamespaceDeclaration nd)
|
||||||
{
|
{
|
||||||
l = nd.loc;
|
locs ~= nd.loc;
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing cpp mangling
|
if (nd.decl.length)
|
||||||
|
|
||||||
@("extern (C++, struct) class")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, struct) class C {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern (C++, struct) struct")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, struct) struct S {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern (C++, class) class")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, class) class C {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern (C++, class) struct")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, class) struct C {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern (C++, struct) {}")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, struct) {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern (C++, class) {}")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, class) {}");
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing namespaces
|
|
||||||
|
|
||||||
@(`"namespace"`)
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", `extern (C++, "namespace") {}`);
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@(`"name"~"space"`)
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", `extern (C++, "name"~"space") {}`);
|
|
||||||
|
|
||||||
scope visitor = new Visitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
extern (C++) static class NamespaceVisitor : SemanticTimeTransitiveVisitor
|
|
||||||
{
|
|
||||||
alias visit = typeof(super).visit;
|
|
||||||
Loc[] l;
|
|
||||||
|
|
||||||
override void visit(CPPNamespaceDeclaration nd)
|
|
||||||
{
|
{
|
||||||
l ~= nd.loc;
|
|
||||||
if (nd.decl.length) {
|
|
||||||
CPPNamespaceDeclaration next = cast(CPPNamespaceDeclaration)nd.decl.pop();
|
CPPNamespaceDeclaration next = cast(CPPNamespaceDeclaration)nd.decl.pop();
|
||||||
next.accept(this);
|
next.accept(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@("multiple namespaces - comma separated")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", `extern (C++, "ns1", "ns2", "ns3") {}`);
|
|
||||||
|
|
||||||
scope visitor = new NamespaceVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.length == 3);
|
|
||||||
foreach (Loc l; visitor.l) {
|
|
||||||
assert(l.linnum == 1);
|
|
||||||
assert(l.charnum == 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@("multiple namespaces - same line")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", `extern (C++, "ns1") extern(C++, "ns2") {}`);
|
|
||||||
|
|
||||||
scope visitor = new NamespaceVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
int charnum = 1;
|
|
||||||
|
|
||||||
assert(visitor.l.length == 2);
|
|
||||||
foreach (Loc l; visitor.l) {
|
|
||||||
assert(l.linnum == 1);
|
|
||||||
assert(l.charnum == charnum);
|
|
||||||
charnum += 20;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@("multiple namespaces - different lines")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "extern (C++, 'ns1')\nextern(C++, 'ns2') {}");
|
|
||||||
|
|
||||||
scope visitor = new NamespaceVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
int linnum = 1;
|
|
||||||
|
|
||||||
assert(visitor.l.length == 2);
|
|
||||||
foreach (Loc l; visitor.l) {
|
|
||||||
assert(l.linnum == linnum);
|
|
||||||
assert(l.charnum == 1);
|
|
||||||
linnum++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Testing linkage
|
|
||||||
|
|
||||||
extern (C++) static class LinkVisitor : SemanticTimeTransitiveVisitor
|
|
||||||
{
|
|
||||||
alias visit = typeof(super).visit;
|
|
||||||
Loc l;
|
|
||||||
|
|
||||||
override void visit(LinkDeclaration ld)
|
override void visit(LinkDeclaration ld)
|
||||||
{
|
{
|
||||||
l = ld.loc;
|
locs ~= ld.loc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@("extern(C++) variable")
|
void testLocs(string src, int[2][] lineCols...)
|
||||||
unittest
|
|
||||||
{
|
{
|
||||||
auto t = parseModule("test.d", " extern(C++) int a;");
|
initDMD();
|
||||||
|
|
||||||
|
auto t = parseModule("test.d", src);
|
||||||
|
|
||||||
scope visitor = new LinkVisitor;
|
scope visitor = new LinkVisitor;
|
||||||
t.module_.accept(visitor);
|
t.module_.accept(visitor);
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
// import std; writeln(visitor.locs.map!SourceLoc);
|
||||||
assert(visitor.l.charnum == 13);
|
|
||||||
|
assert(visitor.locs.length == lineCols.length);
|
||||||
|
foreach (i, lineCol; lineCols)
|
||||||
|
{
|
||||||
|
assert(visitor.locs[i].linnum == lineCol[0]);
|
||||||
|
assert(visitor.locs[i].charnum == lineCol[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
deinitializeDMD();
|
||||||
}
|
}
|
||||||
|
|
||||||
@("extern(C++) function")
|
|
||||||
unittest
|
unittest
|
||||||
{
|
{
|
||||||
auto t = parseModule("test.d", " extern(C++) void f();");
|
testLocs("extern (C++, struct) class C {}", [1, 1]);
|
||||||
|
testLocs("extern (C++, struct) struct S {}", [1, 1]);
|
||||||
|
testLocs("extern (C++, class) class C {}", [1, 1]);
|
||||||
|
testLocs("extern (C++, class) struct C {}", [1, 1]);
|
||||||
|
testLocs("extern (C++, struct) {}", [1, 1]);
|
||||||
|
testLocs("extern (C++, class) {}", [1, 1]);
|
||||||
|
testLocs(`extern (C++, "namespace") {}`, [1, 1]);
|
||||||
|
testLocs(`extern (C++, "name"~"space") {}`, [1, 1]);
|
||||||
|
|
||||||
scope visitor = new LinkVisitor;
|
testLocs(" extern(C++) int a;", [1, 13]);
|
||||||
t.module_.accept(visitor);
|
testLocs(" extern(C++) void f();", [1, 13]);
|
||||||
|
testLocs(" extern(C++) struct C {}", [1, 13]);
|
||||||
|
testLocs(" extern(C++) class C {}", [1, 13]);
|
||||||
|
testLocs("alias t = extern(C++) void f();", [1, 11]);
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
testLocs(`extern (C++, "ns1", "ns2", "ns3") {}`, [1, 1], [1, 1], [1, 1]);
|
||||||
assert(visitor.l.charnum == 13);
|
testLocs("extern (C++, 'ns1')\nextern(C++, 'ns2') {}", [1, 1], [2, 1]);
|
||||||
}
|
testLocs(`extern (C++, "ns1") extern(C++, "ns2") {}`, [1, 1], [1, 21]);
|
||||||
|
|
||||||
@("extern(C++) struct")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", " extern(C++) struct C {}");
|
|
||||||
|
|
||||||
scope visitor = new LinkVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("extern(C++) class")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", " extern(C++) class C {}");
|
|
||||||
|
|
||||||
scope visitor = new LinkVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 13);
|
|
||||||
}
|
|
||||||
|
|
||||||
@("alias t = extern(C++) void f();")
|
|
||||||
unittest
|
|
||||||
{
|
|
||||||
auto t = parseModule("test.d", "alias t = extern(C++) void f();");
|
|
||||||
|
|
||||||
scope visitor = new LinkVisitor;
|
|
||||||
t.module_.accept(visitor);
|
|
||||||
|
|
||||||
assert(visitor.l.linnum == 1);
|
|
||||||
assert(visitor.l.charnum == 11);
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue