diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:04 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-02-11 12:38:11 +0000 |
commit | e3b557809604d036af6e00c60f012c2025b59a5e (patch) | |
tree | 8a11ba2269a3b669601e2fd41145b174008f4da8 /clang/lib/Parse/ParseExpr.cpp | |
parent | 08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff) | |
download | src-e3b557809604d036af6e00c60f012c2025b59a5e.tar.gz src-e3b557809604d036af6e00c60f012c2025b59a5e.zip |
Diffstat (limited to 'clang/lib/Parse/ParseExpr.cpp')
-rw-r--r-- | clang/lib/Parse/ParseExpr.cpp | 166 |
1 files changed, 104 insertions, 62 deletions
diff --git a/clang/lib/Parse/ParseExpr.cpp b/clang/lib/Parse/ParseExpr.cpp index a6a946d7f31b..392ed29467a9 100644 --- a/clang/lib/Parse/ParseExpr.cpp +++ b/clang/lib/Parse/ParseExpr.cpp @@ -30,6 +30,7 @@ #include "clang/Sema/Scope.h" #include "clang/Sema/TypoCorrection.h" #include "llvm/ADT/SmallVector.h" +#include <optional> using namespace clang; /// Simple precedence-based parser for binary/ternary operators. @@ -208,14 +209,14 @@ Parser::ParseConstantExpressionInExprEvalContext(TypeCastState isTypeCast) { return Actions.ActOnConstantExpression(Res); } -ExprResult Parser::ParseConstantExpression(TypeCastState isTypeCast) { +ExprResult Parser::ParseConstantExpression() { // C++03 [basic.def.odr]p2: // An expression is potentially evaluated unless it appears where an // integral constant expression is required (see 5.19) [...]. // C++98 and C++11 have no such rule, but this is only a defect in C++98. EnterExpressionEvaluationContext ConstantEvaluated( Actions, Sema::ExpressionEvaluationContext::ConstantEvaluated); - return ParseConstantExpressionInExprEvalContext(isTypeCast); + return ParseConstantExpressionInExprEvalContext(NotTypeCast); } ExprResult Parser::ParseCaseExpression(SourceLocation CaseLoc) { @@ -943,9 +944,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, ParenParseOption ParenExprType; switch (ParseKind) { case CastParseKind::UnaryExprOnly: - if (!getLangOpts().CPlusPlus) - ParenExprType = CompoundLiteral; - LLVM_FALLTHROUGH; + assert(getLangOpts().CPlusPlus && "not possible to get here in C"); + [[fallthrough]]; case CastParseKind::AnyCastExpr: ParenExprType = ParenParseOption::CastExpr; break; @@ -1004,7 +1004,12 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, break; case tok::kw_nullptr: - Diag(Tok, diag::warn_cxx98_compat_nullptr); + if (getLangOpts().CPlusPlus) + Diag(Tok, diag::warn_cxx98_compat_nullptr); + else + Diag(Tok, getLangOpts().C2x ? diag::warn_c17_compat_nullptr + : diag::ext_c_nullptr); + Res = Actions.ActOnCXXNullPtrLiteral(ConsumeToken()); break; @@ -1038,9 +1043,10 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, return ParseCastExpression(ParseKind, isAddressOfOperand, isTypeCast, isVectorLiteral, NotPrimaryExpression); - case tok::identifier: { // primary-expression: identifier - // unqualified-id: identifier - // constant: enumeration-constant + case tok::identifier: + ParseIdentifier: { // primary-expression: identifier + // unqualified-id: identifier + // constant: enumeration-constant // Turn a potentially qualified name into a annot_typename or // annot_cxxscope if it would be valid. This handles things like x::y, etc. if (getLangOpts().CPlusPlus) { @@ -1068,6 +1074,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_array); REVERTIBLE_TYPE_TRAIT(__is_assignable); REVERTIBLE_TYPE_TRAIT(__is_base_of); + REVERTIBLE_TYPE_TRAIT(__is_bounded_array); REVERTIBLE_TYPE_TRAIT(__is_class); REVERTIBLE_TYPE_TRAIT(__is_complete_type); REVERTIBLE_TYPE_TRAIT(__is_compound); @@ -1093,15 +1100,18 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_nothrow_assignable); REVERTIBLE_TYPE_TRAIT(__is_nothrow_constructible); REVERTIBLE_TYPE_TRAIT(__is_nothrow_destructible); + REVERTIBLE_TYPE_TRAIT(__is_nullptr); REVERTIBLE_TYPE_TRAIT(__is_object); REVERTIBLE_TYPE_TRAIT(__is_pod); REVERTIBLE_TYPE_TRAIT(__is_pointer); REVERTIBLE_TYPE_TRAIT(__is_polymorphic); REVERTIBLE_TYPE_TRAIT(__is_reference); + REVERTIBLE_TYPE_TRAIT(__is_referenceable); REVERTIBLE_TYPE_TRAIT(__is_rvalue_expr); REVERTIBLE_TYPE_TRAIT(__is_rvalue_reference); REVERTIBLE_TYPE_TRAIT(__is_same); REVERTIBLE_TYPE_TRAIT(__is_scalar); + REVERTIBLE_TYPE_TRAIT(__is_scoped_enum); REVERTIBLE_TYPE_TRAIT(__is_sealed); REVERTIBLE_TYPE_TRAIT(__is_signed); REVERTIBLE_TYPE_TRAIT(__is_standard_layout); @@ -1109,10 +1119,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, REVERTIBLE_TYPE_TRAIT(__is_trivially_assignable); REVERTIBLE_TYPE_TRAIT(__is_trivially_constructible); REVERTIBLE_TYPE_TRAIT(__is_trivially_copyable); + REVERTIBLE_TYPE_TRAIT(__is_unbounded_array); REVERTIBLE_TYPE_TRAIT(__is_union); REVERTIBLE_TYPE_TRAIT(__is_unsigned); REVERTIBLE_TYPE_TRAIT(__is_void); REVERTIBLE_TYPE_TRAIT(__is_volatile); +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) \ + REVERTIBLE_TYPE_TRAIT(RTT_JOIN(__, Trait)); +#include "clang/Basic/TransformTypeTraits.def" #undef REVERTIBLE_TYPE_TRAIT #undef RTT_JOIN } @@ -1357,7 +1371,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // Special treatment because of member pointers SourceLocation SavedLoc = ConsumeToken(); PreferredType.enterUnary(Actions, Tok.getLocation(), tok::amp, SavedLoc); - Res = ParseCastExpression(AnyCastExpr, true); + + Res = ParseCastExpression(AnyCastExpr, /*isAddressOfOperand=*/true); if (!Res.isInvalid()) { Expr *Arg = Res.get(); Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg); @@ -1382,7 +1397,8 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Res = ParseCastExpression(AnyCastExpr); if (!Res.isInvalid()) { Expr *Arg = Res.get(); - Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg); + Res = Actions.ActOnUnaryOp(getCurScope(), SavedLoc, SavedKind, Arg, + isAddressOfOperand); if (Res.isInvalid()) Res = Actions.CreateRecoveryExpr(SavedLoc, Arg->getEndLoc(), Arg); } @@ -1413,7 +1429,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, case tok::kw__Alignof: // unary-expression: '_Alignof' '(' type-name ')' if (!getLangOpts().C11) Diag(Tok, diag::ext_c11_feature) << Tok.getName(); - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::kw_alignof: // unary-expression: 'alignof' '(' type-id ')' case tok::kw___alignof: // unary-expression: '__alignof' unary-expression // unary-expression: '__alignof' '(' type-name ')' @@ -1502,7 +1518,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Ty.get(), nullptr); break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::annot_decltype: case tok::kw_char: @@ -1595,7 +1611,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, ParseOptionalCXXScopeSpecifier(SS, /*ObjectType=*/nullptr, /*ObjectHasErrors=*/false, /*EnteringContext=*/false); - AnnotateTemplateIdTokenAsType(SS); + AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes); return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression); @@ -1614,14 +1630,14 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, // translate it into a type and continue parsing as a cast // expression. CXXScopeSpec SS; - AnnotateTemplateIdTokenAsType(SS); + AnnotateTemplateIdTokenAsType(SS, ImplicitTypenameContext::Yes); return ParseCastExpression(ParseKind, isAddressOfOperand, NotCastExpr, isTypeCast, isVectorLiteral, NotPrimaryExpression); } // Fall through to treat the template-id as an id-expression. - LLVM_FALLTHROUGH; + [[fallthrough]]; } case tok::kw_operator: // [C++] id-expression: operator/conversion-function-id @@ -1739,6 +1755,17 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, PreferredType.get(Tok.getLocation())); return ExprError(); } +#define TRANSFORM_TYPE_TRAIT_DEF(_, Trait) case tok::kw___##Trait: +#include "clang/Basic/TransformTypeTraits.def" + // HACK: libstdc++ uses some of the transform-type-traits as alias + // templates, so we need to work around this. + if (!NextToken().is(tok::l_paren)) { + Tok.setKind(tok::identifier); + Diag(Tok, diag::ext_keyword_as_ident) + << Tok.getIdentifierInfo()->getName() << 0; + goto ParseIdentifier; + } + goto ExpectedExpression; case tok::l_square: if (getLangOpts().CPlusPlus11) { if (getLangOpts().ObjC) { @@ -1764,8 +1791,9 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, Res = ParseObjCMessageExpression(); break; } - LLVM_FALLTHROUGH; + [[fallthrough]]; default: + ExpectedExpression: NotCastExpr = true; return ExprError(); } @@ -1795,7 +1823,7 @@ ExprResult Parser::ParseCastExpression(CastParseKind ParseKind, if (Tok.isAtStartOfLine()) return Res; - LLVM_FALLTHROUGH; + [[fallthrough]]; case tok::period: case tok::arrow: break; @@ -1883,7 +1911,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { break; } // Fall through; this isn't a message send. - LLVM_FALLTHROUGH; + [[fallthrough]]; default: // Not a postfix-expression suffix. return LHS; @@ -1934,14 +1962,10 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { ArgExprs.push_back(Idx.get()); } } else if (Tok.isNot(tok::r_square)) { - CommaLocsTy CommaLocs; - if (ParseExpressionList(ArgExprs, CommaLocs)) { + if (ParseExpressionList(ArgExprs)) { LHS = Actions.CorrectDelayedTyposInExpr(LHS); HasError = true; } - assert( - (ArgExprs.empty() || ArgExprs.size() == CommaLocs.size() + 1) && - "Unexpected number of commas!"); } } @@ -2003,10 +2027,9 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { if (OpKind == tok::lesslessless) { ExprVector ExecConfigExprs; - CommaLocsTy ExecConfigCommaLocs; SourceLocation OpenLoc = ConsumeToken(); - if (ParseSimpleExpressionList(ExecConfigExprs, ExecConfigCommaLocs)) { + if (ParseSimpleExpressionList(ExecConfigExprs)) { (void)Actions.CorrectDelayedTyposInExpr(LHS); LHS = ExprError(); } @@ -2046,7 +2069,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { } ExprVector ArgExprs; - CommaLocsTy CommaLocs; auto RunSignatureHelp = [&]() -> QualType { QualType PreferredType = Actions.ProduceCallSignatureHelp( LHS.get(), ArgExprs, PT.getOpenLocation()); @@ -2055,7 +2077,7 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { }; if (OpKind == tok::l_paren || !LHS.isInvalid()) { if (Tok.isNot(tok::r_paren)) { - if (ParseExpressionList(ArgExprs, CommaLocs, [&] { + if (ParseExpressionList(ArgExprs, [&] { PreferredType.enterFunctionArgument(Tok.getLocation(), RunSignatureHelp); })) { @@ -2093,9 +2115,6 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { PT.consumeClose(); LHS = ExprError(); } else { - assert( - (ArgExprs.size() == 0 || ArgExprs.size() - 1 == CommaLocs.size()) && - "Unexpected number of commas!"); Expr *Fn = LHS.get(); SourceLocation RParLoc = Tok.getLocation(); LHS = Actions.ActOnCallExpr(getCurScope(), Fn, Loc, ArgExprs, RParLoc, @@ -2271,6 +2290,13 @@ Parser::ParsePostfixExpressionSuffix(ExprResult LHS) { /// typeof ( expressions ) /// typeof ( type-name ) /// [GNU/C++] typeof unary-expression +/// [C2x] typeof-specifier: +/// typeof '(' typeof-specifier-argument ')' +/// typeof_unqual '(' typeof-specifier-argument ')' +/// +/// typeof-specifier-argument: +/// expression +/// type-name /// /// [OpenCL 1.1 6.11.12] vec_step built-in function: /// vec_step ( expressions ) @@ -2282,8 +2308,9 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, ParsedType &CastTy, SourceRange &CastRange) { - assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_sizeof, tok::kw___alignof, - tok::kw_alignof, tok::kw__Alignof, tok::kw_vec_step, + assert(OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual, tok::kw_sizeof, + tok::kw___alignof, tok::kw_alignof, tok::kw__Alignof, + tok::kw_vec_step, tok::kw___builtin_omp_required_simd_align) && "Not a typeof/sizeof/alignof/vec_step expression!"); @@ -2319,7 +2346,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, } isCastExpr = false; - if (OpTok.is(tok::kw_typeof) && !getLangOpts().CPlusPlus) { + if (OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual) && + !getLangOpts().CPlusPlus) { Diag(Tok, diag::err_expected_after) << OpTok.getIdentifierInfo() << tok::l_paren; return ExprError(); @@ -2345,7 +2373,8 @@ Parser::ParseExprAfterUnaryExprOrTypeTrait(const Token &OpTok, return ExprEmpty(); } - if (getLangOpts().CPlusPlus || OpTok.isNot(tok::kw_typeof)) { + if (getLangOpts().CPlusPlus || + !OpTok.isOneOf(tok::kw_typeof, tok::kw_typeof_unqual)) { // GNU typeof in C requires the expression to be parenthesized. Not so for // sizeof/alignof or in C++. Therefore, the parenthesized expression is // the start of a unary-expression, but doesn't include any postfix @@ -2563,10 +2592,21 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { } case tok::kw___builtin_offsetof: { SourceLocation TypeLoc = Tok.getLocation(); - TypeResult Ty = ParseTypeName(); - if (Ty.isInvalid()) { - SkipUntil(tok::r_paren, StopAtSemi); - return ExprError(); + auto OOK = Sema::OffsetOfKind::OOK_Builtin; + if (Tok.getLocation().isMacroID()) { + StringRef MacroName = Lexer::getImmediateMacroNameForDiagnostics( + Tok.getLocation(), PP.getSourceManager(), getLangOpts()); + if (MacroName == "offsetof") + OOK = Sema::OffsetOfKind::OOK_Macro; + } + TypeResult Ty; + { + OffsetOfStateRAIIObject InOffsetof(*this, OOK); + Ty = ParseTypeName(); + if (Ty.isInvalid()) { + SkipUntil(tok::r_paren, StopAtSemi); + return ExprError(); + } } if (ExpectAndConsume(tok::comma)) { @@ -2589,6 +2629,12 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocStart = Comps.back().LocEnd = ConsumeToken(); + enum class Kind { MemberAccess, ArraySubscript }; + auto DiagExt = [&](SourceLocation Loc, Kind K) { + Diag(Loc, diag::ext_offsetof_member_designator) + << (K == Kind::ArraySubscript) << (OOK == Sema::OOK_Macro); + }; + // FIXME: This loop leaks the index expressions on error. while (true) { if (Tok.is(tok::period)) { @@ -2602,9 +2648,9 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return ExprError(); } + DiagExt(Comps.back().LocStart, Kind::MemberAccess); Comps.back().U.IdentInfo = Tok.getIdentifierInfo(); Comps.back().LocEnd = ConsumeToken(); - } else if (Tok.is(tok::l_square)) { if (CheckProhibitedCXX11Attribute()) return ExprError(); @@ -2620,6 +2666,7 @@ ExprResult Parser::ParseBuiltinPrimaryExpression() { SkipUntil(tok::r_paren, StopAtSemi); return Res; } + DiagExt(Comps.back().LocStart, Kind::ArraySubscript); Comps.back().U.E = Res.get(); ST.consumeClose(); @@ -3089,11 +3136,9 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, } else if (isTypeCast) { // Parse the expression-list. InMessageExpressionRAIIObject InMessage(*this, false); - ExprVector ArgExprs; - CommaLocsTy CommaLocs; - if (!ParseSimpleExpressionList(ArgExprs, CommaLocs)) { + if (!ParseSimpleExpressionList(ArgExprs)) { // FIXME: If we ever support comma expressions as operands to // fold-expressions, we'll need to allow multiple ArgExprs here. if (ExprType >= FoldExpr && ArgExprs.size() == 1 && @@ -3142,7 +3187,7 @@ Parser::ParseParenExpression(ParenParseOption &ExprType, bool stopIfCastExpr, InMessageExpressionRAIIObject InMessage(*this, false); Result = ParseExpression(MaybeTypeCast); - if (!getLangOpts().CPlusPlus && MaybeTypeCast && Result.isUsable()) { + if (!getLangOpts().CPlusPlus && Result.isUsable()) { // Correct typos in non-C++ code earlier so that implicit-cast-like // expressions are parsed correctly. Result = Actions.CorrectDelayedTyposInExpr(Result); @@ -3263,7 +3308,7 @@ ExprResult Parser::ParseGenericSelectionExpression() { } SourceLocation DefaultLoc; - TypeVector Types; + SmallVector<ParsedType, 12> Types; ExprVector Exprs; do { ParsedType Ty; @@ -3392,7 +3437,6 @@ ExprResult Parser::ParseFoldExpression(ExprResult LHS, /// [C++0x] braced-init-list /// \endverbatim bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, - SmallVectorImpl<SourceLocation> &CommaLocs, llvm::function_ref<void()> ExpressionStarts, bool FailImmediatelyOnInvalidExpr, bool EarlyTypoCorrection) { @@ -3436,8 +3480,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, break; // Move to the next argument, remember where the comma was. Token Comma = Tok; - CommaLocs.push_back(ConsumeToken()); - + ConsumeToken(); checkPotentialAngleBracketDelimiter(Comma); } if (SawError) { @@ -3459,9 +3502,7 @@ bool Parser::ParseExpressionList(SmallVectorImpl<Expr *> &Exprs, /// assignment-expression /// simple-expression-list , assignment-expression /// \endverbatim -bool -Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs, - SmallVectorImpl<SourceLocation> &CommaLocs) { +bool Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr *> &Exprs) { while (true) { ExprResult Expr = ParseAssignmentExpression(); if (Expr.isInvalid()) @@ -3469,13 +3510,14 @@ Parser::ParseSimpleExpressionList(SmallVectorImpl<Expr*> &Exprs, Exprs.push_back(Expr.get()); - if (Tok.isNot(tok::comma)) + // We might be parsing the LHS of a fold-expression. If we reached the fold + // operator, stop. + if (Tok.isNot(tok::comma) || NextToken().is(tok::ellipsis)) return false; // Move to the next argument, remember where the comma was. Token Comma = Tok; - CommaLocs.push_back(ConsumeToken()); - + ConsumeToken(); checkPotentialAngleBracketDelimiter(Comma); } } @@ -3589,8 +3631,8 @@ ExprResult Parser::ParseBlockLiteralExpression() { /*NumExceptions=*/0, /*NoexceptExpr=*/nullptr, /*ExceptionSpecTokens=*/nullptr, - /*DeclsInPrototype=*/None, CaretLoc, - CaretLoc, ParamInfo), + /*DeclsInPrototype=*/std::nullopt, + CaretLoc, CaretLoc, ParamInfo), CaretLoc); MaybeParseGNUAttributes(ParamInfo); @@ -3671,7 +3713,7 @@ static bool CheckAvailabilitySpecList(Parser &P, /// availability-spec: /// '*' /// identifier version-tuple -Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { +std::optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { if (Tok.is(tok::star)) { return AvailabilitySpec(ConsumeToken()); } else { @@ -3679,11 +3721,11 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { if (Tok.is(tok::code_completion)) { cutOffParsing(); Actions.CodeCompleteAvailabilityPlatformName(); - return None; + return std::nullopt; } if (Tok.isNot(tok::identifier)) { Diag(Tok, diag::err_avail_query_expected_platform_name); - return None; + return std::nullopt; } IdentifierLoc *PlatformIdentifier = ParseIdentifierLoc(); @@ -3691,7 +3733,7 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { VersionTuple Version = ParseVersionTuple(VersionRange); if (Version.empty()) - return None; + return std::nullopt; StringRef GivenPlatform = PlatformIdentifier->Ident->getName(); StringRef Platform = @@ -3701,7 +3743,7 @@ Optional<AvailabilitySpec> Parser::ParseAvailabilitySpec() { Diag(PlatformIdentifier->Loc, diag::err_avail_query_unrecognized_platform_name) << GivenPlatform; - return None; + return std::nullopt; } return AvailabilitySpec(Version, Platform, PlatformIdentifier->Loc, @@ -3723,7 +3765,7 @@ ExprResult Parser::ParseAvailabilityCheckExpr(SourceLocation BeginLoc) { SmallVector<AvailabilitySpec, 4> AvailSpecs; bool HasError = false; while (true) { - Optional<AvailabilitySpec> Spec = ParseAvailabilitySpec(); + std::optional<AvailabilitySpec> Spec = ParseAvailabilitySpec(); if (!Spec) HasError = true; else |