Skip to content

Commit c8d717e

Browse files
committed
[Parse] Cleanup #if directive parsing
Now that, IfConfigDecl holds ASTNode regardless statements position or declarations postion. We can construct it in single method.
1 parent 2ad22a8 commit c8d717e

File tree

4 files changed

+55
-81
lines changed

4 files changed

+55
-81
lines changed

include/swift/Parse/Parser.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -716,9 +716,10 @@ class Parser {
716716
ParserResult<TypeDecl> parseDeclAssociatedType(ParseDeclOptions Flags,
717717
DeclAttributes &Attributes);
718718

719-
ParserResult<IfConfigDecl> parseDeclIfConfig(ParseDeclOptions Flags);
720-
ParserResult<IfConfigDecl> parseStmtIfConfig(BraceItemListKind Kind
721-
= BraceItemListKind::Brace);
719+
/// Parse a #if ... #endif directive.
720+
/// Delegate callback function to parse elements in the blocks.
721+
ParserResult<IfConfigDecl> parseIfConfig(
722+
llvm::function_ref<void(SmallVectorImpl<ASTNode> &, bool)> parseElements);
722723

723724
/// Parse a #line/#sourceLocation directive.
724725
/// 'isLine = true' indicates parsing #line instead of #sourcelocation

lib/Parse/ParseDecl.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2100,7 +2100,30 @@ Parser::parseDecl(ParseDeclOptions Flags,
21002100
}
21012101

21022102
if (Tok.is(tok::pound_if)) {
2103-
auto IfConfigResult = parseDeclIfConfig(Flags);
2103+
auto IfConfigResult = parseIfConfig(
2104+
[&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
2105+
Optional<Scope> scope;
2106+
if (!IsActive)
2107+
scope.emplace(this, getScopeInfo().getCurrentScope()->getKind(),
2108+
/*inactiveConfigBlock=*/true);
2109+
2110+
ParserStatus Status;
2111+
bool PreviousHadSemi = true;
2112+
while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif,
2113+
tok::eof)) {
2114+
if (Tok.is(tok::r_brace)) {
2115+
diagnose(Tok.getLoc(),
2116+
diag::unexpected_rbrace_in_conditional_compilation_block);
2117+
// If we see '}', following declarations don't look like belong to
2118+
// the current decl context; skip them.
2119+
skipUntilConditionalBlockClose();
2120+
break;
2121+
}
2122+
Status |= parseDeclItem(PreviousHadSemi, Flags,
2123+
[&](Decl *D) {Decls.emplace_back(D);});
2124+
}
2125+
});
2126+
21042127
if (auto ICD = IfConfigResult.getPtrOrNull()) {
21052128
// The IfConfigDecl is ahead of its members in source order.
21062129
Handler(ICD);

lib/Parse/ParseIfConfig.cpp

Lines changed: 21 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -549,129 +549,74 @@ static bool isVersionIfConfigCondition(Expr *Condition) {
549549

550550
} // end anonymous namespace
551551

552-
/// Parse and populate a list of #if/#elseif/#else/#endif clauses.
552+
/// Parse and populate a #if ... #endif directive.
553553
/// Delegate callback function to parse elements in the blocks.
554-
template <unsigned N>
555-
static ParserStatus parseIfConfig(
556-
Parser &P, SmallVectorImpl<IfConfigClause> &Clauses,
557-
SourceLoc &EndLoc, bool HadMissingEnd,
554+
ParserResult<IfConfigDecl> Parser::parseIfConfig(
558555
llvm::function_ref<void(SmallVectorImpl<ASTNode> &, bool)> parseElements) {
556+
557+
SmallVector<IfConfigClause, 4> Clauses;
559558
Parser::StructureMarkerRAII ParsingDecl(
560-
P, P.Tok.getLoc(), Parser::StructureMarkerKind::IfConfig);
559+
*this, Tok.getLoc(), Parser::StructureMarkerKind::IfConfig);
561560

562561
bool foundActive = false;
563562
bool isVersionCondition = false;
564563
while (1) {
565-
bool isElse = P.Tok.is(tok::pound_else);
566-
SourceLoc ClauseLoc = P.consumeToken();
564+
bool isElse = Tok.is(tok::pound_else);
565+
SourceLoc ClauseLoc = consumeToken();
567566
Expr *Condition = nullptr;
568567
bool isActive = false;
569568

570569
// Parse and evaluate the directive.
571570
if (isElse) {
572571
isActive = !foundActive;
573572
} else {
574-
llvm::SaveAndRestore<bool> S(P.InPoundIfEnvironment, true);
575-
ParserResult<Expr> Result = P.parseExprSequence(diag::expected_expr,
573+
llvm::SaveAndRestore<bool> S(InPoundIfEnvironment, true);
574+
ParserResult<Expr> Result = parseExprSequence(diag::expected_expr,
576575
/*isBasic*/true,
577576
/*isForDirective*/true);
578577
if (Result.isNull())
579578
return makeParserError();
580579
Condition = Result.get();
581-
if (validateIfConfigCondition(Condition, P.Context, P.Diags)) {
580+
if (validateIfConfigCondition(Condition, Context, Diags)) {
582581
// Error in the condition;
583582
isActive = false;
584583
isVersionCondition = false;
585584
} else if (!foundActive) {
586585
// Evaludate the condition only if we haven't found any active one.
587-
isActive = evaluateIfConfigCondition(Condition, P.Context);
586+
isActive = evaluateIfConfigCondition(Condition, Context);
588587
isVersionCondition = isVersionIfConfigCondition(Condition);
589588
}
590589
}
591590

592591
foundActive |= isActive;
593592

594-
if (!P.Tok.isAtStartOfLine() && P.Tok.isNot(tok::eof)) {
595-
P.diagnose(P.Tok.getLoc(),
596-
diag::extra_tokens_conditional_compilation_directive);
593+
if (!Tok.isAtStartOfLine() && Tok.isNot(tok::eof)) {
594+
diagnose(Tok.getLoc(),
595+
diag::extra_tokens_conditional_compilation_directive);
597596
}
598597

599598
// Parse elements
600-
SmallVector<ASTNode, N> Elements;
599+
SmallVector<ASTNode, 16> Elements;
601600
if (isActive || !isVersionCondition) {
602601
parseElements(Elements, isActive);
603602
} else {
604-
DiagnosticTransaction DT(P.Diags);
605-
P.skipUntilConditionalBlockClose();
603+
DiagnosticTransaction DT(Diags);
604+
skipUntilConditionalBlockClose();
606605
DT.abort();
607606
}
608607

609608
Clauses.emplace_back(ClauseLoc, Condition,
610-
P.Context.AllocateCopy(Elements), isActive);
609+
Context.AllocateCopy(Elements), isActive);
611610

612-
if (P.Tok.isNot(tok::pound_elseif, tok::pound_else))
611+
if (Tok.isNot(tok::pound_elseif, tok::pound_else))
613612
break;
614613

615614
if (isElse)
616-
P.diagnose(P.Tok, diag::expected_close_after_else_directive);
615+
diagnose(Tok, diag::expected_close_after_else_directive);
617616
}
618617

619-
HadMissingEnd = P.parseEndIfDirective(EndLoc);
620-
return makeParserSuccess();
621-
}
622-
623-
/// Parse #if ... #endif in declarations position.
624-
ParserResult<IfConfigDecl> Parser::parseDeclIfConfig(ParseDeclOptions Flags) {
625-
SmallVector<IfConfigClause, 4> Clauses;
626-
SourceLoc EndLoc;
627-
bool HadMissingEnd = false;
628-
auto Status = parseIfConfig<8>(
629-
*this, Clauses, EndLoc, HadMissingEnd,
630-
[&](SmallVectorImpl<ASTNode> &Decls, bool IsActive) {
631-
Optional<Scope> scope;
632-
if (!IsActive)
633-
scope.emplace(this, getScopeInfo().getCurrentScope()->getKind(),
634-
/*inactiveConfigBlock=*/true);
635-
636-
ParserStatus Status;
637-
bool PreviousHadSemi = true;
638-
while (Tok.isNot(tok::pound_else, tok::pound_endif, tok::pound_elseif,
639-
tok::eof)) {
640-
if (Tok.is(tok::r_brace)) {
641-
diagnose(Tok.getLoc(),
642-
diag::unexpected_rbrace_in_conditional_compilation_block);
643-
// If we see '}', following declarations don't look like belong to
644-
// the current decl context; skip them.
645-
skipUntilConditionalBlockClose();
646-
break;
647-
}
648-
Status |= parseDeclItem(PreviousHadSemi, Flags,
649-
[&](Decl *D) {Decls.emplace_back(D);});
650-
}
651-
});
652-
if (Status.isError())
653-
return makeParserErrorResult<IfConfigDecl>();
654-
655-
IfConfigDecl *ICD = new (Context) IfConfigDecl(CurDeclContext,
656-
Context.AllocateCopy(Clauses),
657-
EndLoc, HadMissingEnd);
658-
return makeParserResult(ICD);
659-
}
660-
661-
/// Parse #if ... #endif in statements position.
662-
ParserResult<IfConfigDecl> Parser::parseStmtIfConfig(BraceItemListKind Kind) {
663-
SmallVector<IfConfigClause, 4> Clauses;
664618
SourceLoc EndLoc;
665-
bool HadMissingEnd = false;
666-
auto Status = parseIfConfig<16>(
667-
*this, Clauses, EndLoc, HadMissingEnd,
668-
[&](SmallVectorImpl<ASTNode> &Elements, bool IsActive) {
669-
parseBraceItems(Elements, Kind, IsActive
670-
? BraceItemListKind::ActiveConditionalBlock
671-
: BraceItemListKind::InactiveConditionalBlock);
672-
});
673-
if (Status.isError())
674-
return makeParserErrorResult<IfConfigDecl>();
619+
bool HadMissingEnd = parseEndIfDirective(EndLoc);
675620

676621
auto *ICD = new (Context) IfConfigDecl(CurDeclContext,
677622
Context.AllocateCopy(Clauses),

lib/Parse/ParseStmt.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,12 @@ ParserStatus Parser::parseBraceItems(SmallVectorImpl<ASTNode> &Entries,
293293
Entries.push_back(D);
294294
TmpDecls.clear();
295295
} else if (Tok.is(tok::pound_if)) {
296-
auto IfConfigResult = parseStmtIfConfig(Kind);
296+
auto IfConfigResult = parseIfConfig(
297+
[&](SmallVectorImpl<ASTNode> &Elements, bool IsActive) {
298+
parseBraceItems(Elements, Kind, IsActive
299+
? BraceItemListKind::ActiveConditionalBlock
300+
: BraceItemListKind::InactiveConditionalBlock);
301+
});
297302

298303
if (IfConfigResult.isParseError()) {
299304
NeedParseErrorRecovery = true;

0 commit comments

Comments
 (0)