@@ -769,11 +769,12 @@ static Expr *findAnyLikelySimulatorEnvironmentTest(Expr *Condition) {
769769
770770// / Parse and populate a #if ... #endif directive.
771771// / Delegate callback function to parse elements in the blocks.
772- template <typename Result>
772+ template <typename Result>
773773Result Parser::parseIfConfigRaw (
774- llvm::function_ref<void (SourceLoc clauseLoc, Expr *condition,
775- bool isActive, IfConfigElementsRole role)>
776- parseElements,
774+ IfConfigContext ifConfigContext,
775+ llvm::function_ref<void (SourceLoc clauseLoc, Expr *condition, bool isActive,
776+ IfConfigElementsRole role)>
777+ parseElements,
777778 llvm::function_ref<Result(SourceLoc endLoc, bool hadMissingEnd)> finish) {
778779 assert (Tok.is (tok::pound_if));
779780
@@ -897,6 +898,24 @@ Result Parser::parseIfConfigRaw(
897898 ClauseLoc, Condition, isActive, IfConfigElementsRole::Skipped);
898899 }
899900
901+ // We ought to be at the end of the clause, diagnose if not and skip to
902+ // the closing token. `#if` + `#endif` are considered stronger delimiters
903+ // than `{` + `}`, so we can skip over those too.
904+ if (Tok.isNot (tok::pound_elseif, tok::pound_else, tok::pound_endif,
905+ tok::eof)) {
906+ if (Tok.is (tok::r_brace)) {
907+ diagnose (Tok, diag::unexpected_rbrace_in_conditional_compilation_block);
908+ } else if (ifConfigContext == IfConfigContext::PostfixExpr) {
909+ diagnose (Tok, diag::expr_postfix_ifconfig_unexpectedtoken);
910+ } else {
911+ // We ought to never hit this case in practice, but fall back to a
912+ // generic 'unexpected tokens' diagnostic if we weren't able to produce
913+ // a better diagnostic during the parsing of the clause.
914+ diagnose (Tok, diag::ifconfig_unexpectedtoken);
915+ }
916+ skipUntilConditionalBlockClose ();
917+ }
918+
900919 // Record the clause range info in SourceFile.
901920 if (shouldEvaluate) {
902921 auto kind = isActive ? IfConfigClauseRangeInfo::ActiveClause
@@ -927,9 +946,11 @@ Result Parser::parseIfConfigRaw(
927946// / Parse and populate a #if ... #endif directive.
928947// / Delegate callback function to parse elements in the blocks.
929948ParserResult<IfConfigDecl> Parser::parseIfConfig (
949+ IfConfigContext ifConfigContext,
930950 llvm::function_ref<void (SmallVectorImpl<ASTNode> &, bool )> parseElements) {
931951 SmallVector<IfConfigClause, 4 > clauses;
932952 return parseIfConfigRaw<ParserResult<IfConfigDecl>>(
953+ ifConfigContext,
933954 [&](SourceLoc clauseLoc, Expr *condition, bool isActive,
934955 IfConfigElementsRole role) {
935956 SmallVector<ASTNode, 16 > elements;
@@ -940,7 +961,8 @@ ParserResult<IfConfigDecl> Parser::parseIfConfig(
940961
941962 clauses.emplace_back (
942963 clauseLoc, condition, Context.AllocateCopy (elements), isActive);
943- }, [&](SourceLoc endLoc, bool hadMissingEnd) {
964+ },
965+ [&](SourceLoc endLoc, bool hadMissingEnd) {
944966 auto *ICD = new (Context) IfConfigDecl (CurDeclContext,
945967 Context.AllocateCopy (clauses),
946968 endLoc, hadMissingEnd);
@@ -953,6 +975,7 @@ ParserStatus Parser::parseIfConfigDeclAttributes(
953975 PatternBindingInitializer *initContext) {
954976 ParserStatus status = makeParserSuccess ();
955977 return parseIfConfigRaw<ParserStatus>(
978+ IfConfigContext::DeclAttrs,
956979 [&](SourceLoc clauseLoc, Expr *condition, bool isActive,
957980 IfConfigElementsRole role) {
958981 if (isActive) {
0 commit comments