Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 16 additions & 4 deletions src/dmd/astbase.d
Original file line number Diff line number Diff line change
Expand Up @@ -340,6 +340,12 @@ struct ASTBase
this.ident = ident;
}

final extern (D) this(const ref Loc loc, Identifier ident)
{
this.loc = loc;
this.ident = ident;
}

void addComment(const(char)* comment)
{
if (!this.comment)
Expand Down Expand Up @@ -618,6 +624,12 @@ struct ASTBase
this.decl = decl;
}

final extern (D) this(const ref Loc loc, Identifier ident, Dsymbols* decl)
{
super(loc, ident);
this.decl = decl;
}

override final inout(AttribDeclaration) isAttribDeclaration() inout
{
return this;
Expand Down Expand Up @@ -1403,9 +1415,9 @@ struct ASTBase
Condition condition;
Dsymbols* elsedecl;

final extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
final extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
super(decl);
super(loc, null, decl);
this.condition = condition;
this.elsedecl = elsedecl;
}
Expand Down Expand Up @@ -1434,9 +1446,9 @@ struct ASTBase

extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
{
extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
super(condition, decl, elsedecl);
super(loc, condition, decl, elsedecl);
}

override void accept(Visitor v)
Expand Down
12 changes: 6 additions & 6 deletions src/dmd/attrib.d
Original file line number Diff line number Diff line change
Expand Up @@ -940,9 +940,9 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration
Condition condition; /// condition deciding whether decl or elsedecl applies
Dsymbols* elsedecl; /// array of Dsymbol's for else block

extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
super(decl);
super(loc, null, decl);
//printf("ConditionalDeclaration::ConditionalDeclaration()\n");
this.condition = condition;
this.elsedecl = elsedecl;
Expand All @@ -951,7 +951,7 @@ extern (C++) class ConditionalDeclaration : AttribDeclaration
override Dsymbol syntaxCopy(Dsymbol s)
{
assert(!s);
return new ConditionalDeclaration(condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
return new ConditionalDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
}

override final bool oneMember(Dsymbol* ps, Identifier ident)
Expand Down Expand Up @@ -1018,16 +1018,16 @@ extern (C++) final class StaticIfDeclaration : ConditionalDeclaration
private bool addisdone = false; /// true if members have been added to scope
private bool onStack = false; /// true if a call to `include` is currently active

extern (D) this(Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
extern (D) this(const ref Loc loc, Condition condition, Dsymbols* decl, Dsymbols* elsedecl)
{
super(condition, decl, elsedecl);
super(loc, condition, decl, elsedecl);
//printf("StaticIfDeclaration::StaticIfDeclaration()\n");
}

override Dsymbol syntaxCopy(Dsymbol s)
{
assert(!s);
return new StaticIfDeclaration(condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
return new StaticIfDeclaration(loc, condition.syntaxCopy(), Dsymbol.arraySyntaxCopy(decl), Dsymbol.arraySyntaxCopy(elsedecl));
}

/****************************************
Expand Down
9 changes: 7 additions & 2 deletions src/dmd/parse.d
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,8 @@ final class Parser(AST) : Lexer

linkage = linksave;

Loc startloc;

switch (token.value)
{
case TOK.enum_:
Expand Down Expand Up @@ -690,6 +692,7 @@ final class Parser(AST) : Lexer
s = parseStaticAssert();
else if (next == TOK.if_)
{
const Loc loc = token.loc;
condition = parseStaticIfCondition();
AST.Dsymbols* athen;
if (token.value == TOK.colon)
Expand All @@ -709,7 +712,7 @@ final class Parser(AST) : Lexer
aelse = parseBlock(pLastDecl);
checkDanglingElse(elseloc);
}
s = new AST.StaticIfDeclaration(condition, athen, aelse);
s = new AST.StaticIfDeclaration(loc, condition, athen, aelse);
}
else if (next == TOK.import_)
{
Expand Down Expand Up @@ -1134,6 +1137,7 @@ final class Parser(AST) : Lexer
break;
}
case TOK.debug_:
startloc = token.loc;
nextToken();
if (token.value == TOK.assign)
{
Expand All @@ -1158,6 +1162,7 @@ final class Parser(AST) : Lexer
goto Lcondition;

case TOK.version_:
startloc = token.loc;
nextToken();
if (token.value == TOK.assign)
{
Expand Down Expand Up @@ -1200,7 +1205,7 @@ final class Parser(AST) : Lexer
aelse = parseBlock(pLastDecl);
checkDanglingElse(elseloc);
}
s = new AST.ConditionalDeclaration(condition, athen, aelse);
s = new AST.ConditionalDeclaration(startloc, condition, athen, aelse);
break;
}
case TOK.semicolon:
Expand Down
95 changes: 95 additions & 0 deletions test/unit/parser/conditionalcompilation_location.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
module parser.conditionalcompilation_location;

import dmd.frontend : parseModule;
import support : afterEach, beforeEach;
import dmd.attrib : ConditionalDeclaration, StaticIfDeclaration;
import dmd.globals : Loc;
import dmd.visitor : SemanticTimeTransitiveVisitor;

@beforeEach
void initializeFrontend()
{
import dmd.frontend : initDMD;

initDMD();
}

@afterEach
void deinitializeFrontend()
{
import dmd.frontend : deinitializeDMD;
deinitializeDMD();
}

extern (C++) class Visitor : SemanticTimeTransitiveVisitor
{
alias visit = typeof(super).visit;
Loc l;

override void visit(ConditionalDeclaration cd)
{
l = cd.loc;
}

override void visit(StaticIfDeclaration sif)
{
l = sif.loc;
}
}

immutable struct Test
{
/*
* The description of the unit test.
*
* This will go into the UDA attached to the `unittest` block.
*/
string description_;

/*
* The code to parse.
*
*/
string code_;

string code()
{
return code_;
}

string description()
{
return description_;
}
}

enum tests = [
Test("`version` symbol and condition on the same line", "version(a)"),
Test("`version` symbol and condition different lines", "version\n(a)"),
Test("`version` symbol, condition and parantheses on different lines", "version\n(\na\n)"),

Test("`debug` symbol and condition on the same line", "debug(a)"),
Test("`debug` symbol and condition different lines", "debug\n(a)"),
Test("`debug` symbol, condition and parantheses on different lines", "debug\n(\na\n)"),

Test("`static if` and condition on the same line", "static if(a)"),
Test("`static if` and condition different lines", "static if\n(a)"),
Test("`static if`, condition and parantheses on different lines", "static if\n(\na\n)"),
Test("`static` and `if` on different lines", "static\nif\n(a)"),
];

static foreach (test; tests)
{
@(test.description)
unittest
{
auto t = parseModule("test.d", "first_token " ~ test.code);

scope visitor = new Visitor;
t.module_.accept(visitor);

assert(visitor.l.linnum == 1);
assert(visitor.l.charnum == 13);
assert(visitor.l.fileOffset == 12);
}
}