Skip to content

[Parser][SE-0034] Replace line directive #line with #setline #1501

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Mar 2, 2016
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
3 changes: 3 additions & 0 deletions include/swift/AST/DiagnosticsParse.def
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,9 @@ NOTE(note_in_decl_extension,none,
WARNING(inout_as_attr_deprecated,none,
"'inout' before a parameter name is deprecated, place it before the parameter type instead",
())
WARNING(line_directive_style_deprecated,none,
"#line directive is deprecated, please use #setline instead",
())

ERROR(declaration_same_line_without_semi,none,
"consecutive declarations on a line must be separated by ';'", ())
Expand Down
5 changes: 3 additions & 2 deletions include/swift/Parse/Parser.h
Original file line number Diff line number Diff line change
Expand Up @@ -695,8 +695,9 @@ class Parser {
DeclAttributes &Attributes);

ParserResult<IfConfigDecl> parseDeclIfConfig(ParseDeclOptions Flags);
/// Parse a #line directive.
ParserStatus parseLineDirective();
/// Parse a #line/#setline directive.
/// 'isLine = true' indicates parsing #line instead of #setline
ParserStatus parseLineDirective(bool isLine = false);

void setLocalDiscriminator(ValueDecl *D);

Expand Down
1 change: 1 addition & 0 deletions include/swift/Parse/Tokens.def
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ POUND_KEYWORD(else)
POUND_KEYWORD(elseif)
POUND_KEYWORD(endif)
POUND_KEYWORD(line)
POUND_KEYWORD(setline)
POUND_KEYWORD(available)
POUND_KEYWORD(selector)

Expand Down
27 changes: 19 additions & 8 deletions lib/Parse/ParseDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1706,10 +1706,11 @@ static bool isKeywordPossibleDeclStart(const Token &Tok) {
case tok::kw_var:
case tok::pound_if:
case tok::identifier:
case tok::pound_setline:
return true;
case tok::pound_line:
// #line at the start of the line is a directive, #line within a line is
// an expression.
// #line at the start of the line is a directive, but it's deprecated.
// #line within a line is an expression.
return Tok.isAtStartOfLine();

case tok::kw_try:
Expand Down Expand Up @@ -2093,8 +2094,11 @@ ParserStatus Parser::parseDecl(SmallVectorImpl<Decl*> &Entries,
}
break;
}
case tok::pound_setline:
Status = parseLineDirective(false);
break;
case tok::pound_line:
Status = parseLineDirective();
Status = parseLineDirective(true);
break;

case tok::kw_func:
Expand Down Expand Up @@ -2556,15 +2560,20 @@ Parser::parseDeclExtension(ParseDeclOptions Flags, DeclAttributes &Attributes) {
return DCC.fixupParserResult(status, ext);
}

ParserStatus Parser::parseLineDirective() {
SourceLoc Loc = consumeToken(tok::pound_line);
ParserStatus Parser::parseLineDirective(bool isLine) {
SourceLoc Loc = consumeToken(isLine ? tok::pound_line
: tok::pound_setline);
if (isLine) {
diagnose(Loc, diag::line_directive_style_deprecated)
.fixItReplace(Loc, "#setline");
}
bool WasInPoundLineEnvironment = InPoundLineEnvironment;
if (WasInPoundLineEnvironment) {
SourceMgr.closeVirtualFile(Loc);
InPoundLineEnvironment = false;
}

// #line\n returns to the main buffer.
// #setline\n returns to the main buffer.
if (Tok.isAtStartOfLine()) {
if (!WasInPoundLineEnvironment) {
diagnose(Tok, diag::unexpected_line_directive);
Expand All @@ -2573,7 +2582,7 @@ ParserStatus Parser::parseLineDirective() {
return makeParserSuccess();
}

// #line 42 "file.swift"\n
// #setline 42 "file.swift"\n
if (Tok.isNot(tok::integer_literal)) {
diagnose(Tok, diag::expected_line_directive_number);
return makeParserError();
Expand All @@ -2594,7 +2603,9 @@ ParserStatus Parser::parseLineDirective() {
return makeParserError();
}

auto Filename = getStringLiteralIfNotInterpolated(*this, Loc, Tok, "#line");
auto Filename = getStringLiteralIfNotInterpolated(*this, Loc, Tok,
isLine ? "#line"
: "#setline");
if (!Filename.hasValue())
return makeParserError();

Expand Down
15 changes: 12 additions & 3 deletions lib/Parse/ParseStmt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ bool Parser::isStartOfStmt() {
case tok::kw_case:
case tok::kw_default:
case tok::pound_if:
case tok::pound_setline:
return true;

case tok::pound_line:
Expand Down Expand Up @@ -291,7 +292,7 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
PreviousHadSemi = false;
if (isStartOfDecl()
&& Tok.isNot(tok::pound_if)
&& Tok.isNot(tok::pound_line)) {
&& Tok.isNot(tok::pound_setline)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor nitpick, you can use Tok.isNot(x, y) here, though it looks like a preexisting issue.

ParserStatus Status =
parseDecl(TmpDecls, IsTopLevel ? PD_AllowTopLevel : PD_Default);
if (Status.isError()) {
Expand Down Expand Up @@ -345,7 +346,11 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
}

} else if (Tok.is(tok::pound_line)) {
ParserStatus Status = parseLineDirective();
ParserStatus Status = parseLineDirective(true);
BraceItemsStatus |= Status;
NeedParseErrorRecovery = Status.isError();
} else if (Tok.is(tok::pound_setline)) {
ParserStatus Status = parseLineDirective(false);
BraceItemsStatus |= Status;
NeedParseErrorRecovery = Status.isError();
} else if (IsTopLevel) {
Expand Down Expand Up @@ -558,7 +563,11 @@ ParserResult<Stmt> Parser::parseStmt() {
case tok::pound_line:
if (LabelInfo) diagnose(LabelInfo.Loc, diag::invalid_label_on_stmt);
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
return parseLineDirective();
return parseLineDirective(true);
case tok::pound_setline:
if (LabelInfo) diagnose(LabelInfo.Loc, diag::invalid_label_on_stmt);
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
return parseLineDirective(false);
case tok::kw_while:
if (tryLoc.isValid()) diagnose(tryLoc, diag::try_on_stmt, Tok.getText());
return parseStmtWhile(LabelInfo);
Expand Down
6 changes: 3 additions & 3 deletions test/DebugInfo/inlinedAt.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,19 @@
// RUN: | FileCheck %s --check-prefix=CHECK-SIL
// RUN: %target-swift-frontend %s -O -I %t -emit-ir -g -o - | FileCheck %s

#line 100 "abc.swift"
#setline 100 "abc.swift"
@inline(__always)
func h(k : Int) -> Int { // 101
return k // 102
}

#line 200 "abc.swift"
#setline 200 "abc.swift"
@inline(__always)
func g(j : Int) -> Int { // 201
return h(j) // 202
}

#line 301 "abc.swift"
#setline 301 "abc.swift"
public func f(i : Int) -> Int { // 301
return g(i) // 302
}
Expand Down
8 changes: 4 additions & 4 deletions test/DebugInfo/line-directive.swift
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
func markUsed<T>(t: T) {}
func f() {
if 1==1 {
#line 42 "abc.swift"
#setline 42 "abc.swift"
markUsed("Hello World")
#line
#setline
}
markUsed("Test")
#line 142 "abc.swift"
#setline 142 "abc.swift"
markUsed("abc again")
#line 142 "def.swift"
#setline 142 "def.swift"
markUsed("jump directly to def")
}

Expand Down
16 changes: 9 additions & 7 deletions test/Parse/line-directive.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,21 @@

let x = 0 // We need this because of the #line-ends-with-a-newline requirement.

#line
#setline
x // expected-error {{parameterless closing #line directive}}

#line 0 "x" // expected-error{{the line number needs to be greater}}
#setline 0 "x" // expected-error{{the line number needs to be greater}}

#line -1 "x" // expected-error{{expected starting line number}}
#setline -1 "x" // expected-error{{expected starting line number}}

#line 1.5 "x" // expected-error{{expected starting line number}}
#setline 1.5 "x" // expected-error{{expected starting line number}}

#line 1 x.swift // expected-error{{expected filename string literal}}
#setline 1 x.swift // expected-error{{expected filename string literal}}

#line 42 "x.swift"
#setline 42 "x.swift"
x x ; // should be ignored by expected_error because it is in a different file
x
#line
#setline
x
x x // expected-error{{consecutive statements}} {{2-2=;}}

Expand All @@ -25,3 +25,5 @@ public struct S { // expected-note{{in declaration of 'S'}}
// expected-error@+1{{expected declaration}}
/ ###line 25 "line-directive.swift"
}
// expected-warning@+1{{#line directive is deprecated, please use #setline instead}}
#line 32000 "troops_on_the_water"
20 changes: 10 additions & 10 deletions utils/gyb.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,7 +529,7 @@ def next_token(self):
class ExecutionContext:
"""State we pass around during execution of a template"""

def __init__(self, line_directive='// ###line', **local_bindings):
def __init__(self, line_directive='// ###setline', **local_bindings):
self.local_bindings = local_bindings
self.line_directive = line_directive
self.local_bindings['__context__'] = self
Expand Down Expand Up @@ -955,14 +955,14 @@ def execute_template(ast, line_directive='', **local_bindings):
... % else:
... THIS SHOULD NOT APPEAR IN THE OUTPUT
... ''')
>>> print execute_template(ast, line_directive='//#line', x=1),
//#line 1 "/dummy.file"
>>> print execute_template(ast, line_directive='//#setline', x=1),
//#setline 1 "/dummy.file"
Nothing
//#line 4 "/dummy.file"
//#setline 4 "/dummy.file"
0
//#line 4 "/dummy.file"
//#setline 4 "/dummy.file"
1
//#line 4 "/dummy.file"
//#setline 4 "/dummy.file"
2

>>> ast = parse_template('/dummy.file', text=
Expand All @@ -973,10 +973,10 @@ def execute_template(ast, line_directive='', **local_bindings):
... % end
... ${a}
... ''')
>>> print execute_template(ast, line_directive='//#line', x=1),
//#line 1 "/dummy.file"
>>> print execute_template(ast, line_directive='//#setline', x=1),
//#setline 1 "/dummy.file"
Nothing
//#line 6 "/dummy.file"
//#setline 6 "/dummy.file"
[0, 1, 2]
"""
executionContext = ExecutionContext(line_directive=line_directive, **local_bindings)
Expand Down Expand Up @@ -1059,7 +1059,7 @@ def succ(a):
parser.add_argument('--test', action='store_true', default=False, help='Run a self-test')
parser.add_argument('--verbose-test', action='store_true', default=False, help='Run a verbose self-test')
parser.add_argument('--dump', action='store_true', default=False, help='Dump the parsed template to stdout')
parser.add_argument('--line-directive', default='// ###line', help='Line directive prefix; empty => no line markers')
parser.add_argument('--line-directive', default='// ###setline', help='Line directive prefix; empty => no line markers')

args = parser.parse_args(sys.argv[1:])

Expand Down