@@ -768,11 +768,12 @@ static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) {
768
768
769
769
// / Parse and populate a #if ... #endif directive.
770
770
// / Delegate callback function to parse elements in the blocks.
771
- template <typename Result>
771
+ template <typename Result>
772
772
Result Parser::parseIfConfigRaw (
773
- llvm::function_ref<void (SourceLoc clauseLoc, Expr *condition,
774
- bool isActive, IfConfigElementsRole role)>
775
- parseElements,
773
+ IfConfigContext ifConfigContext,
774
+ llvm::function_ref<void (SourceLoc clauseLoc, Expr *condition, bool isActive,
775
+ IfConfigElementsRole role)>
776
+ parseElements,
776
777
llvm::function_ref<Result(SourceLoc endLoc, bool hadMissingEnd)> finish) {
777
778
assert (Tok.is (tok::pound_if));
778
779
@@ -896,6 +897,24 @@ Result Parser::parseIfConfigRaw(
896
897
ClauseLoc, Condition, isActive, IfConfigElementsRole::Skipped);
897
898
}
898
899
900
+ // We ought to be at the end of the clause, diagnose if not and skip to
901
+ // the closing token. `#if` + `#endif` are considered stronger delimiters
902
+ // than `{` + `}`, so we can skip over those too.
903
+ if (Tok.isNot (tok::pound_elseif, tok::pound_else, tok::pound_endif,
904
+ tok::eof)) {
905
+ if (Tok.is (tok::r_brace)) {
906
+ diagnose (Tok, diag::unexpected_rbrace_in_conditional_compilation_block);
907
+ } else if (ifConfigContext == IfConfigContext::PostfixExpr) {
908
+ diagnose (Tok, diag::expr_postfix_ifconfig_unexpectedtoken);
909
+ } else {
910
+ // We ought to never hit this case in practice, but fall back to a
911
+ // generic 'unexpected tokens' diagnostic if we weren't able to produce
912
+ // a better diagnostic during the parsing of the clause.
913
+ diagnose (Tok, diag::ifconfig_unexpectedtoken);
914
+ }
915
+ skipUntilConditionalBlockClose ();
916
+ }
917
+
899
918
// Record the clause range info in SourceFile.
900
919
if (shouldEvaluate) {
901
920
auto kind = isActive ? IfConfigClauseRangeInfo::ActiveClause
@@ -926,9 +945,11 @@ Result Parser::parseIfConfigRaw(
926
945
// / Parse and populate a #if ... #endif directive.
927
946
// / Delegate callback function to parse elements in the blocks.
928
947
ParserResult<IfConfigDecl> Parser::parseIfConfig (
948
+ IfConfigContext ifConfigContext,
929
949
llvm::function_ref<void (SmallVectorImpl<ASTNode> &, bool )> parseElements) {
930
950
SmallVector<IfConfigClause, 4 > clauses;
931
951
return parseIfConfigRaw<ParserResult<IfConfigDecl>>(
952
+ ifConfigContext,
932
953
[&](SourceLoc clauseLoc, Expr *condition, bool isActive,
933
954
IfConfigElementsRole role) {
934
955
SmallVector<ASTNode, 16 > elements;
@@ -939,7 +960,8 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
939
960
940
961
clauses.emplace_back (
941
962
clauseLoc, condition, Context.AllocateCopy (elements), isActive);
942
- }, [&](SourceLoc endLoc, bool hadMissingEnd) {
963
+ },
964
+ [&](SourceLoc endLoc, bool hadMissingEnd) {
943
965
auto *ICD = new (Context) IfConfigDecl (CurDeclContext,
944
966
Context.AllocateCopy (clauses),
945
967
endLoc, hadMissingEnd);
@@ -952,6 +974,7 @@ ParserStatus Parser::parseIfConfigDeclAttributes(
952
974
PatternBindingInitializer *initContext) {
953
975
ParserStatus status = makeParserSuccess ();
954
976
return parseIfConfigRaw<ParserStatus>(
977
+ IfConfigContext::DeclAttrs,
955
978
[&](SourceLoc clauseLoc, Expr *condition, bool isActive,
956
979
IfConfigElementsRole role) {
957
980
if (isActive) {
0 commit comments