dmd/compiler/test/unit/parser/linkage_location.d
2022-12-25 06:32:05 +01:00

273 lines
5.6 KiB
D

module parser.linkage_location;
import dmd.frontend : parseModule;
import support : afterEach, beforeEach;
import dmd.attrib : CPPMangleDeclaration, CPPNamespaceDeclaration, LinkDeclaration;
import dmd.location;
import dmd.visitor : SemanticTimeTransitiveVisitor;
@beforeEach initializeFrontend()
{
import dmd.frontend : initDMD;
initDMD();
}
@afterEach deinitializeFrontend()
{
import dmd.frontend : deinitializeDMD;
deinitializeDMD();
}
extern (C++) static class Visitor : SemanticTimeTransitiveVisitor
{
alias visit = typeof(super).visit;
Loc l;
override void visit(CPPMangleDeclaration md)
{
l = md.loc;
}
override void visit(CPPNamespaceDeclaration nd)
{
l = nd.loc;
}
}
// Testing cpp mangling
@("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();
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)
{
l = ld.loc;
}
}
@("extern(C++) variable")
unittest
{
auto t = parseModule("test.d", " extern(C++) int a;");
scope visitor = new LinkVisitor;
t.module_.accept(visitor);
assert(visitor.l.linnum == 1);
assert(visitor.l.charnum == 13);
}
@("extern(C++) function")
unittest
{
auto t = parseModule("test.d", " extern(C++) void f();");
scope visitor = new LinkVisitor;
t.module_.accept(visitor);
assert(visitor.l.linnum == 1);
assert(visitor.l.charnum == 13);
}
@("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);
}