@@ -768,11 +768,12 @@ static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) {
768768
769769// / Parse and populate a #if ... #endif directive.
770770// / Delegate callback function to parse elements in the blocks.
771- template <typename Result>
771+ template <typename Result>
772772Result 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,
776777 llvm::function_ref<Result(SourceLoc endLoc, bool hadMissingEnd)> finish) {
777778 assert (Tok.is (tok::pound_if));
778779
@@ -896,6 +897,24 @@ Result Parser::parseIfConfigRaw(
896897 ClauseLoc, Condition, isActive, IfConfigElementsRole::Skipped);
897898 }
898899
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+
899918 // Record the clause range info in SourceFile.
900919 if (shouldEvaluate) {
901920 auto kind = isActive ? IfConfigClauseRangeInfo::ActiveClause
@@ -926,9 +945,11 @@ Result Parser::parseIfConfigRaw(
926945// / Parse and populate a #if ... #endif directive.
927946// / Delegate callback function to parse elements in the blocks.
928947ParserResult<IfConfigDecl> Parser::parseIfConfig (
948+ IfConfigContext ifConfigContext,
929949 llvm::function_ref<void (SmallVectorImpl<ASTNode> &, bool )> parseElements) {
930950 SmallVector<IfConfigClause, 4 > clauses;
931951 return parseIfConfigRaw<ParserResult<IfConfigDecl>>(
952+ ifConfigContext,
932953 [&](SourceLoc clauseLoc, Expr *condition, bool isActive,
933954 IfConfigElementsRole role) {
934955 SmallVector<ASTNode, 16 > elements;
@@ -939,7 +960,8 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
939960
940961 clauses.emplace_back (
941962 clauseLoc, condition, Context.AllocateCopy (elements), isActive);
942- }, [&](SourceLoc endLoc, bool hadMissingEnd) {
963+ },
964+ [&](SourceLoc endLoc, bool hadMissingEnd) {
943965 auto *ICD = new (Context) IfConfigDecl (CurDeclContext,
944966 Context.AllocateCopy (clauses),
945967 endLoc, hadMissingEnd);
@@ -952,6 +974,7 @@ ParserStatus Parser::parseIfConfigDeclAttributes(
952974 PatternBindingInitializer *initContext) {
953975 ParserStatus status = makeParserSuccess ();
954976 return parseIfConfigRaw<ParserStatus>(
977+ IfConfigContext::DeclAttrs,
955978 [&](SourceLoc clauseLoc, Expr *condition, bool isActive,
956979 IfConfigElementsRole role) {
957980 if (isActive) {
0 commit comments