dmd/compiler/test/unit/parser/linkage_location.d
2025-02-17 19:33:21 +01:00

66 lines
1.6 KiB
D

module parser.linkage_location;
import dmd.frontend : parseModule, initDMD, deinitializeDMD;
import dmd.attrib : CPPMangleDeclaration, CPPNamespaceDeclaration, LinkDeclaration;
import dmd.location;
import dmd.visitor : SemanticTimeTransitiveVisitor;
extern (C++) static class LinkVisitor : SemanticTimeTransitiveVisitor
{
alias visit = typeof(super).visit;
Loc[] locs;
override void visit(CPPMangleDeclaration md)
{
locs ~= md.loc;
}
override void visit(CPPNamespaceDeclaration nd)
{
locs ~= nd.loc;
if (nd.decl.length)
{
CPPNamespaceDeclaration next = cast(CPPNamespaceDeclaration)nd.decl.pop();
next.accept(this);
}
}
override void visit(LinkDeclaration ld)
{
locs ~= ld.loc;
}
}
void testLocs(string src, int[2][] lineCols...)
{
initDMD();
auto t = parseModule("test.d", src);
scope visitor = new LinkVisitor;
t.module_.accept(visitor);
// import std; writeln(visitor.locs.map!SourceLoc);
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();
}
unittest
{
testLocs("extern (C++, class) struct C {}", [1, 1]);
testLocs(`extern (C++, "name"~"space") {}`, [1, 1]);
testLocs(" extern(C++) int a;", [1, 13]);
testLocs("alias t = extern(C++) void f();", [1, 11]);
testLocs(`extern (C++, "ns1", "ns2", "ns3") {}`, [1, 1], [1, 1], [1, 1]);
testLocs("extern (C++, 'ns1')\n extern(C++, 'ns2') {}", [1, 1], [2, 3]);
}