Skip to content

Commit cb8bbf0

Browse files
authored
Merge pull request #7382 from rintaro/parse-ifconfig-fix1
[Parse] Improve '#if' block parsing
2 parents 010d2e8 + 3b42894 commit cb8bbf0

File tree

6 files changed

+30
-14
lines changed

6 files changed

+30
-14
lines changed

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ ERROR(incomplete_conditional_compilation_directive,none,
6565
"incomplete condition in conditional compilation directive", ())
6666
ERROR(extra_tokens_conditional_compilation_directive,none,
6767
"extra tokens following conditional compilation directive", ())
68+
ERROR(unexpected_rbrace_in_conditional_compilation_block,none,
69+
"unexpected '}' in conditional compilation block", ())
6870

6971
ERROR(sourceLocation_expected,none,
7072
"expected '%0' in #sourceLocation directive", (StringRef))

lib/Parse/ParseDecl.cpp

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,6 +3016,7 @@ ParserResult<IfConfigDecl> Parser::parseDeclIfConfig(ParseDeclOptions Flags) {
30163016
ConfigState.setConditionActive(!foundActive);
30173017
} else {
30183018
// Evaluate the condition.
3019+
llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
30193020
ParserResult<Expr> Result = parseExprSequence(diag::expected_expr,
30203021
/*isBasic*/true,
30213022
/*isForDirective*/true);
@@ -3045,19 +3046,18 @@ ParserResult<IfConfigDecl> Parser::parseDeclIfConfig(ParseDeclOptions Flags) {
30453046
if (ConfigState.shouldParse()) {
30463047
ParserStatus Status;
30473048
bool PreviousHadSemi = true;
3048-
while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif)) {
3049-
SourceLoc StartLoc = Tok.getLoc();
3050-
Status |= parseDeclItem(*this, PreviousHadSemi, Flags,
3051-
[&](Decl *D) {Decls.push_back(D);});
3052-
if (StartLoc == Tok.getLoc()) {
3053-
assert(Status.isError() && "no progress without error?");
3049+
while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif,
3050+
tok::eof)) {
3051+
if (Tok.is(tok::r_brace)) {
3052+
diagnose(Tok.getLoc(),
3053+
diag::unexpected_rbrace_in_conditional_compilation_block);
3054+
// If we see '}', following declarations don't look like belong to
3055+
// the current decl context; skip them.
30543056
skipUntilConditionalBlockClose();
30553057
break;
30563058
}
3057-
if (Tok.isAny(tok::eof)) {
3058-
diagnose(Tok, diag::expected_close_to_if_directive);
3059-
break;
3060-
}
3059+
Status |= parseDeclItem(*this, PreviousHadSemi, Flags,
3060+
[&](Decl *D) {Decls.push_back(D);});
30613061
}
30623062
} else {
30633063
DiagnosticTransaction DT(Diags);

lib/Parse/ParseStmt.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,6 @@ Parser::classifyConditionalCompilationExpr(Expr *condition,
17711771
ParserResult<Stmt> Parser::parseStmtIfConfig(BraceItemListKind Kind) {
17721772
StructureMarkerRAII ParsingDecl(*this, Tok.getLoc(),
17731773
StructureMarkerKind::IfConfig);
1774-
llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
17751774
SmallVector<IfConfigStmtClause, 4> Clauses;
17761775

17771776
bool foundActive = false;
@@ -1785,6 +1784,7 @@ ParserResult<Stmt> Parser::parseStmtIfConfig(BraceItemListKind Kind) {
17851784
ConfigState.setConditionActive(!foundActive);
17861785
} else {
17871786
// Evaluate the condition.
1787+
llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
17881788
ParserResult<Expr> Result = parseExprSequence(diag::expected_expr,
17891789
/*basic*/true,
17901790
/*isForDirective*/true);
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
class C2 { // expected-note {{to match this opening '{'}}
4+
#if FOO
5+
func foo() {}
6+
// expected-error @+2 {{expected '}' in class}}
7+
// expected-error @+1 {{expected #else or #endif at end of conditional compilation block}}

test/Parse/ConditionalCompilation/decl_parse_errors.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,14 @@ lazy
2727
var val3: Int = 0;
2828
#line
2929

30-
class C { // expected-note 2 {{in declaration of 'C'}} expected-note {{to match this opening '{'}}
30+
class C { // expected-note {{to match this opening '{'}}
3131

3232
#if os(iOS)
3333
func foo() {}
34-
} // expected-error{{expected declaration}}
34+
} // expected-error{{unexpected '}' in conditional compilation block}}
3535
#else
3636
func bar() {}
3737
func baz() {}
38-
} // expected-error{{expected declaration}}
38+
} // expected-error{{unexpected '}' in conditional compilation block}}
3939
#endif
4040
// expected-error@+1{{expected '}' in class}}

test/Parse/ConditionalCompilation/language_version.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,15 @@
4444
#endif
4545

4646
#if swift(>=2.2.1)
47+
_ = 2.2.1 // expected-error {{expected named member of numeric literal}}
4748
#endif
4849

50+
class C {
51+
#if swift(>=2.2.1)
52+
let val = 2.2.1 // expected-error {{expected named member of numeric literal}}
53+
#endif
54+
}
55+
4956
#if swift(>=2.0, *) // expected-error {{expected only one argument to platform condition}}
5057
#endif
5158

0 commit comments

Comments
 (0)