diff --git a/compiler/test/unit/parser/linkage_location.d b/compiler/test/unit/parser/linkage_location.d index 2d1cab8813..68169d2f7d 100644 --- a/compiler/test/unit/parser/linkage_location.d +++ b/compiler/test/unit/parser/linkage_location.d @@ -1,273 +1,76 @@ module parser.linkage_location; -import dmd.frontend : parseModule; -import support : afterEach, beforeEach; +import dmd.frontend : parseModule, initDMD, deinitializeDMD; 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 +extern (C++) static class LinkVisitor : SemanticTimeTransitiveVisitor { alias visit = typeof(super).visit; - Loc l; + Loc[] locs; override void visit(CPPMangleDeclaration md) { - l = md.loc; + locs ~= md.loc; } override void visit(CPPNamespaceDeclaration nd) { - l = nd.loc; - } -} + locs ~= 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) { + 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; + locs ~= ld.loc; } } -@("extern(C++) variable") -unittest +void testLocs(string src, int[2][] lineCols...) { - auto t = parseModule("test.d", " extern(C++) int a;"); + initDMD(); + + auto t = parseModule("test.d", src); scope visitor = new LinkVisitor; t.module_.accept(visitor); - assert(visitor.l.linnum == 1); - assert(visitor.l.charnum == 13); + // 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(); } -@("extern(C++) function") 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; - t.module_.accept(visitor); + testLocs(" extern(C++) int a;", [1, 13]); + 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); - 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); + testLocs(`extern (C++, "ns1", "ns2", "ns3") {}`, [1, 1], [1, 1], [1, 1]); + testLocs("extern (C++, 'ns1')\nextern(C++, 'ns2') {}", [1, 1], [2, 1]); + testLocs(`extern (C++, "ns1") extern(C++, "ns2") {}`, [1, 1], [1, 21]); }